Not able to close the browser using NightwatchJS - selenium

I am trying to open my url using Nightwatch and I wan't able to close the browser afterwards.
I tried using timeouts, as well as browser.end(), or browser.closeWindow(). None of them seem to be working for my url.
module.exports = {
'Demo test mywrkouts' : function (browser) {
browser.url('https://www.mywrkouts.com/workouts/search')
browser.timeouts('script', 10000, function(result) {
browser.end();
console.log("Test result"+result);
});
//browser.closeWindow();
}
};
It opens the page, but doesn't close the browser. I am using Chrome browser with chromedriver. I am expecting to close the window, but it doesn't work.
Any advice is appreciated.

LE: Like I extensibly described below, you don't need to explicitly close the browser at the end of the test (via browser.end()) as the Nightwatch test-runner does that for you at the end of each feature-file.
But, if you need to do some teardown operations and then explicitly close the session, do it in an after (or afterEach) hook. Try the following snippet:
module.exports = {
before(browser) {
browser.maximizeWindow();
},
'My Wrkouts Test': (browser) => {
browser.url('https://www.mywrkouts.com/');
// Check if the website logo is visible:
browser.expect.element('#barbell-homepage-top-image-desktop img.app-bar-desktop-logo').to.be.visible;
// Check the articles heading text:
browser.expect.element('h3.blog-carousel-title.primary-blue-text.center').text.to.contain('Foundational Education Series');
},
after(browser, done) {
browser.end(() => {
console.info('*--*--*--*--*--*--*--*--*--*--*--*--*');
console.info('*-- Clossing session... Good bye! --*');
console.info('*--*--*--*--*--*--*--*--*--*--*--*--*');
done();
});
}
};
Anyways, I feel you are confusing the way NightwatchJS/WebdriverIO/Protractor (or any other Webdriver-based test solution) is handling a browser session.
First off, you need not worry about closing the active session. Nightwatch does it for you at the end of each test feature-file. Thus, running a suit of let's say three test suites (login.js, register.js, forgot_password.js) will sequentially spawn & close three different browser sessions.
Also, browser.closeWindow() is only used for closing a window instance (taking into account that you have multiple windows associated with the same browser session). It won't close your main window, unless you have switched to another window instance (which was previously opened during your test run).
If you use browser.end() in the middle of your test, then you basically kill the active session, nullifying the following logic from your feature-file:
INFO Request: DELETE /wd/hub/session/4a4bb4cb1b38409ee466b0fc8af78101
- data:
- headers: {"Content-Length":0,"Authorization":"Basic Z29wcm86YmM3MDk2MGYtZGE0Yy00OGUyLTk5MGMtMzA5MmNmZGJhZTMz"}
INFO Response 200 DELETE /wd/hub/session/4a4bb4cb1b38409ee466b0fc8af78101 (56ms) { sessionId: '4a4bb4cb1b38409ee466b0fc8af78101',
status: 0,
value: null }
LOG → Completed command end (57 ms)
Everything after will look like this:
INFO Response 404 POST /wd/hub/session/null/elements (11ms) { sessionId: 'null',
value:
{ error: 'invalid session id',
message: 'No active session with ID null',
stacktrace: '' },
status: 6 }
!Note: There is no support for doing what you are trying to do, nor is it a common use-case, thus the lack of support for it across
all of these testing solutions.
They say a picture is worth 1000 words, so let's me simply put it this way... what you are trying to do is synonymous with the following:

Related

BrowserMob Proxy and Webdriverio minimal, empty HAR file

