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 } };
Advertisement
Answer
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'); },