--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -29,16 +29,17 @@ Cu.import("chrome://marionette/content/e
Cu.import("chrome://marionette/content/evaluate.js");
Cu.import("chrome://marionette/content/event.js");
Cu.import("chrome://marionette/content/interaction.js");
Cu.import("chrome://marionette/content/l10n.js");
Cu.import("chrome://marionette/content/legacyaction.js");
Cu.import("chrome://marionette/content/logging.js");
Cu.import("chrome://marionette/content/modal.js");
Cu.import("chrome://marionette/content/proxy.js");
+Cu.import("chrome://marionette/content/session.js");
Cu.import("chrome://marionette/content/simpletest.js");
this.EXPORTED_SYMBOLS = ["GeckoDriver", "Context"];
var FRAME_SCRIPT = "chrome://marionette/content/listener.js";
const BROWSER_STARTUP_FINISHED = "browser-delayed-startup-finished";
const CLICK_TO_START_PREF = "marionette.debugging.clicktostart";
const CONTENT_LISTENER_PREF = "marionette.contentListener";
@@ -118,58 +119,32 @@ this.GeckoDriver = function (appName, se
this.mainContentFrameId = null;
this.mozBrowserClose = null;
this.currentFrameElement = null;
// frame ID of the current remote frame, used for mozbrowserclose events
this.oopFrameId = null;
this.observing = null;
this._browserIds = new WeakMap();
- // user-defined timeouts
- this.scriptTimeout = 30000; // 30 seconds
- this.searchTimeout = null;
- this.pageTimeout = 300000; // five minutes
-
- // Unsigned or invalid TLS certificates will be ignored if secureTLS
- // is set to false.
- this.secureTLS = true;
-
// The curent context decides if commands should affect chrome- or
// content space.
this.context = Context.CONTENT;
this.importedScripts = new evaluate.ScriptStorageService(
[Context.CHROME, Context.CONTENT]);
this.sandboxes = new Sandboxes(() => this.getCurrentWindow());
this.legacyactions = new legacyaction.Chain();
this.timer = null;
this.inactivityTimer = null;
this.marionetteLog = new logging.ContentLogger();
this.testName = null;
- this.sessionCapabilities = {
- // mandated capabilities
- "browserName": Services.appinfo.name.toLowerCase(),
- "browserVersion": Services.appinfo.version,
- "platformName": Services.sysinfo.getProperty("name").toLowerCase(),
- "platformVersion": Services.sysinfo.getProperty("version"),
- "acceptInsecureCerts": !this.secureTLS,
-
- // supported features
- "rotatable": this.appName == "B2G",
- "proxy": {},
-
- // proprietary extensions
- "specificationLevel": 0,
- "moz:processID": Services.appinfo.processID,
- "moz:profile": Services.dirsvc.get("ProfD", Ci.nsIFile).path,
- "moz:accessibilityChecks": false,
- };
+ this.sessionCapabilities = new session.Capabilities();
this.mm = globalMessageManager;
this.listener = proxy.toListener(() => this.mm, this.sendAsync.bind(this));
// always keep weak reference to current dialogue
this.dialog = null;
let handleDialog = (subject, topic) => {
let winr;
@@ -177,17 +152,19 @@ this.GeckoDriver = function (appName, se
winr = Cu.getWeakReference(subject);
}
this.dialog = new modal.Dialog(() => this.curBrowser, winr);
};
modal.addHandler(handleDialog);
};
Object.defineProperty(GeckoDriver.prototype, "a11yChecks", {
- get: function () { return this.sessionCapabilities["moz:accessibilityChecks"]; }
+ get: function () {
+ return this.sessionCapabilities.get("moz:accessibilityChecks");
+ }
});
GeckoDriver.prototype.QueryInterface = XPCOMUtils.generateQI([
Ci.nsIMessageListener,
Ci.nsIObserver,
Ci.nsISupportsWeakReference,
]);
@@ -461,23 +438,26 @@ GeckoDriver.prototype.registerBrowser =
// set to true if we updated mainContentId
mainContent = mainContent && this.curBrowser.mainContentId !== null;
if (mainContent) {
this.mainContentFrameId = this.curBrowser.curFrameId;
}
this.wins.set(reg.id, listenerWindow);
if (nullPrevious && (this.curBrowser.curFrameId !== null)) {
- this.sendAsync("newSession", this.sessionCapabilities, this.newSessionCommandId);
+ this.sendAsync(
+ "newSession",
+ this.sessionCapabilities.toJSON(),
+ this.newSessionCommandId);
if (this.curBrowser.isNewSession) {
this.newSessionCommandId = null;
}
}
- return [reg, mainContent, this.sessionCapabilities];
+ return [reg, mainContent, this.sessionCapabilities.toJSON()];
};
GeckoDriver.prototype.registerPromise = function() {
const li = "Marionette:register";
return new Promise(resolve => {
let cb = msg => {
let wid = msg.json.value;
@@ -506,38 +486,68 @@ GeckoDriver.prototype.listeningPromise =
let cb = () => {
this.mm.removeMessageListener(li, cb);
resolve();
};
this.mm.addMessageListener(li, cb);
});
};
+Object.defineProperty(GeckoDriver.prototype, "timeouts", {
+ get: function () {
+ return this.sessionCapabilities.get("timeouts");
+ },
+
+ set: function (newTimeouts) {
+ this.sessionCapabilities.set("timeouts", newTimeouts);
+ },
+});
+
+Object.defineProperty(GeckoDriver.prototype, "secureTLS", {
+ get: function () {
+ return !this.sessionCapabilities.get("acceptInsecureCerts");
+ }
+});
+
+Object.defineProperty(GeckoDriver.prototype, "proxy", {
+ get: function () {
+ return this.sessionCapabilities.get("proxy");
+ }
+});
+
/** Create a new session. */
GeckoDriver.prototype.newSession = function*(cmd, resp) {
if (this.sessionId) {
throw new SessionNotCreatedError("Maximum number of active sessions");
}
this.sessionId = cmd.parameters.sessionId ||
cmd.parameters.session_id ||
element.generateUUID();
-
this.newSessionCommandId = cmd.id;
- this.setSessionCapabilities(cmd.parameters.capabilities);
- this.scriptTimeout = 10000;
+ try {
+ this.sessionCapabilities = session.Capabilities.fromJSON(
+ cmd.parameters.capabilities, {merge: true});
+ logger.config("Matched capabilities: " +
+ JSON.stringify(this.sessionCapabilities));
+ } catch (e) {
+ throw new SessionNotCreatedError(e);
+ }
- this.secureTLS = !this.sessionCapabilities.acceptInsecureCerts;
if (!this.secureTLS) {
logger.warn("TLS certificate errors will be ignored for this session");
let acceptAllCerts = new cert.InsecureSweepingOverride();
cert.installOverride(acceptAllCerts);
}
+ if (this.proxy.init()) {
+ logger.info("Proxy settings initialised: " + JSON.stringify(this.proxy));
+ }
+
// If we are testing accessibility with marionette, start a11y service in
// chrome first. This will ensure that we do not have any content-only
// services hanging around.
if (this.a11yChecks && accessibility.service) {
logger.info("Preemptively starting accessibility service in Chrome");
}
let registerBrowsers = this.registerPromise();
@@ -619,138 +629,16 @@ GeckoDriver.prototype.newSession = funct
* ("capabilities") to values, which may be of types boolean,
* numerical or string.
*/
GeckoDriver.prototype.getSessionCapabilities = function (cmd, resp) {
resp.body.capabilities = this.sessionCapabilities;
};
/**
- * Update the sessionCapabilities object with the keys that have been
- * passed in when a new session is created.
- *
- * This is not a public API, only available when a new session is
- * created.
- *
- * @param {Object} newCaps
- * Key/value dictionary to overwrite session's current capabilities.
- */
-GeckoDriver.prototype.setSessionCapabilities = function (newCaps) {
- const copy = (from, to={}) => {
- let errors = [];
-
- // Remove any duplicates between required and desired in favour of the
- // required capabilities
- if (from !== null && from.desiredCapabilities) {
- for (let cap in from.requiredCapabilities) {
- if (from.desiredCapabilities[cap]) {
- delete from.desiredCapabilities[cap];
- }
- }
-
- // Let's remove the sessionCapabilities from desired capabilities
- for (let cap in this.sessionCapabilities) {
- if (from.desiredCapabilities && from.desiredCapabilities[cap]) {
- delete from.desiredCapabilities[cap];
- }
- }
- }
-
- for (let key in from) {
- switch (key) {
- case "desiredCapabilities":
- to = copy(from[key], to);
- break;
-
- case "requiredCapabilities":
- if (from[key].proxy) {
- this.setUpProxy(from[key].proxy);
- to.proxy = from[key].proxy;
- delete from[key].proxy;
- }
- for (let caps in from[key]) {
- if (from[key][caps] !== this.sessionCapabilities[caps]) {
- errors.push(from[key][caps] + " does not equal " +
- this.sessionCapabilities[caps]);
- }
- }
- break;
-
- default:
- to[key] = from[key];
- }
- }
-
- if (Object.keys(errors).length == 0) {
- return to;
- }
-
- throw new SessionNotCreatedError(
- `Not all requiredCapabilities could be met: ${JSON.stringify(errors)}`);
- };
-
- // clone, overwrite, and set
- let caps = copy(this.sessionCapabilities);
- caps = copy(newCaps, caps);
- logger.config("Changing capabilities: " + JSON.stringify(caps));
- this.sessionCapabilities = caps;
-};
-
-GeckoDriver.prototype.setUpProxy = function (proxy) {
- logger.config("User-provided proxy settings: " + JSON.stringify(proxy));
-
- assert.object(proxy);
- if (!proxy.hasOwnProperty("proxyType")) {
- throw new InvalidArgumentError();
- }
- switch (proxy.proxyType.toUpperCase()) {
- case "MANUAL":
- Preferences.set("network.proxy.type", 1);
- if (proxy.httpProxy && proxy.httpProxyPort){
- Preferences.set("network.proxy.http", proxy.httpProxy);
- Preferences.set("network.proxy.http_port", proxy.httpProxyPort);
- }
- if (proxy.sslProxy && proxy.sslProxyPort){
- Preferences.set("network.proxy.ssl", proxy.sslProxy);
- Preferences.set("network.proxy.ssl_port", proxy.sslProxyPort);
- }
- if (proxy.ftpProxy && proxy.ftpProxyPort) {
- Preferences.set("network.proxy.ftp", proxy.ftpProxy);
- Preferences.set("network.proxy.ftp_port", proxy.ftpProxyPort);
- }
- if (proxy.socksProxy) {
- Preferences.set("network.proxy.socks", proxy.socksProxy);
- Preferences.set("network.proxy.socks_port", proxy.socksProxyPort);
- if (proxy.socksVersion) {
- Preferences.set("network.proxy.socks_version", proxy.socksVersion);
- }
- }
- break;
-
- case "PAC":
- Preferences.set("network.proxy.type", 2);
- Preferences.set("network.proxy.autoconfig_url", proxy.proxyAutoconfigUrl);
- break;
-
- case "AUTODETECT":
- Preferences.set("network.proxy.type", 4);
- break;
-
- case "SYSTEM":
- Preferences.set("network.proxy.type", 5);
- break;
-
- case "NOPROXY":
- default:
- Preferences.set("network.proxy.type", 0);
- break;
- }
-};
-
-/**
* Log message. Accepts user defined log-level.
*
* @param {string} value
* Log message.
* @param {string} level
* Arbitrary log level.
*/
GeckoDriver.prototype.log = function (cmd, resp) {
@@ -833,17 +721,17 @@ GeckoDriver.prototype.getContext = funct
* @throws ScriptTimeoutError
* If the script was interrupted due to reaching the {@code
* scriptTimeout} or default timeout.
* @throws JavaScriptError
* If an Error was thrown whilst evaluating the script.
*/
GeckoDriver.prototype.executeScript = function*(cmd, resp) {
let {script, args, scriptTimeout} = cmd.parameters;
- scriptTimeout = scriptTimeout || this.scriptTimeout;
+ scriptTimeout = scriptTimeout || this.timeouts.script;
let opts = {
sandboxName: cmd.parameters.sandbox,
newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||
cmd.parameters.newSandbox,
filename: cmd.parameters.filename,
line: cmd.parameters.line,
debug: cmd.parameters.debug_script,
@@ -906,17 +794,17 @@ GeckoDriver.prototype.executeScript = fu
* @throws ScriptTimeoutError
* If the script was interrupted due to reaching the {@code
* scriptTimeout} or default timeout.
* @throws JavaScriptError
* If an Error was thrown whilst evaluating the script.
*/
GeckoDriver.prototype.executeAsyncScript = function* (cmd, resp) {
let {script, args, scriptTimeout} = cmd.parameters;
- scriptTimeout = scriptTimeout || this.scriptTimeout;
+ scriptTimeout = scriptTimeout || this.timeouts.script;
let opts = {
sandboxName: cmd.parameters.sandbox,
newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||
cmd.parameters.newSandbox,
filename: cmd.parameters.filename,
line: cmd.parameters.line,
debug: cmd.parameters.debug_script,
@@ -956,17 +844,17 @@ GeckoDriver.prototype.execute_ = functio
/**
* Execute pure JavaScript. Used to execute simpletest harness tests,
* which are like mochitests only injected using Marionette.
*
* Scripts are expected to call the {@code finish} global when done.
*/
GeckoDriver.prototype.executeJSScript = function* (cmd, resp) {
let {script, args, scriptTimeout} = cmd.parameters;
- scriptTimeout = scriptTimeout || this.scriptTimeout;
+ scriptTimeout = scriptTimeout || this.timeouts.script;
let opts = {
filename: cmd.parameters.filename,
line: cmd.parameters.line,
async: cmd.parameters.async,
};
switch (this.context) {
@@ -1018,26 +906,26 @@ GeckoDriver.prototype.executeJSScript =
* @param {string} url
* URL to navigate to.
*/
GeckoDriver.prototype.get = function*(cmd, resp) {
assert.content(this.context);
let url = cmd.parameters.url;
- let get = this.listener.get({url: url, pageTimeout: this.pageTimeout});
+ let get = this.listener.get({url: url, pageTimeout: this.timeouts.pageLoad});
// TODO(ato): Bug 1242595
let id = this.listener.activeMessageId;
// If a remoteness update interrupts our page load, this will never return
// We need to re-issue this request to correctly poll for readyState and
// send errors.
this.curBrowser.pendingCommands.push(() => {
cmd.parameters.command_id = id;
- cmd.parameters.pageTimeout = this.pageTimeout;
+ cmd.parameters.pageTimeout = this.timeouts.pageLoad;
this.mm.broadcastAsyncMessage(
"Marionette:pollForReadyState" + this.curBrowser.curFrameId,
cmd.parameters);
});
yield get;
this.curBrowser.browserForTab.focus();
};
@@ -1557,67 +1445,46 @@ GeckoDriver.prototype.switchToFrame = fu
yield registerBrowsers;
yield browserListening;
}
}
};
GeckoDriver.prototype.getTimeouts = function (cmd, resp) {
- return {
- "implicit": this.searchTimeout,
- "script": this.scriptTimeout,
- "page load": this.pageTimeout,
- };
+ return this.timeouts;
};
/**
* Set timeout for page loading, searching, and scripts.
*
* @param {Object.<string, number>}
* Dictionary of timeout types and their new value, where all timeout
* types are optional.
*
* @throws {InvalidArgumentError}
* If timeout type key is unknown, or the value provided with it is
* not an integer.
*/
GeckoDriver.prototype.setTimeouts = function (cmd, resp) {
// backwards compatibility with old API
// that accepted a dictionary {type: <string>, ms: <number>}
- let timeouts = {};
+ let json = {};
if (typeof cmd.parameters == "object" &&
"type" in cmd.parameters &&
"ms" in cmd.parameters) {
logger.warn("Using deprecated data structure for setting timeouts");
- timeouts = {[cmd.parameters.type]: parseInt(cmd.parameters.ms)};
+ json = {[cmd.parameters.type]: parseInt(cmd.parameters.ms)};
} else {
- timeouts = cmd.parameters;
+ json = cmd.parameters;
}
- for (let [typ, ms] of Object.entries(timeouts)) {
- assert.positiveInteger(ms);
-
- switch (typ) {
- case "implicit":
- this.searchTimeout = ms;
- break;
-
- case "script":
- this.scriptTimeout = ms;
- break;
-
- case "page load":
- this.pageTimeout = ms;
- break;
-
- default:
- throw new InvalidArgumentError();
- }
- }
+ // merge with existing timeouts
+ let merged = Object.assign(this.timeouts.toJSON(), json);
+ this.timeouts = session.Timeouts.fromJSON(merged);
};
/** Single tap. */
GeckoDriver.prototype.singleTap = function*(cmd, resp) {
let {id, x, y} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
@@ -1725,17 +1592,17 @@ GeckoDriver.prototype.multiAction = func
* @param {string} value
* Value the client is looking for.
*/
GeckoDriver.prototype.findElement = function*(cmd, resp) {
let strategy = cmd.parameters.using;
let expr = cmd.parameters.value;
let opts = {
startNode: cmd.parameters.element,
- timeout: this.searchTimeout,
+ timeout: this.timeouts.implicit,
all: false,
};
switch (this.context) {
case Context.CHROME:
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);
}
@@ -1768,17 +1635,17 @@ GeckoDriver.prototype.findElement = func
* @param {string} value
* Value the client is looking for.
*/
GeckoDriver.prototype.findElements = function*(cmd, resp) {
let strategy = cmd.parameters.using;
let expr = cmd.parameters.value;
let opts = {
startNode: cmd.parameters.element,
- timeout: this.searchTimeout,
+ timeout: this.timeouts.implicit,
all: true,
};
switch (this.context) {
case Context.CHROME:
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);
}
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_capabilities.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_capabilities.py
@@ -21,22 +21,27 @@ class TestCapabilities(MarionetteTestCas
"return Services.sysinfo.getProperty('version')")
def test_mandated_capabilities(self):
self.assertIn("browserName", self.caps)
self.assertIn("browserVersion", self.caps)
self.assertIn("platformName", self.caps)
self.assertIn("platformVersion", self.caps)
self.assertIn("acceptInsecureCerts", self.caps)
+ self.assertIn("timeouts", self.caps)
self.assertEqual(self.caps["browserName"], self.appinfo["name"].lower())
self.assertEqual(self.caps["browserVersion"], self.appinfo["version"])
self.assertEqual(self.caps["platformName"], self.os_name)
self.assertEqual(self.caps["platformVersion"], self.os_version)
self.assertFalse(self.caps["acceptInsecureCerts"])
+ self.assertDictEqual(self.caps["timeouts"],
+ {"implicit": 0,
+ "page load": 300000,
+ "script": 30000})
def test_supported_features(self):
self.assertIn("rotatable", self.caps)
def test_additional_capabilities(self):
self.assertIn("moz:processID", self.caps)
self.assertEqual(self.caps["moz:processID"], self.appinfo["processID"])
self.assertEqual(self.marionette.process_id, self.appinfo["processID"])
@@ -46,54 +51,195 @@ class TestCapabilities(MarionetteTestCas
self.assertEqual(self.caps["moz:profile"], current_profile)
self.assertEqual(self.marionette.profile, current_profile)
self.assertIn("moz:accessibilityChecks", self.caps)
self.assertFalse(self.caps["moz:accessibilityChecks"])
self.assertIn("specificationLevel", self.caps)
self.assertEqual(self.caps["specificationLevel"], 0)
- def test_we_can_pass_in_capabilities_on_session_start(self):
- self.marionette.delete_session()
- capabilities = {"desiredCapabilities": {"somethingAwesome": "cake"}}
- self.marionette.start_session(capabilities)
- caps = self.marionette.session_capabilities
- self.assertIn("somethingAwesome", caps)
-
def test_set_specification_level(self):
self.marionette.delete_session()
- self.marionette.start_session({"specificationLevel": 1})
+ self.marionette.start_session({"desiredCapabilities": {"specificationLevel": 2}})
caps = self.marionette.session_capabilities
- self.assertEqual(1, caps["specificationLevel"])
+ self.assertEqual(2, caps["specificationLevel"])
- def test_we_dont_overwrite_server_capabilities(self):
self.marionette.delete_session()
- capabilities = {"desiredCapabilities": {"browserName": "ChocolateCake"}}
- self.marionette.start_session(capabilities)
+ self.marionette.start_session({"requiredCapabilities": {"specificationLevel": 3}})
caps = self.marionette.session_capabilities
- self.assertEqual(caps["browserName"], self.appinfo["name"].lower(),
- "This should have appname not ChocolateCake.")
+ self.assertEqual(3, caps["specificationLevel"])
def test_we_can_pass_in_required_capabilities_on_session_start(self):
self.marionette.delete_session()
capabilities = {"requiredCapabilities": {"browserName": self.appinfo["name"].lower()}}
self.marionette.start_session(capabilities)
caps = self.marionette.session_capabilities
self.assertIn("browserName", caps)
- def test_we_pass_in_required_capability_we_cant_fulfil_raises_exception(self):
- self.marionette.delete_session()
- capabilities = {"requiredCapabilities": {"browserName": "CookiesAndCream"}}
- try:
- self.marionette.start_session(capabilities)
- self.fail("Marionette Should have throw an exception")
- except SessionNotCreatedException as e:
- # We want an exception
- self.assertIn("CookiesAndCream does not equal", str(e))
-
# Start a new session just to make sure we leave the browser in the
# same state it was before it started the test
self.marionette.start_session()
+ def test_capability_types(self):
+ for value in ["", "invalid", True, 42, []]:
+ print("testing value {}".format(value))
+ with self.assertRaises(SessionNotCreatedException):
+ print(" with desiredCapabilities")
+ self.marionette.delete_session()
+ self.marionette.start_session({"desiredCapabilities": value})
+ with self.assertRaises(SessionNotCreatedException):
+ print(" with requiredCapabilities")
+ self.marionette.delete_session()
+ self.marionette.start_session({"requiredCapabilities": value})
+
def test_we_get_valid_uuid4_when_creating_a_session(self):
self.assertNotIn("{", self.marionette.session_id,
"Session ID has {{}} in it: {}".format(
self.marionette.session_id))
+
+
+class TestCapabilityMatching(MarionetteTestCase):
+ allowed = [None, "*"]
+ disallowed = ["", 42, True, {}, []]
+
+ def setUp(self):
+ MarionetteTestCase.setUp(self)
+ self.browser_name = self.marionette.session_capabilities["browserName"]
+ self.platform_name = self.marionette.session_capabilities["platformName"]
+ self.marionette.delete_session()
+
+ def test_browser_name_desired(self):
+ self.marionette.start_session({"desiredCapabilities": {"browserName": self.browser_name}})
+ self.assertEqual(self.marionette.session_capabilities["browserName"], self.browser_name)
+
+ def test_browser_name_required(self):
+ self.marionette.start_session({"requiredCapabilities": {"browserName": self.browser_name}})
+ self.assertEqual(self.marionette.session_capabilities["browserName"], self.browser_name)
+
+ def test_browser_name_desired_allowed_types(self):
+ for typ in self.allowed:
+ self.marionette.delete_session()
+ self.marionette.start_session({"desiredCapabilities": {"browserName": typ}})
+ self.assertEqual(self.marionette.session_capabilities["browserName"], self.browser_name)
+
+ def test_browser_name_desired_disallowed_types(self):
+ for typ in self.disallowed:
+ with self.assertRaises(SessionNotCreatedException):
+ self.marionette.start_session({"desiredCapabilities": {"browserName": typ}})
+
+ def test_browser_name_required_allowed_types(self):
+ for typ in self.allowed:
+ self.marionette.delete_session()
+ self.marionette.start_session({"requiredCapabilities": {"browserName": typ}})
+ self.assertEqual(self.marionette.session_capabilities["browserName"], self.browser_name)
+
+ def test_browser_name_requried_disallowed_types(self):
+ for typ in self.disallowed:
+ with self.assertRaises(SessionNotCreatedException):
+ self.marionette.start_session({"requiredCapabilities": {"browserName": typ}})
+
+ def test_browser_name_prefers_required(self):
+ caps = {"desiredCapabilities": {"browserName": "invalid"},
+ "requiredCapabilities": {"browserName": "*"}}
+ self.marionette.start_session(caps)
+
+ def test_browser_name_error_on_invalid_required(self):
+ with self.assertRaises(SessionNotCreatedException):
+ caps = {"desiredCapabilities": {"browserName": "*"},
+ "requiredCapabilities": {"browserName": "invalid"}}
+ self.marionette.start_session(caps)
+
+ # TODO(ato): browser version comparison not implemented yet
+
+ def test_platform_name_desired(self):
+ self.marionette.start_session({"desiredCapabilities": {"platformName": self.platform_name}})
+ self.assertEqual(self.marionette.session_capabilities["platformName"], self.platform_name)
+
+ def test_platform_name_required(self):
+ self.marionette.start_session({"requiredCapabilities": {"platformName": self.platform_name}})
+ self.assertEqual(self.marionette.session_capabilities["platformName"], self.platform_name)
+
+ def test_platform_name_desired_allowed_types(self):
+ for typ in self.allowed:
+ self.marionette.delete_session()
+ self.marionette.start_session({"desiredCapabilities": {"platformName": typ}})
+ self.assertEqual(self.marionette.session_capabilities["platformName"], self.platform_name)
+
+ def test_platform_name_desired_disallowed_types(self):
+ for typ in self.disallowed:
+ with self.assertRaises(SessionNotCreatedException):
+ self.marionette.start_session({"desiredCapabilities": {"platformName": typ}})
+
+ def test_platform_name_required_allowed_types(self):
+ for typ in self.allowed:
+ self.marionette.delete_session()
+ self.marionette.start_session({"requiredCapabilities": {"platformName": typ}})
+ self.assertEqual(self.marionette.session_capabilities["platformName"], self.platform_name)
+
+ def test_platform_name_requried_disallowed_types(self):
+ for typ in self.disallowed:
+ with self.assertRaises(SessionNotCreatedException):
+ self.marionette.start_session({"requiredCapabilities": {"platformName": typ}})
+
+ def test_platform_name_prefers_required(self):
+ caps = {"desiredCapabilities": {"platformName": "invalid"},
+ "requiredCapabilities": {"platformName": "*"}}
+ self.marionette.start_session(caps)
+
+ def test_platform_name_error_on_invalid_required(self):
+ with self.assertRaises(SessionNotCreatedException):
+ caps = {"desiredCapabilities": {"platformName": "*"},
+ "requiredCapabilities": {"platformName": "invalid"}}
+ self.marionette.start_session(caps)
+
+ # TODO(ato): platform version comparison not imlpemented yet
+
+ def test_accept_insecure_certs(self):
+ for capability_type in ["desiredCapabilities", "requiredCapabilities"]:
+ print("testing {}".format(capability_type))
+ for value in ["", 42, {}, []]:
+ print(" type {}".format(type(value)))
+ with self.assertRaises(SessionNotCreatedException):
+ self.marionette.start_session({capability_type: {"acceptInsecureCerts": value}})
+
+ self.marionette.delete_session()
+ self.marionette.start_session({"desiredCapabilities": {"acceptInsecureCerts": True}})
+ self.assertTrue(self.marionette.session_capabilities["acceptInsecureCerts"])
+ self.marionette.delete_session()
+ self.marionette.start_session({"requiredCapabilities": {"acceptInsecureCerts": True}})
+
+ self.assertTrue(self.marionette.session_capabilities["acceptInsecureCerts"])
+
+ def test_page_load_strategy(self):
+ for strategy in ["none", "eager", "normal"]:
+ print("valid strategy {}".format(strategy))
+ self.marionette.delete_session()
+ self.marionette.start_session({"desiredCapabilities": {"pageLoadStrategy": strategy}})
+ self.assertEqual(self.marionette.session_capabilities["pageLoadStrategy"], strategy)
+
+ for value in ["", "EAGER", True, 42, {}, []]:
+ print("invalid strategy {}".format(value))
+ with self.assertRaises(SessionNotCreatedException):
+ self.marionette.start_session({"desiredCapabilities": {"pageLoadStrategy": value}})
+
+ def test_proxy_default(self):
+ self.marionette.start_session()
+ self.assertNotIn("proxy", self.marionette.session_capabilities)
+
+ def test_proxy_desired(self):
+ self.marionette.start_session({"desiredCapabilities": {"proxy": {"proxyType": "manual"}}})
+ self.assertIn("proxy", self.marionette.session_capabilities)
+ self.assertEqual(self.marionette.session_capabilities["proxy"]["proxyType"], "manual")
+ self.assertEqual(self.marionette.get_pref("network.proxy.type"), 1)
+
+ def test_proxy_required(self):
+ self.marionette.start_session({"requiredCapabilities": {"proxy": {"proxyType": "manual"}}})
+ self.assertIn("proxy", self.marionette.session_capabilities)
+ self.assertEqual(self.marionette.session_capabilities["proxy"]["proxyType"], "manual")
+ self.assertEqual(self.marionette.get_pref("network.proxy.type"), 1)
+
+ def test_timeouts(self):
+ timeouts = {u"implicit": 123, u"page load": 456, u"script": 789}
+ caps = {"desiredCapabilities": {"timeouts": timeouts}}
+ self.marionette.start_session(caps)
+ self.assertIn("timeouts", self.marionette.session_capabilities)
+ self.assertDictEqual(self.marionette.session_capabilities["timeouts"], timeouts)
+ self.assertDictEqual(self.marionette._send_message("getTimeouts"), timeouts)