Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protractor timeouts

I've been developing automated tests in Protractor for quite some time and like many of you, I've run into gaps which can only be crossed with the browser.sleep()-bridge. I'm not a fan of hard coding things such as this but if it's a necessity I will.

The tests I've developed have brought me to a point where every browser.sleep(1000) has a major impact on my runtime. The tests are currently testing permissions for different accounts (128 exactly) and this involves logging in and out whilst checking what every account has and has not received access to.

The website I'm testing is a pure AngularJS application which, in my eyes, should make browser.sleep() a deprecated method since there is a browser.waitForAngular() method that accurately waits until the page is fully loaded compared to browser.sleep() which waits a set amount of time and if your website isn't loaded within that time (it happens), you'll have an inconsistent test (nobody likes inconsistency).

Research has led me to believe that browser.waitForAngular() does not take into account animations and related time-consuming features since they're not AngularJS related yet this is not implemented in our website. Also waitForAngular() basically waits for $digest, $http, and $timeout.

What I'm asking is wether this is something which is regarded as an acceptable loss since Protractor is great in general or is there something I'm overlooking here?

TL;DR: Are there solutions out there to allow us not to settle for browser.sleep()?

Sources: Protractor Timeout Docs, Timeout-spec.js (protractor docs), Issue909, Issue279, Issue92, StackQuestion1

like image 424
Tom Nijs Avatar asked Apr 30 '15 11:04

Tom Nijs


1 Answers

If you can devise some sort of test to determine if whatever you're waiting for has completed, you can use browser.wait. Taking ideas from from http://docsplendid.com/archives/209, you can pass a function that returns a promise that resolves to true or false, such as one that uses isPresent

browser.wait(function() {
  return element(by.id('some-element')).isPresent();
}, 1000);

or if you have some more complicated condition you can use promise chaining:

browser.wait(function() {
  return element(by.id('some-element')).isPresent().then(function(isPresent) {
    return !isPresent;
  });
}, 1000);

and the command flow will wait, repeatedly calling the function passed to wait, until the promise it returns resolves to true.

like image 166
Michal Charemza Avatar answered Sep 19 '22 09:09

Michal Charemza