Bug 1359004 - Add preliminary support for unexpected alerts r=whimboo

Add preliminary support for returning unexpected alert open errors when
calling commands that require it according to the WebDriver standard.

Also fixes a faulty test that seems to believe it is fine to click an
element whilst an alert is present.

Further work needs to be done on user prompts, asserts, and the handler
for user prompts in https://bugzilla.mozilla.org/show_bug.cgi?id=1264259.

MozReview-Commit-ID: BiWURoQECji

--HG--
extra : rebase_source : caa1506a0e972c7ad0da2d31993fb0b8ecc1ee17
This commit is contained in:
Andreas Tolfsen 2017-04-20 18:00:46 +01:00
Родитель 2e6b4a7440
Коммит 9d9b0dba43
5 изменённых файлов: 421 добавлений и 139 удалений

Просмотреть файл

@ -142,7 +142,24 @@ assert.window = function (win, msg = "") {
return null;
}
}, msg, NoSuchWindowError)(win);
}
};
/**
* Asserts that there is no current user prompt.
*
* @param {modal.Dialog} dialog
* Reference to current dialogue.
* @param {string=} msg
* Custom error message.
*
* @throws {UnexpectedAlertOpenError}
* If there is a user prompt.
*/
assert.noUserPrompt = function (dialog, msg = "") {
assert.that(d => d === null || typeof d == "undefined",
msg,
UnexpectedAlertOpenError)(dialog);
};
/**
* Asserts that |obj| is defined.

Просмотреть файл

@ -971,10 +971,18 @@ GeckoDriver.prototype.executeJSScript = function* (cmd, resp) {
*
* @param {string} url
* URL to navigate to.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.get = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let url = cmd.parameters.url;
@ -1009,9 +1017,15 @@ GeckoDriver.prototype.get = function* (cmd, resp) {
*
* When in the context of the chrome, this returns the canonical URL
* of the current resource.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getCurrentUrl = function (cmd) {
let win = assert.window(this.getCurrentWindow());
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
switch (this.context) {
case Context.CHROME:
@ -1022,9 +1036,20 @@ GeckoDriver.prototype.getCurrentUrl = function (cmd) {
}
};
/** Gets the current title of the window. */
/**
* Gets the current title of the window.
*
* @return {string}
* Document title of the top-level browsing context.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getTitle = function* (cmd, resp) {
let win = assert.window(this.getCurrentWindow());
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
switch (this.context) {
case Context.CHROME:
@ -1044,9 +1069,21 @@ GeckoDriver.prototype.getWindowType = function (cmd, resp) {
resp.body.value = win.document.documentElement.getAttribute("windowtype");
};
/** Gets the page source of the content document. */
/**
* Gets the page source of the content document.
*
* @return {string}
* String serialisation of the DOM of the current browsing context's
* active document.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getPageSource = function* (cmd, resp) {
let win = assert.window(this.getCurrentWindow());
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
switch (this.context) {
case Context.CHROME:
@ -1063,10 +1100,18 @@ GeckoDriver.prototype.getPageSource = function* (cmd, resp) {
/**
* Cause the browser to traverse one step backward in the joint history
* of the current browsing context.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.goBack = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
if (!this.curBrowser.tab) {
// Navigation does not work for non-browser windows
@ -1102,10 +1147,18 @@ GeckoDriver.prototype.goBack = function* (cmd, resp) {
/**
* Cause the browser to traverse one step forward in the joint history
* of the current browsing context.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.goForward = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
if (!this.curBrowser.tab) {
// Navigation does not work for non-browser windows
@ -1139,11 +1192,20 @@ GeckoDriver.prototype.goForward = function* (cmd, resp) {
};
/**
* Causes the browser to reload the page in in current top-level browsing context.
* Causes the browser to reload the page in current top-level browsing
* context.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.refresh = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
yield this.listener.refresh({pageTimeout: this.timeouts.pageLoad});
};
@ -1264,9 +1326,16 @@ GeckoDriver.prototype.getChromeWindowHandles = function (cmd, resp) {
* @return {Object.<string, number>}
* Object with |x| and |y| coordinates, and |width| and |height|
* of browser window.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getWindowRect = function (cmd, resp) {
let win = assert.window(this.getCurrentWindow());
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
return {
x: win.screenX,
y: win.screenY,
@ -1276,27 +1345,39 @@ GeckoDriver.prototype.getWindowRect = function (cmd, resp) {
};
/**
* Set the window position and size of the browser on the OS Window Manager
* Set the window position and size of the browser on the operating
* system window manager.
*
* The supplied width and height values refer to the window outerWidth
* The supplied |width| and |height| values refer to the window outerWidth
* and outerHeight values, which include browser chrome and OS-level
* window borders.
*
* @param {number} x
* X coordinate of the top/left of the window that it will be
* moved to.
* @param {number} y
* Y coordinate of the top/left of the window that it will be
* moved to.
* @param {number} width
* Width to resize the window to.
* @param {number} height
* Height to resize the window to.
*
* @return {Object.<string, number>}
* Object with |x| and |y| coordinates
* and |width| and |height| dimensions
* Object with |x| and |y| coordinates and |width| and |height|
* dimensions.
*
* @throws {UnsupportedOperationError}
* Not applicable to application.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.setWindowRect = function* (cmd, resp) {
assert.firefox()
let win = assert.window(this.getCurrentWindow());
assert.firefox();
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let {x, y, height, width} = cmd.parameters;
@ -1451,10 +1532,20 @@ GeckoDriver.prototype.getActiveFrame = function (cmd, resp) {
}
};
GeckoDriver.prototype.switchToParentFrame = function*(cmd, resp) {
/**
* Set the current browsing context for future commands to the parent
* of the current browsing context.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.switchToParentFrame = function* (cmd, resp) {
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let res = yield this.listener.switchToParentFrame();
yield this.listener.switchToParentFrame();
};
/**
@ -1465,9 +1556,15 @@ GeckoDriver.prototype.switchToParentFrame = function*(cmd, resp) {
* @param {(string|number)} id
* If element is not defined, then this holds either the id, name,
* or index of the frame to switch to.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.switchToFrame = function* (cmd, resp) {
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let {id, element, focus} = cmd.parameters;
@ -1683,35 +1780,38 @@ GeckoDriver.prototype.singleTap = function*(cmd, resp) {
* Array of objects that each represent an action sequence.
*
* @throws {UnsupportedOperationError}
* If the command is made in chrome context.
* Not yet available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.performActions = function(cmd, resp) {
GeckoDriver.prototype.performActions = function (cmd, resp) {
assert.content(this.context,
"Command 'performActions' is not yet available in chrome context");
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
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});
}
let actions = cmd.parameters.actions;
yield this.listener.performActions({"actions": actions});
};
/**
* Release all the keys and pointer buttons that are currently depressed.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.releaseActions = function(cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
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();
}
yield this.listener.releaseActions();
};
/**
@ -1723,9 +1823,17 @@ GeckoDriver.prototype.releaseActions = function(cmd, resp) {
*
* @return {number}
* Last touch ID.
*
* @throws {UnsupportedOperationError}
* Not applicable to application.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.actionChain = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let {chain, nextId} = cmd.parameters;
@ -1753,20 +1861,23 @@ GeckoDriver.prototype.actionChain = function*(cmd, resp) {
* 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.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.multiAction = function*(cmd, resp) {
GeckoDriver.prototype.multiAction = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
switch (this.context) {
case Context.CHROME:
throw new UnsupportedOperationError(
"Command 'multiAction' is not yet available in chrome context");
let {value, max_length} = cmd.parameters;
case Context.CONTENT:
this.addFrameCloseListener("multi action chain");
yield this.listener.multiAction(cmd.parameters.value, cmd.parameters.max_length);
break;
}
this.addFrameCloseListener("multi action chain");
yield this.listener.multiAction(value, max_length);
};
/**
@ -1776,9 +1887,15 @@ GeckoDriver.prototype.multiAction = function*(cmd, resp) {
* Indicates which search method to use.
* @param {string} value
* Value the client is looking for.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.findElement = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.findElement = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let strategy = cmd.parameters.using;
let expr = cmd.parameters.value;
@ -1859,19 +1976,25 @@ GeckoDriver.prototype.findElements = function*(cmd, resp) {
}
};
/** Return the active element on the page. */
GeckoDriver.prototype.getActiveElement = function*(cmd, resp) {
/**
* Return the active element on the page.
*
* @return {WebElement}
* Active element of the current browsing context's document element.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getActiveElement = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
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;
}
resp.body.value = yield this.listener.getActiveElement();
};
/**
@ -1879,9 +2002,15 @@ GeckoDriver.prototype.getActiveElement = function*(cmd, resp) {
*
* @param {string} id
* Reference ID to the element that will be clicked.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.clickElement = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.clickElement = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -1912,16 +2041,21 @@ GeckoDriver.prototype.clickElement = function*(cmd, resp) {
*
* @return {string}
* Value of the attribute.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getElementAttribute = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.getElementAttribute = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let {id, name} = cmd.parameters;
switch (this.context) {
case Context.CHROME:
let el = this.curBrowser.seenEls.get(id, {frame: win});
resp.body.value = el.getAttribute(name);
break;
@ -1941,9 +2075,15 @@ GeckoDriver.prototype.getElementAttribute = function*(cmd, resp) {
*
* @return {string}
* Value of the property.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getElementProperty = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.getElementProperty = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let {id, name} = cmd.parameters;
@ -1965,9 +2105,18 @@ GeckoDriver.prototype.getElementProperty = function*(cmd, resp) {
*
* @param {string} id
* Reference ID to the element that will be inspected.
*
* @return {string}
* Element's text "as rendered".
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getElementText = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.getElementText = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -1991,9 +2140,18 @@ GeckoDriver.prototype.getElementText = function*(cmd, resp) {
*
* @param {string} id
* Reference ID to the element that will be inspected.
*
* @return {string}
* Local tag name of element.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getElementTagName = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.getElementTagName = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -2014,9 +2172,18 @@ GeckoDriver.prototype.getElementTagName = function*(cmd, resp) {
*
* @param {string} id
* Reference ID to the element that will be inspected.
*
* @return {boolean}
* True if displayed, false otherwise.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.isElementDisplayed = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.isElementDisplayed = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -2040,9 +2207,18 @@ GeckoDriver.prototype.isElementDisplayed = function*(cmd, resp) {
* Reference ID to the element that will be checked.
* @param {string} propertyName
* CSS rule that is being requested.
*
* @return {string}
* Value of |propertyName|.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getElementValueOfCssProperty = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.getElementValueOfCssProperty = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let {id, propertyName: prop} = cmd.parameters;
@ -2064,9 +2240,18 @@ GeckoDriver.prototype.getElementValueOfCssProperty = function*(cmd, resp) {
*
* @param {string} id
* Reference ID to the element that will be checked.
*
* @return {boolean}
* True if enabled, false if disabled.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.isElementEnabled = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.isElementEnabled = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -2082,16 +2267,25 @@ GeckoDriver.prototype.isElementEnabled = function*(cmd, resp) {
resp.body.value = yield this.listener.isElementEnabled(id);
break;
}
},
};
/**
* Check if element is selected.
*
* @param {string} id
* Reference ID to the element that will be checked.
*
* @return {boolean}
* True if selected, false if unselected.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.isElementSelected = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.isElementSelected = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -2109,8 +2303,15 @@ GeckoDriver.prototype.isElementSelected = function*(cmd, resp) {
}
};
GeckoDriver.prototype.getElementRect = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
/**
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getElementRect = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -2139,9 +2340,16 @@ GeckoDriver.prototype.getElementRect = function*(cmd, resp) {
* Reference ID to the element that will be checked.
* @param {string} value
* Value to send to the element.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.sendKeysToElement = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.sendKeysToElement = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let {id, text} = cmd.parameters;
assert.string(text);
@ -2172,9 +2380,15 @@ GeckoDriver.prototype.setTestName = function*(cmd, resp) {
*
* @param {string} id
* Reference ID to the element that will be cleared.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.clearElement = function*(cmd, resp) {
let win = assert.window(this.getCurrentWindow());
GeckoDriver.prototype.clearElement = function* (cmd, resp) {
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let id = cmd.parameters.id;
@ -2200,19 +2414,28 @@ GeckoDriver.prototype.clearElement = function*(cmd, resp) {
*
* @param {string} id element id.
*/
GeckoDriver.prototype.switchToShadowRoot = function*(cmd, resp) {
assert.content(this.context)
GeckoDriver.prototype.switchToShadowRoot = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
let id;
if (cmd.parameters) { id = cmd.parameters.id; }
let 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)
/**
* Add a cookie to the document.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.addCookie = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let cb = msg => {
this.mm.removeMessageListener("Marionette:addCookie", cb);
@ -2239,18 +2462,36 @@ GeckoDriver.prototype.addCookie = function*(cmd, resp) {
*
* This is the equivalent of calling {@code document.cookie} and parsing
* the result.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.getCookies = function*(cmd, resp) {
assert.content(this.context)
GeckoDriver.prototype.getCookies = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
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)
/**
* Delete all cookies that are visible to a document.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.deleteAllCookies = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let cb = msg => {
let cookie = msg.json;
@ -2268,10 +2509,20 @@ GeckoDriver.prototype.deleteAllCookies = function*(cmd, resp) {
this.mm.removeMessageListener("Marionette:deleteCookie", cb);
};
/** Delete a cookie by name. */
GeckoDriver.prototype.deleteCookie = function*(cmd, resp) {
assert.content(this.context)
/**
* Delete a cookie by name.
*
* @throws {UnsupportedOperationError}
* Not available in current context.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.deleteCookie = function* (cmd, resp) {
assert.content(this.context);
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let cb = msg => {
this.mm.removeMessageListener("Marionette:deleteCookie", cb);
@ -2292,16 +2543,23 @@ GeckoDriver.prototype.deleteCookie = function*(cmd, resp) {
/**
* Close the currently selected tab/window.
*
* With multiple open tabs present the currently selected tab will be closed.
* 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.
* With multiple open tabs present the currently selected tab will
* be closed. 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.
*
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.close = function (cmd, resp) {
assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
let nwins = 0;
@ -2600,11 +2858,17 @@ GeckoDriver.prototype.setScreenOrientation = function (cmd, resp) {
* Maximizes the user agent window as if the user pressed the maximise
* button.
*
* Not Supported on B2G or Fennec.
* @throws {UnsupportedOperationError}
* Not available for current application.
* @throws {NoSuchWindowError}
* Top-level browsing context has been discarded.
* @throws {UnexpectedAlertOpenError}
* A modal dialog is open, blocking this operation.
*/
GeckoDriver.prototype.maximizeWindow = function (cmd, resp) {
assert.firefox()
let win = assert.window(this.getCurrentWindow());
assert.firefox();
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
win.maximize()
};

Просмотреть файл

@ -26,6 +26,7 @@ const ERRORS = new Set([
"StaleElementReferenceError",
"TimeoutError",
"UnableToSetCookieError",
"UnexpectedAlertOpenError",
"UnknownCommandError",
"UnknownError",
"UnsupportedOperationError",
@ -450,6 +451,13 @@ class UnableToSetCookieError extends WebDriverError {
}
}
class UnexpectedAlertOpenError extends WebDriverError {
constructor (message) {
super(message);
this.status = "unexpected alert open";
}
}
class UnknownCommandError extends WebDriverError {
constructor (message) {
super(message);
@ -472,9 +480,9 @@ class UnsupportedOperationError extends WebDriverError {
}
const STATUSES = new Map([
["element click intercepted", ElementClickInterceptedError],
["element not accessible", ElementNotAccessibleError],
["element not interactable", ElementNotInteractableError],
["element click intercepted", ElementClickInterceptedError],
["insecure certificate", InsecureCertificateError],
["invalid argument", InvalidArgumentError],
["invalid element state", InvalidElementStateError],
@ -491,6 +499,7 @@ const STATUSES = new Map([
["stale element reference", StaleElementReferenceError],
["timeout", TimeoutError],
["unable to set cookie", UnableToSetCookieError],
["unexpected alert open", UnexpectedAlertOpenError],
["unknown command", UnknownCommandError],
["unknown error", UnknownError],
["unsupported operation", UnsupportedOperationError],

Просмотреть файл

@ -3,8 +3,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_driver.by import By
from marionette_driver.errors import NoAlertPresentException, ElementNotInteractableException
from marionette_driver.expected import element_present
from marionette_driver import errors
from marionette_driver.marionette import Alert
from marionette_driver.wait import Wait
@ -17,7 +17,7 @@ class BaseAlertTestCase(WindowManagerMixin, MarionetteTestCase):
try:
Alert(self.marionette).text
return True
except NoAlertPresentException:
except errors.NoAlertPresentException:
return False
def wait_for_alert(self, timeout=None):
@ -53,8 +53,10 @@ class TestTabModalAlerts(BaseAlertTestCase):
super(TestTabModalAlerts, self).tearDown()
def test_no_alert_raises(self):
self.assertRaises(NoAlertPresentException, Alert(self.marionette).accept)
self.assertRaises(NoAlertPresentException, Alert(self.marionette).dismiss)
with self.assertRaises(errors.NoAlertPresentException):
Alert(self.marionette).accept()
with self.assertRaises(errors.NoAlertPresentException):
Alert(self.marionette).dismiss()
def test_alert_accept(self):
self.marionette.find_element(By.ID, "tab-modal-alert").click()
@ -112,7 +114,7 @@ class TestTabModalAlerts(BaseAlertTestCase):
alert.dismiss()
def test_alert_text(self):
with self.assertRaises(NoAlertPresentException):
with self.assertRaises(errors.NoAlertPresentException):
alert = self.marionette.switch_to_alert()
alert.text
self.marionette.find_element(By.ID, "tab-modal-alert").click()
@ -122,7 +124,7 @@ class TestTabModalAlerts(BaseAlertTestCase):
alert.accept()
def test_prompt_text(self):
with self.assertRaises(NoAlertPresentException):
with self.assertRaises(errors.NoAlertPresentException):
alert = self.marionette.switch_to_alert()
alert.text
self.marionette.find_element(By.ID, "tab-modal-prompt").click()
@ -132,7 +134,7 @@ class TestTabModalAlerts(BaseAlertTestCase):
alert.accept()
def test_confirm_text(self):
with self.assertRaises(NoAlertPresentException):
with self.assertRaises(errors.NoAlertPresentException):
alert = self.marionette.switch_to_alert()
alert.text
self.marionette.find_element(By.ID, "tab-modal-confirm").click()
@ -142,11 +144,13 @@ class TestTabModalAlerts(BaseAlertTestCase):
alert.accept()
def test_set_text_throws(self):
self.assertRaises(NoAlertPresentException, Alert(self.marionette).send_keys, "Foo")
with self.assertRaises(errors.NoAlertPresentException):
Alert(self.marionette).send_keys("Foo")
self.marionette.find_element(By.ID, "tab-modal-alert").click()
self.wait_for_alert()
alert = self.marionette.switch_to_alert()
self.assertRaises(ElementNotInteractableException, alert.send_keys, "Foo")
with self.assertRaises(errors.ElementNotInteractableException):
alert.send_keys("Foo")
alert.accept()
def test_set_text_accept(self):
@ -194,31 +198,11 @@ class TestTabModalAlerts(BaseAlertTestCase):
alert.accept()
self.wait_for_condition(lambda mn: mn.get_url() == "about:blank")
@skip_if_e10s("Bug 1325044")
def test_unrelated_command_when_alert_present(self):
click_handler = self.marionette.find_element(By.ID, "click-handler")
text = self.marionette.find_element(By.ID, "click-result").text
self.assertEqual(text, "")
self.marionette.find_element(By.ID, "tab-modal-alert").click()
self.wait_for_alert()
# Commands succeed, but because the dialog blocks the event loop,
# our actions aren't reflected on the page.
text = self.marionette.find_element(By.ID, "click-result").text
self.assertEqual(text, "")
click_handler.click()
text = self.marionette.find_element(By.ID, "click-result").text
self.assertEqual(text, "")
alert = self.marionette.switch_to_alert()
alert.accept()
self.wait_for_alert_closed()
click_handler.click()
text = self.marionette.find_element(By.ID, "click-result").text
self.assertEqual(text, "result")
with self.assertRaises(errors.UnexpectedAlertOpen):
self.marionette.find_element(By.ID, "click-result")
class TestModalAlerts(BaseAlertTestCase):

Просмотреть файл

@ -33,6 +33,14 @@ add_test(function test_platforms() {
run_next_test();
});
add_test(function test_noUserPrompt() {
assert.noUserPrompt(null);
assert.noUserPrompt(undefined);
Assert.throws(() => assert.noUserPrompt({}), UnexpectedAlertOpenError);
run_next_test();
});
add_test(function test_defined() {
assert.defined({});
Assert.throws(() => assert.defined(undefined), InvalidArgumentError);