Bug 1213875 - Add ability to not scroll into view element on screen capture; r=whimboo

Implements a `scroll` argument for choosing the scroll into view behaviour
when taking screen captures of elements.

https://w3c.github.io/webdriver/webdriver-spec.html#take-element-screenshot

MozReview-Commit-ID: BOKBrKqQ916

--HG--
extra : rebase_source : 290f9a6a7c64c0f2932128679a84044138d96b6c
This commit is contained in:
Andreas Tolfsen 2016-12-20 14:30:48 +00:00
Родитель c48ea8d3bb
Коммит 2d255984aa
3 изменённых файлов: 70 добавлений и 89 удалений

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

@ -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.
*

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

@ -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.<string>=} 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) {
switch (format) {
case capture.Format.Hash:
return capture.toHash(canvas);
} else {
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);
}
};

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

@ -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,6 +1617,8 @@ function getAppCacheStatus(msg) {
/**
* 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.
@ -1629,79 +1628,57 @@ function getAppCacheStatus(msg) {
* @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.
*
* @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.<UUID>=} 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.<UUID>=} 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