Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protractor E2E test times out when app polls an API at regular intervals #49

Closed
stickel opened this issue Aug 20, 2013 · 32 comments
Closed
Assignees

Comments

@stickel
Copy link

stickel commented Aug 20, 2013

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?

@juliemr
Copy link
Member

juliemr commented Aug 22, 2013

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.

@stickel
Copy link
Author

stickel commented Aug 22, 2013

Thanks @juliemr. If you more details on what the app is doing (to reproduce or test a fix) let me know.

@blandinw
Copy link

Would love to see it fixed :)
It's been a recurring problem with Angular E2E testing, even with Testacular.

@ghost ghost assigned juliemr Sep 6, 2013
@juliemr
Copy link
Member

juliemr commented Sep 6, 2013

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.

@juliemr
Copy link
Member

juliemr commented Sep 6, 2013

For the record, here's a link to the Angular Scenario Runner Issue of this same thing.

@juliemr
Copy link
Member

juliemr commented Sep 6, 2013

Added a kind of lame temporary fix with 73821fb

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.

@juliemr
Copy link
Member

juliemr commented Sep 19, 2013

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!

@apankov1
Copy link

@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

@juliemr
Copy link
Member

juliemr commented Oct 16, 2013

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 angular/angular.js@2b5ce84 for more details.

@fedenunez
Copy link

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!

@elgalu
Copy link
Contributor

elgalu commented Jan 24, 2014

@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(...)

@fedenunez
Copy link

@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!

@panuhorsmalahti
Copy link

Any update on this? I still need to set ptor.ignoreSynchronization = true; in beforeEach() and ptor.ignoreSynchronization = false; in afterEach().

@wilfredjonathanjames
Copy link

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?

@elgalu
Copy link
Contributor

elgalu commented Mar 26, 2014

I use 7mins spec timeouts, also have long running e2e tests:

    allScriptsTimeout: 7*60*1000,

@wilfredjonathanjames
Copy link

Should add that we're already using

allScriptsTimeout: 120000

And still getting the 3000 msec error

@elgalu
Copy link
Contributor

elgalu commented Mar 26, 2014

You're getting the 30secs timeout on Firefox or Chrome or Both?

@wilfredjonathanjames
Copy link

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

@juliemr
Copy link
Member

juliemr commented Mar 26, 2014

@wilfredjamesgodfrey it sounds like your tests actually take more than 30 seconds. Increasing the timeout in this case seems reasonable.

@wilfredjonathanjames
Copy link

thanks @juliemr, I would do that with allScriptsTimeout, right? It just doesn't seem to be working. Re: #49 (comment)

@juliemr
Copy link
Member

juliemr commented Mar 26, 2014

@wilfredjonathanjames
Copy link

Ah, that's amazing @juliemr. Thanks!

@AlexCppns
Copy link

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?

ghillert added a commit to ghillert/spring-xd that referenced this issue Aug 7, 2014
* Made the documentation (README.md) clearer regarding issue `Could not find chromedriver...`
* Due to the recently introduced addition of polling the E2E tests were partially broken also. Add `browser.ignoreSynchronization=true` to the tests as described at angular/protractor#49
ghillert added a commit to ghillert/spring-xd that referenced this issue Aug 26, 2014
* Made the documentation (README.md) clearer regarding issue `Could not find chromedriver...`
* Due to the recently introduced addition of polling the E2E tests were partially broken also. Add `browser.ignoreSynchronization=true` to the tests as described at angular/protractor#49
ilayaperumalg pushed a commit to spring-attic/spring-xd that referenced this issue Aug 26, 2014
* Made the documentation (README.md) clearer regarding issue `Could not find chromedriver...`
* Due to the recently introduced addition of polling the E2E tests were partially broken also.
  Add `browser.ignoreSynchronization=true` to the tests as described at angular/protractor#49

XD-2015 Reference `protractor.conf.js` explicitly

* Bump versions in `package.json`
* Have NPM execute `webdriver-manager update`

XD-2015 Polishing, updating `README.md`
kegsay added a commit to matrix-org/synapse that referenced this issue Sep 22, 2014
This uses the ignoreSynchronization flag because of the longpoll on the event
stream. It would be better to use $interval, but couldn't get that to
*reliably* work when testing. I suspect that $interval won't help us here,
since there is genuinely an open $http connection, as we're doing a long
poll. angular/protractor#49 for more info.
ghillert added a commit to ghillert/spring-xd-admin-ui-client that referenced this issue Apr 21, 2015
* Made the documentation (README.md) clearer regarding issue `Could not find chromedriver...`
* Due to the recently introduced addition of polling the E2E tests were partially broken also.
  Add `browser.ignoreSynchronization=true` to the tests as described at angular/protractor#49

XD-2015 Reference `protractor.conf.js` explicitly

* Bump versions in `package.json`
* Have NPM execute `webdriver-manager update`

XD-2015 Polishing, updating `README.md`
@nvsoares
Copy link

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

@tobiaseisenschenk
Copy link

tobiaseisenschenk commented Apr 11, 2017

@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.

@heathkit
Copy link
Contributor

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!

@MuraliMolluru
Copy link

@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

@wswebcreation
Copy link
Contributor

@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.

@MuraliMolluru
Copy link

@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.

@wswebcreation
Copy link
Contributor

@MuraliMolluru , can you give me the link on SO, then I can check if I can help you there

@MuraliMolluru
Copy link

@MuraliMolluru
Copy link

@wswebcreation Did u get a chance to look at the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests