Failed: script timeout: result was not received in 11 seconds From: Task: Protractor.waitForAngular() - Locator: By(css selector, #my-btn)
Asked Answered
G

2

6

I'm trying to write some e2e test for my Angular application using Protractor.

I have a simple html button having id=my-btn which I want to click, using:

$('#my-btn').click();

Unfortunately I'm getting the following errors:

Failed: script timeout: result was not received in 11 seconds

From: Task: Protractor.waitForAngular() - Locator: By(css selector, #my-btn)

(Session info: chrome=73.0.3683.75)
(Driver info: chromedriver=2.46.628411 (3324f4c8be9ff2f70a05a30ebc72ffb013e1a71e),platform=Mac OS X 10.14.3 x86_64)

If before the click I set:

browser.waitForAngularEnabled(false);

then I don't get any errors. The problem is that doing that means:

 * If set to false, Protractor will not wait for Angular $http and $timeout
 * tasks to complete before interacting with the browser. This can cause
 * flaky tests, but should be used if, for instance, your app continuously
 * polls an API with $timeout.

So I would like what is causing the waitForAngular operation to timeout.

Is there a way to check what http or timeout are still hanging?

I want to debug my application to understand what's going on.

Gmur answered 19/3, 2019 at 12:1 Comment(1)
add your test script and html to get a better view on the issue.Wilmot
E
15

I had some trouble with this. There are a few things you can try.

  1. Manually check to see if you have any timed operations. My app, for example, had a timer that does a health check every 5 minutes. But this timer operation being on the stack constantly meant that Angular never stabilized.

If you do find such an operation, you can use ngZone.runOutsideAngular() to keep it from destabilizing your tests.

constructor(
    private ngZone: NgZone
  ) {}

ngOnInit() {
  this.ngZone.runOutsideAngular(() => {
    this.appStatusInterval = interval(this.appStatusUpdateIntervalTime)
       // rest of your code here
    });
  });
}
  1. Open the dev tools and run getAllAngularTestabilities(). Try to get what information you can from there. You can try to get extra data from the source code. This bit in particular might be useful to you:
isStable(): boolean {
    return this._isZoneStable && this._pendingCount === 0 && !this._ngZone.hasPendingMacrotasks;
}

You can at least get more of an idea on what's destabilizing Angular by checking each of these three conditions in turn.

Ettore answered 19/3, 2019 at 17:18 Comment(2)
thanks a lot, that is exactly what I was looking for.Gmur
@FrancescoBorzi It's a tricky problem without an easy out-of-the-box solution. Good luck :) Let me know if you have any other questions.Ettore
P
0

As the error message suggests, a simple solution is to use waitForAngularEnabled(false) in conjunction with hard-coded sleep for however long you want to allow your page to load without failing the test (say, 3 seconds). The test will only be flaky if the page isn't actually finished loading into a static state after 3 seconds:

await browser.sleep(3000)

and then run your expectations while waitForAngularEnabled is false

browser.waitForAngularEnabled(false)
// expectations here
browser.waitForAngularEnabled(true)

This isn't the preferred solution when you can use graceful callbacks to confirm that Angular is done and your element is loaded. If the page loads faster than 3 seconds, your test is wasting time... It is, however, simple, readable and reliable. It allows you to enforce a limit on the page loading time while also being able to check the element in an environment free from the unpredictability of Protractor's behavior in regard to angular callbacks on pages that aren't playing nice. Reliability is more important than performance when it comes to front-end automation.

Prague answered 22/7, 2021 at 16:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.