Spreading promises in Protractor

前端 未结 2 1170
眼角桃花
眼角桃花 2020-12-07 01:28

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 sprea

相关标签:
2条回答
  • 2020-12-07 01:50

    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 callback
    function spread(callback) {
        // and returns a new function which will be used by `then()`
        return function (array) {
            // with a result of calling callback via apply to spread array values
            return 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 variables
        const [currentElementID, activeElementID] = values; 
        jasmine.matchersUtil.equals(currentElementID, activeElementID);
    }));
    
    0 讨论(0)
  • 2020-12-07 01:57

    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:

    • Take elements while a condition evaluates to true (extending 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.

    0 讨论(0)
提交回复
热议问题