24
describe('my homepage', function() {
    var ptor = protractor.getInstance();
    beforeEach(function(){
        // ptor.ignoreSynchronization = true;
        ptor.get('http://localhost/myApp/home.html');
        // ptor.sleep(5000);
    })
    describe('login', function(){

        var email = element.all(protractor.By.id('email'))
            , pass = ptor.findElement(protractor.By.id('password'))
            , loginBtn = ptor.findElement(protractor.By.css('#login button'))
            ;

        it('should input and login', function(){
            // email.then(function(obj){
            //  console.log('email', obj)
            // })
            email.sendKeys('josephine@hotmail.com');
            pass.sendKeys('shakalakabam');
            loginBtn.click();

        })
    })

});

the above code returns

 Error: Error while waiting for Protractor to sync with the page: {}

and I have no idea why this is, ptor load the page correctly, it seem to be the selection of the elements that fails.

TO SSHMSH:

Thanks, your almost right, and gave me the right philosophy, so the key is to ptor.sleep(3000) to have each page wait til ptor is in sync with the project.

user2167582
  • 5,986
  • 13
  • 64
  • 121

7 Answers7

39

I got the same error message (Angular 1.2.13). My tests were kicked off too early and Protractor didn't seem to wait for Angular to load.

It appeared that I had misconfigured the protractor config file. When the ng-app directive is not defined on the BODY-element, but on a descendant, you have to adjust the rootElement property in your protractor config file to the selector that defines your angular root element, for example:

// protractor-conf.js
rootElement: '.my-app',

when your HTML is:

<div ng-app="myApp" class="my-app">
Nissa
  • 4,636
  • 8
  • 29
  • 37
Ludder
  • 2,665
  • 1
  • 25
  • 26
  • 1
    Worded another way, you'll get this error whenever Protractor can't find the `ng-app` directive on the page (given the rootElement config). Another example of when this occurs is if the page fails to load (e.g. a traceback is displayed instead). – Asherah Nov 23 '14 at 22:40
  • 1
    What happens if ng-app directive is defined in the BODY element and stil you get this error? – Ram Pasala Apr 30 '16 at 08:43
13

I'm using ChromeDriver and the above error usually occurs for the first test. I've managed to get around it like this:

ptor.ignoreSynchronization = true;
ptor.get(targetUrl);
ptor.wait(
    function() {
            return ptor.driver.getCurrentUrl().then(
                function(url) {
                    return targetUrl == url;
                });
    }, 2000, 'It\'s taking too long to load ' + targetUrl + '!'
);

Essentially you are waiting for the current URL of the browser to become what you've asked for and allow 2s for this to happen. You probably want to switch the ignoreSynchronization = false afterwards, possibly wrapping it in a ptor.wait(...). Just wondering, would uncommenting the ptor.sleep(5000); not help?

EDIT: After some experience with Promise/Deferred I've realised the correct way of doing this would be:

loginBtn.click().then(function () {
    ptor.getCurrentUrl(targetUrl).then(function (newURL){
        expect(newURL).toBe(whatItShouldBe);
    });
});

Please note that if you are changing the URL (that is, moving away from the current AngularJS activated page to another, implying the AngularJS library needs to reload and init) than, at least in my experience, there's no way of avoiding the ptor.sleep(...) call. The above will only work if you are staying on the same Angular page, but changing the part of URL after the hashtag.

