Protractor times out waiting for sync with page when using $resource

19,945

Solution 1

This is a known issue, but there is a temporary workaround. Set ptor.ignoreSynchronization = true.

For example:

describe('Testing Protractor', function() {
  var draftList;
  var ptor;

  beforeEach(function() {
    ptor = protractor.getInstance();
    ptor.ignoreSynchronization = true;
  });

  it('should count the number of drafts', function() {
    ptor.get('#/');
    draftList = element.all(by.repeater('newsletter in drafts'));
    expect(draftList.count()).toEqual(2);
  });
});

Solution 2

browser.ignoreSynchronization = true; worked out for me.

Solution 3

Instead of using browser.ignoreSynchronization, use browser.waitForAngularEnabled(*boolean*). browser.waitForAngularEnabled(false) sets browser.ignoreSynchronization to true, browser.waitForAngularEnabled(true) sets browser.ignoreSynchronization to false.

you can also include this as part of your test suites' config file:

onPrepare: function () {
    'use strict';
    browser.waitForAngularEnabled(false);
}

Solution 4

I'm using Protractor 3.3.0 and to get this to work in my test I had to defer the ignore synchronisation until after I had done the setup.

So in my beforeEach I call my action:

var searchBox = element(by.css('#inpt_search'));
searchBox.sendKeys('test');

I then have to wait for the mock backend to populate the view (I'm not happy about these sleep calls so if anyone has a better way of doing this please comment, I can't get expectedConditions.presenceOf to work as it's part of the same bug) using browser.sleep(500). Then in the test I set browser.ignoreSynchronization = true which unblocks whatever is blocked and sees the browser content.

describe('standard search', function (){
    beforeEach(function (){
        openApp();
        var searchBox = element(by.css('#inpt_search'));
        searchBox.sendKeys('test');
        browser.sleep(500);
    });
    it('should work or summat', function () {
        browser.ignoreSynchronization = true;
        var fileItems = element.all(by.repeater('item in list'));
        expect(fileItems.count()).toEqual(50);
    });
});
Share:
19,945

Related videos on Youtube

Joseph S.
Author by

Joseph S.

Updated on June 04, 2022

Comments

  • Joseph S.
    Joseph S. almost 2 years

    I'm testing Protractor with a small AngularJS app.

    This is the test:

    describe('Testing Protractor', function() {
      var draftList;
    
      it('should count the number of drafts', function() {
        browser.get('#/');
        draftList = element.all(by.repeater('newsletter in drafts'));
        expect(draftList.count()).toEqual(2);
      });
    });
    

    Controller:

    angular.module('myApp.controllers', []).
      controller('DraftsCtrl', ['$scope', 'Draft', function($scope, Draft) {
        $scope.drafts = Draft.query();
    }])
    

    Draft service:

    angular.module('myApp.services', ['ngResource']).
      factory('Draft', ['$resource',
        function($resource) {
          return $resource('api/drafts/:id')
        }])
    

    Running this test using Protractor results in the following error:

    Error: Timed out waiting for Protractor to synchronize with the page after 11 seconds
    

    However, if in the controller I change this line:

    $scope.drafts = Draft.query();
    

    to this:

    $scope.drafts = [];
    

    The test fails as expected, but more importantly: it does not time out.

    With query() enabled, both when running the app manually in a browser and when looking at the browser window opened by Protractor, the data returned by the API is correctly displayed by a repeater.

    Why is Protractor not able to synchronize with the page when the service is communicating with the API?

    AngularJS is v1.2.0-rc3. Protractor is v0.12.0.

  • Joseph S.
    Joseph S. over 10 years
    Thanks, I'll try this out later and let you know whether it worked. I actually did read that GitHub issue before posting here, but I was under the impression that the workaround is only required when polling an API at regular intervals which my test app is not doing. It only sends the API request once, when the controller is initialized.
  • Joseph S.
    Joseph S. over 10 years
    This was indeed the correct solution. Since Protractor 0.12.0 exposes the instance of Protractor as browser, it was enough to just add browser.ignoreSynchronization = true; before element.all(by.repeater(' ... '));.
  • orszaczky
    orszaczky almost 7 years
    protractor.getInstance() had been unused (replaced by global browser in v0.12.0) and is now removed.