diff --git a/testing/marionette/capture.js b/testing/marionette/capture.js index ea10b4e8c41d..274d205675c7 100644 --- a/testing/marionette/capture.js +++ b/testing/marionette/capture.js @@ -17,6 +17,11 @@ const XHTML_NS = "http://www.w3.org/1999/xhtml"; /** Provides primitives to capture screenshots. */ this.capture = {}; +capture.Format = { + Base64: 0, + Hash: 1, +}; + /** * Take a screenshot of a single element. * diff --git a/testing/marionette/driver.js b/testing/marionette/driver.js index b6341f642f0b..c63cfcf0aca7 100644 --- a/testing/marionette/driver.js +++ b/testing/marionette/driver.js @@ -2425,15 +2425,19 @@ GeckoDriver.prototype.clearImportedScripts = function*(cmd, resp) { * If called in the chrome context, the screenshot will always represent the * entire viewport. * - * @param {string} id - * Reference to a web element. - * @param {string} highlights + * @param {string=} id + * Optional web element reference to take a screenshot of. + * If undefined, a screenshot will be taken of the document element. + * @param {Array.=} highlights * List of web elements to highlight. * @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 {boolean} hash + * @param {boolean=} hash * True if the user requests a hash of the image data. + * @param {boolean=} scroll + * Scroll to element if |id| is provided. If undefined, it will + * scroll to the element. * * @return {string} * If {@code hash} is false, PNG image encoded as base64 encoded string. If @@ -2441,26 +2445,22 @@ GeckoDriver.prototype.clearImportedScripts = function*(cmd, resp) { * string. */ GeckoDriver.prototype.takeScreenshot = function (cmd, resp) { - let {id, highlights, full, hash} = cmd.parameters; + 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 canvas; - let highlightEls = []; - let container = {frame: this.getCurrentWindow().document.defaultView}; - if (!container.frame) { - throw new NoSuchWindowError('Unable to locate window'); + throw new NoSuchWindowError("Unable to locate window"); } - for (let h of highlights) { - let el = this.curBrowser.seenEls.get(h, container); - highlightEls.push(el); - } + let highlightEls = highlights.map( + ref => this.curBrowser.seenEls.get(ref, container)); // viewport + let canvas; if (!id && !full) { canvas = capture.viewport(container.frame, highlightEls); @@ -2476,18 +2476,17 @@ GeckoDriver.prototype.takeScreenshot = function (cmd, resp) { canvas = capture.element(node, highlightEls); } - if (hash) { - return capture.toHash(canvas); - } else { - return capture.toBase64(canvas); + switch (format) { + case capture.Format.Hash: + return capture.toHash(canvas); + + case capture.Format.Base64: + return capture.toBase64(canvas); } + break; case Context.CONTENT: - if (hash) { - return this.listener.getScreenshotHash(id, full, highlights); - } else { - return this.listener.takeScreenshot(id, full, highlights); - } + return this.listener.takeScreenshot(format, cmd.parameters); } }; diff --git a/testing/marionette/listener.js b/testing/marionette/listener.js index f3b62b51b4ad..7e0db6d84bcc 100644 --- a/testing/marionette/listener.js +++ b/testing/marionette/listener.js @@ -239,7 +239,6 @@ var switchToShadowRootFn = dispatch(switchToShadowRoot); var getCookiesFn = dispatch(getCookies); var singleTapFn = dispatch(singleTap); var takeScreenshotFn = dispatch(takeScreenshot); -var getScreenshotHashFn = dispatch(getScreenshotHash); var performActionsFn = dispatch(performActions); var releaseActionsFn = dispatch(releaseActions); var actionChainFn = dispatch(actionChain); @@ -297,7 +296,6 @@ function startListeners() { addMessageListenerId("Marionette:getAppCacheStatus", getAppCacheStatus); addMessageListenerId("Marionette:setTestName", setTestName); addMessageListenerId("Marionette:takeScreenshot", takeScreenshotFn); - addMessageListenerId("Marionette:getScreenshotHash", getScreenshotHashFn); addMessageListenerId("Marionette:addCookie", addCookieFn); addMessageListenerId("Marionette:getCookies", getCookiesFn); addMessageListenerId("Marionette:deleteAllCookies", deleteAllCookiesFn); @@ -403,7 +401,6 @@ function deleteSession(msg) { removeMessageListenerId("Marionette:getAppCacheStatus", getAppCacheStatus); removeMessageListenerId("Marionette:setTestName", setTestName); removeMessageListenerId("Marionette:takeScreenshot", takeScreenshotFn); - removeMessageListenerId("Marionette:getScreenshotHash", getScreenshotHashFn); removeMessageListenerId("Marionette:addCookie", addCookieFn); removeMessageListenerId("Marionette:getCookies", getCookiesFn); removeMessageListenerId("Marionette:deleteAllCookies", deleteAllCookiesFn); @@ -1620,88 +1617,68 @@ function getAppCacheStatus(msg) { /** * Perform a screen capture in content context. * - * @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.=} highlights - * Draw a border around the elements found by their web element - * references. + * 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.=} 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.} opts + * Options. * * @return {string} - * Base64 encoded string of an image/png type. + * Base64 encoded string or a SHA-256 hash of the screenshot. */ -function takeScreenshot(id, full=true, highlights=[]) { - let canvas = screenshot(id, full, highlights); - return capture.toBase64(canvas); -} +function takeScreenshot(format, opts = {}) { + let id = opts.id; + let full = !!opts.full; + let highlights = opts.highlights || []; + let scroll = !!opts.scroll; -/** -* Perform a screen capture in content context. -* -* @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.=} highlights -* Draw a border around the elements found by their web element -* references. -* -* @return {string} -* Hex Digest of a SHA-256 hash of the base64 encoded string of an -* image/png type. -*/ -function getScreenshotHash(id, full=true, highlights=[]) { - let canvas = screenshot(id, full, highlights); - return capture.toHash(canvas); -} + let highlightEls = highlights.map(ref => seenEls.get(ref, curContainer)); -/** -* Perform a screen capture in content context. -* -* @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.=} highlights -* Draw a border around the elements found by their web element -* references. -* -* @return {HTMLCanvasElement} -* The canvas element to be encoded or hashed. -*/ -function screenshot(id, full=true, highlights=[]) { let canvas; - let highlightEls = []; - for (let h of highlights) { - let el = seenEls.get(h, curContainer); - highlightEls.push(el); - } - // viewport if (!id && !full) { canvas = capture.viewport(curContainer.frame, highlightEls); // element or full document element } else { - let node; + let el; if (id) { - node = seenEls.get(id, curContainer); + el = seenEls.get(id, curContainer); + if (scroll) { + element.scrollIntoView(el); + } } else { - node = curContainer.frame.document.documentElement; + el = curContainer.frame.document.documentElement; } - canvas = capture.element(node, highlightEls); + canvas = capture.element(el, highlightEls); } - return canvas; + 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); + } } // Call register self when we get loaded