2

I want to test my app with protracor but test fails with this errors :

Failed: Error while waiting for Protractor to sync with the page: "root element (html) has no injector. this may mean it is not inside ng-app."

it seems that angular doesn't load completely, and browser.waitForAngular(); not working. how can I setup protractor to continue test after RequireJs load dependencies ?

also adding this :

onPrepare:function(){
        browser.manage().timeouts().pageLoadTimeout(40000);
        browser.manage().timeouts().implicitlyWait(25000);
    }

to ocnfig file(As mentioned here) cause this error:

Failed: Error while waiting for Protractor to sync with the page: "angular could not be found on the window"
Community
  • 1
  • 1
Saman Mohamadi
  • 4,454
  • 4
  • 38
  • 58
  • Can you show us some test code? And just a first shot - does this link perhaps help: http://stackoverflow.com/questions/23634648/getting-error-error-while-waiting-for-protractor-to-sync-with-the-page – timtos Sep 03 '15 at 07:41
  • Did you properly bootstrap your app when using requireJS? This link might be helpful http://www.sitepoint.com/using-requirejs-angularjs-applications/ – ccg Sep 03 '15 at 07:51
  • yes app work correctly when loading manualy with browser. – Saman Mohamadi Sep 03 '15 at 07:54

3 Answers3

3

You will need a manual way to know that Angular has bootstrapped from within your specs. Here's the basic run-down of how I have this set up with Angular, RequireJS and Protractor. This works for me with jasmine2 and old jasmine.

We want to add a class of ng-app to the element that Angular bootstraps. For example:

index.html

<html lang="en" class="ng-app">

But rather than putting this in the HTML file, we want to add the class using the same RequireJS module that is manually bootstrapping your Angular App. Eg:

ng-bootstrap.js

require(['angular'], function (angular, otherdeps) {

  // Start the Angular App
  angular.bootstrap(document, ['MyApp']);

  // Set the ng-app class for Angular Protractor tests
  var root = document.documentElement;

  angular.element(root).addClass('ng-app');
});

Check that your page adds this class after bootstrapping. then set up your protractor.conf exports to run the onprepare test. This spec is executed each time Protractor is launched and we will use it to check for the class you added in the ng-bootstrap.js module.

protractor-conf.js

exports.config = {

    // Every time protractor is launched:
    onPrepare: 'onprepare.e2e.js',

};

In your onprepare.e2e.js spec file, you can trigger the load of the home page. Then ask Protractor to wait until the class .ng-app is found on the root element, Ie: Angular has bootstrapped and is ready to run Protractor tests.

onprepare.e2e.js

describe("On prepare", function () {

  // Replace with your own URL
  var baseUrl = 'http://127.0.0.1:8001/#/';

  // Begin fetching the page
  browser.driver.get(baseUrl);

  // Wait until `.ng-app` is found on the root elem
  browser.driver.wait(function () {
    return browser.driver.getCurrentUrl().then(function (url) {
      return browser.driver.isElementPresent(by.className('ng-app')).then(function () {
        return true;
      });
    });
  });

});

Keep in mind that if you a running lots of spec files together, your page could is being re-loaded when a new test starts. Your page also may be being reloaded if your Angular router is using a reload: true param.

This means that the app has to bootstrap again; And you will need to wait for the bootstrap class again before you can use Protractor.

Add a helper for this and include it in your protractor-conf.js.

helpers.js

module.exports = {

  get: function (url) {
    browser.driver.get(url);

    browser.driver.wait(function () {
      return browser.driver.getCurrentUrl().then(function (url) {
        return browser.driver.isElementPresent(by.className('ng-app')).then(function () {
          return true;
        });
      });
    });
  },

};

protractor-conf.js

helpers = require('helpers.js');

exports.config = {
  onPrepare: 'onprepare.e2e.js',

  specs: [
    'my-spec.js'
  ]
};

Now your helper is globally visible to your specs and you can use your new helper.get(url) method instead of browser.driver.get(url). Example:

my-spec.js

describe("Users", function() {

  it('should login', function () {

    // Wait for Angular and RequireJS to finish
    helpers.get('http://127.0.0.1:8001/#/login');

    // ...tests here...

  });

});
f1lt3r
  • 2,176
  • 22
  • 26
2

I had some similar problem, maybe it is because the way our app is loaded, but you can try having some custom wait:

browser.driver.wait(function() {
    return browser.driver.isElementPresent(by.css('.ng-scope'));
            }, 50000);//                           ^^or some other locator for your angular
});

inside your beforeEach() for example.

Edit: Also for someone it helps to change browser windows size:

browser.manage().window().setSize(1280, 1024);

in onPrepare()

cvakiitho
  • 1,377
  • 13
  • 27
  • Tnx @cvakiitho , I try it but doens't help me :( . still same errors. – Saman Mohamadi Sep 05 '15 at 04:54
  • And do you have `ng-scope` class inside your angular app? You can try other locators, because sleep works, it means that you only have to wait for angular app to load, as protractor itself has some problem with it. – cvakiitho Sep 07 '15 at 09:24
-2

I can run test by adding browser.driver.sleep(3000) to beforeEach. but this isn't the right solution.

Saman Mohamadi
  • 4,454
  • 4
  • 38
  • 58