I have a case where I need to wait for the "Waiting for data to load" modal to disappear and said modal depends on $http request running.
I've used browser.wait statement, using Expected Conditions according to Protractor API.
My statement has currently this form:
beforeEach(function() {
browser.wait(element(EC.invisibilityOf(element(by.css(".msg-overlay"))), 30000);
});
it("describes something", function() {
...do some actions involving clicking...
})
Unfortunately spec always fails with message:
Message:
Failed: Timed out waiting for Protractor to synchronize with the page after 11 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md
While waiting for element with locator - Locator: By(css selector, .msg-overlay).
The following tasks were pending:
- $http:
Stack:
Error: Failed: Timed out waiting for Protractor to synchronize with the page after 11 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md
While waiting for element with locator - Locator: By(css selector, .msg-overlay).
The following tasks were pending:
- $http:
at /usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:101:16
at Promise.invokeCallback_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:1329:14)
at TaskQueue.execute_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2790:14)
at TaskQueue.executeNext_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2773:21)
I don't want to set allScriptsTimeout to 30000, as this would slow down actual fails, I would just like Protractor to wait for one modal to disappear. Help?
I think you can temporarily change the allScriptsTimeout on the fly in as similar fashion as you would do with the jasmine default timeout interval (not tested):
var originalTimeout;
beforeEach(function() {
originalTimeout = browser.allScriptsTimeout;
browser.allScriptsTimeout = 35000;
browser.wait(element(EC.invisibilityOf(element(by.css(".msg-overlay"))), 30000);
});
afterEach(function() {
browser.allScriptsTimeout = originalTimeout;
});
Related
I'm new to Protractor and I am trying to run my script.
describe('Navigator homepage', function() {
it('should proceed to login', function() {
browser.get('url');
});
it('Clicks the proceed button', function() {
const proceedButton = element(by.id('auth-login-page-button'));
proceedButton.click();
});
});
But whenever I run it the browser opens up and proceeds to the website and then waits for 20 sec and I get Error: ScriptTimeoutError: asynchronous script timeout: result was not received in 20 seconds. The element is clearly there and can be clicked, however not for the protractor. Am I doing something wrong?
Config file looks like this:
// An example configuration file.
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['login_spec.js'],
allScriptsTimeout: 20000,
getPageTimeout: 15000,
framework: 'jasmine',
jasmineNodeOpts: {
isVerbose: false,
showColors: true,
includeStackTrace: false,
defaultTimeoutInterval: 40000
}
};
Given your added error-message (see comment), the cause seems an continuously polling $timeout, which lets a promise unresolved for indefinite time and therefore leads to a asynchronous timeout of protractor (see details here).
solution
The correct solution is to avoid the use of $timeout and use $interval instead. That way protractor can stay in charge of the ControlFlow, managing your asynchronous tasks. So it's kind of a software bug, not a protractor error.
your error message:
Failed: Timed out waiting for asynchronous Angular tasks to finish after 20 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular While waiting for element with locator - Locator: By(css selector, md-raised md-primary md-button md-ink-ripple).
*The following tasks were pending: - $timeout: function (){return _this.getVersion()}*
Workaround
The not so nice workaround is to switch off the waitForAngular part of Protractor by setting browser.waitForAngularEnabled(false); (either in a beforeEach or directly in the spec.
However this also means, taking manually care of the controlFlow within the test specs itself. This requires using a lot of .then() and ExpectedConditions, losing one of the main advantages of Protractor.
Debug possibilities
Check the descriptions here for potential causes and workarounds.
Specifically try also browser.waitForAngularEnabled(false); to exclude angular-protractor-issues.
If you can't find cause, it could be a timing issue (unlikely, but worth being examined at that point).
You can try to add log-messages to narrow down the effective order of execution:
describe('Navigator homepage', function() {
it('should proceed to login', function() {
browser.get('url').then(function(){
console.log("Page is fully loaded");
});
});
it('Clicks the proceed button',function() {
console.log("Start 2nd Test");
const proceedButton = element(by.id('auth-login-page-button'));
proceedButton.click();
});
});
Or you put the actions in the same test case, using then() to execute them synchronously:
describe('Navigator homepage', function() {
it('should proceed to login', function() {
browser.get('url').then(function(){
const proceedButton = element(by.id('auth-login-page-button'));
proceedButton.click();
});
});
Open Homepage within onPrepare
As one nice side remark: If you always load the Homepage first, just put it into an onPrepare-part of your conf.js and it will always be executed once before your tests start:
onPrepare: function () {
browser.driver.manage().window().maximize();
browser.get('url');
},
I had a similar issue, I solved it by turning on ignore sync
browser.ignoreSynchronization = true
I'm working in Protractor cucumber framework.I do not get native selenium errors such as 'Element not Found' or 'No Such Element Found' or 'Element is not clickable' if the element is not found in page or not clickable.Instead i get "TimeoutError: Wait timed out after 10002ms"
Only if i get these errors I will come to know i have made some mistake in my element xpath or I have tried to click a disabled button etc.
Generic error like time out does not help me fix the failed test cases easily.
Below is my code.contactPage.js is the implementation.util.js is some helper methods in my framework
File contactPage.js
var contact = element(by.xpath("//p[contains(text(),'Contact Me')]"));
function clickUserGuide() {
return util.isDisplayed(contact, 10000).then(() => {
return util.clickElement(contact, 10000);
});
File util.js
function isDisplayed(element, milliseconds) {
return browser.wait(EC.visibilityOf(element), milliseconds).then(() => {
return element.isDisplayed();
});
};
function clickElement(element, milliseconds) {
return browser.wait(EC.visibilityOf(element), milliseconds).then(() => {
element.click();
return true;
});
};
}
The reason why you are getting TimeoutError: Wait timed out after 10002ms is because of the method browser.wait(EC.visibilityOf(element), milliseconds) you are using.
The method doesn't have a fail "hard" like the No Such Element Found, it just keeps waiting for the element to match the expected condition, in your case you are waiting for:
the element is be displayed
AND the height and width to be greater than 0
If this doesn't happen in the given amount of seconds the condition fails with a message that the element couldn't match the condition within the given time.
What happens is you use browser.wait(EC.presenceOf(element), milliseconds), is the element really present in the DOM?
I am trying to test my website which is a non angular website through Protractor. My code is:
describe("Supplier Portal: Login ", function () {
//ui.setSmallScreenSize();
// ui.testLogger(100);
it("test", co.wrap(function* () {
browser.ignoreSynchronization = true;
yield browser.driver.get("https://cit.supplier.ext.here.com/");
yield element(by.xpath("//*[#id=\"rnav\"]/li[2]/a")).click();
var elmOK = element(by.xpath( "//*[#id=\"sign-in-email\"]"));
browser.driver.wait(protractor.until.elementIsVisible(elmOK.getWebElement()))
}));
});
But when I try to execute the code I got the following error:
Failed: No element found using locator: By(xpath, //*[#id="sign-in-email"])
But the element is there on the website.
Please advice what I'm doing wrong
Since you are working on a non-angular site and using browser.ignoreSynchronization = true, Protractor will not wait for the angular variable to become available, so it starts firing tests off because it thinks the app is ready, more info here.
You need to manipulate the Control Flow by using Expected Conditions so Protractor knows that it is waiting for something. This will make your tests more consistent and reliable.
A few examples to guide you:
Wait for an element to be loaded/present in the DOM:
var EC = protractor.ExpectedConditions;
var ele = element(by.css('div.class'));
browser.wait(EC.presenceOf(ele), 5000);
The 5000 parameter value I passed in says wait a maximum of 5 seconds, if not present in 5 seconds then fail.
Wait for an element visible:
browser.wait(EC.visibilityOf(ele), 5000);
Wait for an element to be clickable:
browser.wait(EC.elementToBeClickable(ele), 5000);
Again, it's important to note that these are implicit waits and they will wait a maximum of the time parameter provided. It is not a guaranteed amount of time to wait, they fire off ASAP when they find the element you told it to wait for.
I'm using angular-growl-v2 notifications in my app.
They work ok, the problem comes on my protractor tests. I have to use a TTL (around 6 seconds) as it is a requirement. Then I have the following test:
it('should send a request and notify the user about the result',function(){
detailPage.verifyEmailtButton.click().then(function(){
var expectedDiv = element(by.css('.alert-success'));
expect(expectedDiv).toBeDefined();
});
});
But it is always throwing an error:
NoSuchElementError: No element found using locator: By.cssSelector(".alert-success")
This does not happens when the TLL is -1.
Someone can help here? Thanks in advance.
angular-growl-2 uses $timeout, which doesn't play nicely with protractor: protractor waits for the timeout to end before it completes its sync with angular process.
So by the time it reaches your expect call, the timeout has elapsed and the alert is no longer there. Check out the Waiting for page synchronization section of this doc:
https://github.com/angular/protractor/blob/master/docs/timeouts.md
(This page relates to timeouts, which you don't appear to be experiencing, but since the default timeout is 11 seconds, it could well be that the entire process, including your 6 second TTL, takes place before a timeout happens)
There's a PR to angular-growl-v2 to use $interval instead of $timeout, but its currently waiting for tests:
https://github.com/JanStevens/angular-growl-2/pull/85
Explicitly wait for the alert to be present after clicking the button:
detailPage.verifyEmailtButton.click();
var EC = protractor.ExpectedConditions;
var expectedDiv = element(by.css('.alert-success'));
browser.wait(EC.presenceOf(expectedDiv), 10000, "No alert present");
using the element(by.model()) syntax to find a field and input text.
element(by.model('sample_ad.id')).sendKeys('batman');
gets the exception from chromedriver:
Stacktrace:
Error: Timed out waiting for Protractor to synchronize with the page after 11 seconds
at Error (<anonymous>)
==== async task ====
WebDriver.executeScript()
at Protractor.waitForAngular (/Users/jon/dev/project_name/node_modules/protractor/lib/protractor.js:278:22)
at Protractor.findElement (/Users/jon/dev/project_name/node_modules/protractor/lib/protractor.js:427:8)
at Object.elementFinder.(anonymous function) [as sendKeys] (/Users/jon/dev/project_name/node_modules/protractor/lib/protractor.js:62:21)
at null.<anonymous> (/Users/jon/dev/project_name/test/e2e/features/somedirectiveSpec.js:24:39)
at /Users/jon/dev/project_name/node_modules/protractor/jasminewd/index.js:54:12
==== async task ====
at null.<anonymous> (/Users/jon/dev/project_name/node_modules/protractor/jasminewd/index.js:53:12)
at null.<anonymous> (/Users/jon/dev/project_name/node_modules/protractor/node_modules/minijasminenode/lib/async-callback.js:45:37)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
Not sure why this is breaking, but Protractor seems very fragile right now... I have no issues using the browser object to find elements, input text, etc...
Any help would be appreciated
EDIT: if I change the line to the following, I am able to interact with the text field.
browser.driver.findElement(protractor.By.id('sample_ad_id')).sendKeys('batman');
hopefully this will help others....
Found this on github (see references link). The issue I believe is a script not returning, thus the sendKeys didn't work. Before interacting with the dom using protractor objects (element, ptor, etc), set this variable:
browser.ignoreSynchronization = true;
The reason the following works is because it doesn't rely on async calls, its just directly interacts with the dom and inserts the keys into the input field.
browser.driver.findElement(protractor.By.id('sample_ad_id')).sendKeys('batman');
The reason my call didn't work (I believe) is because there was an async call that didn't return in time.
element(by.model('sample_ad.id')).sendKeys('batman');
references:
https://github.com/angular/protractor/issues/325
See https://github.com/angular/protractor/blob/master/docs/faq.md#my-tests-time-out-in-protractor-but-everythings-working-fine-when-running-manually-whats-up
for more information on timeouts.
It looks like your test is timing out. The default timeout for protractor is 11 seconds.
Try setting a different timeout for this test:
it('should override timeout', function() {
// Timeout of 30 seconds.
element(by.model('sample_ad.id')).sendKeys('batman');
}, 30000)
You can also override the timeout for all your tests in the protractor configuration file. See this sample config file:
https://github.com/andresdominguez/protractor-meetup/blob/master/protractor-config.js#L19
// Inside the protractor config file.
onPrepare: function() {
// Override the timeout for webdriver.
var ptor = protractor.getInstance();
ptor.driver.manage().timeouts().setScriptTimeout(60000);
}