admin管理员组文章数量:1312852
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. The spread function “spreads” the values over the arguments of the fulfillment handler.
return getUsername()
.then(function (username) {
return [username, getUser(username)];
})
.spread(function (username, user) {
});
In protractor, we are trying to use the built-in protractor.promise
ing from WebDriverJS
.
The Question:
Is it possible to have the "spread" functionality with protractor.promise
?
Example use case:
We've implemented a custom jasmine matcher to check if an element is focused. Here we need to resolve two promises before making an equality parison. Currently, we are using protractor.promise.all()
and then()
:
protractor.promise.all([
elm.getId(),
browser.driver.switchTo().activeElement().getId()
]).then(function (values) {
jasmine.matchersUtil.equals(values[0], values[1]);
});
which ideally we'd like to have in a more readable state:
protractor.promise.all([
elm.getId(),
browser.driver.switchTo().activeElement().getId()
]).spread(function (currentElementID, activeElementID) {
return jasmine.matchersUtil.equals(currentElementID, activeElementID);
})
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. The spread function “spreads” the values over the arguments of the fulfillment handler.
return getUsername()
.then(function (username) {
return [username, getUser(username)];
})
.spread(function (username, user) {
});
In protractor, we are trying to use the built-in protractor.promise
ing from WebDriverJS
.
The Question:
Is it possible to have the "spread" functionality with protractor.promise
?
Example use case:
We've implemented a custom jasmine matcher to check if an element is focused. Here we need to resolve two promises before making an equality parison. Currently, we are using protractor.promise.all()
and then()
:
protractor.promise.all([
elm.getId(),
browser.driver.switchTo().activeElement().getId()
]).then(function (values) {
jasmine.matchersUtil.equals(values[0], values[1]);
});
which ideally we'd like to have in a more readable state:
protractor.promise.all([
elm.getId(),
browser.driver.switchTo().activeElement().getId()
]).spread(function (currentElementID, activeElementID) {
return jasmine.matchersUtil.equals(currentElementID, activeElementID);
})
Share
Improve this question
edited May 23, 2017 at 12:03
CommunityBot
11 silver badge
asked Aug 7, 2015 at 22:58
alecxealecxe
474k127 gold badges1.1k silver badges1.2k bronze badges
10
- How do you expect this to happen if these are two different libraries? Unless WebDriverJS promise is wrapped in Q or Bluebird you can't get functionality of another library – Kirill Slatin Commented Aug 7, 2015 at 23:39
-
1
hmm, that might make sense to replace the promise engine from the very beginning. I thought of wrapping a specific promise instance. Something similar to bluebird's
promisify
– Kirill Slatin Commented Aug 8, 2015 at 0:17 -
1
However I think this might not work, Protractor makes use of ControlFlow, which is implemented inside WebDriverJS. And
Protractor.promise
most likely is just a reference, so changing it won't help. What really should be changed to slot in a new promise engine isrequire('webdriver').promise
somehow – Kirill Slatin Commented Aug 8, 2015 at 0:59 -
1
Thought: Starting with a Protractor promise, if you need some sugar method offered by Q, then you could try coercing to Q, using Q's sugar, then coercing back into Protractor, eg.
var newProtratorPromise = protractor.promise.when(Q.when(someProtractorPromise).sugarMethod(...));
. Probably not worth the bother for your.spread()
case but worth considering for more involved sugar, providing Protractor's "ControlFlow" aspects are not lost in the double-shuffle. – Roamer-1888 Commented Aug 8, 2015 at 10:53 -
1
@KirillSlatin actually, making webdriverjs and protractor to use
q
worked for me. I've posted it as an answer and created a github thread. I'm really not sure about the problems it can cause, but so far, my tests work as before. Thanks again for the participation. – alecxe Commented Aug 8, 2015 at 23:14
2 Answers
Reset to default 7 +100It may e 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);
}));
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 {
pare: 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.
本文标签: javascriptSpreading promises in ProtractorStack Overflow
版权声明:本文标题:javascript - Spreading promises in Protractor - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741877341a2402541.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论