How to track which async tasks protractor is waiting on?

后端 未结 4 1787
孤城傲影
孤城傲影 2021-01-31 04:39

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 sur

相关标签:
4条回答
  • 2021-01-31 04:49

    berkov,

    I really need your help to get task list using the functionality provided by you.

    I added import 'zone.js/dist/task-tracking'; to polyfills.ts and below code to constructor method of AppModule.ts. but it is throwing error Cannot find name 'moduleInstance'.

    // app.module.ts
    
    const ngZone = moduleInstance.injector.get(NgZone);
    setInterval(() => {
        var taskTrackingZone = (<any>ngZone)._inner.getZoneWith("TaskTrackingZone");
        if (!taskTrackingZone) {
            throw new Error("'TaskTrackingZone' zone not found! Have you loaded 'node_modules/zone.js/dist/task-tracking.js'?");
        }
        var tasks: any[] = taskTrackingZone._properties.TaskTrackingZone.getTasksFor("macroTask");
        tasks = _.clone(tasks);
        if (_.size(tasks) > 0) {
            console.log("ZONE pending tasks=", tasks);
        }
    }, 1000);
    

    If it is possible, can you please provide any working example. That will be your great help.

    Thank you,

    Jignesh Raval

    CC: @hodossy-szabolcs

    0 讨论(0)
  • 2021-01-31 04:51

    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#L134

    Here is how to:

    1. Import node_modules/zone.js/dist/task-tracking.js file after zone.js
    2. Then in your code get NgZone instance and use it like
    import * as _ from "lodash";
    ...
    const ngZone = moduleInstance.injector.get(NgZone);
    setInterval(() => {
        var taskTrackingZone = (<any>ngZone)._inner.getZoneWith("TaskTrackingZone");
        if (!taskTrackingZone) {
            throw new Error("'TaskTrackingZone' zone not found! Have you loaded 'node_modules/zone.js/dist/task-tracking.js'?");
        }
        var tasks: any[] = taskTrackingZone._properties.TaskTrackingZone.getTasksFor("macroTask");
        tasks = _.clone(tasks);
        if (_.size(tasks) > 0) {
            console.log("ZONE pending tasks=", tasks);
        }
    }, 1000);
    
    

    Example is placed here: https://stackblitz.com/edit/zonejs-pending-tasks.

    How it works:

    0 讨论(0)
  • 2021-01-31 04:57

    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 for setTimeout).
    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 press Enter.
    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) some setTimeout or setInterval.
    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.

    1. Go to node_modules/zone.js/dist/zone.js.
    2. Look for Zone's constructor function: function Zone(parent, zoneSpec)
    3. Add the following inside: this._tasks = {}
    4. Add counter variable in global scope: let counter = 0
    5. Look for Zone.prototype.scheduleTask and add the following right before the call to this._updateTaskCount(task,1):

      task.id = counter++;
      this._tasks[task.id] = task;
      
    6. Look for Zone.prototype.scheduleTask and add the following right before the call to this._updateTaskCount(task,-1):

      delete this._tasks[task.id]
      
    7. Recompile the application and run it

    Assuming you did the above tweaks you can always access the pending tasks like this:

    tasks = Object.values(window.getAllAngularTestabilities()[0]._ngZone._inner._tasks)
    

    To get all the pending macro tasks that affect the testability state:

    tasks.filter(t => t.type === 'macroTask' && t._state === 'scheduled')
    

    After that similarly to the previous solution check out the .callback.[[FunctionLocation]] and fix by running outside of Angular zone.

    0 讨论(0)
  • 2021-01-31 05:02

    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.

    0 讨论(0)
提交回复
热议问题