-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Protractor fails when app is bootstrapped with ngUpgrade #4290
Comments
I had similar issue that was solved by wrapping this upgrade code like that:
And in config I AM NOT USING any of those:
|
Could you take a look at #4234 and see if you're having the same problem? Also, in ngUpgrade |
@Evilweed - thanks for the suggestion, unfortunately that doesn't seem to solve it for me. @heathkit - I found one long running $interval by searching the whole project, but even after removing it, the problem persists. I've also commented out all usages of $interval or $timeout in the whole app and it still fails with the same error. Do you know if there are any ways to debug and find out what it is that could be blocking if it is a problem with something async? |
Can you post your full error? It's supposed to show what tasks are pending in the error message, but it's possible it could be missing some. For example, the error won't yet show pending tasks from the Angular side. If you have long running async tasks in the Angular part of your app, you'll need to run those outside the Angular zone to keep from blocking Protractor. (See https://github.com/angular/protractor/blob/master/docs/timeouts.md) |
Thanks again for replying. The error detail is below. A few things to note:
|
Exactly the same - with a fresh new 'quickstart' angular4 config and a very basic protractor test. Everything is working well on non hybrid mode.
|
I am still seeing this issue. |
If someone could share a repo that shows the problem, I'll look into it further. |
What I've discovered so farAfter some digging I've discovered one of the causes of the timeout I'm seeing (or one of them, I suspect it's not the only one). It turns out that one of the dependencies I'm using is calling This ran fine when my app was running just AngularJS but causes a timeout issue when bootstrapped as a hybrid app (presumably because of the way it is run in zones). Example RepoI've created an example repo at https://github.com/mattwilson1024/angular-hybrid. It's a hybrid (NgUpgrade) app with the following parts:
The master branch contains the working app and a single protractor tests which passes no problem. The angular-moment branch adds a dependency on the TimeoutsTo confirm this is happening I tried adding various different kinds of timeout to the AngularJS controller, with the following results. This confirmed that $interval works, but $timeout, setInterval or setTimeout do not.
Next StepsHaving managed to track down what's happening I'm still not sure what the solution is. I understand that it may be necessary to run certain pieces of code "outside the Angular zone", though I am not sure how to do this from AngularJS segments where I don't have a TypeScript class in which to inject the zone etc. Even then, if the problem code is happening inside a third party library (as is the case in my example with angular-moment) - what would be the approach for working around this problem to get the tests working as they did before upgrading to a hybrid setup? |
Zones are set on the window, so you don't need to inject NgZone. You can run outside the Angular zone in AngularJS like this if (Zone && Zone.current.name === 'angular') {
let angularZone = Zone.current;
Zone.parent.run(() => {
$timeout(() => {
// Stuff here is run outside the Angular zone and will not be change detected
angularZone.run(() => {
// Inside the zone and will be change detected.
});
}, 500);
});
} You are correct that any use of setTimeout or setInterval, even in third party code, can block Protractor stability and cause timeouts. We're adding task tracking to Angular and AngularJS that should make it easier to debug these problems by showing you where the async task that Protractor timed out on came from. Realistically, it'll be a couple months before we can get that into Protractor. As far as angular-moment goes, your best option might be to submit a PR to them making it zone-aware as shown above. Otherwise, you can selectively turn off |
In our situation, tests can be written the generic (without Angular sync) way ( This basically nullifies our entire E2E automated test suite. Using Protractor 5.1.2, if I set
So obviously the angular.io documentation is out of date here: https://angular.io/guide/upgrade#e2e-tests Famous last words from self same document:
In light of that statement on angular.io: @heathkit Thanks for the tip about running inside and outside of zones, but to be honest we are looking for a solution that runs with our existing AngularJS code, as is. We have an extensive Protractor suite which relies on implicit AngularJS synchronization. Our goal is to migrate our AngularJS to Angular using ngUpgrade, but this issue with not being able to run our existing Protractor suite in Hybrid upgrade mode has thwarted our initiative. A sensible fix would be most welcome right about now. If we're doing something fundamentally wrong, we'd sure like to know what. |
Facing the same issue! :0 |
Seeing the same thing here: AngularJS 1.6 -> Angular 4.2.4 Anybody know any sort of workaround, however big it may be? Without reverting back to 1.6 that is. |
@quinw68 - @heathkit suggests a method of running the code outside of the Angular 'Zone' in his previous response in this thread. I think this means changes to the source code of your app to make it work, and may even depend on third party libraries adding support. Please correct me if I'm wrong. Another 'work-around' I'm aware of is to treat your existing app like it's not an AngularJS app anymore. This means that you will have to change your Protractor tests so that they don't inherently wait for Angular anymore, but explicitly check for the presence of elements on the page before querying them for their state. Depending on the size of your app, this could be a daunting task. Hope that helps. |
As far as I understand the issue, this is not ngUpgrade-specific, but rather Angular specific. I mean, even in a pure Angular (2+) app, having a long @heathkit, can you confirm that or did I miss something? Is ngUpgrade throwing Protractor off or making things worse in some way? |
@gkalpak You're right that this is more of an Angular-specific issue, but people are encountering it when they use ngUpgrade with a large AngularJS app. In AngularJS, Protractor would only wait for async tasks started with |
So, how would one solve this for a pure Angular app? What would one do if a third party Angular library was setting a long |
@vikerman I hear you are going to help get a new team member up and running on this one pretty soon, so assigning to you until they're aboard. |
We don't really have a good answer for the case where a third party app is setting a long timeout. At the moment, all you could do is turn off |
The project I work on had this problem before but they wrapped continuous polling function to run outside of the angular zone so that it didnt affect browser.waitForAngular(); |
First thank you to the Protractor team/contributors. Protractor has been the bedrock for my app to have very few production issues over dozens of releases over 3 years, over 200 services, directives, components, controllers with about 400 e2e Protractor tests. This is a good reminder how much I rely on Protractor but this issue has stopped my Angular upgrade in its tracks after having dedicated 2 weeks committed to just bootstrapping ngUpgrade and the ancillary needs. That's done but now the e2e tests can't be run and deployment is stopped without a visible path forward (yet). Thanks to the great info from @mattwilson1024, I've made sure But, I've found that
I'm surprised when I see significantly used angular libraries that don't ensure Protractor validity. On that, I agree with @heathkit that those libraries need to fix themselves. But, I'm hoping that Protractor can step in and mitigate it all with one fell swoop. Even a nice workaround would be golden. I'm disappointed that I'll have to back out my ngUpgrade for now until I dig out all those I am continuing to research for my app (specific culprits causing the timeout(s), how to move forward, etc) and will report back anything that might be of use to others. Where I've found $timeout:
ui-select
angular-resource |
Hi - we are working on a change to let you configure which tasks Protractor waits for, that can help you handle the above issue. This is a broad change involving Zone.js and Angular and don't have specific ETA(will be in the order of weeks). Will update on progress here. |
I have the same issue when I bootstrap my [email protected] app with NgUpgrade to [email protected]. I've found a workaournd in my case, by adding For example, one of my test did a simple select in a group of radio button, and expect that the correct option is selected:
When I try to debug this code, I found that timeout occurred at the last step. I suppose the underlying problem is a toolip from angular-ui-bootstrap, with the use $timeout: https://github.com/angular-ui/bootstrap/blob/master/src/tooltip/tooltip.js However, there are no async calls in this test. So what I do, is simply add ignoreSynchronization at the beginning and reset it in the end:
I don't know if this is the recommended way or if it will make the tests more flaky. But for tests that do not require any async calls but still suffer the timeout issue, it should fix them. |
Hi @vikerman - Any update on this? #4290 (comment) |
My solution: In this Repository: https://github.com/Innovic-io/protractor-angular-hybrid-app Wait for app here: |
@vikerman Is there any update on this? |
Has anyone good advice on how to find these long running timeouts so i can get them out of my application? |
From: Castaway(s?) on Island of AngularJS stranded by Protractor Issue #4290 Ahoy! Could we get an update on this issue? Last update on Oct 16 was an ETA in the "order of weeks". Or, please close this issue so we can move on. These are the rafts I'm currently considering:
|
Our team is in the process of upgrading our complex application and protractor tests are failing when bootstrapped with NgUpgrade. We had to revert our changes because now we cannot deal with all of the failing tests which are false positives. Where are we with this issue? I'm worried I'm going to have to move to a different testing framework so we can keep our plans of upgrading Angular. |
@tonybranfort: In the exact same boat as you... We rely heavily on |
We are having the same problem. Can someone from protractor update us on this please? We are halfway into upgrading our app from Angular V1 and hate to have this cause is to go back to V1 and ditch all the work done for the upgrade to Angular V5 so far. |
Throwing another vote in here, we are in the process of upgrading our app to Angular and we are currently using a piecemeal application of |
We just hit this issue as well, specifically when it comes to $interval service. Sometimes protractor is waiting for it and sometimes not - I did not find the pattern yet. Long time edit: apparently it depends when interval gets invoked (in the zone or not) |
Hi @vikerman - Any news on the changes to let you configure which tasks Protractor waits for? |
Same issue here. @vikerman is there any update or workaround? |
We're running into the same issues. Would be great if there would be some progress on this issue. |
Sadly, I do have the same issue. Is there any progress in sight concerning this? |
@heathkit Is this already done somewhere? we are having a hard time to identify those places in our codebase.
|
I think this will help you to run your tests "angular hybrid + protractor". It helped me. Check the link: ui-router/angular-hybrid#39 (comment) |
We've made a little headway into understanding what's going on with this problem. We seem to be having the same one. It appears that upgraded angularjs watcher/digest cycle works a little differently and can enable some infinite digest cycle loops. We found 1 with a 3rd party we were using, and are investigating the next one. But basically the watcher was causing a change to the thing being watched, causing the watcher to trigger, etc. To test if you're having the same problem, in chrome just open dev tools, go to performance, record a few seconds, and see if you have NgZone calls being made a lot. If you do, then somewhere in your code you have an infinite digest cycle. Drilling into the calls can help point you in the direction of what's causing it |
You can also modify local zone.js file a bit and add console logs where timeout/interval tasks gets patched to see what is calling them. Easy way to do that:
Edit: so fun to format code on mobile! |
@vikerman Do you have any update on this? It would be great if you could provide your opinion on how soon this will be fixed? Thanks. |
Where would you put that code to track the timeouts/intervals? |
@maurycyg patchTimer -> patchMethod function should do the trick |
This thread is disheartening to see. Is there ANY update on this? |
A potential workaround to not use app.config(function($provide) {
function isUnderProtractor() {
var nav = window.navigator;
var lowercasedUserAgent = nav.userAgent;
return !lowercasedUserAgent || lowercasedUserAgent.contains('protractor');
}
if (isUnderE2ETest()) {
$provide.decorator('$timeout', ['$interval', '$delegate', function($interval, $delegate) {
var newTimeout = function(fn, delay, invokeApply, pass) {
if (!delay)
return $interval(fn, delay, 1, invokeApply, pass);
else
return $delegate(fn, delay, invokeApply, pass);
};
newTimeout.cancel = $delegate.cancel;
return newTimeout;
}]);
}
} |
Starting from zone.js v0.8.9, you can choose which web API modules you want to patch as to reduce overhead introduced by the patching of these modules. Add zone-flags.ts file with content below Import it in polyfills.ts before zone.js
|
It appeared that above solution with disabling zone timers messes up with Obserables, (ex. asyncValidators). Solution that finally worked for me is monkey-patching setTimeout.
|
Perhaps the issue is not in the Protractor itself, but in the application code. With the transition from the Angular JS which uses a digest cycle to track changes, to Hybrid App with Angular2+ witch uses zone.js to detect changes, Protractor began to fall with timeouts. Protractor starts the next test action only when the application is stable. Stability in the case of a hybrid app means stability of Angular JS part of the application and Angular2+ part of the application. Both parts must be stable. Angular JS stability is defined through Now we understand the issue. Angular 2+ part of the application is always unstable and therefore Protractor waits indefinitely until it becomes stable and falls with timeouts. Angular JS stability in the case of a hybrid app should not have changed and does not affect the Protractor timeouts. From this we can conclude that it is necessary to fix the instability of the Angular2+ zone and then Protractor will begin to work as expected. First attempt to fix:
Although this approach has proven to be workable, as time has shown, this approach has its own disadvantages. The main one is that it is impossible to determine which zone will be (root or angular) for a specific part of the hybrid app. For normal operation Angular2+ requires that it is always in the Angular zone, and decorators can cause the Angular2+ components to be in the root zone. ngUpgrade implies that the Angular zone covers most of the application. To avoid this, there was a 2nd fix attempt with a deeper analysis of the reasons, abandoning decorators and returning to the original issue. Now we need to understand what code makes the zone unstable. For this, zone.js has special utilities, such as TaskTrackingZoneSpec (\node_modules\zone.js\dist\task-tracking.js), which allows to track which tasks are in the zone and where they were created (
Thus, find the places in the application where the microtasks and macrotasks are in the zone for a long time (microTasks.lenght! == 0 && macroTasks.lenght! == 0). Then you need to get this code out of the Angular zone. To do this, wrap code in After the Angular zone becomes stable, the Protractor will no longer fall with timeouts. Hope this helps. |
I came up with a temporary hack to solve this issue by overriding the
|
I am working on migrating an AngularJS (1.6) app to Angular (4) and now have a hybrid application, bootstrapped with NgUpgrade. This seems to have completely broken my Protractor tests.
Forgive me if this is just something I am doing wrong, but I can't find any answer as to why this won't work.
The error I get is:
Hybrid app changes
The application seems to run fine, and both AngularJS and Angular components are working as expected. The changes I made in the bootstrapping process are:
1 Removed ng-app from html tag:
<html lang="en" *ng-app="myapp">
2 Added an AppModules (@NgModule) etc.
3 Used NgUpgrade to bootstrap the app:
Protractor tests
Based on the error above, the problem seems to be related to whatever Protractor does when it is waiting for Angular. I have a beforeEach block which loads the login page, fills in the details and logs in. Weirdly it is still opening the page and entering text into the username field, but then it fails to go any further.
I have tried, with no success:
The text was updated successfully, but these errors were encountered: