Bug 1464461 - add back mochitests for screenshot command; r=ochameau, nchevobbe
MozReview-Commit-ID: 4yGM74AXwoP
--- a/devtools/client/webconsole/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/test/mochitest/browser.ini
@@ -98,16 +98,17 @@ support-files =
test-ineffective-iframe-sandbox-warning4.html
test-ineffective-iframe-sandbox-warning5.html
test-insecure-frame.html
test-insecure-passwords-about-blank-web-console-warning.html
test-insecure-passwords-web-console-warning.html
test-inspect-cross-domain-objects-frame.html
test-inspect-cross-domain-objects-top.html
test-jsterm-dollar.html
+ test_jsterm_screenshot_command.html
test-local-session-storage.html
test-location-debugger-link-console-log.js
test-location-debugger-link-errors.js
test-location-debugger-link.html
test-location-styleeditor-link-1.css
test-location-styleeditor-link-2.css
test-location-styleeditor-link.html
test-message-categories-canvas-css.html
@@ -222,16 +223,20 @@ skip-if = os != 'mac' # The tested ctrl+
[browser_jsterm_instance_of.js]
[browser_jsterm_multiline.js]
[browser_jsterm_no_autocompletion_on_defined_variables.js]
[browser_jsterm_no_input_and_tab_key_pressed.js]
[browser_jsterm_no_input_change_and_tab_key_pressed.js]
[browser_jsterm_null_undefined.js]
[browser_jsterm_popup_close_on_tab_switch.js]
[browser_jsterm_popup.js]
+[browser_jsterm_screenshot_command_clipboard.js]
+subsuite = clipboard
+[browser_jsterm_screenshot_command_file.js]
+skip-if = (os == 'win') # Bug 1464461, disabled on Win due to timeouts
[browser_jsterm_selfxss.js]
subsuite = clipboard
[browser_webconsole_allow_mixedcontent_securityerrors.js]
tags = mcb
[browser_webconsole_batching.js]
[browser_webconsole_block_mixedcontent_securityerrors.js]
tags = mcb
[browser_webconsole_cached_messages.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_clipboard.js
@@ -0,0 +1,209 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that screenshot command works properly
+
+"use strict";
+
+const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
+ "test/mochitest/test_jsterm_screenshot_command.html";
+
+// on some machines, such as macOS, dpr is set to 2. This is expected behavior, however
+// to keep tests consistant across OSs we are setting the dpr to 1
+const dpr = "--dpr 1";
+
+add_task(async function() {
+ const hud = await openNewTabAndConsole(TEST_URI);
+ ok(hud, "web console opened");
+
+ await testClipboard(hud);
+ await testFullpageClipboard(hud);
+ await testSelectorClipboard(hud);
+
+ // overflow
+ await createScrollbarOverflow();
+ await testFullpageClipboardScrollbar(hud);
+});
+
+async function testClipboard(hud) {
+ const command = `:screenshot --clipboard ${dpr}`;
+ const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
+ hud.jsterm.execute(command);
+ await onMessage;
+ const contentSize = await getContentSize();
+ const imgSize = await getImageSizeFromClipboard();
+
+ is(imgSize.width, contentSize.innerWidth,
+ "Clipboard: Image width matches window size");
+ is(imgSize.height, contentSize.innerHeight,
+ "Clipboard: Image height matches window size");
+}
+
+async function testFullpageClipboard(hud) {
+ const command = `:screenshot --fullpage --clipboard ${dpr}`;
+ const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
+ hud.jsterm.execute(command);
+ await onMessage;
+ const contentSize = await getContentSize();
+ const imgSize = await getImageSizeFromClipboard();
+
+ is(imgSize.width,
+ (contentSize.innerWidth + contentSize.scrollMaxX -
+ contentSize.scrollMinX),
+ "Fullpage Clipboard: Image width matches page size");
+ is(imgSize.height,
+ (contentSize.innerHeight + contentSize.scrollMaxY -
+ contentSize.scrollMinY),
+ "Fullpage Clipboard: Image height matches page size");
+}
+
+async function testSelectorClipboard(hud) {
+ const command = `:screenshot --selector "img#testImage" --clipboard ${dpr}`;
+ const messageReceived = waitForMessage(hud, "Screenshot copied to clipboard.");
+ hud.jsterm.execute(command);
+ await messageReceived;
+ const imgSize1 = await getImageSizeFromClipboard();
+ await ContentTask.spawn(
+ gBrowser.selectedBrowser,
+ imgSize1,
+ function(imgSize) {
+ const img = content.document.querySelector("#testImage");
+ is(imgSize.width, img.clientWidth,
+ "Selector Clipboard: Image width matches element size");
+ is(imgSize.height, img.clientHeight,
+ "Selector Clipboard: Image height matches element size");
+ }
+ );
+}
+
+async function testFullpageClipboardScrollbar(hud) {
+ const command = `:screenshot --fullpage --clipboard ${dpr}`;
+ const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
+ hud.jsterm.execute(command);
+ await onMessage;
+ const contentSize = await getContentSize();
+ const scrollbarSize = await getScrollbarSize();
+ const imgSize = await getImageSizeFromClipboard();
+
+ is(imgSize.width,
+ (contentSize.innerWidth + contentSize.scrollMaxX -
+ contentSize.scrollMinX) - scrollbarSize.width,
+ "Scroll Fullpage Clipboard: Image width matches page size minus scrollbar size");
+ is(imgSize.height,
+ (contentSize.innerHeight + contentSize.scrollMaxY -
+ contentSize.scrollMinY) - scrollbarSize.height,
+ "Scroll Fullpage Clipboard: Image height matches page size minus scrollbar size");
+}
+
+async function createScrollbarOverflow() {
+ // Trigger scrollbars by forcing document to overflow
+ // This only affects results on OSes with scrollbars that reduce document size
+ // (non-floating scrollbars). With default OS settings, this means Windows
+ // and Linux are affected, but Mac is not. For Mac to exhibit this behavior,
+ // change System Preferences -> General -> Show scroll bars to Always.
+ await ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
+ content.document.body.classList.add("overflow");
+ });
+}
+
+async function getScrollbarSize() {
+ const scrollbarSize = await ContentTask.spawn(
+ gBrowser.selectedBrowser,
+ {},
+ function() {
+ const winUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ const scrollbarHeight = {};
+ const scrollbarWidth = {};
+ winUtils.getScrollbarSize(true, scrollbarWidth, scrollbarHeight);
+ return {
+ width: scrollbarWidth.value,
+ height: scrollbarHeight.value,
+ };
+ }
+ );
+ info(`Scrollbar size: ${scrollbarSize.width}x${scrollbarSize.height}`);
+ return scrollbarSize;
+}
+
+async function getContentSize() {
+ const contentSize = await ContentTask.spawn(
+ gBrowser.selectedBrowser,
+ {},
+ function() {
+ return {
+ scrollMaxY: content.scrollMaxY,
+ scrollMaxX: content.scrollMaxX,
+ scrollMinY: content.scrollMinY,
+ scrollMinX: content.scrollMinX,
+ innerWidth: content.innerWidth,
+ innerHeight: content.innerHeight
+ };
+ }
+ );
+
+ info(`content size: ${contentSize.innerWidth}x${contentSize.innerHeight}`);
+ return contentSize;
+}
+
+async function getImageSizeFromClipboard() {
+ const clipid = Ci.nsIClipboard;
+ const clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
+ const trans = Cc["@mozilla.org/widget/transferable;1"]
+ .createInstance(Ci.nsITransferable);
+ const flavor = "image/png";
+ trans.init(null);
+ trans.addDataFlavor(flavor);
+
+ clip.getData(trans, clipid.kGlobalClipboard);
+ const data = {};
+ const dataLength = {};
+ trans.getTransferData(flavor, data, dataLength);
+
+ ok(data.value, "screenshot exists");
+ ok(dataLength.value > 0, "screenshot has length");
+
+ let image = data.value;
+ let dataURI = `data:${flavor};base64,`;
+
+ // Due to the differences in how images could be stored in the clipboard the
+ // checks below are needed. The clipboard could already provide the image as
+ // byte streams, but also as pointer, or as image container. If it's not
+ // possible obtain a byte stream, the function returns `null`.
+ if (image instanceof Ci.nsISupportsInterfacePointer) {
+ image = image.data;
+ }
+
+ if (image instanceof Ci.imgIContainer) {
+ image = Cc["@mozilla.org/image/tools;1"]
+ .getService(Ci.imgITools)
+ .encodeImage(image, flavor);
+ }
+
+ if (image instanceof Ci.nsIInputStream) {
+ const binaryStream = Cc["@mozilla.org/binaryinputstream;1"]
+ .createInstance(Ci.nsIBinaryInputStream);
+ binaryStream.setInputStream(image);
+ const rawData = binaryStream.readBytes(binaryStream.available());
+ const charCodes = Array.from(rawData, c => c.charCodeAt(0) & 0xff);
+ let encodedData = String.fromCharCode(...charCodes);
+ encodedData = btoa(encodedData);
+ dataURI = dataURI + encodedData;
+ } else {
+ throw new Error("Unable to read image data");
+ }
+
+ const img = document.createElementNS("http://www.w3.org/1999/xhtml", "img");
+
+ const loaded = once(img, "load");
+
+ img.src = dataURI;
+ document.documentElement.appendChild(img);
+ await loaded;
+ img.remove();
+
+ return {
+ width: img.width,
+ height: img.height,
+ };
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_file.js
@@ -0,0 +1,39 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that screenshot command works properly
+
+"use strict";
+
+const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
+ "test/mochitest/test_jsterm_screenshot_command.html";
+
+const FileUtils = (ChromeUtils.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
+// on some machines, such as macOS, dpr is set to 2. This is expected behavior, however
+// to keep tests consistant across OSs we are setting the dpr to 1
+const dpr = "--dpr 1";
+
+add_task(async function() {
+ await addTab(TEST_URI);
+
+ const hud = await openConsole();
+ ok(hud, "web console opened");
+
+ await testFile(hud);
+});
+
+async function testFile(hud) {
+ // Test capture to file
+ const file = FileUtils.getFile("TmpD", [ "TestScreenshotFile.png" ]);
+ const command = `:screenshot ${file.path} ${dpr}`;
+ const onMessage = waitForMessage(hud, `Saved to ${file.path}`);
+ hud.jsterm.execute(command);
+ await onMessage;
+
+ ok(file.exists(), "Screenshot file exists");
+
+ if (file.exists()) {
+ file.remove(false);
+ }
+}
+
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/mochitest/test_jsterm_screenshot_command.html
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <style>
+ img {
+ height: 100px;
+ width: 100px;
+ }
+ .overflow {
+ overflow: scroll;
+ height: 200%;
+ width: 200%;
+ }
+ </style>
+ </head>
+ <body>
+ <img id="testImage" ></img>
+ </body>
+</html>
--- a/devtools/server/actors/webconsole/screenshot.js
+++ b/devtools/server/actors/webconsole/screenshot.js
@@ -1,17 +1,17 @@
/* 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/. */
"use strict";
const { Ci, Cu } = require("chrome");
const { getRect } = require("devtools/shared/layout/utils");
-const { LocalizationHelper } = require("devtools/shared/L10N");
+const { LocalizationHelper } = require("devtools/shared/l10n");
const CONTAINER_FLASHING_DURATION = 500;
const STRINGS_URI = "devtools/shared/locales/screenshot.properties";
const L10N = new LocalizationHelper(STRINGS_URI);
exports.screenshot = function takeAsyncScreenshot(owner, args = {}) {
if (args.help) {
// Early return as help will be handled on the client side.