Protractor tests inconsistently passing / failing for AngularJS app Protractor tests inconsistently passing / failing for AngularJS app angularjs angularjs

Protractor tests inconsistently passing / failing for AngularJS app


I was able to resolve the issue based on the following:

As mentioned by Nguyen Vu Hoang's comment to the original question, I am testing a pure Angular app with what I think is pure Protractor (no webdriver calls). I know ptor.ignoreSynchronization=true should not be required in this case, but for some reason, the tests are not proceeding at button click without this setting.

My new spec:

describe('Login', function() {  var ptor;  beforeEach(function() {    ptor = protractor.getInstance();    ptor.ignoreSynchronization = true;    ptor.waitForAngular();    ptor.get('https://127.0.0.1:8443');    ptor.findElement(by.id('splash')).then(function(elem) {        elem.click();    });  });  describe('with correct email and password', function() {    beforeEach(function() {        ptor.findElement(by.id('email')).then(function(elem) {            elem.sendKeys('admin@email.com');        });        ptor.findElement(by.id('password')).then(function(elem) {            elem.sendKeys('adminpassword');        });        ptor.findElement(by.id('loginButton')).then(function(elem) {            elem.click();        });    });    afterEach(function() {        ptor.findElement(by.id('logout')).then(function(elem) {            elem.click();        });    });    it('does not show alert', function() {        expect(ptor.isElementPresent(by.css('.alert-danger'))).toBe(false);    });    it('changes route to /admin', function() {        expect(ptor.getCurrentUrl()).toMatch(/\/admin/);    });  });});


There is also an another technique to make your tests more stable: Explicit Waits and Expected Conditions (docs).

I've found using Expected Conditions especially useful when testing against non-angular pages or angular applications that have a lot of animations involved.

For example, you can wait for an element to be clickable before making a click:

var EC = protractor.ExpectedConditions;var link = element(by.id("mylink"));browser.wait(EC.elementToBeClickable(link), "10000", "The link is still not clickable");link.click();

There are also other built-in Expected Conditions, such as:

  • presenseOf()
  • visibilityOf()
  • alertIsPresent()
  • textToBePresentInElementValue()
  • etc

And, it is easy to write a custom Expected Condition, example use case:

You can also combine Expected Conditions using and, or and not, e.g.:

var urlChanged = function() {  return browser.getCurrentUrl().then(function(url) {    return url != 'http://www.angularjs.org';  });};// condition to wait for url to change, title to contain 'foo', and $('abc') element to contain text 'bar'var condition = EC.and(urlChanged, EC.titleContains('foo'), EC.textToBePresentInElement($('abc'), 'bar'));$('navButton').click();browser.wait(condition, 5000); //wait for condition to be true.


browser.ignoreSynchronization = true; has a global effect for all your tests. you may have to set it back to false, so protractor waits for angular to be finished rendering the page. e.g. in or before your second beforeEach function