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

Some screens require waitForAngularEnabled(false) to work properly, even though whole app is angular #5315

Open
jkelleyCE opened this issue Sep 12, 2019 · 5 comments

Comments

@jkelleyCE
Copy link

jkelleyCE commented Sep 12, 2019

For some reason, certain pages (screens) in my angular app aren't respected as angular, and the only way to get protractor to interact with elements on these screens is to set waitForAngularEnabled(false). This then creates flaky tests and requires all kinds of ugly browser.waits. Anyone else ever experienced this or know how to resolve it?

Bug report

  • Node Version: 12.3.1
  • Protractor Version: 5.4.2
  • Angular Version: 7.2.3
  • Browser(s): Chrome
  • Operating System and Version Windows 10

conf file

// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');
global.util = require('./src/util/phoenix-protractor-util.js');

exports.config = {
  SELENIUM_PROMISE_MANAGER: false,

  allScriptsTimeout: 30000,

  specs: [
    './src/**/waivers-spec.js'
  ],

  capabilities: {
    browserName: 'chrome',
		acceptInsecureCerts: true,
		chromeOptions: {
			args: ['disable-infobars', 'lang=en-US', '--allow-insecure-localhost'],
			prefs: {
				download: {
					prompt_for_download: false,
					directory_upgrade: true,
					default_directory: '/tmp',
				},
				'profile.password_manager_enabled': false,
				credentials_enable_service: false,
				password_manager_enabled: false,
			},
		},
  },

  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  },

  onPrepare() {
    require('ts-node').register({
      project: require('path').join(__dirname, './tsconfig.e2e.json')
    });
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
    
    // TODO: Workaround for https://github.com/angular/protractor/issues/4294
    //  This can be removed once the issue is fixed
    let currentCommand = Promise.resolve();
    // Serialise all webdriver commands to prevent EPIPE errors
    const webdriverSchedule = browser.schedule;
    browser.schedule = (command, description) => {
      currentCommand = currentCommand.then(
        () => webdriverSchedule.call(browser, command, description)
      );
      return currentCommand;
    };
    // end workaround
    
    // TODO: Workaround for https://github.com/angular/protractor/issues/4507
    //  This can be removed once the issue is fixed
    element.map = mapFn => {
      const finders = this.asElementFinders_();
      return finders.then(arr => {
        let promise = finders.then(() => []);
        arr.forEach((elementFinder, index) => {
          promise = promise.then(result => {
            const mapResult = seleniumWebDriver1.promise
              .fullyResolved(mapFn(elementFinder, index));
            return mapResult.then(mr => result.concat([mr]));
          });
        });
        return promise;
      });
    };
    // end workaround

    browser.driver.manage().window().maximize()
    util.implicitWait(30000);
    util.pageLoadWait(30000);
  },
};

code example

beforeAll(async () => {
   	await util.loadApp(env.APP_URL);
   	await loginPage.loginApplication(USERNAME, PASSWORD);
   	await setupPage.configureApp(be, sp, pn, sn);
   	await setupPage.startApp();
   });

In this code example, util.loadApp will simply navigate to the URL. The login page / screen will work just fine as well. The setup page / screen will also work, however once it reaches the last screen to run to app, protractor can no longer interact with elements from this point on unless waitForAngularEnabled(false). This causes a problem because it forces me to use ugly waits and removes the whole benefit of using protractor in the first place.

Does anyone have any idea what could cause protractor not recognize some screens as angular and others as non-angular?

@baflQA
Copy link

baflQA commented Sep 18, 2019

Protractor requires

window.getAllAngularTestabilities()[0].isStable()

to return true. Ensure that Your app is stable.

Check out this page for the details: https://www.protractortest.org/#/timeouts#timeouts-from-protractor

@jkelleyCE
Copy link
Author

I'll do some research and report back with my findings. Thank you, baflQA.

@jkelleyCE
Copy link
Author

jkelleyCE commented Sep 19, 2019

Protractor requires

window.getAllAngularTestabilities()[0].isStable()

to return true. Ensure that Your app is stable.

Check out this page for the details: https://www.protractortest.org/#/timeouts#timeouts-from-protractor

window.getAllAngularTestabilities()[0].isStable()
returns false.
However, the getAllAngularTestabilities() object contains isStable: true under _ngZone.
I read that this is not enough for protractor, however. The object also contains hasPendingMacrotasks: true. Our devs say there aren't any macrotasks running at this point.

Ever run into this?

@baflQA
Copy link

baflQA commented Sep 19, 2019

If angular says that there are the macrotasks Pending, then trust me, they are there even If developers say the opposite.
In my project we had a Launchdarkly macrotasks, as well as the Google maps component causing testability being not ready for 40s. Your developers should be able to find what macrotask is running quite easily.

@cod-e-ash
Copy link

Simple way to check is put a break on ngzone

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.

https://stackoverflow.com/questions/48627074/how-to-track-which-async-tasks-protractor-is-waiting-on

I am having the same issue, except I know it is caused by requestAnimationFrame and a setTimeout, but both are critical to my project, atleast RAF is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants