I have a medium sized Angular application and for some reasons some of my protractor tests are timing out when run against my live production environment.
I am fairly sure the timeouts happen because of protractor waiting on some asynchronous task. I know about zones and I tried to keep all long running async tasks out of the ngZone (as per the FAQ), but for some reason protractor is still timing out.
It's possible I missed something but I don't know how to debug the problem. Is there any way to find out which part of the code protractor is waiting on?
The NgZone only exposes functions to determine if there are microtasks or macrotasks running, but doesn't tell me which one.
EDIT: A typical example of such a timeout error as shown by protractor:
Failed: Timed out waiting for asynchronous Angular tasks to finish after 11 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, [data-e2e='scroll-to-offer'])
The element exists on the page (I have verified this manually), but protractor still times out.
There is no particular way to track protractor's async tasks. What you might do is investigate which async tasks might be blocking your flow. If you're testing there are 2 main cues for debugging : async tasks in your app code and async tasks in your tests.
In your tests, if you're using something like Jasmine, have you tried something like changing
jasmine.DEFAULT_TIMEOUT_INTERVAL;
?Anyway, I don't see a better option to debug this other than start logging all your async tasks on start and on callback.
I had a similar problem, the Testability was unstable and all I knew is that I have some
pendingMacroTasks
. It's indeed a bit tricky to localize these tasks (you won't go through the whole code base and look forsetTimeout
).However I managed to do this eventually.
Relatively simple solution
First thing you can do is open your Dev Tools in Chrome, press
Ctrl+O
, type zone.js and pressEnter
.This will open zone.js source file (not Typescript, yet something).
Inside zone.js look for
Zone.prototype.runTask
and put a breakpoint inside this method.Enable the breakpoint after your application is loaded, otherwise it will get hit too many times.
If your Testability is not stabilizing, it probably means that you have some repetitive macro task that reschedules itself. At least that was my case.
If this is the case, the breakpoint will get hit every X time after the application is loaded.
Once the breakpoint is hit, go to
task.callback.[[FunctionLocation]]
this will take you to (most probably) somesetTimeout
orsetInterval
.To fix it run it outside of Angular zone.
A bit trickier solution
This involves tweaking the Zone.js code, but gives you a more persistent debug information.
node_modules/zone.js/dist/zone.js
.function Zone(parent, zoneSpec)
this._tasks = {}
let counter = 0
Look for
Zone.prototype.scheduleTask
and add the following right before the call tothis._updateTaskCount(task,1)
:Look for
Zone.prototype.scheduleTask
and add the following right before the call tothis._updateTaskCount(task,-1)
:Assuming you did the above tweaks you can always access the pending tasks like this:
To get all the pending macro tasks that affect the testability state:
After that similarly to the previous solution check out the
.callback.[[FunctionLocation]]
and fix by running outside of Angular zone.JeB did a great job suggesting his way (some solution is better than nothing). In fact, there is way to get list of pending tasks without patching
zone.js
file. I get this idea while looking at angular sources: https://github.com/angular/angular/blob/master/packages/core/src/zone/ng_zone.ts#L134Here is how to:
node_modules/zone.js/dist/task-tracking.js
file afterzone.js
NgZone
instance and use it likeExample is placed here: https://stackblitz.com/edit/zonejs-pending-tasks.
How it works:
berkov,
I really need your help to get task list using the functionality provided by you.
I added
import 'zone.js/dist/task-tracking'
; topolyfills.ts
and below code to constructor method of AppModule.ts. but it is throwing errorCannot find name 'moduleInstance'.
If it is possible, can you please provide any working example. That will be your great help.
Thank you,
Jignesh Raval
CC: @hodossy-szabolcs