summaryrefslogtreecommitdiffstats
path: root/widget/headless/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--widget/headless/tests/.eslintrc.js5
-rw-r--r--widget/headless/tests/headless.html6
-rw-r--r--widget/headless/tests/headless_button.html6
-rw-r--r--widget/headless/tests/moz.build7
-rw-r--r--widget/headless/tests/test_headless.js215
-rw-r--r--widget/headless/tests/test_headless_clipboard.js46
-rw-r--r--widget/headless/tests/xpcshell.ini10
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