I was wondering if anyone has any idea as to what could be the problem or additional steps I could take in resolving the following issue.
I have a requirement to capture the network traffic so I can write some selenium tests verifying certain request headers.
The problem is when trying to use Webdriver.io + Browsermob proxy the HAR file created contains very minimal information.
I have tried using the C# bindings of the proxy and that resulted in the same issue as the Javascript ones. The only bindings that I got to work which returned data in the HAR file were the Java ones. There's a business requirement though that I must use Webdriver.io to implement this.
I have checked a number of other Questions and Answers from stack overflow but to no avail. Most have not been answered and the ones that have been have not worked for me just yet.
The code I am currently running is very similar to this one with the difference being the URL I'm trying to get the information from.
The difference between my Java code which worked and the Javascript and C# ones was that the Java one sets up the proxy programmatically whereas the other two expect the proxy to be already running and just connect to it.
Even with that in mind, when I start the C# or Javascript tests the proxy registers the new connection. The selenium server also starts up fine. Both cleanup with no issues according to their respective consoles once the tests are finished.
Are there any other ways to potentially debug this? Or even alternatives to capture the network traffic (Must work cross browser - already have a solution which works for chrome using chrome-remote-interface but we saw suggestions to use browsermob proxy for cross browser network capture).
Thanks for your time
Something I forgot to mention which is pretty important. Below is the npm package I am using for the browsermob-proxy :
https://www.npmjs.com/package/browsermob-proxy
Okay so, I figured out why I wasn't getting any data. I hope this saves others some time and hassle.
The problem is the way browsermob proxy handles localhost. I instead switched the proxy to use my IPV4 address and it started capturing all the HAR data.
See the code below:
//BroswerMobProxy + webdriver.io
//npm package used https://www.npmjs.com/package/browsermob-proxy
var webdriverio = require('webdriverio');
//proxy settings, host is IPV4 address
var Proxy = require('browsermob-proxy').Proxy
, fs = require('fs')
, proxy = new Proxy({host: 'Put IPV4 Address Here', proxyPort: 8081 , selHost: 'Put IPV4 Address Here'});
;
//convenience method that
proxy.cbHAR({captureHeaders: true, captureContent: true, captureBinaryContent: true }, doSeleniumStuff, function(err, data) {
if (err) {
console.error('ERR: ' + err);
} else {
/* Make sure har results are in the correct shape
* for any further processing
*/
var harResultsString = JSON.stringify(data);
var harResultsJson = JSON.parse(harResultsString);
//Write HAR file
fs.writeFileSync('DemoFile.json', harResultsJson, 'utf8');
//Print to console
console.log(harResultsJson);
}
});
//webdriver.io options
const opts = {
desiredCapabilities:{
browserName: 'chrome',
proxy: {
proxyType: 'MANUAL',
httpProxy: String(proxy.host)+":"+String(proxy.proxyPort),
sslProxy: String(proxy.host)+":"+String(proxy.proxyPort),
socksProxy:String(proxy.host)+":"+String(proxy.proxyPort),
socksVersion: 4,
autodetect: false
},
acceptSslCerts: true,
acceptInsecureCerts: true
},
host: 'Put IPV4 Address here',
port: 4444,
protocol: 'http',
coloredLogs: true,
proxy: 'http://'+String(proxy.host)+":"+String(proxy.proxyPort),
}
function doSeleniumStuff(proxy, cb) {
var browser = webdriverio.remote(opts);
// console.log(browser.options);
browser
.init()
.url('http://yahoo.com.au')
.getTitle().then(function(title) {
console.log('Title was: ' + title);
})
.end().then(cb).catch(e => console.log(e));
}

Basic authentication with Selenium in Internet Explorer 11

I read Basic authentication with Selenium in Internet Explorer 10
And I change my register key and when I use the user and pass in the url I don't see the basic authentication popup, but actually the page is not load. I see blank page!
I see my url in the IE but nothing happened - I see white page.
Must I change somethin in IE too?
It is not possible without some workarounds.
I also needed the same feature and previous SO answer confirms, that is it either impossible or possible with high probability of failure.
One thing I learned about Protrator is not to try to make too complicated stuff with it, or I'll have a bad time.
As for the feature- I ended up making Protractor to initiate Node.js task, which use request to make the authentication and provide back the data.
Taken straight from request module:
request.get('http://some.server.com/').auth('username', 'password', false);
// or
request.get('http://some.server.com/', {
'auth': {
'user': 'username',
'pass': 'password',
'sendImmediately': false
}
});
// or
request.get('http://some.server.com/').auth(null, null, true, 'bearerToken');
// or
request.get('http://some.server.com/', {
'auth': {
'bearer': 'bearerToken'
}
});

Reuse the browser session for Selenium WebDriver for Nightwatch.js tests

