How to debug timeouts of pending asynchronous Angular tasks? Could not find elements on Angular page

Edit: Please note that I found the root of my problem after help from @ ernst-zwingli, so if you have the same error, one of its fixes may help you. My problem is a known problem with Protractor itself, if you think it might be you, I have expanded my steps to determine the root of the problem after my initial question.


I am trying to use Protractor in an Angular2 application (Angular only) built using angular-cli.

My problem: Elements on the Angular application page were not found when browser.waitForAngularEnabled is in the default settings of true (as in the section “I assume that I am on the Angular page) and would like to use Protractor to make it magic”). They are found very well if I set browser.waitForAngularEnabled to false (as in "I'm not on an Angular page and would like to deal with it myself, take the place of the placeholder"). How can I track what causes this on my specific Angular pages?

I have a product with an unregistered Angular Auth0 page that provides access to the rest of the product, which is written in Angular (Angular 4.3.2, to be precise). I successfully logged in to the waitForAngularEnabled login page to false to facilitate login to the Angular system. I returned it to true the moment I expected my initial landing page (Angular) to load after clicking the submit button. The code is as follows:

  browser.waitForAngularEnabled(false); browser.driver.get('https://dashboard.net/projects'); browser.driver.sleep(10000); browser.driver.findElement(By.css("[type='email']")); browser.driver.findElement(By.css("[type='email']")).sendKeys(" email@example.com "); browser.driver.findElement(By.css(".auth0-label-submit")).click(); browser.driver.findElement(By.id("passwordInput")).sendKeys("password"); browser.driver.findElement(By.id("submitButton")).click(); browser.driver.sleep(5000); // needed if not waiting for Angular //browser.waitForAngularEnabled(true); // Back to Protractor land we go let elementToFind = element(by.className("header-text")); elementToFind.isDisplayed().then(function() {grabTheDarnLocalStorage()}); expect(elementToFind.isDisplayed()).toBeTruthy(); 

If I uncomment the line browser.waitForAngularEnabled(true); , to indicate that I returned to Angular code, I get an error trace as follows:

 Failed: Timed out waiting for asynchronous Angular tasks to finish after 30 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, .header-text) ScriptTimeoutError: asynchronous script timeout: result was not received in 30 seconds (Session info: chrome=61.0.3163.100) (Driver info: chromedriver=2.32.498550 (9dec58e66c31bcc53a9ce3c7226f0c1c5810906a),platform=Windows NT 10.0.14393 x86_64) at WebDriverError (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\error.js:27:5) at ScriptTimeoutError (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\error.js:203:5) at Object.checkLegacyResponse (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\error.js:505:15) at parseHttpResponse (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\http.js:509:13) at doSend.then.response (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\http.js:440:13) at process._tickCallback (internal/process/next_tick.js:109:7) From: Task: Protractor.waitForAngular() - Locator: By(css selector, .header-text) 

I referred to the FAQ: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular I have my developers claiming that they do not use $ timeout (they use ( Edit: NOT $ interval) Observable Interval, thank you very much) and they are not sure about $ http.

I found this solution on the canonical way of debugging problems with the Angular prototype: The canonical way of debugging problems with Protractor-to-Angular synchronization, but I'm not sure if the solution works without access to modifying the dev code to run the software tracker. (Edit: I never figured out how to make this work)

I also found this about the long timeout that you add before each test, but I believe that this is an extra overhead that makes your overall test run take longer than necessary without understanding the root cause of the problem: questions / 156574 / ... (Edit: yes, this is a bad idea and adds extra time to your tests, please do not do this)

The depressing bit is that this seems like a common occurrence, and there seems to be no orderly documentation on how to deal with this. Log in using the Angular page only to go to the Angular page. Angular pages that were not properly matched by the Transporter. All the examples that I find on the Internet are bits of code in which I have no reference to where they should be in my common test environment. I would kill for a complete example of someone testing an Angular-free login that goes to a completely Angular website with configuration configuration and real test examples. (Edit: this is still true, but I cannot do it myself, since my application is in a bad gray area, check out my RCA below for more details.)

