Protractor continues to wait for completed HTTP requests

I have a RESTful API, and now I am developing an angular2 application that uses data services to call the API. Then I wanted to implement end-to-end tests using a protractor. I wanted to start at a very low level, so I ran tests to check if my components are present when I click on the link. The test is as follows:

describe('my-webclient', () => { it('app should load', () => { browser.get('/'); expect(element(by.css('my-app')).isPresent()).toBe(true); }); it('app should have a top navigation', () => { expect(element(by.css('my-nav-top')).isPresent()).toBe(true); }); it('app should have a side navigation', () => { expect(element(by.css('my-nav-side')).isPresent()).toBe(true); }); it('app should have a content', () => { expect(element(by.css('my-content')).isPresent()).toBe(true); }); it('app should load the overview for route "/"', () => { expect(element(by.css('my-overview')).isPresent()).toBe(true); }); }); 

The problem is that the browse component performs HTTP requests in the ngOnInit function using some data service. The protractor will simply be blocked forever, although HTTP requests have long been completed.

When I control the test, I see how the application loads, including all the data received from my API. Then nothing happens, and the protractor ultimately fails, saying that a timeout has been reached.

The exact error message is:

 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, my-app) 

When searching for help on google, I came across a few tips that the protractor will wait for angular to finish everything. Well, thatโ€™s exactly what I want. When I track the network tab in the developer chrome tools ( F12 ), nothing appears shortly after downloading the application. Thus, there are no more pending requests or anything else for the protractor. However, this is so, and I just donโ€™t know why.

So here is my question . Do I have to consider something special when working with data services that handle HTTP requests? Or: what can I do for debugging, why the protractor is still waiting until the timeout expires.

By the way, this is definitely a data service. If I comment on everything inside the OverviewComponent::ngOnInit , then the tests will go exactly as expected.

+5
source share
2 answers

(The short answer is that any lengthy tasks (timeouts, intervals, Promises or Observables) will block testing if it is not configured correctly. Http is cleared after itself, therefore, most likely, not a problem.)

Http is probably not your problem.

Angular 2 uses zones to detect a stable / unstable state, and Protractor uses a specific injection class - Check class - to determine the state of an application. The health check of all existing Angular2 applications on the page is exposed to the window object, namely, how Protractor stores tabs on Angular 2.

Angular uses zones to maintain change detection. In userland, we get some control over where our code comes from (to or from angular) via NgZone, useful for two things - testing and performance. Any task performed in the Angular zone (which happens unless we specify otherwise) will cause change detection, and any async task that we expect is checked as unstable.

This means that some things can affect the stability of your application:

  • a time-out channel behind the scenes (most likely in your particular case, as discussed here )
  • a component or service performing a continuous asynchronous task:
    • Listening to tracked routes.
    • Setting a repeating timeout or interval
    • ...

To fix this, you need to run your tasks outside of angular using NgZone:

 this.ngZone.runOutsideAngular(() => { this._sub = Observable.timer(2000) .subscribe(() => this.ngZone.run(() => {this.content = "Loaded!"})); }) 

See a working example in this plunk , and this talk from Julie Ralph for more details - she is the brain behind the Protractor.

+7
source

So Tiago's answer definitely pointed me in the right direction. I was afraid that this could be a problem with my observables. It was nice to know that it was just window.setInterval (), which I used to update my jwt. This was decided as follows:

 constructor(private ngZone: NgZone) { } this.ngZone.runOutsideAngular(() => { Observable.interval(4 * 60 * 1000) .subscribe(data => { this.refreshJwt(); }); }); 
+2
source

All Articles