Search code examples
angulartestingautomationprotractorwait

Protractor can't find angular variable and wait until jasmine default time resulting in failure of tests


I am automating some test cases for an angular app. I have the following understanding with Protractor as:

  1. In angular apps there is no need of explicit waiting like selenium as protractor 90% commands return promises i.e. it means that protractor waits by its own.
  2. Protractor's function WaitForAngularEnabled() is by default true.

The problem i am having is that while automating tests for my angular app, when i test my app, protractor waits (and i guess it waits for angular variable) until jasmine default time expires and all test cases fails. When I test my app as Non-Angular (change my protractor conf. settings (code attached)), all test cases work finely, but I have to explicitly add waits which results in much flaky tests. It also increases test execution time. Can anyone help me in above mentioned issue. Will be much thankful to you.

onPrepare() {
    require('ts-node').register({
      project: 'e2e/tsconfig.e2e.json'
    });
    browser.waitForAngularEnabled(false);//Disabled angular here
    browser.driver.manage().window().maximize();
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
  }


Solution

  • When Protractor communicates with Angular, it uses the Angular Testability API, the API returns a variable called is_stable. When this variable is true, it means that your Angular website is stable. Which means that all the promises in your page has been resolved and there are no active processes that the page is waiting for finish.

    NOTE: The is_stable flag will give you false if there are still elements that require resolution in your page. This issue usually occurs if your website has any third party integrations that keep running in the background or if there is something in the mobile side that does not load on the webpage. If that is the case, you will need to check if there are any processes pending on your webpage. If there are any processes, you will have to move it outside the Angular's scope. That way Angular will resolve all promises and let Protractor know that it is ready to receive commands.

    The other way you can remove explicit waits from your code is by using async await. Async await is simple to use and will explicitly wait for any promise resolution before proceeding froward. Currently the selenium promise manager takes care of all the promises if you are running an older version of protractor, if not, the promise manager is disabled (deprecated) so you will have to manually take care of all the promises.