Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protractor fails when app is bootstrapped with ngUpgrade #4290

Open
matt-senseye opened this Issue May 16, 2017 · 45 comments

Comments

Projects
None yet
@matt-senseye
Copy link

matt-senseye commented May 16, 2017

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:

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, .toggle-summary-button)

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:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
  const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
  upgrade.bootstrap(document.body, ['myapp'], {strictDi: true});
});

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:

  • adding "rootElement: 'body'" to my protractor config file
  • adding "ng12Hybrid: true" to my protractor config file - I get a message saying that it should no longer be needed as it auto detects.
  • increasing the allScriptsTimeout setting from 11000 to 60000 and it still times out.
  • turning off the waitForAngularEnabled setting. This solves the problem with the login fields, but then none of my http mocks work and the tests fail.
@Evilweed

This comment has been minimized.

Copy link

Evilweed commented May 16, 2017

I had similar issue that was solved by wrapping this upgrade code like that:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';

angular.element(document).ready(() => {
  platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
    const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
    upgrade.bootstrap(document.body, ['myapp'], {strictDi: true});
  });
});

And in config I AM NOT USING any of those:

//ng12Hybrid: true,
//useAllAngular2AppRoots: true,
//rootElement: 'body',
@heathkit

This comment has been minimized.

Copy link
Member

heathkit commented May 16, 2017

Could you take a look at #4234 and see if you're having the same problem? Also, in ngUpgrade $interval will now block Protractor where it didn't before (angular/angular#16349), but I'm working on that.

@matt-senseye

This comment has been minimized.

Copy link
Author

matt-senseye commented May 17, 2017

@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?

@heathkit

This comment has been minimized.

Copy link
Member

heathkit commented May 17, 2017

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)

@matt-senseye

This comment has been minimized.

Copy link
Author

matt-senseye commented May 17, 2017

