问题
Following Configuring multiple capabilities with promises topic.
Use case: I have two separate tests that require Firefox to be fired with javascript disabled and local storage disabled. Which means that I need two firefox profiles with javascript.enabled = false
and dom.storage.enabled = false
desired capabilities/preferences set.
I'm using getMultiCapabilities()
that was introduced in protractor 1.6. Till this moment, I needed only one custom firefox profile and it worked, here is the configuration:
getMultiCapabilities: function() {
var deferred = q.defer();
var multiCapabilities = [
{
browserName: "chrome",
specs: [
"*.spec.js"
],
exclude: [
"footer.disabledJavascript.spec.js"
]
}
];
// Wait for a server to be ready or get capabilities asynchronously.
setTimeout(function() {
var firefoxProfile = new FirefoxProfile();
firefoxProfile.setPreference("javascript.enabled", false);
firefoxProfile.encoded(function (encodedProfile) {
var capabilities = {
"browserName": "firefox",
"firefox_profile": encodedProfile,
"specs": [
"footer.disabledJavascript.spec.js"
]
};
multiCapabilities.push(capabilities);
deferred.resolve(multiCapabilities);
});
}, 1000);
return deferred.promise;
},
Problem: Now I need the second firefox profile instance with dom.storage.enabled = false
, but I'm stuck at how should I resolve the deferred
in this case, since there are now two encoded()
calls and two capabilities added to multiCapabilities.
Question: How can I configure multiple firefox profiles using getMultiCapabilities
?
The only way I made it work is nesting one profile into another and calling resolve()
at the deepest level (in case of two profiles it might be okay - but this solution doesn't really scale):
var multiCapabilities = [
{
browserName: "chrome",
specs: [
"*.spec.js"
],
exclude: [
"footer.disabledJavascript.spec.js",
"disabledLocalStorage.spec.js"
]
}
];
// Wait for a server to be ready or get capabilities asynchronously.
setTimeout(function() {
// profile with disabled javascript
var firefoxProfile = new FirefoxProfile();
firefoxProfile.setPreference("javascript.enabled", false);
firefoxProfile.encoded(function (encodedProfile) {
var capabilities = {
browserName: "firefox",
directConnect: true,
firefox_profile: encodedProfile,
specs: [
"footer.disabledJavascript.spec.js"
]
};
multiCapabilities.push(capabilities);
// profile with disabled local storage
var newFirefoxProfile = new FirefoxProfile();
newFirefoxProfile.setPreference("dom.storage.enabled", false);
newFirefoxProfile.encoded(function (newEncodedProfile) {
var newCapabilities = {
browserName: "firefox",
directConnect: true,
firefox_profile: newEncodedProfile,
specs: [
"disabledLocalStorage.spec.js"
]
};
multiCapabilities.push(newCapabilities);
deferred.resolve(multiCapabilities);
});
});
}, 1000);
return deferred.promise;
},
回答1:
You can use q.all to do this. Essentially you want to do something like this:
return q.all([
capabilityPromise1,
capabilityPromise2,
...
]);
Exactly how you get the capability promises is up to you. Here's one generic way:
var makeFirefoxProfile = function(preferenceMap, capabilityMap) {
var deferred = q.defer();
var firefoxProfile = new FirefoxProfile();
// TODO: iterate over preferenceMap and set preference for each
firefoxProfile.encoded(function (encodedProfile) {
var capabilities = {
"browserName": "firefox",
"firefox_profile": encodedProfile,
};
// TODO: iterate over capabilityMap and set key/value for each
deferred.resolve(capabilities);
});
return deferred.promise;
};
getMultiCapabilities: function() {
return q.all([
makeFirefoxProfile({javascript.enabled: false}, {specs: ['spec1.js']})
makeFirefoxProfile({dom.storage.enabled: false}, {specs: ['spec2.js']})
]);
}
If you don't want to create a helper function and want to generate the capability promises in 1 function, that's up to you. Essentially, I think the key here is to use q.all
, the rest really depends on how complex your capabilities objects are and how you want to structure your code
回答2:
Following @hakduan's suggestion to use q.all()
and have a reusable function, here is the configuration that worked for me (note how clean it is):
var makeFirefoxProfile = function(preferenceMap, specs) {
var deferred = q.defer();
var firefoxProfile = new FirefoxProfile();
for (var key in preferenceMap) {
firefoxProfile.setPreference(key, preferenceMap[key]);
};
firefoxProfile.encoded(function (encodedProfile) {
var capabilities = {
browserName: "firefox",
directConnect: true,
firefox_profile: encodedProfile,
specs: specs
};
deferred.resolve(capabilities);
});
return deferred.promise;
};
exports.config = {
getMultiCapabilities: function() {
return q.all([
{
browserName: "chrome",
directConnect: true,
specs: [
"*.spec.js"
],
exclude: [
"footer.disabledJavascript.spec.js",
"disabledLocalStorage.spec.js"
]
},
makeFirefoxProfile({"javascript.enabled": false}, ["footer.disabledJavascript.spec.js"]),
makeFirefoxProfile({"dom.storage.enabled": false}, ["disabledLocalStorage.spec.js"])
]);
},
...
};
来源:https://stackoverflow.com/questions/28619251/multiple-firefox-profiles-in-protractor