I need to write multiple tests (e.g. login test, use application once logged in tests, logout test, etc.) and need them all to be in separate files. The issue I run into is after each test, at the beginning of the next test being run, a new browser session start and it is no longer logged in due to the new session, so all my tests will fail except the login test.
So, is there a way to use the same browser session to run all of my tests sequentially without having to duplicate my login code? Sorry if this is a repost but I have searched and researched and not found any answers.
OR, is there a way to chain the test files somehow? Like having one file that you run that just calls all the other test files?
Using this function to chain together files:
extend = function(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
and adding files to this master file like this:
require("./testName.js");
module.exports = extend(module.exports,testName);
and having the test file look like this:
testName = {
"Test" : function(browser) {
browser
// Your test code
}
};
allowed me to have one file that could link all the tests to, and keep the same browser session the entire time. It runs the tests in the order you require them in the master file and if you do not call browser.end() until the last test is finished it will use one browser window for all tests.
Reuse of session is not good idea as you may run tests in different oreder, but
You could place login code into before function or even extract it into custom commands.
Example:
https://github.com/dimetron/backbone_app/blob/master/nightwatch/custom-commands/login.js
1 - In nightwatch config add
"custom_commands_path" : "nightwatch/custom-commands",
2 - Create custom-commands/login.js
exports.command = function(username, password, callback) {
var self = this;
this
.frame(null)
.waitForElementPresent('input[name=username]', 10000)
.setValue('input[name=username]', username)
.waitForElementPresent('input[name=password]', 10000)
.setValue('input[name=password]', password)
.click('#submit');
if( typeof callback === "function"){
callback.call(self);
}
return this; // allows the command to be chained.
};
3 - Test code - Before using .login(user, apssword)
module.exports = {
before: function(browser) {
console.log("Setting up...");
browser
.windowSize('current', 1024, 768)
.url("app:8000/")
.waitForElementVisible("body", 1000)
.login('user', 'password')
},
after : function(browser) {
browser.end()
console.log("Closing down...");
},
beforeEach: function(browser) {
browser
.pause(2000)
.useCss()
},
"Test 1": function(browser) {
browser
.assert.containsText("#div1", "some tex")
.pause(5000);
},
"Test 2": function(browser) {
browser
.assert.containsText("#div2", "some text")
.pause(5000);
}
}

Ember-auth signin test fails with json

I am having some issues with testing my signin/signout and related features of my app. The app works, but the test fail.
For testing, I use a QUnit with testem (I also tried teaspoon)
test "after signin, should redirect user back to previous page", ->
visit '/library'
fillIn '.signin-email', 'example#example.com'
fillIn '.signin-password', 'examplepass'
click '.signin-btn'
andThen ->
equal(testing().path(), 'library', "Should redirect back to library (was #{testing().path()})")
After running the test, I get a failure:
(screenshot here )
Authentication: visiting restricted page as non authenticated user: after signin, should redirect user back to previous page (2, 0, 2)Rerun544 ms
{user_id: 2, auth_token: wVveiyDLuXBXu69pQ2XQwg}
Source:
at Test.QUnitAdapter.Test.Adapter.extend.exception (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50149:5)
at superWrapper [as exception] (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:13374:16)
at Object.onerror (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50009:22)
at onerror (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20453:16)
at EventTarget.trigger (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20286:22)
at null.<anonymous> (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20439:14)
at EventTarget.trigger (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20286:22)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20588:17
Should redirect back to library (was signin)
Expected:
"library"
Result:
"signin"
Diff:
"library" "signin"
Source:
at http://localhost:7357/public/assets/spec/javascripts/integration/authentication_pages_spec.js.js:22:14
at andThen (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:50258:20)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49817:21
at isolate (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49989:14)
at http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:49972:12
at invokeCallback (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20463:19)
at null.<anonymous> (http://localhost:7357/public/assets/application-aad0a1b2c887cc25124c361787446e83.js:20513:11)
Also, auth.coffee:
App.Auth = Em.Auth.extend
request: 'jquery'
response: 'json'
strategy: 'token'
session: 'cookie'
modules: [
'emberData',
'authRedirectable',
'actionRedirectable'
]
signInEndPoint: '/signin'
signOutEndPoint: '/signout'
tokenKey: 'auth_token'
tokenIdKey: 'user_id'
tokenLocation: 'param'
emberData:
userModel: 'user' # create user model on login
authRedirectable:
route: 'signin'
actionRedirectable:
signInRoute: 'library'
# signInSmart: true
# signInBlacklist: ['signin']
signOutRoute: 'index'
I am unable to find the source of the error, so maybe it is something to do with ember-auth. Any ideas would be very appreciated.
Update 1 [Jan 4th]:
I've written an additional test, which passes only halfway. The test is simpler than the previous in that it does not check a redirect, but only checks that the user name appears in the UI after signin.
test "after signin, TEST", ->
visit '/library'
fillIn '.signin-email', 'user#example.com'
fillIn '.signin-password', 'foobargaz'
click '.signin-btn'
andThen ->
ok exists('.menu-signout'), "signout button exists"
The assertions passes, but I get an additional error reporting the returned JSON as seen in this screenshot. The screenshot basically shows:
[Fail] {user_id: 2, auth_token: wVveiyDLuXBXu69pQ2XQwg}
[Pass] signout button exists
Additionally, I've also run the tests by mocking the ajax requests with mockjax, but with the same failure.
Third, I should note that I had to patch "ember-auth-request-jquery.js" to make it work with ember testing as suggested here
I'm pretty sure you're failing to wait on the first visit to happen, so here's how I read it (I'm no CS person)
You're telling Ember to go to library
Before being sure it's finished navigating you're trying to fill in 2 fields and click a button (all of which probably doesn't exist)
then you check to see if it's library, but while waiting after you thought you clicked, really the page finishes rendering the login page from the visit
Here's what js2coffe says it'd kind of look like (my main point is the then after the visit).
test "after signin, should redirect user back to previous page", ->
visit("/library").then ->
fillIn ".signin-email", "example#example.com"
fillIn ".signin-password", "examplepass"
click(".signin-btn").then ->
equal testing().path(), "library", "Should redirect back to library (was " + (testing().path()) + ")"
Update 1/4: Documentation changed on me
Now we move to educated guess time. Looking through the Ember-auth code it might not be creating any timers/promises that Ember is aware of, in affect Ember thinks it's finished the signin process immediately. So the click promise is resolved immediately and you run your test immediately (andThen waits on the global testing promise to resolve). To test the theory you can do some terrible timeout and see if it does indeed redirect after some time
test "after signin, should redirect user back to previous page", ->
visit "/library"
fillIn ".signin-email", "example#example.com"
fillIn ".signin-password", "examplepass"
click ".signin-btn"
stop()
Ember.run.later this, (->
start()
equal testing().path(), "library", "Should redirect back to library (was " + (testing().path()) + ")"
), 5000
It turns out my coffeescript was not the best in the world.
The module function in QUnit should NOT compile to:
module('Authentication: visiting restricted page as non authenticated user', function() {
return setup(function() {
return Em.run(App, App.advanceReadiness);
});
});
but to:
module('Authentication: visiting restricted page as non authenticated user', {
setup: function() {
Ember.run(App, App.advanceReadiness);
},
// This is also new
teardown: function() {
App.reset();
}
});
Additionally, in my spec_helper.coffee file I had something like this:
QUnit.testStart(function() {
// FIXME: this below made it fail every time
// Ember.run(function() {
// return App.reset();
// });
Ember.testing = true;
});
QUnit.testDone(function() {
Ember.testing = false;
});
QUnit.done(function() {
return Ember.run(function() {
return App.reset();
});
});
which seems to have caused some issues, so I just deleted it and the tests now pass.

Why doesn't dojo.io.script.get() execute the provided error function when receiving a 404?

I am trying to use the following to do a cross-domain get:
dojo.io.script.get({
url: myUrl,
callbackParamName: "callback",
preventCache: true,
load: dojo.hitch( this, loadFunction ),
error: dojo.hitch( this, function() {
console.log('Error!!!');
})
});
The load function runs fine, however, when the server returns a 404, the error function does not run. Can anyone tell me why?
EDIT
After some investigation, I found that a timeout and handler could be implemented in the following way:
dojo.io.script.get({
url: myUrl,
callbackParamName: "callback",
timeout: 2000
}).then(function(data){
console.log(data);
}, function(error){
alert(error);
});
This uses functionality provided by the dojo.Deferred object.
When accessing server with script tags (that what dojo.io.script.get does), status code and headers are not available.
You may try some other ways to detect a problem, like using a timeout and analyzing a content of a script. The latter is problematic for JSONP calls (like in your example).
I realize this is old but I thought I'd share a solution in case others, like I had, come across this thread.
dojo.io.script is essentially adding a <script/> to your html page. So you can try this:
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', myUrl);
script.onerror = function() {
debugger
}
script.onload = function() {
debugger
}
document.getElementsByTagName('body')[0].appendChild(script);
That way if the script fails to load the onerror event is called.
*This may not work in every instance but is a good start