Thanks again for replying. The error detail is below. A few things to note:

  • My test file has a beforeAll block which is supposed to fill out the username and password fields to login. It fills the username field successfully but then times out in waitForAngular and doesn't fill in password field. This is what the first half of the error seems to be about. The second half is the actual failing test (which makes sense, because it failed to login so the element is not present).

  • The error suggests the problem may stem from an HTTP call, so maybe not $interval or $timeout.

  • I don't have much on the Angular side at the moment, it is nearly all still AngularJS. It doesn't get as far as showing the new Angular component because it doesn't manage to login (so I doubt the http call is to do with the Angular 4 component)

  Message:
    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, *[name="password"])
  Stack:
    ScriptTimeoutError: asynchronous script timeout: result was not received in 11 seconds
      (Session info: chrome=58.0.3029.110)
      (Driver info: chromedriver=2.29.461585,platform=Mac OS X 10.12.4 x86_64) (WARNING: The server did not provide any stacktrace information)
    Command duration or timeout: 11.07 seconds
    Build info: version: '3.4.0', revision: 'unknown', time: 'unknown'
    System info: host: 'Matt.lan', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.12.4', java.version: '1.8.0_111'
    Driver info: org.openqa.selenium.chrome.ChromeDriver
    Capabilities [{applicationCacheEnabled=false, rotatable=false, mobileEmulationEnabled=false, networkConnectionEnabled=false, chrome={chromedriverVersion=2.29.461585, takesHeapSnapshot=true, pageLoadStrategy=normal, databaseEnabled=false, handlesAlerts=true, hasTouchScreen=false, version=58.0.3029.110, platform=MAC, browserConnectionEnabled=false, nativeEvents=true, acceptSslCerts=true, locationContextEnabled=true, webStorageEnabled=true, browserName=chrome, takesScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true, unexpectedAlertBehaviour=}]
    Session ID: 40deafceb49b72b1c0188ad0895c1179
        at Object.checkLegacyResponse (/Users/matt/web-app/node_modules/selenium-webdriver/lib/error.js:505:15)
        at parseHttpResponse (/Users/matt/web-app/node_modules/selenium-webdriver/lib/http.js:509:13)
        at doSend.then.response (/Users/matt/web-app/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, *[name="password"])
        at thenableWebDriverProxy.schedule (/Users/matt/web-app/node_modules/selenium-webdriver/lib/webdriver.js:816:17)
        at ProtractorBrowser.executeAsyncScript_ (/Users/matt/web-app/node_modules/protractor/lib/browser.ts:608:24)
        at angularAppRoot.then (/Users/matt/web-app/node_modules/protractor/lib/browser.ts:642:23)
        at ManagedPromise.invokeCallback_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:1366:14)
        at TaskQueue.execute_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2970:14)
        at TaskQueue.executeNext_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2953:27)
        at asyncRun (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2813:27)
        at /Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:676:7
        at process._tickCallback (internal/process/next_tick.js:109:7)Error
        at ElementArrayFinder.applyAction_ (/Users/matt/web-app/node_modules/protractor/lib/element.ts:482:23)
        at ElementArrayFinder.(anonymous function).args [as sendKeys] (/Users/matt/web-app/node_modules/protractor/lib/element.ts:96:21)
        at ElementFinder.(anonymous function).args [as sendKeys] (/Users/matt/web-app/node_modules/protractor/lib/element.ts:873:14)
        at /Users/matt/web-app/e2e-tests/modules/authentication.js:83:38
        at ManagedPromise.invokeCallback_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:1366:14)
        at TaskQueue.execute_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2970:14)
        at TaskQueue.executeNext_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2953:27)
        at asyncRun (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2813:27)
        at /Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:676:7
        at process._tickCallback (internal/process/next_tick.js:109:7)
    From: Task: Run beforeAll in control flow
        at Object.<anonymous> (/Users/matt/web-app/node_modules/jasminewd2/index.js:94:19)
    From asynchronous test: 
    Error
        at Suite.<anonymous> (/Users/matt/web-app/e2e-tests/specs/home/asset.spec.js:28:3)
        at Object.<anonymous> (/Users/matt/web-app/e2e-tests/specs/home/asset.spec.js:7:1)
        at Module._compile (module.js:571:32)
        at Object.Module._extensions..js (module.js:580:10)
        at Module.load (module.js:488:32)
        at tryModuleLoad (module.js:447:12)
  Message:
    Failed: No element found using locator: By(css selector, .toggle-asset-summary-button)
  Stack:
    NoSuchElementError: No element found using locator: By(css selector, .toggle-asset-summary-button)
        at elementArrayFinder.getWebElements.then (/Users/matt/web-app/node_modules/protractor/lib/element.ts:851:17)
        at ManagedPromise.invokeCallback_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:1366:14)
        at TaskQueue.execute_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2970:14)
        at TaskQueue.executeNext_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2953:27)
        at asyncRun (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2813:27)
        at /Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:676:7
        at process._tickCallback (internal/process/next_tick.js:109:7)Error
        at ElementArrayFinder.applyAction_ (/Users/matt/web-app/node_modules/protractor/lib/element.ts:482:23)
        at ElementArrayFinder.(anonymous function).args [as click] (/Users/matt/web-app/node_modules/protractor/lib/element.ts:96:21)
        at ElementFinder.(anonymous function).args [as click] (/Users/matt/web-app/node_modules/protractor/lib/element.ts:873:14)
        at Page.showAssetSummaryComponent (/Users/matt/web-app/e2e-tests/specs/home/page-object.js:289:31)
        at Object.<anonymous> (/Users/matt/web-app/e2e-tests/specs/home/asset.spec.js:63:12)
        at /Users/matt/web-app/node_modules/jasminewd2/index.js:112:25
        at new ManagedPromise (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:1067:7)
        at ControlFlow.promise (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2396:12)
        at schedulerExecute (/Users/matt/web-app/node_modules/jasminewd2/index.js:95:18)
        at TaskQueue.execute_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2970:14)
    From: Task: Run fit("should open asset summary component") in control flow
        at Object.<anonymous> (/Users/matt/web-app/node_modules/jasminewd2/index.js:94:19)
        at /Users/matt/web-app/node_modules/jasminewd2/index.js:64:48
        at ControlFlow.emit (/Users/matt/web-app/node_modules/selenium-webdriver/lib/events.js:62:21)
        at ControlFlow.shutdown_ (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2565:10)
        at shutdownTask_.MicroTask (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2490:53)
        at MicroTask.asyncRun (/Users/matt/web-app/node_modules/selenium-webdriver/lib/promise.js:2619:9)
    From asynchronous test: 
    Error
        at Suite.<anonymous> (/Users/matt/web-app/e2e-tests/specs/home/asset.spec.js:62:5)
        at Suite.<anonymous> (/Users/matt/web-app/e2e-tests/specs/home/asset.spec.js:60:3)
        at Object.<anonymous> (/Users/matt/web-app/e2e-tests/specs/home/asset.spec.js:7:1)
