I am running protractor to test angularjs app. All working fine, but when the browser window is spawned, it is in the background, so I have to cmd-tab to find it, and miss what happens at the start.
Is there any way I can programmatically bring the browser window to the foreground?
You can trigger an alert and immediately accept it. Put the following into onPrepare():
onPrepare: function () {
return browser.executeScript("alert('Test');").then(function () {
return browser.switchTo().alert().accept();
});
},
Or, as #LeoGalucci pointed out, take a screenshot:
onPrepare: function () {
return browser.takeScreenshot();
},
Note that return is important here - in this case, Protractor would not start executing tests until the promise returned from onPrepare() is resolved.
Both options worked for me.
Related
I'm using Protractor with Cucumber to write some tests but I'm stuck at some point. In step after login, I'm rerouting to another page using browser.get(url) function provided by protractor. But it always returns before the page is completely loaded. I have tried many solutions so far but no luck. I have tried with browser.wait, browser.get(url).then(function(){ // code when it loads}) but Im getting 0 positive results.
Here's my code:
// Steps will be implemented here
this.Given(/^I am logged in as user \'([^\']*)\'$/, function (user, callback) {
console.log('USER: ' + user);
browser.driver.get('https://cit-was70-l06/ipa')
browser.driver.findElement(by.xpath('my_xpath')).sendKeys(user);
browser.driver.findElement(by.xpath('my_xpath')).sendKeys(user);
browser.driver.findElement(by.xpath('my_xpath')).click().then(callback);
});
this.Then(/^The screen is shown, with title \'([^\']*)\'$/, function (title, callback) {
console.log('Title from feature file: ' + title);
var url = 'some/url/in/application/';
browser.get(url).then(function(){
// This portion executes before page is completely loaded.
// So if I try to get any element, it throws me an error.
// [15:32:13] E/launcher - "process.on('uncaughtException'" error, see
// launcher
// [15:32:13] E/launcher - Process exited with error code 199
// It works if I add static delay to wait for page load completely
// but that will not be a good solution if I have too much pages to test
callback();
});
console.log('After page laoad');
});
Any suggested work around will be much appreciated.
[15:32:13] E/launcher - "process.on('uncaughtException'" error, see launcher
[15:32:13] E/launcher - Process exited with error code 199
The above error can be caused due to various reasons mostly related to promises. But it should throw the correct message. There is already a work around provided here https://github.com/angular/protractor/issues/3384 to catch the exact error message.
You could change the launcher.ts file in your protractor dependency as mentioned in above forum to catch the error inorder to debug your issue.
And I would suggest you to return your promises instead of callbacks when writing step definitions in protractor-cucumber, in this way cucumber would know when to complete its async actions.
Try the below code.check whether it helps.
browser.get(url);
browser.waitForAngular();
then try to call your function.
Use protractor.ExpectedConditions to check visibility of any elements on page which will be displayed after successful login. Write a customized method as shown below.
If element displayed, then navigate other page using browser.get();
Code Snippet
EC = protractor.ExpectedConditions;
//targetElement=element(locator);
this.isElementVisible = function (targetElement, timeOut) {
'use strict';
timeOut = timeOut !== undefined ? timeOut : 8000;
browser.wait(EC.visibilityOf(targetElement),
timeOut).thenCatch(function()
{
assert.fail(' element is not visible');
});
};
What are the methods we can use to wait for an Angular site to be loaded in order to test it with protractor in order to avoid this error caused by jasmine : A Jasmine spec timed out. Resetting the WebDriver Control Flow ?
I'm able to make the login and go to home page that test is passed, but from the second test i have problems of jasmine.
I have configured this problem by adding this function into my config file :
onPrepare: function() {
return browser.getProcessedConfig().then(function(config) {
var browserName = config.capabilities.browserName;
browser.manage().timeouts().setScriptTimeout(60000);
});
});
You can use the browser object of Protractor to wait for angular.
As soon as you load your page add the following :
browser.waitForAngular();
This error means that your test took too much time and exceeded the default Jasmine spec timeout interval which is 30 seconds by default (It looks like you've configured the timeout to be 60 seconds). It can be configured in the jasmineNodeOpts object in your Protractor config:
jasmineNodeOpts: {defaultTimeoutInterval: timeout_in_millis},
The solution is usually use-case specific and it usually indicates there is an error in the test code. In order to fully understand what is going, we would need to see the code itself.
In your particular case, for starters, you should try moving the "ignore synchronization" and the browser.get() part into the beforeEach. Also, since you are turning the sync off, you need to wait for the element to be present on the page before interacting with it:
describe("my app", function () {
beforeEach(function () {
browser.ignoreSynchronization = true;
browser.get("...");
});
it("should make the login test", function () {
// ...
var EC = protractor.ExpectedConditions;
var username = element(by.model("credentials.username"));
browser.wait(EC.presenceOf(username), 10000);
username.sendKeys("RET02");
// ...
});
});
And, I am not sure if you really need to turn the synchronization off since this is an AngularJS page you are working with.
Can you wait for a url?
Let's assume that when you click on the login button your page is redirected to another url. So you can wait for the expected url. Example:
browser.driver.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
// Dashboard is the loaded url after login (in this example)
return /Dashboard/.test(url);
});
}, 60000);
This code waits for the page browser.baseUrl/Dashboard to be loaded, for 60 seconds
Due to Protractor 2.0's breaking changes, I have to refactor my at() function. I use this on non-angular pages to both wait for the page to load, and return true, so it's expectable (if that's a word).
Because 2.0 no longer returns a promise from a locator, it's breaking my wait (wait fires immediately). Thus, I've turned to the new ExpectedConditions... which works fine. My question is, am I using this correctly, or is there a better solution?
Page object locator:
this.pageLoaded = $('div#splash[style="display: none;"]');
Works in Protractor 1.8.0 (breaks in 2.0.0):
this.at = function() {
var that = this;
return browser.wait(function() {
return browser.isElementPresent(that.pageLoaded);
});
};
My working solution for Protractor 2.0.0:
this.at = function() {
var that = this;
return browser.wait(function() {
return protractor.ExpectedConditions.presenceOf(that.pageLoaded);
});
};
And for example, I would call this like so:
expect(mainPage.at()).toBeTruthy();
It looks like there was another breaking change in the Protractor 2.0 changelog, referring to a problem in WebDriver 2.45 that makes the wait parameter required:
Due to changes in WebDriverJS, wait without a timeout will now default to waiting for 0 ms instead of waiting indefinitely.
Before:
browser.wait(fn); // would wait indefinitely
After:
browser.wait(fn, 8000) // to fix, add an explicit timeout
This will be reverted in the next version of WebDriverJS.
In our Protractor tests, we always refer to a common helper class var helper = require("..\helpers.scenario.js"). To fix this problem, we just wrapped browser.wait in the helper class and passed in a timeout.
wait: function(f) {
return browser.wait(f, 30000);
},
We then used find-replace to change from browser.wait to helper.wait.
Is it possible to leave the test browser windows open after Angular Protractor tests run? I have a tough test failing in FireFox and it'd be useful to access the state of the web page to see what's going on.
You can use Protractor debug/pause feature to pause the e2e run which will ultimately leave the browser open: more info here
To do so, add this line on your protractor test before the failing one
browser.pause();
There is also a very useful tool called elementor that you may want to take a look later on.
browser.pause no longer works with current Node v8.1.0, see here, but you could use browser.sleep(10000); to keep the browser open for e.g. 10 seconds
If you configured the test script to run using grunt, you could use the following code:
grunt.initConfig({
// ...
protractor: {
options: {
configFile: "protractor.conf.js",
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false // If true, protractor will not use colors in its output.
},
run: {}
},
// ...
});
If you have Node 8+, bumped into issue "Error: Cannot find module '_debugger'" while attempting browser.pause solution from the accepted answer and you couldn't fix it using this github solution then you can workaround it as follows:
Install protractor as a module of the automation framework (i.e. without -g flag)
npm install protractor
Run webdriver-manager update for this protractor instance as well:
node ./node_modules/protractor/bin/webdriver-manager update
Where you have browser.pause(); in your code, replace it with debugger; statement
Run your code as follows:
node inspect ./node_modules/protractor/bin/protractor protractorConf.js
Where protractorConf.js is the config file of your protractor instance
If debugger waits for an input from you at the command line, just type cont and hit enter (to continue the execution)
super simple solution, that does exactly what's needed
The idea is that you don't really want to keep alive the session but rather pause it for a very long time when tests are done and be able to resume on-close procedures at any time
So just add this to your config.js
async onComplete() {
await browser.waitForAngularEnabled(false);
await browser.wait(
async () => {
let url = await browser.getCurrentUrl();
return url.includes('close/');
},
5 * 60 * 1000,
'Keep-alive timeout reached, closing the session...',
);
},
What the code does is, after all tests passed or failed, it waits until you type and submit close/ in browser's url field, or times out itself in 5 mins.
The reason await browser.waitForAngularEnabled(false); is needed here, because the browser opens an empty page when you type close/ which is non angular
You can even improve it and make it conditional, based on a parameter you pass to protractor config
I am new to protractor and I am trying to figure out how to make the test/runner pause on failure. Ideally I would love to transition to the nodejs debugger but am open to any suggestion.
My use case is basically, when a test fails I would like to see what state the UI is in to help understand why the test failed.
Nick.
You can also add to the jasmine config, to stop when spec fails:
(same as how protractor-screenshot-reporter works)
for jasmine 1:
onPrepare: function () {
exports.config = {
onPrepare: function () {
jasmine.getEnv().addReporter({
reportSpecResults: function (spec) {
if (!spec.results().passed()) {
spec.results().items_.forEach(function (v) {
console.log(v.trace.stack);
});
browser.pause();
}
}
});
}
}
}
for jasmine2:
onPrepare: function () {
jasmine.getEnv().addReporter({
specDone: function (spec) {
if (spec.status === 'failed') {
console.dir(spec.failedExpectations.length);
console.log(spec.failedExpectations[0].message);
console.log(spec.failedExpectations[0].stack);
browser.pause();
}
}
});
}
then by typing "repl" in the console you switch to interactive mode, so you can try out the protractor commands.
You can put browser to sleep after or before your expect line to see what's going on.
browser.sleep(20000); // sleep 20 seconds
Update:
protractor now supports .pause() method.
browser.pause()
Read the docs here: https://angular.github.io/protractor/#/api?view=Protractor.prototype.pause
You should put browser.debugger() where you want your test to stop.
You have to have selenium standalone server running. You can start it using webdriver-manager start from command prompt. In your configuration file for protractor you have to have entry for selenium server pointing to that server like
seleniumAddress: 'http://localhost:4444/wd/hub', and entry for chromeOnly should be set to false. Debugging only works for chrome browser. Once you run you application it will drop into nodejs debugger. You have to press 'c' to continue. Once you debug statement is hit, you can do F12 to open debugger, and under console, you can use window.clientSideScripts to see what you have. I myself am at this point, but documentation for clientSideScripts is non-existant, so you can type the name of the function and it will give you the function definition. Then, you can try to figure out parameters it expects.