--- a/testing/marionette/assert.js
+++ b/testing/marionette/assert.js
@@ -113,16 +113,35 @@ assert.content = function (context, msg
* If the current browser is not B2G or Fennec.
*/
assert.mobile = function (msg = "") {
msg = msg || "Only supported in Fennec or B2G";
assert.that(() => isFennec() || isB2G(), msg, UnsupportedOperationError)();
};
/**
+ * Asserts that |win| is open.
+ *
+ * @param {ChromeWindow} win
+ * Chrome window to test.
+ * @param {string=} msg
+ * Custom error message.
+ *
+ * @return {ChromeWindow}
+ * |win| is returned unaltered.
+ *
+ * @throws {NoSuchWindowError}
+ * If |win| has been closed.
+ */
+assert.window = function (win, msg = "") {
+ msg = msg || "Unable to locate window";
+ return assert.that(w => w && w.document.defaultView, msg, NoSuchWindowError)(win);
+}
+
+/**
* Asserts that |obj| is defined.
*
* @param {?} obj
* Value to test.
* @param {string=} msg
* Custom error message.
*
* @return {?}
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -300,32 +300,44 @@ GeckoDriver.prototype.sendTargettedAsync
throw new WebDriverError(e);
}
}
};
/**
* Gets the current active window.
*
+ * @param {Context=} forcedContext
+ * Optional name of the context to use for the checks.
+ * Defaults to the current context.
+ *
* @return {nsIDOMWindow}
*/
-GeckoDriver.prototype.getCurrentWindow = function() {
- let typ = null;
+GeckoDriver.prototype.getCurrentWindow = function (forcedContext = undefined) {
+ let context = typeof forcedContext == "undefined" ? this.context : forcedContext;
+ let win = null;
+
if (this.curFrame === null) {
if (this.curBrowser === null) {
- if (this.context == Context.CONTENT) {
- typ = "navigator:browser";
+ let typ = (context === Context.CONTENT) ? "navigator:browser" : null;
+ win = Services.wm.getMostRecentWindow(typ);
+ } else {
+ if (context === Context.CHROME) {
+ win = this.curBrowser.window;
+ } else {
+ if (this.curBrowser.tab && browser.getBrowserForTab(this.curBrowser.tab)) {
+ win = this.curBrowser.window;
+ }
}
- return Services.wm.getMostRecentWindow(typ);
- } else {
- return this.curBrowser.window;
}
} else {
- return this.curFrame;
+ win = this.curFrame;
}
+
+ return win;
};
GeckoDriver.prototype.addFrameCloseListener = function (action) {
let win = this.getCurrentWindow();
this.mozBrowserClose = e => {
if (e.target.id == this.oopFrameId) {
win.removeEventListener("mozbrowserclose", this.mozBrowserClose, true);
this.switchToGlobalMessageManager();
@@ -742,16 +754,18 @@ 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) {
+ assert.window(this.getCurrentWindow());
+
let {script, args, scriptTimeout} = cmd.parameters;
scriptTimeout = scriptTimeout || this.timeouts.script;
let opts = {
sandboxName: cmd.parameters.sandbox,
newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||
cmd.parameters.newSandbox,
filename: cmd.parameters.filename,
@@ -815,16 +829,18 @@ 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) {
+ assert.window(this.getCurrentWindow());
+
let {script, args, scriptTimeout} = cmd.parameters;
scriptTimeout = scriptTimeout || this.timeouts.script;
let opts = {
sandboxName: cmd.parameters.sandbox,
newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||
cmd.parameters.newSandbox,
filename: cmd.parameters.filename,
@@ -865,28 +881,29 @@ 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 win = assert.window(this.getCurrentWindow());
+
let {script, args, scriptTimeout} = cmd.parameters;
scriptTimeout = scriptTimeout || this.timeouts.script;
let opts = {
filename: cmd.parameters.filename,
line: cmd.parameters.line,
async: cmd.parameters.async,
};
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let wargs = element.fromJson(args, this.curBrowser.seenEls, win);
let harness = new simpletest.Harness(
win,
Context.CHROME,
this.marionetteLog,
scriptTimeout,
function() {},
this.testName);
@@ -925,16 +942,17 @@ GeckoDriver.prototype.executeJSScript =
* the supplied URL and wait until document.readyState equals "complete"
* or the page timeout duration has elapsed.
*
* @param {string} url
* URL to navigate to.
*/
GeckoDriver.prototype.get = function*(cmd, resp) {
assert.content(this.context);
+ assert.window(this.getCurrentWindow());
let url = cmd.parameters.url;
let get = this.listener.get({url: url, pageTimeout: this.timeouts.pageLoad});
// 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.
@@ -960,67 +978,72 @@ GeckoDriver.prototype.get = function*(cm
* On Desktop this returns a string representation of the URL of the
* current top level browsing context. This is equivalent to
* document.location.href.
*
* When in the context of the chrome, this returns the canonical URL
* of the current resource.
*/
GeckoDriver.prototype.getCurrentUrl = function (cmd) {
+ let win = assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
- return this.getCurrentWindow().location.href;
+ return win.location.href;
case Context.CONTENT:
- let isB2G = this.appName == "B2G";
- return this.listener.getCurrentUrl(isB2G);
+ return this.listener.getCurrentUrl();
}
};
/** Gets the current title of the window. */
GeckoDriver.prototype.getTitle = function* (cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
resp.body.value = win.document.documentElement.getAttribute("title");
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getTitle();
break;
}
};
/** Gets the current type of the window. */
GeckoDriver.prototype.getWindowType = function (cmd, resp) {
- let win = this.getCurrentWindow();
+ let win = assert.window(this.getCurrentWindow());
+
resp.body.value = win.document.documentElement.getAttribute("windowtype");
};
/** Gets the page source of the content document. */
GeckoDriver.prototype.getPageSource = function* (cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let s = new win.XMLSerializer();
resp.body.value = s.serializeToString(win.document);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getPageSource();
break;
}
};
/**
* Cause the browser to traverse one step backward in the joint history
* of the current browsing context.
*/
GeckoDriver.prototype.goBack = function* (cmd, resp) {
assert.content(this.context);
+ assert.window(this.getCurrentWindow());
if (!this.curBrowser.tab) {
// Navigation does not work for non-browser windows
return;
}
let contentBrowser = browser.getBrowserForTab(this.curBrowser.tab)
if (!contentBrowser.webNavigation.canGoBack) {
@@ -1052,16 +1075,17 @@ GeckoDriver.prototype.goBack = function*
};
/**
* Cause the browser to traverse one step forward in the joint history
* of the current browsing context.
*/
GeckoDriver.prototype.goForward = function* (cmd, resp) {
assert.content(this.context);
+ assert.window(this.getCurrentWindow());
if (!this.curBrowser.tab) {
// Navigation does not work for non-browser windows
return;
}
let contentBrowser = browser.getBrowserForTab(this.curBrowser.tab)
if (!contentBrowser.webNavigation.canGoForward) {
@@ -1090,16 +1114,17 @@ GeckoDriver.prototype.goForward = functi
});
yield goForward;
};
/** Refresh the page. */
GeckoDriver.prototype.refresh = function*(cmd, resp) {
assert.content(this.context);
+ assert.window(this.getCurrentWindow());
yield this.listener.refresh();
};
/**
* Forces an update for the given browser's id.
*/
GeckoDriver.prototype.updateIdForBrowser = function (browser, newId) {
@@ -1136,16 +1161,18 @@ GeckoDriver.prototype.getIdForBrowser =
* Return an opaque server-assigned identifier to this window that
* uniquely identifies it within this Marionette instance. This can
* be used to switch to this window at a later point.
*
* @return {string}
* Unique window handle.
*/
GeckoDriver.prototype.getWindowHandle = function (cmd, resp) {
+ assert.window(this.getCurrentWindow(Context.CONTENT));
+
// curFrameId always holds the current tab.
if (this.curBrowser.curFrameId) {
resp.body.value = this.curBrowser.curFrameId;
return;
}
for (let i in this.browsers) {
if (this.curBrowser == this.browsers[i]) {
@@ -1177,16 +1204,18 @@ GeckoDriver.prototype.getWindowHandles =
* Return an opaque server-assigned identifier to this window that
* uniquely identifies it within this Marionette instance. This can
* be used to switch to this window at a later point.
*
* @return {string}
* Unique window handle.
*/
GeckoDriver.prototype.getChromeWindowHandle = function (cmd, resp) {
+ assert.window(this.getCurrentWindow(Context.CHROME));
+
for (let i in this.browsers) {
if (this.curBrowser == this.browsers[i]) {
resp.body.value = i;
return;
}
}
};
@@ -1203,17 +1232,18 @@ GeckoDriver.prototype.getChromeWindowHan
/**
* Get the current window position.
*
* @return {Object.<string, number>}
* Object with |x| and |y| coordinates.
*/
GeckoDriver.prototype.getWindowPosition = function (cmd, resp) {
- let win = this.getCurrentWindow();
+ let win = assert.window(this.getCurrentWindow());
+
return {
x: win.screenX,
y: win.screenY,
};
};
/**
* Set the window position of the browser on the OS Window Manager
@@ -1329,16 +1359,18 @@ GeckoDriver.prototype.switchToWindow = f
}
}
} else {
throw new NoSuchWindowError(`Unable to locate window: ${switchTo}`);
}
};
GeckoDriver.prototype.getActiveFrame = function (cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
// no frame means top-level
resp.body.value = null;
if (this.curFrame) {
let elRef = this.curBrowser.seenEls
.add(this.curFrame.frameElement);
let el = element.makeWebElement(elRef);
@@ -1352,29 +1384,33 @@ GeckoDriver.prototype.getActiveFrame = f
let el = element.makeWebElement(this.currentFrameElement);
resp.body.value = el;
}
break;
}
};
GeckoDriver.prototype.switchToParentFrame = function*(cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
let res = yield this.listener.switchToParentFrame();
};
/**
* Switch to a given frame within the current window.
*
* @param {Object} element
* A web element reference to the element to switch to.
* @param {(string|number)} id
* If element is not defined, then this holds either the id, name,
* or index of the frame to switch to.
*/
GeckoDriver.prototype.switchToFrame = function* (cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
let {id, element, focus} = cmd.parameters;
const otherErrorsExpr = /about:.+(error)|(blocked)\?/;
const checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
let curWindow = this.getCurrentWindow();
let checkLoad = function() {
@@ -1556,16 +1592,18 @@ GeckoDriver.prototype.setTimeouts = func
// 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) {
+ assert.window(this.getCurrentWindow());
+
let {id, x, y} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
throw new UnsupportedOperationError(
"Command 'singleTap' is not yet available in chrome context");
case Context.CONTENT:
@@ -1580,30 +1618,34 @@ GeckoDriver.prototype.singleTap = functi
*
* @param {Array.<?>} actions
* Array of objects that each represent an action sequence.
*
* @throws {UnsupportedOperationError}
* If the command is made in chrome context.
*/
GeckoDriver.prototype.performActions = function(cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
throw new UnsupportedOperationError(
"Command 'performActions' is not yet available in chrome context");
case Context.CONTENT:
return this.listener.performActions({"actions": cmd.parameters.actions});
}
};
/**
* Release all the keys and pointer buttons that are currently depressed.
*/
GeckoDriver.prototype.releaseActions = function(cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
throw new UnsupportedOperationError(
"Command 'releaseActions' is not yet available in chrome context");
case Context.CONTENT:
return this.listener.releaseActions();
}
@@ -1615,25 +1657,26 @@ GeckoDriver.prototype.releaseActions = f
* @param {Object} value
* A nested array where the inner array represents each event,
* and the outer array represents a collection of events.
*
* @return {number}
* Last touch ID.
*/
GeckoDriver.prototype.actionChain = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let {chain, nextId} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
// be conservative until this has a use case and is established
// to work as expected in Fennec
- assert.firefox()
-
- let win = this.getCurrentWindow();
+ assert.firefox();
+
resp.body.value = yield this.legacyactions.dispatchActions(
chain, nextId, {frame: win}, this.curBrowser.seenEls);
break;
case Context.CONTENT:
this.addFrameCloseListener("action chain");
resp.body.value = yield this.listener.actionChain(chain, nextId);
break;
@@ -1644,16 +1687,18 @@ GeckoDriver.prototype.actionChain = func
* A multi-action chain.
*
* @param {Object} value
* A nested array where the inner array represents eache vent,
* the middle array represents a collection of events for each
* finger, and the outer array represents all fingers.
*/
GeckoDriver.prototype.multiAction = function*(cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
throw new UnsupportedOperationError(
"Command 'multiAction' is not yet available in chrome context");
case Context.CONTENT:
this.addFrameCloseListener("multi action chain");
yield this.listener.multiAction(cmd.parameters.value, cmd.parameters.max_length);
@@ -1665,31 +1710,33 @@ GeckoDriver.prototype.multiAction = func
* Find an element using the indicated search strategy.
*
* @param {string} using
* Indicates which search method to use.
* @param {string} value
* Value the client is looking for.
*/
GeckoDriver.prototype.findElement = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let strategy = cmd.parameters.using;
let expr = cmd.parameters.value;
let opts = {
startNode: cmd.parameters.element,
timeout: this.timeouts.implicit,
all: false,
};
switch (this.context) {
case Context.CHROME:
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);
}
- let container = {frame: this.getCurrentWindow()};
+ let container = {frame: win};
if (opts.startNode) {
opts.startNode = this.curBrowser.seenEls.get(opts.startNode, container);
}
let el = yield element.find(container, strategy, expr, opts);
let elRef = this.curBrowser.seenEls.add(el);
let webEl = element.makeWebElement(elRef);
resp.body.value = webEl;
@@ -1708,31 +1755,33 @@ GeckoDriver.prototype.findElement = func
* Find elements using the indicated search strategy.
*
* @param {string} using
* Indicates which search method to use.
* @param {string} value
* Value the client is looking for.
*/
GeckoDriver.prototype.findElements = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let strategy = cmd.parameters.using;
let expr = cmd.parameters.value;
let opts = {
startNode: cmd.parameters.element,
timeout: this.timeouts.implicit,
all: true,
};
switch (this.context) {
case Context.CHROME:
if (!SUPPORTED_STRATEGIES.has(strategy)) {
throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);
}
- let container = {frame: this.getCurrentWindow()};
+ let container = {frame: win};
if (opts.startNode) {
opts.startNode = this.curBrowser.seenEls.get(opts.startNode, container);
}
let els = yield element.find(container, strategy, expr, opts);
let elRefs = this.curBrowser.seenEls.addAll(els);
let webEls = elRefs.map(element.makeWebElement);
resp.body = webEls;
@@ -1744,16 +1793,18 @@ GeckoDriver.prototype.findElements = fun
cmd.parameters.value,
opts);
break;
}
};
/** Return the active element on the page. */
GeckoDriver.prototype.getActiveElement = function*(cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
throw new UnsupportedOperationError(
"Command 'getActiveElement' is not yet available in chrome context");
case Context.CONTENT:
resp.body.value = yield this.listener.getActiveElement();
break;
@@ -1762,21 +1813,22 @@ GeckoDriver.prototype.getActiveElement =
/**
* Send click event to element.
*
* @param {string} id
* Reference ID to the element that will be clicked.
*/
GeckoDriver.prototype.clickElement = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
yield interaction.clickElement(el, this.a11yChecks);
break;
case Context.CONTENT:
// We need to protect against the click causing an OOP frame to close.
// This fires the mozbrowserclose event when it closes so we need to
// listen for it and then just send an error back. The person making the
@@ -1794,21 +1846,22 @@ GeckoDriver.prototype.clickElement = fun
* Web element reference ID to the element that will be inspected.
* @param {string} name
* Name of the attribute which value to retrieve.
*
* @return {string}
* Value of the attribute.
*/
GeckoDriver.prototype.getElementAttribute = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let {id, name} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
resp.body.value = el.getAttribute(name);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementAttribute(id, name);
break;
@@ -1822,21 +1875,22 @@ GeckoDriver.prototype.getElementAttribut
* Web element reference ID to the element that will be inspected.
* @param {string} name
* Name of the property which value to retrieve.
*
* @return {string}
* Value of the property.
*/
GeckoDriver.prototype.getElementProperty = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let {id, name} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
resp.body.value = el[name];
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementProperty(id, name);
break;
}
@@ -1845,22 +1899,23 @@ GeckoDriver.prototype.getElementProperty
/**
* Get the text of an element, if any. Includes the text of all child
* elements.
*
* @param {string} id
* Reference ID to the element that will be inspected.
*/
GeckoDriver.prototype.getElementText = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// for chrome, we look at text nodes, and any node with a "label" field
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
let lines = [];
this.getVisibleText(el, lines);
resp.body.value = lines.join("\n");
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementText(id);
@@ -1870,21 +1925,22 @@ GeckoDriver.prototype.getElementText = f
/**
* Get the tag name of the element.
*
* @param {string} id
* Reference ID to the element that will be inspected.
*/
GeckoDriver.prototype.getElementTagName = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
resp.body.value = el.tagName.toLowerCase();
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementTagName(id);
break;
}
@@ -1892,21 +1948,22 @@ GeckoDriver.prototype.getElementTagName
/**
* Check if element is displayed.
*
* @param {string} id
* Reference ID to the element that will be inspected.
*/
GeckoDriver.prototype.isElementDisplayed = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
resp.body.value = yield interaction.isElementDisplayed(
el, this.a11yChecks);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.isElementDisplayed(id);
break;
@@ -1917,21 +1974,22 @@ GeckoDriver.prototype.isElementDisplayed
* Return the property of the computed style of an element.
*
* @param {string} id
* Reference ID to the element that will be checked.
* @param {string} propertyName
* CSS rule that is being requested.
*/
GeckoDriver.prototype.getElementValueOfCssProperty = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let {id, propertyName: prop} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
let sty = win.document.defaultView.getComputedStyle(el);
resp.body.value = sty.getPropertyValue(prop);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.getElementValueOfCssProperty(id, prop);
break;
@@ -1940,22 +1998,23 @@ GeckoDriver.prototype.getElementValueOfC
/**
* Check if element is enabled.
*
* @param {string} id
* Reference ID to the element that will be checked.
*/
GeckoDriver.prototype.isElementEnabled = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// Selenium atom doesn't quite work here
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
resp.body.value = yield interaction.isElementEnabled(
el, this.a11yChecks);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.isElementEnabled(id);
break;
@@ -1964,39 +2023,41 @@ GeckoDriver.prototype.isElementEnabled =
/**
* Check if element is selected.
*
* @param {string} id
* Reference ID to the element that will be checked.
*/
GeckoDriver.prototype.isElementSelected = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// Selenium atom doesn't quite work here
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
resp.body.value = yield interaction.isElementSelected(
el, this.a11yChecks);
break;
case Context.CONTENT:
resp.body.value = yield this.listener.isElementSelected(id);
break;
}
};
GeckoDriver.prototype.getElementRect = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
let rect = el.getBoundingClientRect();
resp.body = {
x: rect.x + win.pageXOffset,
y: rect.y + win.pageYOffset,
width: rect.width,
height: rect.height
};
@@ -2012,53 +2073,57 @@ GeckoDriver.prototype.getElementRect = f
* Send key presses to element after focusing on it.
*
* @param {string} id
* Reference ID to the element that will be checked.
* @param {string} value
* Value to send to the element.
*/
GeckoDriver.prototype.sendKeysToElement = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let {id, value} = cmd.parameters;
assert.defined(value, `Expected character sequence: ${value}`);
switch (this.context) {
case Context.CHROME:
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
yield interaction.sendKeysToElement(
el, value, true, this.a11yChecks);
break;
case Context.CONTENT:
yield this.listener.sendKeysToElement(id, value);
break;
}
};
/** Sets the test name. The test name is used for logging purposes. */
GeckoDriver.prototype.setTestName = function*(cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
let val = cmd.parameters.value;
this.testName = val;
yield this.listener.setTestName({value: val});
};
/**
* Clear the text of an element.
*
* @param {string} id
* Reference ID to the element that will be cleared.
*/
GeckoDriver.prototype.clearElement = function*(cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let id = cmd.parameters.id;
switch (this.context) {
case Context.CHROME:
// the selenium atom doesn't work here
- let win = this.getCurrentWindow();
let el = this.curBrowser.seenEls.get(id, {frame: win});
if (el.nodeName == "textbox") {
el.value = "";
} else if (el.nodeName == "checkbox") {
el.checked = false;
}
break;
@@ -2070,25 +2135,27 @@ GeckoDriver.prototype.clearElement = fun
/**
* Switch to shadow root of the given host element.
*
* @param {string} id element id.
*/
GeckoDriver.prototype.switchToShadowRoot = function*(cmd, resp) {
assert.content(this.context)
+ assert.window(this.getCurrentWindow());
let id;
if (cmd.parameters) { id = cmd.parameters.id; }
yield this.listener.switchToShadowRoot(id);
};
/** Add a cookie to the document. */
GeckoDriver.prototype.addCookie = function*(cmd, resp) {
assert.content(this.context)
+ assert.window(this.getCurrentWindow());
let cb = msg => {
this.mm.removeMessageListener("Marionette:addCookie", cb);
let cookie = msg.json;
Services.cookies.add(
cookie.domain,
cookie.path,
cookie.name,
@@ -2108,23 +2175,25 @@ GeckoDriver.prototype.addCookie = functi
/**
* Get all the cookies for the current domain.
*
* This is the equivalent of calling {@code document.cookie} and parsing
* the result.
*/
GeckoDriver.prototype.getCookies = function*(cmd, resp) {
assert.content(this.context)
+ assert.window(this.getCurrentWindow());
resp.body = yield this.listener.getCookies();
};
/** Delete all cookies that are visible to a document. */
GeckoDriver.prototype.deleteAllCookies = function*(cmd, resp) {
assert.content(this.context)
+ assert.window(this.getCurrentWindow());
let cb = msg => {
let cookie = msg.json;
cookieManager.remove(
cookie.host,
cookie.name,
cookie.path,
false,
@@ -2135,16 +2204,17 @@ GeckoDriver.prototype.deleteAllCookies =
this.mm.addMessageListener("Marionette:deleteCookie", cb);
yield this.listener.deleteAllCookies();
this.mm.removeMessageListener("Marionette:deleteCookie", cb);
};
/** Delete a cookie by name. */
GeckoDriver.prototype.deleteCookie = function*(cmd, resp) {
assert.content(this.context)
+ assert.window(this.getCurrentWindow());
let cb = msg => {
this.mm.removeMessageListener("Marionette:deleteCookie", cb);
let cookie = msg.json;
cookieManager.remove(
cookie.host,
cookie.name,
cookie.path,
@@ -2164,19 +2234,21 @@ GeckoDriver.prototype.deleteCookie = fun
* Otherwise the window itself will be closed. If it is the last window
* currently open, the window will not be closed to prevent a shutdown of the
* application. Instead the returned list of window handles is empty.
*
* @return {Array.<string>}
* Unique window handles of remaining windows.
*/
GeckoDriver.prototype.close = function (cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
let nwins = 0;
+
let winEn = Services.wm.getEnumerator(null);
-
while (winEn.hasMoreElements()) {
let win = winEn.getNext();
// For browser windows count the tabs. Otherwise take the window itself.
let tabbrowser = browser.getTabBrowser(win);
if (tabbrowser) {
nwins += tabbrowser.tabs.length;
} else {
@@ -2205,21 +2277,21 @@ GeckoDriver.prototype.close = function (
* closed to prevent a shutdown of the application. Instead the returned
* list of chrome window handles is empty.
*
* @return {Array.<string>}
* Unique chrome window handles of remaining chrome windows.
*/
GeckoDriver.prototype.closeChromeWindow = function (cmd, resp) {
assert.firefox();
-
- // Get the total number of windows
+ assert.window(this.getCurrentWindow(Context.CHROME));
+
let nwins = 0;
+
let winEn = Services.wm.getEnumerator(null);
-
while (winEn.hasMoreElements()) {
nwins++;
winEn.getNext();
}
// If there is only 1 window left, do not close it. Instead return a faked
// empty array of window handles. This will instruct geckodriver to terminate
// the application.
@@ -2290,16 +2362,18 @@ GeckoDriver.prototype.deleteSession = fu
cert.uninstallOverride();
this.sessionId = null;
this.capabilities = new session.Capabilities();
};
/** Returns the current status of the Application Cache. */
GeckoDriver.prototype.getAppCacheStatus = function* (cmd, resp) {
+ assert.window(this.getCurrentWindow());
+
switch (this.context) {
case Context.CHROME:
throw new UnsupportedOperationError(
"Command 'getAppCacheStatus' is not yet available in chrome context");
case Context.CONTENT:
resp.body.value = yield this.listener.getAppCacheStatus();
break;
@@ -2362,26 +2436,25 @@ GeckoDriver.prototype.clearImportedScrip
* scroll to the element.
*
* @return {string}
* If {@code hash} is false, PNG image encoded as base64 encoded string. If
* 'hash' is True, hex digest of the SHA-256 hash of the base64 encoded
* string.
*/
GeckoDriver.prototype.takeScreenshot = function (cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
+
let {id, highlights, full, hash, scroll} = cmd.parameters;
highlights = highlights || [];
let format = hash ? capture.Format.Hash : capture.Format.Base64;
switch (this.context) {
case Context.CHROME:
- let container = {frame: this.getCurrentWindow().document.defaultView};
- if (!container.frame) {
- throw new NoSuchWindowError("Unable to locate window");
- }
+ let container = {frame: win.document.defaultView};
let highlightEls = highlights.map(
ref => this.curBrowser.seenEls.get(ref, container));
// viewport
let canvas;
if (!id && !full) {
canvas = capture.viewport(container.frame, highlightEls);
@@ -2416,62 +2489,63 @@ GeckoDriver.prototype.takeScreenshot = f
* Get the current browser orientation.
*
* Will return one of the valid primary orientation values
* portrait-primary, landscape-primary, portrait-secondary, or
* landscape-secondary.
*/
GeckoDriver.prototype.getScreenOrientation = function (cmd, resp) {
assert.fennec();
-
- resp.body.value = this.getCurrentWindow().screen.mozOrientation;
+ let win = assert.window(this.getCurrentWindow());
+
+ resp.body.value = win.screen.mozOrientation;
};
/**
* Set the current browser orientation.
*
* The supplied orientation should be given as one of the valid
* orientation values. If the orientation is unknown, an error will
* be raised.
*
* Valid orientations are "portrait" and "landscape", which fall
* back to "portrait-primary" and "landscape-primary" respectively,
* and "portrait-secondary" as well as "landscape-secondary".
*/
GeckoDriver.prototype.setScreenOrientation = function (cmd, resp) {
assert.fennec();
+ let win = assert.window(this.getCurrentWindow());
const ors = [
"portrait", "landscape",
"portrait-primary", "landscape-primary",
"portrait-secondary", "landscape-secondary",
];
let or = String(cmd.parameters.orientation);
assert.string(or);
let mozOr = or.toLowerCase();
if (!ors.includes(mozOr)) {
throw new InvalidArgumentError(`Unknown screen orientation: ${or}`);
}
- let win = this.getCurrentWindow();
if (!win.screen.mozLockOrientation(mozOr)) {
throw new WebDriverError(`Unable to set screen orientation: ${or}`);
}
};
/**
* Get the size of the browser window currently in focus.
*
* Will return the current browser window size in pixels. Refers to
* window outerWidth and outerHeight values, which include scroll bars,
* title bars, etc.
*/
GeckoDriver.prototype.getWindowSize = function (cmd, resp) {
- let win = this.getCurrentWindow();
+ let win = assert.window(this.getCurrentWindow());
return {
width: win.outerWidth,
height: win.outerHeight,
};
};
/**
* Set the size of the browser window currently in focus.
@@ -2485,19 +2559,19 @@ GeckoDriver.prototype.getWindowSize = fu
* @param {number} height
* Requested window outer height.
*
* @return {Map.<string, number>}
* New outerWidth/outerHeight dimensions.
*/
GeckoDriver.prototype.setWindowSize = function* (cmd, resp) {
assert.firefox()
+ let win = assert.window(this.getCurrentWindow());
const {width, height} = cmd.parameters;
- const win = this.getCurrentWindow();
yield new Promise(resolve => {
// When the DOM resize event claims that it fires _after_ the document
// view has been resized, it is lying.
//
// Because resize events fire at a high rate, DOM modifications
// such as updates to outerWidth/outerHeight are not guaranteed to
// have processed. To overcome this... abomination... of the web
@@ -2519,77 +2593,80 @@ GeckoDriver.prototype.setWindowSize = fu
/**
* Maximizes the user agent window as if the user pressed the maximise
* button.
*
* Not Supported on B2G or Fennec.
*/
GeckoDriver.prototype.maximizeWindow = function (cmd, resp) {
assert.firefox()
-
- let win = this.getCurrentWindow();
+ let win = assert.window(this.getCurrentWindow());
+
win.maximize()
};
/**
* Dismisses a currently displayed tab modal, or returns no such alert if
* no modal is displayed.
*/
GeckoDriver.prototype.dismissDialog = function (cmd, resp) {
+ assert.window(this.getCurrentWindow());
this._checkIfAlertIsPresent();
let {button0, button1} = this.dialog.ui;
(button1 ? button1 : button0).click();
this.dialog = null;
};
/**
* Accepts a currently displayed tab modal, or returns no such alert if
* no modal is displayed.
*/
GeckoDriver.prototype.acceptDialog = function (cmd, resp) {
+ assert.window(this.getCurrentWindow());
this._checkIfAlertIsPresent();
let {button0} = this.dialog.ui;
button0.click();
this.dialog = null;
};
/**
* Returns the message shown in a currently displayed modal, or returns a no such
* alert error if no modal is currently displayed.
*/
GeckoDriver.prototype.getTextFromDialog = function (cmd, resp) {
+ assert.window(this.getCurrentWindow());
this._checkIfAlertIsPresent();
let {infoBody} = this.dialog.ui;
resp.body.value = infoBody.textContent;
};
/**
* Sends keys to the input field of a currently displayed modal, or
* returns a no such alert error if no modal is currently displayed. If
* a tab modal is currently displayed but has no means for text input,
* an element not visible error is returned.
*/
GeckoDriver.prototype.sendKeysToDialog = function (cmd, resp) {
+ let win = assert.window(this.getCurrentWindow());
this._checkIfAlertIsPresent();
// see toolkit/components/prompts/content/commonDialog.js
let {loginContainer, loginTextbox} = this.dialog.ui;
if (loginContainer.hidden) {
throw new ElementNotVisibleError("This prompt does not accept text input");
}
- let win = this.dialog.window ? this.dialog.window : this.getCurrentWindow();
event.sendKeysToElement(
cmd.parameters.value,
loginTextbox,
{ignoreVisibility: true},
- win);
+ this.dialog.window ? this.dialog.window : win);
};
GeckoDriver.prototype._checkIfAlertIsPresent = function() {
if (!this.dialog || !this.dialog.ui) {
throw new NoAlertOpenError(
"No tab modal was open when attempting to get the dialog text");
}
};
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_click_chrome.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_click_chrome.py
@@ -1,34 +1,39 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_driver.by import By
-from marionette_harness import MarionetteTestCase
+from marionette_harness import MarionetteTestCase, WindowManagerMixin
-class TestClickChrome(MarionetteTestCase):
+class TestClickChrome(WindowManagerMixin, MarionetteTestCase):
+
def setUp(self):
- MarionetteTestCase.setUp(self)
- self.root_window = self.marionette.current_window_handle
+ super(TestClickChrome, self).setUp()
+
self.marionette.set_context("chrome")
- self.marionette.execute_script(
- "window.open('chrome://marionette/content/test.xul', 'foo', 'chrome,centerscreen')")
- self.marionette.switch_to_window("foo")
- self.assertNotEqual(self.root_window, self.marionette.current_window_handle)
def tearDown(self):
- self.assertNotEqual(self.root_window, self.marionette.current_window_handle)
- self.marionette.execute_script("window.close()")
- self.marionette.switch_to_window(self.root_window)
- MarionetteTestCase.tearDown(self)
+ self.close_all_windows()
+
+ super(TestClickChrome, self).tearDown()
def test_click(self):
+
+ def open_with_js():
+ self.marionette.execute_script("""
+ window.open('chrome://marionette/content/test.xul',
+ 'foo', 'chrome,centerscreen'); """)
+
+ win = self.open_window(open_with_js)
+ self.marionette.switch_to_window(win)
+
def checked():
return self.marionette.execute_script(
"return arguments[0].checked",
script_args=[box])
box = self.marionette.find_element(By.ID, "testBox")
self.assertFalse(checked())
box.click()
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_element_state_chrome.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_element_state_chrome.py
@@ -1,85 +1,58 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_driver.by import By
-from marionette_harness import MarionetteTestCase, skip
+from marionette_harness import MarionetteTestCase, skip, WindowManagerMixin
-class TestIsElementEnabledChrome(MarionetteTestCase):
+class TestElementState(WindowManagerMixin, MarionetteTestCase):
+
def setUp(self):
- MarionetteTestCase.setUp(self)
+ super(TestElementState, self).setUp()
+
self.marionette.set_context("chrome")
- self.win = self.marionette.current_window_handle
- self.marionette.execute_script("window.open('chrome://marionette/content/test.xul', 'foo', 'chrome,centerscreen');")
- self.marionette.switch_to_window('foo')
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
+
+ def open_window_with_js():
+ self.marionette.execute_script("""
+ window.open('chrome://marionette/content/test.xul',
+ 'foo', 'chrome,centerscreen');
+ """)
+
+ self.win = self.open_window(open_window_with_js)
+ self.marionette.switch_to_window(self.win)
def tearDown(self):
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
- self.marionette.execute_script("window.close();")
- self.marionette.switch_to_window(self.win)
- MarionetteTestCase.tearDown(self)
+ self.close_all_windows()
+
+ super(TestElementState, self).tearDown()
+
+ @skip("Switched off in bug 896043, and to be turned on in bug 896046")
+ def test_is_displayed(self):
+ l = self.marionette.find_element(By.ID, "textInput")
+ self.assertTrue(l.is_displayed())
+ self.marionette.execute_script("arguments[0].hidden = true;", [l])
+ self.assertFalse(l.is_displayed())
+ self.marionette.execute_script("arguments[0].hidden = false;", [l])
def test_enabled(self):
l = self.marionette.find_element(By.ID, "textInput")
self.assertTrue(l.is_enabled())
self.marionette.execute_script("arguments[0].disabled = true;", [l])
self.assertFalse(l.is_enabled())
self.marionette.execute_script("arguments[0].disabled = false;", [l])
def test_can_get_element_rect(self):
l = self.marionette.find_element(By.ID, "textInput")
rect = l.rect
self.assertTrue(rect['x'] > 0)
self.assertTrue(rect['y'] > 0)
-
-@skip("Switched off in bug 896043, and to be turned on in bug 896046")
-class TestIsElementDisplayed(MarionetteTestCase):
- def test_isDisplayed(self):
- l = self.marionette.find_element(By.ID, "textInput")
- self.assertTrue(l.is_displayed())
- self.marionette.execute_script("arguments[0].hidden = true;", [l])
- self.assertFalse(l.is_displayed())
- self.marionette.execute_script("arguments[0].hidden = false;", [l])
-
-
-class TestGetElementAttributeChrome(MarionetteTestCase):
- def setUp(self):
- MarionetteTestCase.setUp(self)
- self.marionette.set_context("chrome")
- self.win = self.marionette.current_window_handle
- self.marionette.execute_script("window.open('chrome://marionette/content/test.xul', 'foo', 'chrome,centerscreen');")
- self.marionette.switch_to_window('foo')
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
-
- def tearDown(self):
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
- self.marionette.execute_script("window.close();")
- self.marionette.switch_to_window(self.win)
- MarionetteTestCase.tearDown(self)
-
- def test_get(self):
+ def test_get_attribute(self):
el = self.marionette.execute_script("return window.document.getElementById('textInput');")
self.assertEqual(el.get_attribute("id"), "textInput")
-class TestGetElementProperty(MarionetteTestCase):
- def setUp(self):
- MarionetteTestCase.setUp(self)
- self.marionette.set_context("chrome")
- self.win = self.marionette.current_window_handle
- self.marionette.execute_script("window.open('chrome://marionette/content/test.xul', 'foo', 'chrome,centerscreen');")
- self.marionette.switch_to_window('foo')
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
-
- def tearDown(self):
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
- self.marionette.execute_script("window.close();")
- self.marionette.switch_to_window(self.win)
- MarionetteTestCase.tearDown(self)
-
- def test_get(self):
+ def test_get_property(self):
el = self.marionette.execute_script("return window.document.getElementById('textInput');")
self.assertEqual(el.get_property("id"), "textInput")
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_execute_script.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_execute_script.py
@@ -309,35 +309,16 @@ class TestExecuteChrome(WindowManagerMix
def test_async_script_timeout(self):
with self.assertRaises(errors.ScriptTimeoutException):
self.marionette.execute_async_script("""
var cb = arguments[arguments.length - 1];
setTimeout(function() { cb() }, 250);
""", script_timeout=100)
- @skip_if_mobile("New windows not supported in Fennec")
- def test_invalid_chrome_handle(self):
- try:
- win = self.open_window()
- self.marionette.switch_to_window(win)
-
- # Close new window and don't switch back to the original one
- self.marionette.close_chrome_window()
- self.assertNotEqual(self.start_window, win)
-
- # Call execute_script on an invalid chrome handle
- with self.marionette.using_context('chrome'):
- self.marionette.execute_script("""
- return true;
- """)
-
- finally:
- self.close_all_windows()
-
def test_lasting_side_effects(self):
pass
def test_return_web_element(self):
pass
def test_return_web_element_array(self):
pass
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_findelement_chrome.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_findelement_chrome.py
@@ -1,33 +1,39 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_driver.by import By
from marionette_driver.errors import NoSuchElementException
from marionette_driver.marionette import HTMLElement
-from marionette_harness import MarionetteTestCase
+from marionette_harness import MarionetteTestCase, WindowManagerMixin
-class TestElementsChrome(MarionetteTestCase):
+class TestElementsChrome(WindowManagerMixin, MarionetteTestCase):
+
def setUp(self):
- MarionetteTestCase.setUp(self)
+ super(TestElementsChrome, self).setUp()
+
self.marionette.set_context("chrome")
- self.win = self.marionette.current_window_handle
- self.marionette.execute_script("window.open('chrome://marionette/content/test.xul', 'foo', 'chrome,centerscreen');")
- self.marionette.switch_to_window('foo')
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
+
+ def open_window_with_js():
+ self.marionette.execute_script("""
+ window.open('chrome://marionette/content/test.xul',
+ 'foo', 'chrome,centerscreen');
+ """)
+
+ win = self.open_window(open_window_with_js)
+ self.marionette.switch_to_window(win)
def tearDown(self):
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
- self.marionette.execute_script("window.close();")
- self.marionette.switch_to_window(self.win)
- MarionetteTestCase.tearDown(self)
+ self.close_all_windows()
+
+ super(TestElementsChrome, self).tearDown()
def test_id(self):
el = self.marionette.execute_script("return window.document.getElementById('textInput');")
found_el = self.marionette.find_element(By.ID, "textInput")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_that_we_can_find_elements_from_css_selectors(self):
@@ -45,38 +51,49 @@ class TestElementsChrome(MarionetteTestC
def test_child_elements(self):
el = self.marionette.find_element(By.ID, "textInput3")
parent = self.marionette.find_element(By.ID, "things")
found_els = parent.find_elements(By.TAG_NAME, "textbox")
self.assertTrue(el.id in [found_el.id for found_el in found_els])
def test_tag_name(self):
- el = self.marionette.execute_script("return window.document.getElementsByTagName('vbox')[0];")
+ el = self.marionette.execute_script(
+ "return window.document.getElementsByTagName('vbox')[0];")
found_el = self.marionette.find_element(By.TAG_NAME, "vbox")
self.assertEquals('vbox', found_el.tag_name)
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_class_name(self):
- el = self.marionette.execute_script("return window.document.getElementsByClassName('asdf')[0];")
+ el = self.marionette.execute_script(
+ "return window.document.getElementsByClassName('asdf')[0];")
found_el = self.marionette.find_element(By.CLASS_NAME, "asdf")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_xpath(self):
el = self.marionette.execute_script("return window.document.getElementById('testBox');")
found_el = self.marionette.find_element(By.XPATH, "id('testBox')")
self.assertEqual(HTMLElement, type(found_el))
self.assertEqual(el, found_el)
def test_not_found(self):
self.marionette.timeout.implicit = 1
- self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "I'm not on the page")
+ self.assertRaises(NoSuchElementException,
+ self.marionette.find_element, By.ID, "I'm not on the page")
self.marionette.timeout.implicit = 0
- self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "I'm not on the page")
+ self.assertRaises(NoSuchElementException,
+ self.marionette.find_element, By.ID, "I'm not on the page")
def test_timeout(self):
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "myid")
self.marionette.timeout.implicit = 4
- self.marionette.execute_script("window.setTimeout(function() {var b = window.document.createElement('button'); b.id = 'myid'; document.getElementById('things').appendChild(b);}, 1000)")
+ self.marionette.execute_script("""
+ window.setTimeout(function () {
+ var b = window.document.createElement('button');
+ b.id = 'myid';
+ document.getElementById('things').appendChild(b);
+ }, 1000); """)
self.assertEqual(HTMLElement, type(self.marionette.find_element(By.ID, "myid")))
- self.marionette.execute_script("window.document.getElementById('things').removeChild(window.document.getElementById('myid'));")
+ self.marionette.execute_script("""
+ var elem = window.document.getElementById('things');
+ elem.removeChild(window.document.getElementById('myid')); """)
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_management.py
@@ -0,0 +1,168 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from marionette_driver import By
+from marionette_driver.errors import NoSuchWindowException
+
+from marionette_harness import MarionetteTestCase, WindowManagerMixin, skip_if_mobile
+
+
+class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
+
+ def setUp(self):
+ super(TestNoSuchWindowContent, self).setUp()
+
+ def tearDown(self):
+ self.close_all_windows()
+ super(TestNoSuchWindowContent, self).tearDown()
+
+ @skip_if_mobile("Fennec doesn't support other chrome windows")
+ def test_closed_chrome_window(self):
+
+ def open_with_link():
+ with self.marionette.using_context("content"):
+ test_page = self.marionette.absolute_url("windowHandles.html")
+ self.marionette.navigate(test_page)
+ self.marionette.find_element(By.ID, "new-window").click()
+
+ win = self.open_window(open_with_link)
+ self.marionette.switch_to_window(win)
+ self.marionette.close_chrome_window()
+
+ # When closing a browser window both handles are not available
+ for context in ("chrome", "content"):
+ with self.marionette.using_context(context):
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_chrome_window_handle
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+
+ self.marionette.switch_to_window(self.start_window)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(win)
+
+ @skip_if_mobile("Fennec doesn't support other chrome windows")
+ def test_closed_chrome_window_while_in_frame(self):
+
+ def open_window_with_js():
+ with self.marionette.using_context("chrome"):
+ self.marionette.execute_script("""
+ window.open('chrome://marionette/content/test.xul',
+ 'foo', 'chrome,centerscreen');
+ """)
+
+ win = self.open_window(trigger=open_window_with_js)
+ self.marionette.switch_to_window(win)
+ with self.marionette.using_context("chrome"):
+ self.marionette.switch_to_frame("iframe")
+ self.marionette.close_chrome_window()
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_chrome_window_handle
+
+ self.marionette.switch_to_window(self.start_window)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(win)
+
+ def test_closed_tab(self):
+ with self.marionette.using_context("content"):
+ tab = self.open_tab()
+ self.marionette.switch_to_window(tab)
+ self.marionette.close()
+
+ # Check that only the content window is not available in both contexts
+ for context in ("chrome", "content"):
+ with self.marionette.using_context(context):
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+ self.marionette.current_chrome_window_handle
+
+ self.marionette.switch_to_window(self.start_tab)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(tab)
+
+ def test_closed_tab_while_in_frame(self):
+ with self.marionette.using_context("content"):
+ tab = self.open_tab()
+ self.marionette.switch_to_window(tab)
+ self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
+ frame = self.marionette.find_element(By.ID, "test_iframe")
+ self.marionette.switch_to_frame(frame)
+ self.marionette.close()
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+ self.marionette.current_chrome_window_handle
+
+ self.marionette.switch_to_window(self.start_tab)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(tab)
+
+
+class TestNoSuchWindowChrome(TestNoSuchWindowContent):
+
+ def setUp(self):
+ super(TestNoSuchWindowChrome, self).setUp()
+ self.marionette.set_context("chrome")
+
+ def tearDown(self):
+ self.close_all_windows()
+ super(TestNoSuchWindowChrome, self).tearDown()
+
+
+class TestSwitchWindow(WindowManagerMixin, MarionetteTestCase):
+
+ def setUp(self):
+ super(TestSwitchWindow, self).setUp()
+ self.marionette.set_context("chrome")
+
+ def tearDown(self):
+ self.close_all_windows()
+ super(TestSwitchWindow, self).tearDown()
+
+ def test_windows(self):
+ def open_browser_with_js():
+ self.marionette.execute_script(" window.open(); ")
+
+ new_window = self.open_window(trigger=open_browser_with_js)
+ self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
+
+ # switch to the other window
+ self.marionette.switch_to_window(new_window)
+ self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
+ self.assertNotEqual(self.marionette.current_chrome_window_handle, self.start_window)
+
+ # switch back and close original window
+ self.marionette.switch_to_window(self.start_window)
+ self.assertEqual(self.marionette.current_chrome_window_handle, self.start_window)
+ self.marionette.close_chrome_window()
+
+ self.assertNotIn(self.start_window, self.marionette.chrome_window_handles)
+ self.assertEqual(len(self.marionette.chrome_window_handles), len(self.start_windows))
+
+ def test_should_load_and_close_a_window(self):
+ def open_window_with_link():
+ test_html = self.marionette.absolute_url("test_windows.html")
+ with self.marionette.using_context("content"):
+ self.marionette.navigate(test_html)
+ self.marionette.find_element(By.LINK_TEXT, "Open new window").click()
+
+ new_window = self.open_window(trigger=open_window_with_link)
+ self.marionette.switch_to_window(new_window)
+ self.assertEqual(self.marionette.current_chrome_window_handle, new_window)
+ self.assertEqual(len(self.marionette.chrome_window_handles), 2)
+
+ with self.marionette.using_context('content'):
+ self.assertEqual(self.marionette.title, "We Arrive Here")
+
+ # Let's close and check
+ self.marionette.close_chrome_window()
+ self.marionette.switch_to_window(self.start_window)
+ self.assertEqual(len(self.marionette.chrome_window_handles), 1)
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_status_chrome.py
@@ -0,0 +1,24 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import sys
+
+# add this directory to the path
+sys.path.append(os.path.dirname(__file__))
+
+from test_window_status_content import TestNoSuchWindowContent
+
+
+class TestNoSuchWindowChrome(TestNoSuchWindowContent):
+
+ def setUp(self):
+ super(TestNoSuchWindowChrome, self).setUp()
+
+ self.marionette.set_context("chrome")
+
+ def tearDown(self):
+ self.close_all_windows()
+
+ super(TestNoSuchWindowChrome, self).tearDown()
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_status_content.py
@@ -0,0 +1,115 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from marionette_driver import By
+from marionette_driver.errors import NoSuchWindowException
+
+from marionette_harness import MarionetteTestCase, WindowManagerMixin, skip_if_mobile
+
+
+class TestNoSuchWindowContent(WindowManagerMixin, MarionetteTestCase):
+
+ def setUp(self):
+ super(TestNoSuchWindowContent, self).setUp()
+
+ self.test_page = self.marionette.absolute_url("windowHandles.html")
+ with self.marionette.using_context("content"):
+ self.marionette.navigate(self.test_page)
+
+ def tearDown(self):
+ self.close_all_windows()
+ super(TestNoSuchWindowContent, self).tearDown()
+
+ def open_tab_in_foreground(self):
+ with self.marionette.using_context("content"):
+ link = self.marionette.find_element(By.ID, "new-tab")
+ link.click()
+
+ @skip_if_mobile("Fennec doesn't support other chrome windows")
+ def test_closed_chrome_window(self):
+
+ def open_with_link():
+ with self.marionette.using_context("content"):
+ test_page = self.marionette.absolute_url("windowHandles.html")
+ self.marionette.navigate(test_page)
+ self.marionette.find_element(By.ID, "new-window").click()
+
+ win = self.open_window(open_with_link)
+ self.marionette.switch_to_window(win)
+ self.marionette.close_chrome_window()
+
+ # When closing a browser window both handles are not available
+ for context in ("chrome", "content"):
+ with self.marionette.using_context(context):
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_chrome_window_handle
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+
+ self.marionette.switch_to_window(self.start_window)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(win)
+
+ @skip_if_mobile("Fennec doesn't support other chrome windows")
+ def test_closed_chrome_window_while_in_frame(self):
+
+ def open_window_with_js():
+ with self.marionette.using_context("chrome"):
+ self.marionette.execute_script("""
+ window.open('chrome://marionette/content/test.xul',
+ 'foo', 'chrome,centerscreen');
+ """)
+
+ win = self.open_window(trigger=open_window_with_js)
+ self.marionette.switch_to_window(win)
+ with self.marionette.using_context("chrome"):
+ self.marionette.switch_to_frame("iframe")
+ self.marionette.close_chrome_window()
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_chrome_window_handle
+
+ self.marionette.switch_to_window(self.start_window)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(win)
+
+ def test_closed_tab(self):
+ with self.marionette.using_context("content"):
+ tab = self.open_tab(self.open_tab_in_foreground)
+ self.marionette.switch_to_window(tab)
+ self.marionette.close()
+
+ # Check that only the content window is not available in both contexts
+ for context in ("chrome", "content"):
+ with self.marionette.using_context(context):
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+ self.marionette.current_chrome_window_handle
+
+ self.marionette.switch_to_window(self.start_tab)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(tab)
+
+ def test_closed_tab_while_in_frame(self):
+ with self.marionette.using_context("content"):
+ tab = self.open_tab(self.open_tab_in_foreground)
+ self.marionette.switch_to_window(tab)
+ self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
+ frame = self.marionette.find_element(By.ID, "test_iframe")
+ self.marionette.switch_to_frame(frame)
+ self.marionette.close()
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.current_window_handle
+ self.marionette.current_chrome_window_handle
+
+ self.marionette.switch_to_window(self.start_tab)
+
+ with self.assertRaises(NoSuchWindowException):
+ self.marionette.switch_to_window(tab)
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_window_title_chrome.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_title_chrome.py
@@ -1,26 +1,33 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-from marionette_harness import MarionetteTestCase
+from marionette_harness import MarionetteTestCase, WindowManagerMixin
-class TestTitleChrome(MarionetteTestCase):
+class TestTitleChrome(WindowManagerMixin, MarionetteTestCase):
+
def setUp(self):
- MarionetteTestCase.setUp(self)
+ super(TestTitleChrome, self).setUp()
+
self.marionette.set_context("chrome")
- self.win = self.marionette.current_window_handle
- self.marionette.execute_script("window.open('chrome://marionette/content/test.xul', 'foo', 'chrome,centerscreen');")
- self.marionette.switch_to_window('foo')
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
def tearDown(self):
- self.assertNotEqual(self.win, self.marionette.current_window_handle)
- self.marionette.execute_script("window.close();")
- self.marionette.switch_to_window(self.win)
- MarionetteTestCase.tearDown(self)
+ self.close_all_windows()
+
+ super(TestTitleChrome, self).tearDown()
def test_get_chrome_title(self):
- title = self.marionette.execute_script("return window.document.documentElement.getAttribute('title');")
+
+ def open_window_with_js():
+ self.marionette.execute_script("""
+ window.open('chrome://marionette/content/test.xul',
+ 'foo', 'chrome,centerscreen');
+ """)
+
+ win = self.open_window(open_window_with_js)
+ self.marionette.switch_to_window(win)
+
+ title = self.marionette.execute_script(
+ "return window.document.documentElement.getAttribute('title');")
self.assertEqual(title, self.marionette.title)
- self.assertEqual('Title Test', self.marionette.title)
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_type_chrome.py
@@ -0,0 +1,33 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from marionette_harness import MarionetteTestCase, WindowManagerMixin
+
+
+class TestWindowTypeChrome(WindowManagerMixin, MarionetteTestCase):
+
+ def setUp(self):
+ super(TestWindowTypeChrome, self).setUp()
+
+ self.marionette.set_context("chrome")
+
+ def tearDown(self):
+ self.close_all_windows()
+
+ super(TestWindowTypeChrome, self).tearDown()
+
+ def test_get_window_type(self):
+
+ def open_window_with_js():
+ self.marionette.execute_script("""
+ window.open('chrome://marionette/content/test.xul',
+ 'foo', 'chrome,centerscreen');
+ """)
+
+ win = self.open_window(open_window_with_js)
+ self.marionette.switch_to_window(win)
+
+ window_type = self.marionette.execute_script(
+ "return window.document.documentElement.getAttribute('windowtype');")
+ self.assertEqual(window_type, self.marionette.get_window_type())
--- a/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini
+++ b/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini
@@ -71,23 +71,25 @@ skip-if = appname == 'fennec'
[test_window_handles_chrome.py]
skip-if = appname == 'fennec'
[test_window_handles_content.py]
[test_window_close_chrome.py]
skip-if = appname == 'fennec'
[test_window_close_content.py]
[test_window_position.py]
skip-if = appname == 'fennec'
+[test_window_status_content.py]
+[test_window_status_chrome.py]
[test_screenshot.py]
[test_cookies.py]
[test_window_title.py]
[test_window_title_chrome.py]
skip-if = appname == 'fennec'
-[test_window_type.py]
+[test_window_type_chrome.py]
skip-if = appname == 'fennec'
[test_implicit_waits.py]
[test_wait.py]
[test_expected.py]
[test_date_time_value.py]
[test_getactiveframe_oop.py]
skip-if = true # Bug 925688
[test_chrome_async_finish.js]