Protractor - Wait for async promise before doing next
Asked Answered
W

2

11

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
Wineskin answered 20/6, 2015 at 2:12 Comment(3)
The "test Func - step 2" is happening before "Last trace" in your it, which is what your question says you want to happen (the beforeEach happens before the it). If you want to make steps within the beforeEach dependent, you need to express that explicitly (via a then or separate control flow registrations), that's just how JavaScript/WebDriver/Protractor work.Cannular
I tried to define a control flow without success... Can you show me a solution?Wineskin
for anyone coming here, browser.wait returns a promise. There is no need to construct a promise within and return it.Chalice
C
12

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")
  });

});
Cannular answered 21/6, 2015 at 0:15 Comment(2)
perfect. Exactly what I was looking for. Thx for explanation concerning browser.wait promiseWineskin
Could you show the actual running output you got from this code?Givens
P
0

The two console.logs (steps 1 & 3)in your testFunc, that are not wrapped in the promise, will fire immediately when you call the function. Which is proven by your output. Then your promise (which looks to be working great!), returns the step 2 log when the promise is resolved (but after the logs have already fired).

And thus, it looks like this is doing what you want? I.e. your beforeEach does indeed look like it's firing the async function before hitting your first spec.

Putamen answered 20/6, 2015 at 16:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.