Bug 1410649 - Let WebDriver:TakeScreenshot accept web elements. r?whimboo
The WebDriver:TakeScreenshot command used to take an "id" field
with a web element reference UUID, as well as an array of UUIDs for
the "highlights" field. The first has been renamed to "element",
falling back to "id" if missing, and both changed to also accept
web element JSON Objects.
This will allow us to simplify the input to the command and for
the web elements to be automatically serialised and deserialised
as they reach the content frame script.
The fallbacks must be left in place until Firefox 60 ships.
MozReview-Commit-ID: 8Gh1y23Vi4r
--- a/testing/marionette/capture.js
+++ b/testing/marionette/capture.js
@@ -16,21 +16,16 @@ const XHTML_NS = "http://www.w3.org/1999
/**
* Provides primitives to capture screenshots.
*
* @namespace
*/
this.capture = {};
-capture.Format = {
- Base64: 0,
- Hash: 1,
-};
-
/**
* Take a screenshot of a single element.
*
* @param {Node} node
* The node to take a screenshot of.
* @param {Array.<Node>=} highlights
* Optional array of nodes, around which a border will be marked to
* highlight them in the screenshot.
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2946,57 +2946,63 @@ GeckoDriver.prototype.deleteSession = fu
* scroll to the element.
*
* @return {string}
* If <var>hash</var> is false, PNG image encoded as Base64 encoded
* string. If <var>hash</var> is true, hex digest of the SHA-256
* hash of the Base64 encoded string.
*/
GeckoDriver.prototype.takeScreenshot = function(cmd) {
- let win = assert.window(this.getCurrentWindow());
-
- let {id, highlights, full, hash} = cmd.parameters;
- highlights = highlights || [];
- let format = hash ? capture.Format.Hash : capture.Format.Base64;
+ const win = assert.window(this.getCurrentWindow());
+
+ // TODO(ato): id is deprecated and can be removed with Firefox 60
+ let area = cmd.parameters.element || cmd.parameters.id;
+ if (typeof area == "string") {
+ area = WebElement.fromUUID(area, this.context);
+ } else if (area) {
+ area = WebElement.fromJSON(area, this.context);
+ }
+
+ // TODO(ato): with Firefox 60 highlights becomes an array of
+ // web elements instead of an array of string UUIDs
+ let highlights = cmd.parameters.highlights || [];
+ highlights.forEach((highlight, i, arr) => {
+ if (typeof highlight == "string") {
+ arr[i] = WebElement.fromUUID(highlight, this.context);
+ } else if (typeof highlight != "undefined") {
+ arr[i] = WebElement.fromJSON(highlight, this.context);
+ }
+ });
+
+ let {full, hash, scroll} = cmd.parameters;
switch (this.context) {
case Context.Chrome:
let highlightEls = highlights
- .map(ref => WebElement.fromUUID(ref, Context.Chrome))
.map(webEl => this.curBrowser.seenEls.get(webEl));
- // viewport
let canvas;
- if (!id && !full) {
+ if (!area && !full) {
canvas = capture.viewport(win, highlightEls);
-
- // element or full document element
+ } else if (area) {
+ let el = this.curBrowser.seenEls.get(area);
+ canvas = capture.element(el, highlightEls);
} else {
- let node;
- if (id) {
- let webEl = WebElement.fromUUID(id, Context.Chrome);
- node = this.curBrowser.seenEls.get(webEl);
- } else {
- node = win.document.documentElement;
- }
-
- canvas = capture.element(node, highlightEls);
+ let {documentElement} = win.document;
+ canvas = capture.element(documentElement, highlightEls);
}
- switch (format) {
- case capture.Format.Hash:
- return capture.toHash(canvas);
-
- case capture.Format.Base64:
- return capture.toBase64(canvas);
+ if (hash) {
+ return capture.toHash(canvas);
}
- break;
+ return capture.toBase64(canvas);
case Context.Content:
- return this.listener.takeScreenshot(format, cmd.parameters);
+ return this.listener.takeScreenshot(
+ {area, highlights, full, scroll, hash});
}
throw new TypeError(`Unknown context: ${this.context}`);
};
/**
* Get the current browser orientation.
*
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -1638,82 +1638,58 @@ function switchToFrame(msg) {
sendOk(commandID);
}
}
/**
* Perform a screen capture in content context.
*
- * Accepted values for |opts|:
- *
- * @param {UUID=} id
- * Optional web element reference of an element to take a screenshot
- * of.
- * @param {boolean=} full
- * True to take a screenshot of the entire document element. Is not
- * considered if {@code id} is not defined. Defaults to true.
- * @param {Array.<UUID>=} highlights
- * Draw a border around the elements found by their web element
- * references.
- * @param {boolean=} scroll
- * When |id| is given, scroll it into view before taking the
- * screenshot. Defaults to true.
- *
- * @param {capture.Format} format
- * Format to return the screenshot in.
- * @param {Object.<string, ?>} opts
- * Options.
+ * @param {WebElement=} area
+ * Optional web element to take a screenshot of. By default
+ * @param {Array.<WebElement>=} highlights
+ * Draw a border around the elements.
+ * @param {boolean=} [full=true] full
+ * True to take a screenshot of the entire document element.
+ * Is not considered <var>captureElement</var> is not defined.
+ * Defaults to true.
+ * @param {boolean=} [scroll=true] scroll
+ * When <var>captureElement</var> is given, scroll it into view
+ * before taking the screenshot. Defaults to true.
*
* @return {string}
* Base64 encoded string or a SHA-256 hash of the screenshot.
*/
-function takeScreenshot(format, opts = {}) {
- let id = opts.id;
- let full = !!opts.full;
- let highlights = opts.highlights || [];
- let scroll = !!opts.scroll;
-
- let win = curContainer.frame;
+function takeScreenshot(
+ {
+ area = null,
+ highlights = [],
+ full = true,
+ scroll = true,
+ hash = true,
+ } = {}) {
+ const win = curContainer.frame;
let canvas;
- let highlightEls = highlights
- .map(ref => WebElement.fromUUID(ref, "content"))
- .map(webEl => seenEls.get(webEl, win));
-
- // viewport
- if (!id && !full) {
- canvas = capture.viewport(win, highlightEls);
-
- // element or full document element
+ if (!area && !full) {
+ canvas = capture.viewport(win, highlights);
+ } else if (area) {
+ if (scroll) {
+ element.scrollIntoView(area);
+ }
+ canvas = capture.element(area, highlights);
} else {
- let el;
- if (id) {
- let webEl = WebElement.fromUUID(id, "content");
- el = seenEls.get(webEl, win);
- if (scroll) {
- element.scrollIntoView(el);
- }
- } else {
- el = win.document.documentElement;
- }
-
- canvas = capture.element(el, highlightEls);
+ let {documentElement} = win.document;
+ canvas = capture.element(documentElement, highlights);
}
- switch (format) {
- case capture.Format.Base64:
- return capture.toBase64(canvas);
-
- case capture.Format.Hash:
- return capture.toHash(canvas);
-
- default:
- throw new TypeError("Unknown screenshot format: " + format);
+ if (hash) {
+ return capture.toHash(canvas);
}
+ return capture.toBase64(canvas);
}
function flushRendering() {
let content = curContainer.frame;
let anyPendingPaintsGeneratedInDescendants = false;
let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);