Protractor blocking wait

I’ve been working with non-angular protractor testing lately, and have been frustrated at the lack of documentation for how to perform simple tasks. For example, blocking execution while waiting for an element to appear, or another condition. My team’s tests were relying heavily on sleep() in the absence of such knowledge.

This week, I figured out the secret to a blocking wait.

Let’s say you’ve got some page rendering going on, and you need to wait for an element to show up before continuing:

browser.wait(element(by.id('some-element')).isPresent);

That’s it! Now, and this is absolutely vital: note that we pass in the function isPresent, not the promise it returns. This is because browser.wait() may run the function *many* times, and return many promises, until one of them resolves and passes the test.

What if we have a more complex condition, such as waiting for the element to be removed? In that case, we need to return our own promise-returning function:

browser.wait(function() {
  var deferred = protractor.promise.defer();
  element(by.id('some-element')).isPresent()
  	.then(function (isPresent) {
      deferred.fulfill(!isPresent);
    });
  return deferred.promise;
});

browser.wait() will execute our outer anonymous function as many times as it needs to until the promise is fulfilled with a truthy value.

Here’s a more generic function to handle pretty much any blocking-wait-for-condition that you’ll need:

function waitForPromiseTest(promiseFn, testFn) {
  browser.wait(function () {
    var deferred = protractor.promise.defer();
    promiseFn().then(function (data) {
      deferred.fulfill(testFn(data));
    });
    return deferred.promise;
  });
}

…then use this like so:

waitForPromiseTest(element(by.id('some-element')).isPresent,
  function (isPresent) {
    return !isPresent;
  });

Not a single line of code will execute until your test function returns true.

Note about browser vs. protractor.getInstance(): they’re exactly the same object! browser is the new preferred syntax.