sshmsh
  • 181
  • 10
  • 1
    i get this message instead and for some reason the wait fn holds the testing and does not go to the specs. – user2167582 Nov 19 '13 at 16:55
  • Would you mind moving the `element.all(protractor.By.id('email'))` and the rest of the assignments inside the `it(...)` block? They might get called a bit _too early_. So, just to make sure, the URL that times out DOES exist (you can see it in your browser). – sshmsh Nov 19 '13 at 18:36
  • 1
    You should avoid using ptor.sleep(...), it's making your tests slow. This is a known issue, see [Protractor times out waiting for sync with page when using $resource](http://stackoverflow.com/questions/19741896/protractor-times-out-waiting-for-sync-with-page-when-using-resource) and [issue 49 on GitHub](https://github.com/angular/protractor/issues/49). As a workaround you should use `ptor.ignoreSynchronization = true` before the line that causes the error. Use with caution, this may have side effects see provided links! – sshmsh Nov 21 '13 at 14:07
  • 1
    Why do you use 'get' instead of 'getCurrentUrl' in your seceond code-block? Isn't get supposed to navigate to another page? Just curious, just getting started with protractor. – hugo der hungrige Jan 11 '14 at 06:42
  • As a note, this should no longer be necessary with the latest (**0.18.1**) version of Protractor. – Damiya Feb 08 '14 at 21:55
  • @Damiya: sounds good. I couldn't find it on the release notes, do you mind providing a link for details? – sshmsh Feb 14 '14 at 11:58
  • sorry for being pedantic but the fixes in question [_increase wait timeout_](https://github.com/angular/protractor/commit/10aec0ff212987bfdb9ab4011e6cb2f9c646fca2), [_add a message when page load does not complete in time_](https://github.com/angular/protractor/commit/11c4210fe740771707d5421a4940bdce43d3d33e) and [_improve error messages when timeouts occur_](https://github.com/angular/protractor/commit/6ae626158ee0610b70501af5d57ad4ff379c5ead) will not really fix the problem. Error reporting will be a bit better tho. – sshmsh Feb 15 '14 at 09:54
  • The right way to handle login scenario is this: [**How do I deal with my log-in page?**](https://github.com/angular/protractor/blob/master/docs/faq.md#how-do-i-deal-with-my-log-in-page), here's a [configuration example](https://github.com/angular/protractor/blob/master/spec/junitOutputConf.js). Haven't tried it yet, but the `onPrepare` hook seems like the right thing to use. – sshmsh Feb 15 '14 at 15:11
  • In fact, what I've suggested in my initial answer has also been used in one of the [official Protratctor examples](https://github.com/angular/protractor/blob/master/spec/withLoginConf.js) inside the `onPrepare` hook. Polling wait seems to be the only way. – sshmsh Feb 15 '14 at 16:45
  • The last paragraph is key here. – Snekse Sep 11 '14 at 22:49
6

In my case, I encountered the error with the following code:

describe("application", function() {
  it("should set the title", function() {
    browser.getTitle().then(function(title) {
      expect(title).toEqual("Welcome");
    });
  });
});

Fixed it by doing this:

describe("application", function() {
  it("should set the title", function() {
    browser.get("#/home").then(function() {
      return browser.getTitle();
    }).then(function(title) {
      expect(title).toEqual("Welcome");
    });
  });
});

In other words, I was forgetting to navigate to the page I wanted to test, so Protractor was having trouble finding Angular. D'oh!

XåpplI'-I0llwlg'I -
  • 21,649
  • 28
  • 102
  • 151
2

The rootElement param of the exports.config object defined in your protractor configuration file must match the element containing your ng-app directive. This doesn't have to be uniquely identifying the element -- 'div' suffices if the directive is in a div, as in my case.

From referenceConf.js:

// 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: 'div',

I got started with Protractor by watching the otherwise excellent egghead.io lecture, where he uses a condensed exports.config. Since rootElement defaults to body, there is no hint as to what is wrong with your configuration if you don't start with a copy of the provided reference configuration, and even then the

Error while waiting for Protractor to sync with the page: {}

message doesn't give much of a clue.

ivarg
  • 755
  • 1
  • 8
  • 11
  • 1
    just wanted to comment that using 'div' as a value didn't work for me--I needed to give my div tag an id and then reference the id as the solution below suggests: `
    ` and then in protractor config: `rootElement: '#myAppId'`
    – FireDragon Oct 24 '14 at 02:16
  • 1
    And I managed to get away without slapping an id onto my div tag by setting rootElement to `div[ng-app]`. – Chris Kobrzak Sep 22 '15 at 10:53
1

I had to switch from doing this:

    describe('navigation', function(){

        browser.get('');

        var navbar = element(by.css('#nav'));

        it('should have a link to home in the navbar', function(){
            //validate
        });

        it('should have a link to search in the navbar', function(){
            //validate
        });
    });

to doing this:

    describe('navigation', function(){

        beforeEach(function(){
            browser.get('');
        });
        var navbar = element(by.css('#nav'));

        it('should have a link to home in the navbar', function(){
            //validate
        });

        it('should have a link to search in the navbar', function(){
            //validate
        });
    });

the key diff being:

    beforeEach(function(){
        browser.get('');
    });

hope this may help someone.

philn5d
  • 636
  • 7
  • 12
0

I was getting this error:

Failed: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"

The solution was to call page.navigateTo() before page.getTitle().

Before:

import { AppPage } from './app.po';

describe('App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should have the correct title', () => {
    expect(page.getTitle()).toEqual('...');
  })
});

After:

import { AppPage } from './app.po';

describe('App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
    page.navigateTo();
  });

  it('should have the correct title', () => {
    expect(page.getTitle()).toEqual('...');
  })
});
Jesus is Lord
  • 14,971
  • 11
  • 66
  • 97
0

If you are using

browser.restart()

in your spec some times, it throws the same error. Try to use

await browser.restart()

Ganesh H
  • 1,649
  • 3
  • 14
  • 20