Our app has a poller which makes calls to an API every 3 seconds. When I load a page with has an active instance of the poller Protractor will always time out.
The poller is started when the page loads and uses the Angular $timeout function.
Is there a way to get Protractor to ignore the poller or send a signal to the app to pause the poller momentarily so the E2E test can finish running?
Not yet - Protractor attempts to avoid syncing problems by waiting for any $timeout calls to finish, so if you have constant calls it will time out. This is probably an issue that others will run into, so I'll call it a bug.
Thanks @juliemr. If you more details on what the app is doing (to reproduce or test a fix) let me know.
Would love to see it fixed :)
It's been a recurring problem with Angular E2E testing, even with Testacular.
Will be exploring this issue in the poll branch
The issue is basically - how do I tell if the site is just being slow, or if there's some intentional polling going on and it's OK to resume the E2E test?
First step - give better error messages when timeouts occur.
For the record, here's a link to the Angular Scenario Runner Issue of this same thing.
Added a kind of lame temporary fix with 73821fb6b6d252a93cc15ce990b4ec4738b87b95
You can turn off synchronization using protractor.ignoreSynchronization
But of course, this means that Protractor will NEVER wait for $timeout or $http to finish before fulfilling, which can make tests flaky. Leaving this bug open as I discuss better solutions.
EDIT: See my note below about ignoreSynchronization being an instance variable, not a static / class variable.
Important comment!
ignoreSynchronization is an instance variable, NOT a static variable of the protractor namespace! I apologize for making this unclear above. So if you have
var ptor = protractor.getInstance()
You will want to set ptor.ignoreSynchronization, NOT protractor.ignoreSynchronization
Sorry for the confusion!
@juliemr, I'm stuck. I don't know is it ignoreSynchronization not working or my code is wrong:
var util = require('util');
var loginAsExistingUser;
var firstName = 'Andrew';
var lastName = 'Auto1'
loginAsExistingUser = function (ptor) {
ptor.findElement(protractor.By.css('input[name=email]')).sendKeys("email");
ptor.findElement(protractor.By.css('input[name=password]')).sendKeys("123");
ptor.findElement(protractor.By.css('button.green.large')).click();
};
describe('Portal SignIn Page', function() {
var ptor;
beforeEach(function() {
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true;
console.log("What's up with ignoreSynchronization?" + ptor.ignoreSynchronization);
//ptor.driver.manage().timeouts().setScriptTimeout(500);
}, 20000);
it ('Check URL after Sign In', function(){
ptor.get('#/login/');
ptor.waitForAngular();
var expectedURL = ptor.baseUrl + 'home';
loginAsExistingUser(ptor);
ptor.sleep(5000);
expect(ptor.getCurrentUrl()).toBe(expectedURL);
}, 20000);
it ('Checking username', function(){
var name = (firstName + lastName);
ptor.findElement(protractor.By.css('.login-menu-button')).getText().
then(function(username) {
expect(username).toEqual(name);
});
}, 30000);
});
It looks like ignoreSynchronization gets set correct but test still times out:
Failures:
1) Portal SignIn Page Checking username
Message:
timeout: timed out after 30000 msec waiting for spec to complete
Stacktrace:
undefined
Finished in 54.854 seconds
3 tests, 3 assertions, 1 failure
Hey everyone,
With Angular 1.2rc3, you can now use the $interval service to do your polling! Protractor will _not_ wait for anything registered with $interval! Check out https://github.com/angular/angular.js/commit/2b5ce84fca7b41fca24707e163ec6af84bc12e83 for more details.
In our case, we have our own service that keep synchronized a local model with the server database using long polling.
As a workaround to this issue, we replaced clientSideScripts.waitForAngular with a function that wait for angular $$phase and wait for our own service to be ready. This solve all our issues.
@juliemr: Will be really handy if it is possible to overwrite the waitForAngular function from test configuration!
@fedenunez Could you share more details about this $$phase patch?
I'm currently facing the same issue and don't have control over the source base to change $timeout usage to $interval as @juliemr mentions
Using browser.ignoreSynchronization = true; breaks the tests event with manuals browser.sleep(...)
@elgalu under protractor/lib/clientsidescripts.js you will find the implementation of waitForAngular function. That function is executed by protractor to synchronize the Control Flow with angular state.
I just replaced that code with my own implementation that looks something like this:
clientSideScripts.waitForAngular = function() {
var selector = arguments[0];
var callback = arguments[1];
var TIMEOUT_MS = 18000; // ms
var INTERVAL_MS = 5; //ms
var elapsed = 0;
var el = document.querySelector(selector);
// "inject" $rootScope service
var $rootScope = angular.element(el).injector().get('$rootScope');
// "inject" our own longpolling service
var modelService = angular.element(el).injector().get('model');
var checkLoop = function() {
if (elapsed <= TIMEOUT_MS ) {
// check angular digest state and check our longpoll service state (modelService state)
if (!$rootScope.$$phase && ( !modelService.isProcessing() )) {
// everything is synchronized!
callback();
} else {
// somebody is still processing, wait a little bit more.
elapsed = elapsed + INTERVAL_MS;
setTimeout( checkLoop, INTERVAL_MS );
}
} else {
callback( "Timedout while waiting for angular!" );
}
}
//initialize checking loop
setTimeout( checkLoop, 0 );
};
I hope this help!
Any update on this? I still need to set ptor.ignoreSynchronization = true; in beforeEach() and ptor.ignoreSynchronization = false; in afterEach().
I have a situation where we're loading an index page, which can take quite a long time - about ten seconds.
Protractor then goes and finds a few items on the index page, clicks a button to open a modal (Another HTTP request), fills out a form and clicks a button (Another HTTP request), then repeats.
It does this for almost 100 items, or it would if it could get through three of them before getting -
timeout: timed out after 30000 msec waiting for spec to complete
This is a huge pain in the ass. Any ideas on how to fix this, or just indefinitely extend the the 30000ms limit?
I use 7mins spec timeouts, also have long running e2e tests:
allScriptsTimeout: 7*60*1000,
Should add that we're already using
allScriptsTimeout: 120000
And still getting the 3000 msec error
You're getting the 30secs timeout on Firefox or Chrome or Both?
Chrome 33.0.1750.152
Angular 1.2.8
Protractor 0.20.1
We're only testing in Chrome - thankfully we have very specific requirements from the client
@wilfredjamesgodfrey it sounds like your tests actually take more than 30 seconds. Increasing the timeout in this case seems reasonable.
thanks @juliemr, I would do that with allScriptsTimeout, right? It just doesn't seem to be working. Re: https://github.com/angular/protractor/issues/49#issuecomment-38747093
You want to change this one: https://github.com/angular/protractor/blob/master/referenceConf.js#L138
Ah, that's amazing @juliemr. Thanks!
I have a permanent $interval in my app and I can't stop it via a click event since it waits to synchronize before running the test. Is there a workaround to this?
Given that Angular 2, as of yet, at least to my knowledge, does not provide an interval service for polling. Would you propose people using protractor to test angular 2 apps workaround this issue? In cases where dropping synchronization is not possible.
In our use case we have a timeout of 20 minutes, set up as a sort of ticker, to revalidate a JWT token. When our protractor tests hit the homepage, they sit there waiting for a 20min timeout.
Cheers,
Nuno
@nvsoares That is exactly what I wanted to write as well! Is there any solution or workaround for this yet?
Edit:
I found this issue, which I guess should be linked here.
Please see our updated documentation (https://github.com/angular/protractor/blob/master/docs/timeouts.md#angular) on this issue and let us know if we need to make it more clear. Thanks!
@juliemr
using $interval service is not working for long running api calls when running protractor e2e tests.. I am still getting timeout for pending http tasks. What could be the fix for this issue? please respond asap i am struggling with this issue since couple of weeks.
Thanks
Murali
@MuraliMolluru ,
Addressing protractor members won't help directly. If you still experience problems please create a new issue and use the issue template in which you provide all needed info. Otherwise you can ask a question on Stackoverflow with the 'protractor' tag or post in the Gitter Channel to get help.
@wswebcreation
I had already created an issue but it was closed without answer and told me that i have to ask in stackoverflow. I even asked in stakoverflow but have not get any answer.
@MuraliMolluru , can you give me the link on SO, then I can check if I can help you there
@wswebcreation Thank you for the response.
https://stackoverflow.com/questions/44813083/protractor-timeout-with-long-running-http-asynchronous-tasks
@wswebcreation Did u get a chance to look at the issue?