Protractor - Wait for async promise before doing next

aorfevre picture aorfevre · Jun 20, 2015 · Viewed 16.4k times · Source

First of all, I've already checked various post and blogs concerning that point and I still can't figure out how to make it correctly.

I have tried many different combinaison of :

  • browser wait
  • protractor.controlFlow().execute
  • protractor.controlFlow().await(

...Still no success..

My problem

Within my beforeEach function, I'd like to call a protractor promise and wait for it to resolve before performing the rest of my code.

My Code

I've prepared this simple test for anyone willing to help me

describe('testAsync', function() {

  beforeEach(function() {
    console.log('beforeEach - step 1 ')

    browser.get("https://angularjs.org/");
    console.log('beforeEach - step 2 ')
    testFunc()
    console.log('beforeEach - after testFunc - step 3')

  });

  var testFunc = function(){

    console.log("testFunc - step 1")

    browser.wait(function() {
      var deferred = protractor.promise.defer();
      element(by.id('twitter-widget-1')).isPresent()
        .then(function (isPresent) {
          console.log("testFunc - step 2")
          deferred.fulfill(isPresent);
      });
      return deferred.promise;
    });

    console.log("testFunc - step 3")

  }

  it('test after BeforeEach', function() {
    console.log("Last trace")
  });

});

Current Output

[launcher] Running 1 instances of WebDriver
beforeEach - step 1
beforeEach - step 2
testFunc - step 1
testFunc - step 3
beforeEach - after testFunc - step 3
testFunc - step 2
Last trace

Expected Output

[launcher] Running 1 instances of WebDriver
beforeEach - step 1
beforeEach - step 2
testFunc - step 1
testFunc - step 2 // <------  This is within the promise resolve
testFunc - step 3
beforeEach - after testFunc - step 3
Last trace

Answer

P.T. picture P.T. · Jun 21, 2015

I think this will get the output you want:

describe('testAsync', function() {

  beforeEach(function() {
    console.log('beforeEach - step 1 ');

    // `get` implicitly registers a promise with the control flow
    browser.get("https://angularjs.org/");

    console.log('beforeEach - step 2 '); // runs "before" get above returns!

    testFunc().then(function() {
       // use a then to explicitly chain a dependency off a promise
       console.log('beforeEach - after testFunc - step 3');
    })

    protractor.promise.controlFlow().execute(function() {
       console.log('beforeEach - after testFunc, via controlFlow - step 4');
    });

    console.log('beforeEach - end of beforeEach - everything registered, nothing done');
  });

  var testFunc = function(){

    console.log("testFunc - step 1")

    // return browser wait promise to caller
    // `wait` also implicitly registers with the control flow
    return browser.wait(function() {
      return element(by.id('twitter-widget-1')).isPresent()
        .then(function (isPresent) {
          console.log("testFunc - step 2")
          return true; // tell wait its done by resolving then promise->element promise->wait
      });
    });
  }

  it('test after BeforeEach', function() {
    console.log("Last trace")
  });

});