@sebhorin

This comment has been minimized.

Copy link

sebhorin commented Jun 4, 2017

Exactly the same - with a fresh new 'quickstart' angular4 config and a very basic protractor test. Everything is working well on non hybrid mode.


Failed: Timed out waiting for asynchronous Angular tasks to finish after 50 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, #loginModal h4)
@angNewbie

This comment has been minimized.

Copy link

angNewbie commented Jun 13, 2017

I am still seeing this issue.
Using: @angular/upgrade 4.2.2
which contains the fix from @heathkit (angular/angular#16836) to get the Testability api stable, but it still doesn't seem to work

@heathkit

This comment has been minimized.

Copy link
Member

heathkit commented Jun 13, 2017

If someone could share a repo that shows the problem, I'll look into it further.

@mattwilson1024

This comment has been minimized.

Copy link

mattwilson1024 commented Jun 15, 2017

What I've discovered so far

After 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 window.setTimeout() which is preventing Protractor from syncing (in my case, it's
angular-moment.

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 Repo

I've created an example repo at https://github.com/mattwilson1024/angular-hybrid. It's a hybrid (NgUpgrade) app with the following parts:

  • The outermost page (the CharactersPage) is provided by AngularJS (1.6).
  • The page contains CharacterListComponent, which is a downgraded Angular (4) component.
  • The CharacterListComponent uses another Angular 4 component, CharacterDetail component.

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 angular-moment library and uses its am-time-ago directive to add a label to the page showing how many years ago it is since the first episode. The app itself runs fine, but the protractor test now fails to sync.

Timeouts

To 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.

function sayHello() { console.log('Hello, world'); }

$interval(sayHello, 30000); // Succeeds (with Angular 4.2.0 and later - see https://github.com/angular/angular/pull/16836)
$timeout(sayHello, 30000); // Fails - Timed out waiting for asynchronous Angular tasks to finish after 11 seconds
setInterval(sayHello, 30000); // Fails - Timed out waiting for asynchronous Angular tasks to finish after 11 seconds
setTimeout(sayHello, 300000); // Fails - Timed out waiting for asynchronous Angular tasks to finish after 11 seconds

Next Steps

Having 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?

@heathkit

This comment has been minimized.

Copy link
Member

heathkit commented Jun 15, 2017

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 waitForAngular and use browser.wait and ExpectedConditions instead. We're working on a more flexible waitForAngular API that will let you control which tasks you wait for, but that's still a ways off.

@Red-3

This comment has been minimized.

Copy link

Red-3 commented Jun 21, 2017

In our situation, tests can be written the generic (without Angular sync) way (browser.ignoreSynchronization = true using ECs, etc.), but fail when setting browser.ignoreSynchronization = false; with "Error while waiting for Protractor to sync with the page: "Cannot read property '$$testability' of undefined"

This basically nullifies our entire E2E automated test suite.

Using Protractor 5.1.2, if I set ng12Hybrid: true I get the message:

You have set ng12Hybrid. As of Protractor 4.1.0, Protractor can automatically infer if you are using an ngUpgrade app (as long as ng1 is loaded before you call platformBrowserDynamic()), and this flag is no longer needed for most users

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:

E2E tests aren't really that concerned with the internal structure of the application components. That also means that, although you modify the project quite a bit during the upgrade, the E2E test suite should keep passing with just minor modifications. You didn't change how the application behaves from the user's point of view.

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.

@justtal

This comment has been minimized.

Copy link

justtal commented Jun 29, 2017

Facing the same issue! :0

@quinw68

This comment has been minimized.

Copy link

quinw68 commented Jun 29, 2017

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.

@Red-3

This comment has been minimized.

Copy link

Red-3 commented Jun 29, 2017

@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.

@gkalpak

This comment has been minimized.

Copy link
Member

gkalpak commented Jul 5, 2017

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 setTimeout (either directly or via a 3rd-party library) will cause protractor to time out.

@heathkit, can you confirm that or did I miss something? Is ngUpgrade throwing Protractor off or making things worse in some way?

@heathkit

This comment has been minimized.

Copy link
Member

heathkit commented Jul 5, 2017

@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 $browser.defer() - basically just $timeout and $http calls in the application code. Once someone starts using ngUpgrade, their existing Protractor tests will start timing out due to long setTimeout calls (potentially from third-party libraries) where they didn't before. So mostly, the issue is that ngUpgrade is working as intended, and now people's AngularJS app and Protractor tests are suddenly subject to Angular (2+) semantics.

@gkalpak

This comment has been minimized.

Copy link
Member

gkalpak commented Jul 5, 2017

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 setTimeout, causing Protractor to time out?

@naomiblack

This comment has been minimized.

Copy link
Member

naomiblack commented Jul 20, 2017

@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.

@heathkit

This comment has been minimized.

Copy link
Member

heathkit commented Jul 21, 2017

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 waitForAngular and rely on ExpectedConditions, but that's not ideal. I am working on adding a feature to Protractor that will give people more control over which macrotasks their tests wait for, but that's still a ways off.

@evansonjohn

This comment has been minimized.

Copy link

evansonjohn commented Sep 19, 2017

@heathkit @vikerman Any update on this one please?

@gd46

This comment has been minimized.

Copy link

gd46 commented Sep 21, 2017

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();

@tonybranfort

This comment has been minimized.

Copy link

tonybranfort commented Oct 16, 2017

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 $timeout, setTimeout, setInterval are not used in our app.

But, I've found that angular-ui-bootstrap (v.2.5.6) and ui-select (v0.19.8) do use $timeout. I use both libraries extensively. It seems a lot of others rely on them as well - angular-ui-bootstrap - 400k npm downloads/mo, ui-select 100k+/mo.

angular-ui-bootstrap created an issue in 2015 to replace $timeout with $interval specifically due to this issue but unfortunately has decided "this bug should be fixed in protractor and not here. Closing this." Also, angular-ui-bootstrap is no longer providing updates in liu of their Angular version @ng-bootstrap/ng-bootstrap which is in beta.

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 $timeout dependencies and, possibly, rather than just including ngGrade and starting to pick off items for upgrade when feasible, I likely have a dependency to upgrade or migrate from those 3rd party items along with adding ngUpgrade. Ugh.

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:
angular-ui-bootstrap v2.5.6

  • UibAlertController
  • UibCarouselController
  • UibDatepickerPopupController
  • UibTypeaheadController
  • UibTooltip

ui-select

  • uiSelect
  • uiSelectMultiple
  • uiSelectSingle
  • uiSelectSort
  • uisOpenClose

angular-resource $resource injects and uses $timeout
angular-filter ($window.setTimeout)

@vikerman

This comment has been minimized.

Copy link
Contributor

vikerman commented Oct 17, 2017

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.

@zhenyi2697

This comment has been minimized.

Copy link

zhenyi2697 commented Jan 5, 2018

I have the same issue when I bootstrap my Angular@1.6.1 app with NgUpgrade to Angular@5.1.2.
Thanks for the comments above, especially @mattwilson1024 and @tonybranfort, which helps me understand better the issue.

I've found a workaournd in my case, by adding browser.ignoreSynchronization = true/false; around the code that times out.

For example, one of my test did a simple select in a group of radio button, and expect that the correct option is selected:

it('should be able to pick option', function () {
        expect(myPage.optionSelected()).toBe(false);
        myPage.pickOption('Option 1');
        expect(myPage.anyOptionSelected()).toBe(true);
        expect(myPage.getSelectedOption()).toBe('Option 1');
});

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:

it('should be able to pick a font', function () {
        browser.ignoreSynchronization = true;  // tell protractor do not waitForAngular
        expect(myPage.optionSelected()).toBe(false);
        myPage.PickOption('Option 1');
        expect(myPage.anyOptionSelected()).toBe(true);
        expect(myPage.getSelectedOption()).toBe('Option 1');
        browser.ignoreSynchronization = false;  // reset the flag
});

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.

@tonybranfort

This comment has been minimized.

Copy link

tonybranfort commented Jan 10, 2018

Hi @vikerman - Any update on this? #4290 (comment)

@sn0lan-vpm

This comment has been minimized.

Copy link

sn0lan-vpm commented Jan 31, 2018

@vikerman Is there any update on this?

@TimMeissner

This comment has been minimized.

Copy link

TimMeissner commented Feb 6, 2018

Has anyone good advice on how to find these long running timeouts so i can get them out of my application?

@tonybranfort

This comment has been minimized.

Copy link

tonybranfort commented Feb 15, 2018

From: Castaway(s?) on Island of AngularJS stranded by Protractor Issue #4290
To: @vikerman @juliemr

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:

  • Replace all angular-ui-bootstrap / ui-select. This is significant for me. It needs to be done anyway but my concern is that something else will pop up and I'll still be stuck on AngularJS after that work. Lesson learned : wrap 3rd party components with my own components.
  • waitForAngularEnabled(false) for all tests as suggested by @vladotesanovic. I'm skeptical of this for an entire app but I haven't tested it. I use waitForAngularEnabled in only one situation now and only for a very specific case.
  • Upgrade the entire app to Angular rather than AngularJS/Angular side by side incremental migration: Nope, just not an option with my resources.
  • Migrate to Vue or React instead of Angular. High on the list especially considering both can coexist with AngularJs.
  • Move to Puppeteer and ditch all Protractor tests - This is likely strategic direction.
  • OR a fix from #4290 and I can uncomment those few lines needed to start using ngUpgrade :)
@ajklotz

This comment has been minimized.

Copy link

ajklotz commented Feb 20, 2018

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.

@theandrewlane

This comment has been minimized.

Copy link
Contributor

theandrewlane commented Feb 21, 2018

@tonybranfort: In the exact same boat as you... We rely heavily on ui-select and angular-ui-bootstrap- this is a major blocker for our upgrade. Looks like you've taken the lead on this issue however, please keep us updated! 😁

@apantea01

This comment has been minimized.

Copy link

apantea01 commented Mar 1, 2018

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.

@underscorebrody

This comment has been minimized.

Copy link

underscorebrody commented Mar 8, 2018

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 waitForAngularEnabled(false) to get these to pass without putting the entire suite at greater risk. It's extraordinarily unideal, though, so a better solution would be greatly appreciated.

@FDIM

This comment has been minimized.

Copy link

FDIM commented Apr 17, 2018

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)

@mobislan

This comment has been minimized.

Copy link

mobislan commented Aug 22, 2018

Hi @vikerman - Any news on the changes to let you configure which tasks Protractor waits for?

@mjunker

This comment has been minimized.

Copy link

mjunker commented Aug 22, 2018

Same issue here.

@vikerman is there any update or workaround?

@tobiasfiechter

This comment has been minimized.

Copy link

tobiasfiechter commented Aug 22, 2018

We're running into the same issues. Would be great if there would be some progress on this issue.

@flockisoft

This comment has been minimized.

Copy link

flockisoft commented Sep 3, 2018

Sadly, I do have the same issue. Is there any progress in sight concerning this?

@fischermatte

This comment has been minimized.

Copy link

fischermatte commented Sep 3, 2018

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.

@heathkit Is this already done somewhere? we are having a hard time to identify those places in our codebase.

also it would be nice to have some documentation what protractor is excatly waiting for. This one seems to be outdated: https://www.protractortest.org/#/system-setup. it only mentions to replace $timeout by $interval. Nothing about setTimeout or setInterval.
some docs are here: http://www.protractortest.org/#/timeouts. but no hints how to detect them...

@mustafa90

This comment has been minimized.

Copy link

mustafa90 commented Sep 7, 2018

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)

@silkcom

This comment has been minimized.

Copy link

silkcom commented Nov 30, 2018

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

@FDIM

This comment has been minimized.

Copy link

FDIM commented Nov 30, 2018

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:

try {
  throw new Error("track");
} catch(err) {
  console.debug(err);
}

Edit: so fun to format code on mobile!

@nmehta6

This comment has been minimized.

Copy link

nmehta6 commented Dec 20, 2018

@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.

@maurycyg

This comment has been minimized.

Copy link

maurycyg commented Jan 3, 2019

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:

try {
  throw new Error("track");
} catch(err) {
  console.debug(err);
}

Edit: so fun to format code on mobile!

Where would you put that code to track the timeouts/intervals?

@FDIM

This comment has been minimized.

Copy link

FDIM commented Jan 3, 2019

@maurycyg patchTimer -> patchMethod function should do the trick

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.