Protractor can't detect Angular 5 on deployed application
Asked Answered
O

5

8

I am trying to create a repository with E2E tests for my web application using Protractor and Cucumber. I have started with this repository: https://github.com/spektrakel-blog/angular-protractor-cucumber

When I am forcing Protractor to treat the application as a regular webpage, the tests run fine. Test runner is interacting with the application and expecting some outcome. The thing is, that I would like to make Protractor detect Angular in order to wait for zones to be stable before checking 'Then' asserts.

Here is my protractor.conf.js:

exports.config = {
  allScriptsTimeout: 30000,
  capabilities: {
    browserName: 'chrome',
    chromeOptions: {
      args: ['--no-sandbox']
    }
  },
  directConnect: true,
  baseUrl: 'http://<ci-server-address>/',

  specs: [
    './e2e/features/*.feature'
  ],

  framework: 'custom',
  frameworkPath: require.resolve('protractor-cucumber-framework'),

  cucumberOpts: {
    require: ['./e2e/steps/**/*.ts'],
    strict: true,
    format: [
      'json:reports/summary.json'
    ],
    dryRun: false,
    compiler: []
  },

  onPrepare() {
    browser.ignoreSynchronization = true;
    require('ts-node').register({
      project: 'e2e/tsconfig.e2e.json'
    });
  }
};

In short - the tests run with the following config, but when I remove browser.ignoreSynchronization = true;, I get the following error: Timed out waiting for asynchronous Angular tasks to finish after 30 seconds. This may be because the current page is not an Angular application..

Things I have tried so far (with no improvement):

  • adding ng-app to the <body> tag
  • checking window.getAllAngularRootElements() - returns app-root correctly
  • checking window.getAllAngularTestabilities() - returns a Testability object
  • launching the tests on Chrome (with or without sandbox)
  • launching the tests on Firefox
  • trying both the CI server with our application deployed and local env with ng serve

I am using the latest versions of Protractor, Cucumber, Chai and TypeScript. Any help would be much appreciated. Thank you very much in advance!

Opaline answered 15/5, 2018 at 7:35 Comment(5)
It is stange that you have working solution and ask why did not work some other things. Why you can not just use working one? What advantanges you would like to get?Scientist
Where did I write that I have a working solution?Opaline
When I am forcing Protractor to treat the application as a regular webpage, the tests run fine. this one. I just want to understand maybe you try to resolve the issue (definetly, it is the issue), but you might choose another way.Scientist
When Protractor is not able to detect Angular, it's not able to wait for resolving the zones. In such case, I need to put timeouts in my E2E tests in order to them to pass. This is unacceptable, not to mention that I'm using Protractor because of that Angular integration. ;)Opaline
why you could not to wait the zonez by explicit waiters?Scientist
F
6

This sounds like a potential Zone issue to me. Angular depends on ZoneJS (ngZone). It is not that uncommon to run into this error when using any asynchronous javaScript functions such as setTimeout(), setInterval(), etc...

The reason being is that ZoneJS monkey patches those functions and it does so out of the context of the Angular zone. At which point when Protractor is trying to connect to your application it no longer is running in the Angular Zone and therefor Protractor will hang and eventually timeout with the error you're getting.

If I were you I would take a look at your application for any asynchronous functions that ZoneJS monkey patches. Also in general, look for anything in your code that is running outside the context of your applications zone.

Here is a good article on ZoneJS that not only helps you understand ZoneJS, but also lists the functions that are monkey patched Understanding ZoneJS

Fencer answered 17/7, 2018 at 23:10 Comment(4)
Once you ignore synchronization, you should not have a zone problem because the browser should not wait for Angular stability. So if you remove the ignoreSynchronization and you are on an Angular app, it can be a zone issue. I like this answer and might put bets on this.Wye
This solved it for us! I've been trying to figure out what happened to our Protractor automation forever and would have never thought of this. Thank you!Dishwasher
This seems like a good track! Thank you very much, I'll check this out during the weekend.Opaline
In the end it turned out that we had setInverval somewhere in the app that should be run outside of Angular zone. Thank you very much, your suggestion was very helpful!Opaline
T
1

Verify that your app actually gets stable:

  constructor(zone:NgZone)
  {
    zone.onStable.subscribe(()=> window.console.info('onStable'));
    zone.onUnstable.subscribe(()=> window.console.info('onUnstable'));
    zone.onMicrotaskEmpty.subscribe(()=> window.console.info('onMicrotaskEmpty'));
  }
Tiliaceous answered 22/7, 2018 at 0:48 Comment(1)
Thank you, by using your code I was quickly able to verify that I have in fact problems with using zones in my app. :)Opaline
O
0

Try below options

// CSS Selector for the element housing the angular app - this defaults to
// body, but is necessary if ng-app is on a descendant of <body>.
rootElement: 'body',

// The timeout in milliseconds for each script run on the browser. This should
// be longer than the maximum time your application needs to stabilize between
// tasks.
allScriptsTimeout: 3600 * 1000,

// How long to wait for a page to load.
getPageTimeout: 3600 * 1000,

and if your angular page take more time to load the page try to disable the animations with below code

    var disableNgAnimate = function () {
        angular.module('disableNgAnimate', []).run(['$animate', function ($animate) {
            $animate.enabled(false);
        }]);
    };
    browser.addMockModule('disableNgAnimate', disableNgAnimate);

Hope the above solutions helps you. browser.ignoreSynchronization = true; is deprecated try using browser.waitForAngularEnabled(true); refer here for more inputs

Ovate answered 19/7, 2018 at 11:39 Comment(2)
ignoreSynchronization is deprecated but still works. It is preferred to use the waitForAngularEnabled and setting it to false. See github.com/angular/protractor/blob/…Wye
Thank you for your input. Unfortunately, I've already tried increasing the timeouts with no positive result. Also, we don't use Angular animations module. By the way, your code seems like written in AngularJS, and I'm using Angular (5.2 to be exact).Opaline
B
0

protractor/globals have been removed from v4.0.9 , now we can simply import protractor helpers directly from protractor namespace which is much cleaner.

Example:

import {browser} from 'protractor';
Bosomy answered 24/7, 2018 at 8:18 Comment(0)
M
-1

trying remove baseUrl: 'http://<ci-server-address>/', in protractor conf.js

Myrtlemyrvyn answered 15/5, 2018 at 7:41 Comment(6)
It doesn't seem to be a problem - the browser opens correct page, just hangs and does nothing. Still, I've tried it and got the same results. FYI< I'm running the tests like that: protractor --baseUrl http://url-to-my-ci-server.Opaline
The page opened by http://url-to-my-ci-server is an Angular page or not?Myrtlemyrvyn
Have you tried move the browser.get('http://url-to-my-ci-server') into test case and remove it from baseUrl conf.js and don't specify it in cmd line too. If still not fix the issue, try latest protractorMyrtlemyrvyn
When I did so, there was the same result, just with a bit different error message: Could not find Angular on page http://server-name/login : angular never provided resumeBootstrap. I'm already using the latest version of Protractor - 5.3.1.Opaline
How to about to prepare an new spec to test another Angular app, like Angular official website: angular.io to see whether the issue comes from your code and the dependencies.Myrtlemyrvyn
I think I've tried that already. I'll take a look once more if everything else fails. Thanks!Opaline

© 2022 - 2024 — McMap. All rights reserved.