Skip to content Skip to sidebar Skip to footer

Spreading Promises In Protractor

q library has this neat feature to resolve and spread multiple promises into separate arguments: If you have a promise for an array, you can use spread as a replacement for then

Solution 1:

It may come a bit ugly to use, but you can define an independent helper function, which can be passed to then() as a parameter and have a callback, which is usually passed to then() to be passed to it. This function will then convert array value to function arguments:

protractor.promise.all([
    elm.getId(),
    browser.driver.switchTo().activeElement().getId()
]).then(spread(function (currentElementID, activeElementID) {
    // ---^^^----- use helper function to spread args
    jasmine.matchersUtil.equals(currentElementID, activeElementID);
}));


// helper function gets a callbackfunctionspread(callback) {
    // and returns a new function which will be used by `then()`returnfunction (array) {
        // with a result of calling callback via apply to spread array valuesreturn callback.apply(null, array);
    };
}

You can still chain it with another then() and provide rejection callbacks; it keeps all the behavior of Protractor promises the same, but just converts array of values to arguments.

Drawbacks are that it is does not have a perfect look like in your example (not .all().spread() but .all().then(spread()) ) and you'll probably have to create a module for this helper or define it globally to be able to use it easily in multiple test files.

Update:

With ES2015 it is possible to use destructuring assignment along with then():

protractor.promise.all([
    elm.getId(),
    browser.driver.switchTo().activeElement().getId()
]).then(function (values) {
    // Destructure values to separate variablesconst [currentElementID, activeElementID] = values; 
    jasmine.matchersUtil.equals(currentElementID, activeElementID);
}));

Solution 2:

TL;DR Apparently, it's not entirely safe to replace protractor.promise with q. For instance, I've got a hanging test run once I've decided to extend ElementArrayFinder:


Old answer:

Here is what I've done to solve it.

I've replaced protractor.promise with q on the fly (not sure if it's actually safe to do):

onPrepare: {
    protractor.promise = require("q");
},

But, nothing broke so far and now I'm able to use spread() and other syntactic sugar provided by q through protractor.promise:

toBeActive: function() {
    return {
        compare: function(elm) {
            return {
                pass: protractor.promise.all([
                    elm.getId(),
                    browser.driver.switchTo().activeElement().getId()
                ]).spread(function (currentElementID, activeElementID) {
                    return jasmine.matchersUtil.equals(currentElementID, activeElementID);
                })
            };
        }
    };
}

Relevant github thread: protractor.promise to use q.

Post a Comment for "Spreading Promises In Protractor"