beNerd
beNerd

Reputation: 3374

how to properly chain promises in protractor

Consider the following snippet:

        getApiEndpoints.billingCycle()
           .then(apiURL=>{
                return RestClient.doGet(apiURL);
            }).then(console.log(data))

In the above snippet, getApiEndpoints.billingCycle() and RestClient.doGet(apiURL) both return promises. The above code just hangs the web driver and later crash with timeout error.

Is there something I am missing here?

UPDATE: RestClient.doGet(apiURL)

function doGet(url){
var defer = Helper.getPromise().defer();
      request.get(url, (error, response, body) => {
        if (response&&(response.statusCode == 200 || response.statusCode == 201)) {
          defer.fulfill(JSON.parse(body));
        } else {
          defer.reject(error);
        }
        });
      return defer.promise;

}

WHAT I TRIED

let flow = browser.controlFlow();
           flow.execute(getApiEndpoints.billingCycle())
           .then((apiURL)=> console.log(apiURL))

gets me Failed: fn is not a function error...

Upvotes: 2

Views: 2510

Answers (2)

alecxe
alecxe

Reputation: 473933

Failed: fn is not a function

You should pass a function to execute() (do not call it):

flow.execute(getApiEndpoints.billingCycle)

Or, if needed to pass parameters:

flow.execute(function () {
    return getApiEndpoints.billingCycle(param1, param2);
});

Upvotes: 2

AdityaReddy
AdityaReddy

Reputation: 3645

Protractor has its own control flow of Promises and non -Webdriver promises are not chained by default

So there are two ways you can handle this.I personally prefer the second one as it leverages the options provided by Protractor config.

  1. Insert a non-Web-driver promise into Protractor Control flow.There is a beautiful post on how to implement this.

  2. If this is something related to data setup or a pre-requisite for execution I would suggest adding it in onPrepare() section of conf.js

  • You can specify a file containing code to run by setting onPrepare to * the filename string. onPrepare can optionally return a promise, which * Protractor will wait for before continuing execution. This can be used if * the preparation involves any asynchronous calls, e.g. interacting with * the browser. Otherwise Protractor cannot guarantee order of execution * and may start the tests before preparation finishes.
 onPrepare: function() {
       return getApiEndpoints.billingCycle()
           .then(apiURL=>{
           return RestClient.doGet(apiURL)
   }).then(
       // Any value you want to set with API response. Some examples below
       browser.profile = data.user.name;  
       browser.params.password = data.user.password;    

       // Or else get the complete JSON onto global browser and use it through-out test case
       browser.apiresponse = data;

       )
    },

Upvotes: 0

Related Questions