diff options
Diffstat (limited to '')
-rw-r--r-- | widget/headless/tests/.eslintrc.js | 5 | ||||
-rw-r--r-- | widget/headless/tests/headless.html | 6 | ||||
-rw-r--r-- | widget/headless/tests/headless_button.html | 6 | ||||
-rw-r--r-- | widget/headless/tests/moz.build | 7 | ||||
-rw-r--r-- | widget/headless/tests/test_headless.js | 215 | ||||
-rw-r--r-- | widget/headless/tests/test_headless_clipboard.js | 46 | ||||
-rw-r--r-- | widget/headless/tests/xpcshell.ini | 10 |
7 files changed, 295 insertions, 0 deletions
diff --git a/widget/headless/tests/.eslintrc.js b/widget/headless/tests/.eslintrc.js new file mode 100644 index 0000000000..69e89d0054 --- /dev/null +++ b/widget/headless/tests/.eslintrc.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = { + extends: ["plugin:mozilla/xpcshell-test"], +}; diff --git a/widget/headless/tests/headless.html b/widget/headless/tests/headless.html new file mode 100644 index 0000000000..bbde895077 --- /dev/null +++ b/widget/headless/tests/headless.html @@ -0,0 +1,6 @@ +<html> +<head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"></head> +<body style="background-color: rgb(0, 255, 0); color: rgb(0, 0, 255)"> +Hi +</body> +</html> diff --git a/widget/headless/tests/headless_button.html b/widget/headless/tests/headless_button.html new file mode 100644 index 0000000000..5641066bfe --- /dev/null +++ b/widget/headless/tests/headless_button.html @@ -0,0 +1,6 @@ +<html> +<head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"></head> +<body> +<button id="btn">button</button> +</body> +</html> diff --git a/widget/headless/tests/moz.build b/widget/headless/tests/moz.build new file mode 100644 index 0000000000..e48fa734e0 --- /dev/null +++ b/widget/headless/tests/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +XPCSHELL_TESTS_MANIFESTS += ["xpcshell.ini"] diff --git a/widget/headless/tests/test_headless.js b/widget/headless/tests/test_headless.js new file mode 100644 index 0000000000..79486a9d8c --- /dev/null +++ b/widget/headless/tests/test_headless.js @@ -0,0 +1,215 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); +const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js"); + +const gProfDir = do_get_profile(); +const server = new HttpServer(); +server.registerDirectory("/", do_get_cwd()); +server.start(-1); +const ROOT = `http://localhost:${server.identity.primaryPort}`; +const BASE = `${ROOT}/`; +const HEADLESS_URL = `${BASE}/headless.html`; +const HEADLESS_BUTTON_URL = `${BASE}/headless_button.html`; +registerCleanupFunction(() => { + server.stop(() => {}); +}); + +// Refrences to the progress listeners to keep them from being gc'ed +// before they are called. +const progressListeners = new Map(); + +function loadContentWindow(windowlessBrowser, uri) { + return new Promise((resolve, reject) => { + let loadURIOptions = { + triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), + }; + windowlessBrowser.loadURI(uri, loadURIOptions); + let docShell = windowlessBrowser.docShell; + let webProgress = docShell + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebProgress); + let progressListener = { + onLocationChange(progress, request, location, flags) { + // Ignore inner-frame events + if (progress != webProgress) { + return; + } + // Ignore events that don't change the document + if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) { + return; + } + let contentWindow = docShell.domWindow; + webProgress.removeProgressListener(progressListener); + progressListeners.delete(progressListener); + contentWindow.addEventListener( + "load", + event => { + resolve(contentWindow); + }, + { once: true } + ); + }, + QueryInterface: ChromeUtils.generateQI([ + "nsIWebProgressListener", + "nsISupportsWeakReference", + ]), + }; + progressListeners.set(progressListener, progressListener); + webProgress.addProgressListener( + progressListener, + Ci.nsIWebProgress.NOTIFY_LOCATION + ); + }); +} + +add_task(async function test_snapshot() { + let windowlessBrowser = Services.appShell.createWindowlessBrowser(false); + let contentWindow = await loadContentWindow(windowlessBrowser, HEADLESS_URL); + const contentWidth = 400; + const contentHeight = 300; + // Verify dimensions. + contentWindow.resizeTo(contentWidth, contentHeight); + equal(contentWindow.innerWidth, contentWidth); + equal(contentWindow.innerHeight, contentHeight); + + // Snapshot the test page. + let canvas = contentWindow.document.createElementNS( + "http://www.w3.org/1999/xhtml", + "html:canvas" + ); + let context = canvas.getContext("2d"); + let width = contentWindow.innerWidth; + let height = contentWindow.innerHeight; + canvas.width = width; + canvas.height = height; + context.drawWindow(contentWindow, 0, 0, width, height, "rgb(255, 255, 255)"); + let imageData = context.getImageData(0, 0, width, height).data; + ok( + imageData[0] === 0 && + imageData[1] === 255 && + imageData[2] === 0 && + imageData[3] === 255, + "Page is green." + ); + + // Search for a blue pixel (a quick and dirty check to see if the blue text is + // on the page) + let found = false; + for (let i = 0; i < imageData.length; i += 4) { + if (imageData[i + 2] === 255) { + found = true; + break; + } + } + ok(found, "Found blue text on page."); + + windowlessBrowser.close(); +}); + +add_task(async function test_snapshot_widget_layers() { + let windowlessBrowser = Services.appShell.createWindowlessBrowser(false); + // nsIWindowlessBrowser inherits from nsIWebNavigation. + let contentWindow = await loadContentWindow(windowlessBrowser, HEADLESS_URL); + const contentWidth = 1; + const contentHeight = 2; + // Verify dimensions. + contentWindow.resizeTo(contentWidth, contentHeight); + equal(contentWindow.innerWidth, contentWidth); + equal(contentWindow.innerHeight, contentHeight); + + // Snapshot the test page. + let canvas = contentWindow.document.createElementNS( + "http://www.w3.org/1999/xhtml", + "html:canvas" + ); + let context = canvas.getContext("2d"); + let width = contentWindow.innerWidth; + let height = contentWindow.innerHeight; + canvas.width = width; + canvas.height = height; + context.drawWindow( + contentWindow, + 0, + 0, + width, + height, + "rgb(255, 255, 255)", + context.DRAWWINDOW_DRAW_CARET | + context.DRAWWINDOW_DRAW_VIEW | + context.DRAWWINDOW_USE_WIDGET_LAYERS + ); + ok(true, "Snapshot with widget layers didn't crash."); + + windowlessBrowser.close(); +}); + +// Ensure keydown events are triggered on the windowless browser. +add_task(async function test_keydown() { + let windowlessBrowser = Services.appShell.createWindowlessBrowser(false); + // nsIWindowlessBrowser inherits from nsIWebNavigation. + let contentWindow = await loadContentWindow(windowlessBrowser, HEADLESS_URL); + + let keydown = new Promise(resolve => { + contentWindow.addEventListener( + "keydown", + () => { + resolve(); + }, + { once: true } + ); + }); + + let tip = Cc["@mozilla.org/text-input-processor;1"].createInstance( + Ci.nsITextInputProcessor + ); + let begun = tip.beginInputTransactionForTests(contentWindow); + ok( + begun, + "nsITextInputProcessor.beginInputTransactionForTests() should succeed" + ); + tip.keydown( + new contentWindow.KeyboardEvent("", { + key: "a", + code: "KeyA", + keyCode: contentWindow.KeyboardEvent.DOM_VK_A, + }) + ); + + await keydown; + ok(true, "Send keydown didn't crash"); + + windowlessBrowser.close(); +}); + +// Test dragging the mouse on a button to ensure the creation of the drag +// service doesn't crash in headless. +add_task(async function test_mouse_drag() { + let windowlessBrowser = Services.appShell.createWindowlessBrowser(false); + // nsIWindowlessBrowser inherits from nsIWebNavigation. + let contentWindow = await loadContentWindow( + windowlessBrowser, + HEADLESS_BUTTON_URL + ); + contentWindow.resizeTo(400, 400); + + let target = contentWindow.document.getElementById("btn"); + let rect = target.getBoundingClientRect(); + let left = rect.left; + let top = rect.top; + + let utils = contentWindow.windowUtils; + utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEvent("mousemove", left, top, 0, 1, 0, false, 0, 0); + // Wait for a turn of the event loop since the synthetic mouse event + // that creates the drag service is processed during the refresh driver. + await new Promise(r => { + executeSoon(r); + }); + utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0); + + ok(true, "Send mouse event didn't crash"); + + windowlessBrowser.close(); +}); diff --git a/widget/headless/tests/test_headless_clipboard.js b/widget/headless/tests/test_headless_clipboard.js new file mode 100644 index 0000000000..6c0ffcd5a1 --- /dev/null +++ b/widget/headless/tests/test_headless_clipboard.js @@ -0,0 +1,46 @@ +/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set sts=2 sw=2 et tw=80: */ +"use strict"; +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +function getString(clipboard) { + var str = ""; + + // Create transferable that will transfer the text. + var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance( + Ci.nsITransferable + ); + trans.init(null); + trans.addDataFlavor("text/unicode"); + + clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard); + + try { + var data = {}; + trans.getTransferData("text/unicode", data); + + if (data) { + data = data.value.QueryInterface(Ci.nsISupportsString); + str = data.data; + } + } catch (ex) { + // If the clipboard is empty getTransferData will throw. + } + + return str; +} + +add_task(async function test_clipboard() { + let clipboard = Services.clipboard; + + // Test copy. + const data = "random number: " + Math.random(); + let helper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( + Ci.nsIClipboardHelper + ); + helper.copyString(data); + equal(getString(clipboard), data, "Data was successfully copied."); + + clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard); + equal(getString(clipboard), "", "Data was successfully cleared."); +}); diff --git a/widget/headless/tests/xpcshell.ini b/widget/headless/tests/xpcshell.ini new file mode 100644 index 0000000000..307a12cb0d --- /dev/null +++ b/widget/headless/tests/xpcshell.ini @@ -0,0 +1,10 @@ +[DEFAULT] +skip-if = toolkit != "gtk" && toolkit != "windows" +headless = true + +[test_headless_clipboard.js] +[test_headless.js] +skip-if = appname == "thunderbird" +support-files = + headless.html + headless_button.html |