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.