I just need the ability to complete my login, and then successfully navigate to my Angular pages and be able to rely on Protractor to work with Angular pages. I need to know what to look for, it can be a lengthy asynchronous process (what exactly can I check in Chrome dev tools?). I would be interested to understand what is required to be used as default parameters for use in the Angular application of my application / website (is there something outside of <app-root _nghost-c0="" ng-version="4.3.2"> in HTML?). Before this work, I worked in Java, so all this asynchrony and Angular is new to me, so I know that I miss the well-known things that experienced Javascript knows about.


Analysis of my solution / root cause

Running the list suggested by @ ernst-zwingli:

for Angular (2) Check if the object window.getAllAngularRootElements returns at least one value.

He returned at least one value, so I switched.

useAllAngular2AppRoots: true,

I tried this and still ran into an asynchronous timeout.

And if interval or other long asynchronous tasks are used, problems can arise due to zones

Previously, @ ernst-zwingli also mentioned a testing method, except that it was an old way. Through research and testing, I found that the window object also has a getAllAngularTestabilities method. This led to an interesting rabbit hole. Example output from the Chrome console (put window.getAllAngularTestabilities() in the Chrome console window, look at the list) as follows:

 t: _callbacks:..., _didWork:true, _isZoneStable: true (this looks promising, but why isn't Protractor working then?!?) _ngZone: hasPendingMacrotasks: true, hasPendingMicrotasks: false, isStable: true 

I would think that isZoneStable would be enough, but apparently this is not the case for Protractor. Then, looking that Macrotasks is true, I needed to see what the hell is Macrotask: What does hasPendingMacrotasks and hasPendingMicrotasks do for? .

Macro load can be:

i.e. setTimeout, setInterval, setImmediate

Thus, @ ernst-zwingli's note about the time causing the problems in the zones was remembered and something was finally clicked. The first github issue about zone instability

Another issue github complains about is the need to use the .driver browser to get everything done with browser.waitForAngularEnabled. Apparently this is the expected behavior, it led me to release # 3349

Problem No. 3349 - Actual cause of my problem. My developers do not actively jump and leave the zones around the observed ones. Although these observables have only one subscriber. Since they live in the Angular zone at this time, they are a long “Macroscope” that Prototrans awaits endlessly.

I cannot rewrite the code with these wrappers, because currently I am not good enough at Angular to do this safely, and we are currently racing by November deadline. I think that for now I will have to deal with using browser.driver and hope that I can not fix it later. I hope my RCA was useful for you.

+5
source share
2 answers

Next, I list a set of potential causes and opportunities for their correction / resolution.

How AngularJS and Angular (2) work / What I can check in Dev browser mode

I can’t explain it, and Andrei Agibalov is on his blog here , so check it out (also for developers).

In principle, the objects required by Protractor, you can check in your Chrome Dev.

for AngularJS Check if the window.angular object is set window.angular , i.e. Search for window.angular.version and also try window.angular.getTestability your Root element

for Angular (2) Check if the object window.getAllAngularRootElements at least one value.

Root Element (AngularJS)

Potentially, your Angular application is somewhere wrapped in a body like something like <div ng-app="my-app"> . In this case, you must configure rootElement: body inside config.ts . Learn more about this answer .

Angular (2)

If you are using Angular (aka Angular2) then ngZone appears. In this case, your config.js should additionally contain the following:

 exports.config = { framework: 'jasmine', seleniumAddress: 'http://localhost:4444/wd/hub', specs: ['spec.js'], useAllAngular2AppRoots: true, // rootElement: 'root-element' }; 

check window.getAllAngularRootElements in your browser for an additional line in conf.js about this.

If you can, perhaps take advantage of several zones. Create a second zone, configure rootElement: 'root-element' to focus on only one zone, and then move some asynchronous tasks to another zone until you find which task will lead to a timeout. Keep these tasks (if possible) in a separate zone, so Protractor ignores these tasks.

And if $interval or other lengthy asynchronous tasks are used, problems can occur due to zones. Repeated or lengthy tasks must be started outside the zone, and then moved to the zone, since otherwise the Transporter could work with timeouts. Developers need a workaround to avoid these issues for Protractor. read all about it here

browser.driver. - side note

browser.driver.get() works like ignoreSynchronization = true , since you directly assign the browser driver and you bypass the Protractor synchronization logic. Read more about this here .

I hope I can give you some more materials and you can solve your problem. Please let me know the results.

+5
source

Could you install

  browser.ignoreSynchronization = true; 

and try

0
source

Source: https://habr.com/ru/post/1272367/


All Articles