summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/ext/browser
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/tests/ext/browser')
-rw-r--r--browser/components/urlbar/tests/ext/browser/.eslintrc.js7
-rw-r--r--browser/components/urlbar/tests/ext/browser/browser.ini18
-rw-r--r--browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_attributionURL.js16
-rw-r--r--browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_clearInput.js31
-rw-r--r--browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_dynamicResult.js137
-rw-r--r--browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_engagementTelemetry.js18
-rw-r--r--browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_extensionTimeout.js16
-rw-r--r--browser/components/urlbar/tests/ext/browser/dynamicResult.css36
-rw-r--r--browser/components/urlbar/tests/ext/browser/head.js253
9 files changed, 532 insertions, 0 deletions
diff --git a/browser/components/urlbar/tests/ext/browser/.eslintrc.js b/browser/components/urlbar/tests/ext/browser/.eslintrc.js
new file mode 100644
index 0000000000..e57058ecb1
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ env: {
+ webextensions: true,
+ },
+};
diff --git a/browser/components/urlbar/tests/ext/browser/browser.ini b/browser/components/urlbar/tests/ext/browser/browser.ini
new file mode 100644
index 0000000000..416fc52eb3
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/browser.ini
@@ -0,0 +1,18 @@
+# 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/.
+
+[DEFAULT]
+support-files =
+ ../../browser/head-common.js
+ ../api.js
+ ../schema.json
+ head.js
+
+[browser_ext_urlbar_attributionURL.js]
+[browser_ext_urlbar_clearInput.js]
+[browser_ext_urlbar_dynamicResult.js]
+support-files =
+ dynamicResult.css
+[browser_ext_urlbar_engagementTelemetry.js]
+[browser_ext_urlbar_extensionTimeout.js]
diff --git a/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_attributionURL.js b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_attributionURL.js
new file mode 100644
index 0000000000..a5bccc8eba
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_attributionURL.js
@@ -0,0 +1,16 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* global browser */
+
+// This tests the browser.experiments.urlbar.engagementTelemetry WebExtension
+// Experiment API.
+
+"use strict";
+
+add_settings_tasks("browser.partnerlink.attributionURL", "string", () => {
+ browser.test.onMessage.addListener(async (method, arg) => {
+ let result = await browser.experiments.urlbar.attributionURL[method](arg);
+ browser.test.sendMessage("done", result);
+ });
+});
diff --git a/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_clearInput.js b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_clearInput.js
new file mode 100644
index 0000000000..afeff3b8a1
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_clearInput.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* global browser */
+
+// This tests the browser.experiments.urlbar.clearInput WebExtension Experiment
+// API.
+
+"use strict";
+
+add_task(async function test() {
+ // Load a page so that pageproxystate is valid. When the extension calls
+ // clearInput, the pageproxystate should become invalid.
+ await BrowserTestUtils.withNewTab("http://example.com/", async () => {
+ Assert.notEqual(gURLBar.value, "", "Input is not empty");
+ Assert.equal(gURLBar.getAttribute("pageproxystate"), "valid");
+
+ let ext = await loadExtension({
+ background: async () => {
+ await browser.experiments.urlbar.clearInput();
+ browser.test.sendMessage("done");
+ },
+ });
+ await ext.awaitMessage("done");
+
+ Assert.equal(gURLBar.value, "", "Input is empty");
+ Assert.equal(gURLBar.getAttribute("pageproxystate"), "invalid");
+
+ await ext.unload();
+ });
+});
diff --git a/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_dynamicResult.js b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_dynamicResult.js
new file mode 100644
index 0000000000..a710d8949d
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_dynamicResult.js
@@ -0,0 +1,137 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* global browser */
+
+// This tests dynamic results using the WebExtension Experiment API.
+
+"use strict";
+
+add_task(async function test() {
+ let ext = await loadExtension({
+ extraFiles: {
+ "dynamicResult.css": await (
+ await fetch("file://" + getTestFilePath("dynamicResult.css"))
+ ).text(),
+ },
+ background: async () => {
+ browser.experiments.urlbar.addDynamicResultType("testDynamicType");
+ browser.experiments.urlbar.addDynamicViewTemplate("testDynamicType", {
+ stylesheet: "dynamicResult.css",
+ children: [
+ {
+ name: "text",
+ tag: "span",
+ },
+ {
+ name: "button",
+ tag: "span",
+ attributes: {
+ role: "button",
+ },
+ },
+ ],
+ });
+ browser.urlbar.onBehaviorRequested.addListener(query => {
+ return "restricting";
+ }, "test");
+ browser.urlbar.onResultsRequested.addListener(query => {
+ return [
+ {
+ type: "dynamic",
+ source: "local",
+ heuristic: true,
+ payload: {
+ dynamicType: "testDynamicType",
+ },
+ },
+ ];
+ }, "test");
+ browser.experiments.urlbar.onViewUpdateRequested.addListener(payload => {
+ return {
+ text: {
+ textContent: "This is a dynamic result.",
+ },
+ button: {
+ textContent: "Click Me",
+ },
+ };
+ }, "test");
+ browser.urlbar.onResultPicked.addListener((payload, elementName) => {
+ browser.test.sendMessage("onResultPicked", [payload, elementName]);
+ }, "test");
+ },
+ });
+
+ // Wait for the provider and dynamic type to be registered before continuing.
+ await TestUtils.waitForCondition(
+ () =>
+ UrlbarProvidersManager.getProvider("test") &&
+ UrlbarResult.getDynamicResultType("testDynamicType"),
+ "Waiting for provider and dynamic type to be registered"
+ );
+ Assert.ok(
+ UrlbarProvidersManager.getProvider("test"),
+ "Provider should be registered"
+ );
+ Assert.ok(
+ UrlbarResult.getDynamicResultType("testDynamicType"),
+ "Dynamic type should be registered"
+ );
+
+ // Do a search.
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "test",
+ waitForFocus: SimpleTest.waitForFocus,
+ });
+
+ // Get the row.
+ let row = await UrlbarTestUtils.waitForAutocompleteResultAt(window, 0);
+ Assert.equal(
+ row.result.type,
+ UrlbarUtils.RESULT_TYPE.DYNAMIC,
+ "row.result.type"
+ );
+ Assert.equal(
+ row.getAttribute("dynamicType"),
+ "testDynamicType",
+ "row[dynamicType]"
+ );
+
+ let text = row.querySelector(".urlbarView-dynamic-testDynamicType-text");
+
+ // The view's call to provider.getViewUpdate is async, so we need to make sure
+ // the update has been applied before continuing to avoid intermittent
+ // failures.
+ await TestUtils.waitForCondition(
+ () => text.textContent == "This is a dynamic result."
+ );
+
+ // Check the elements.
+ Assert.equal(
+ text.textContent,
+ "This is a dynamic result.",
+ "text.textContent"
+ );
+ let button = row.querySelector(".urlbarView-dynamic-testDynamicType-button");
+ Assert.equal(button.textContent, "Click Me", "button.textContent");
+
+ // The result's button should be selected since the result is the heuristic.
+ Assert.equal(
+ UrlbarTestUtils.getSelectedElement(window),
+ button,
+ "Button should be selected"
+ );
+
+ // Pick the button.
+ let pickPromise = ext.awaitMessage("onResultPicked");
+ await UrlbarTestUtils.promisePopupClose(window, () =>
+ EventUtils.synthesizeKey("KEY_Enter")
+ );
+ let [payload, elementName] = await pickPromise;
+ Assert.equal(payload.dynamicType, "testDynamicType", "Picked payload");
+ Assert.equal(elementName, "button", "Picked element name");
+
+ await ext.unload();
+});
diff --git a/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_engagementTelemetry.js b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_engagementTelemetry.js
new file mode 100644
index 0000000000..50ded14d4e
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_engagementTelemetry.js
@@ -0,0 +1,18 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* global browser */
+
+// This tests the browser.experiments.urlbar.engagementTelemetry WebExtension
+// Experiment API.
+
+"use strict";
+
+add_settings_tasks("browser.urlbar.eventTelemetry.enabled", "boolean", () => {
+ browser.test.onMessage.addListener(async (method, arg) => {
+ let result = await browser.experiments.urlbar.engagementTelemetry[method](
+ arg
+ );
+ browser.test.sendMessage("done", result);
+ });
+});
diff --git a/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_extensionTimeout.js b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_extensionTimeout.js
new file mode 100644
index 0000000000..de09ef263c
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/browser_ext_urlbar_extensionTimeout.js
@@ -0,0 +1,16 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* global browser */
+
+// This tests the browser.experiments.urlbar.engagementTelemetry WebExtension
+// Experiment API.
+
+"use strict";
+
+add_settings_tasks("browser.urlbar.extension.timeout", "number", () => {
+ browser.test.onMessage.addListener(async (method, arg) => {
+ let result = await browser.experiments.urlbar.extensionTimeout[method](arg);
+ browser.test.sendMessage("done", result);
+ });
+});
diff --git a/browser/components/urlbar/tests/ext/browser/dynamicResult.css b/browser/components/urlbar/tests/ext/browser/dynamicResult.css
new file mode 100644
index 0000000000..efd0c8c950
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/dynamicResult.css
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+.urlbarView-row[dynamicType=testDynamicType] > .urlbarView-row-inner {
+ display: flex;
+ align-items: center;
+ min-height: 32px;
+ width: 100%;
+}
+
+.urlbarView-dynamic-testDynamicType-text {
+ flex-grow: 1;
+ flex-shrink: 1;
+ padding: 10px;
+}
+
+.urlbarView-dynamic-testDynamicType-button {
+ min-height: 16px;
+ padding: 8px;
+ border: none;
+ border-radius: 2px;
+ font-size: 0.93em;
+ color: inherit;
+ background-color: var(--urlbarView-button-background);
+ min-width: 8.75em;
+ text-align: center;
+ flex-basis: initial;
+ flex-shrink: 0;
+ margin-inline-end: 10px;
+}
+
+.urlbarView-dynamic-testDynamicType-button[selected] {
+ color: white;
+ background-color: var(--urlbarView-primary-button-background);
+ box-shadow: 0 0 0 1px #0a84ff inset, 0 0 0 1px #0a84ff, 0 0 0 4px rgba(10, 132, 255, 0.3);
+}
diff --git a/browser/components/urlbar/tests/ext/browser/head.js b/browser/components/urlbar/tests/ext/browser/head.js
new file mode 100644
index 0000000000..8d11a88066
--- /dev/null
+++ b/browser/components/urlbar/tests/ext/browser/head.js
@@ -0,0 +1,253 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * The files in this directory test the browser.urlbarExperiments WebExtension
+ * Experiment APIs, which are the WebExtension APIs we ship in our urlbar
+ * experiment extensions. Unlike the WebExtension APIs we ship in mozilla-
+ * central, which have continuous test coverage [1], our WebExtension Experiment
+ * APIs would not have continuous test coverage were it not for the fact that we
+ * copy and test them here. This is especially useful for APIs that are used in
+ * experiments that target multiple versions of Firefox, and for APIs that are
+ * reused in multiple experiments. See [2] and [3] for more info on
+ * experiments.
+ *
+ * [1] See browser/components/extensions/test
+ * [2] browser/components/urlbar/docs/experiments.rst
+ * [3] https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/basics.html#webextensions-experiments
+ */
+
+"use strict";
+
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/browser/components/urlbar/tests/browser/head-common.js",
+ this
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ Preferences: "resource://gre/modules/Preferences.sys.mjs",
+});
+
+const SCHEMA_BASENAME = "schema.json";
+const SCRIPT_BASENAME = "api.js";
+
+const SCHEMA_PATH = getTestFilePath(SCHEMA_BASENAME);
+const SCRIPT_PATH = getTestFilePath(SCRIPT_BASENAME);
+
+let schemaSource;
+let scriptSource;
+
+add_setup(async function loadSource() {
+ schemaSource = await (await fetch("file://" + SCHEMA_PATH)).text();
+ scriptSource = await (await fetch("file://" + SCRIPT_PATH)).text();
+});
+
+/**
+ * Loads a mock extension with our browser.experiments.urlbar API and a
+ * background script. Be sure to call `await ext.unload()` when you're done
+ * with it.
+ *
+ * @param {object} options
+ * Options object
+ * @param {Function} options.background
+ * This function is serialized and becomes the background script.
+ * @param {object} [options.extraFiles]
+ * Extra files to load in the extension.
+ * @returns {object}
+ * The extension.
+ */
+async function loadExtension({ background, extraFiles = {} }) {
+ let ext = ExtensionTestUtils.loadExtension({
+ manifest: {
+ permissions: ["urlbar"],
+ experiment_apis: {
+ experiments_urlbar: {
+ schema: SCHEMA_BASENAME,
+ parent: {
+ scopes: ["addon_parent"],
+ paths: [["experiments", "urlbar"]],
+ script: SCRIPT_BASENAME,
+ },
+ },
+ },
+ },
+ files: {
+ [SCHEMA_BASENAME]: schemaSource,
+ [SCRIPT_BASENAME]: scriptSource,
+ ...extraFiles,
+ },
+ isPrivileged: true,
+ background,
+ });
+ await ext.startup();
+ return ext;
+}
+
+/**
+ * Tests toggling a preference value via an experiments.urlbar API.
+ *
+ * @param {string} prefName
+ * The name of the pref to be tested.
+ * @param {string} type
+ * The type of the pref being set. One of "string", "boolean", or "number".
+ * @param {Function} background
+ * Boilerplate function that returns the value from calling the
+ * browser.experiments.urlbar.prefName[method] APIs.
+ */
+function add_settings_tasks(prefName, type, background) {
+ let defaultPreferences = new Preferences({ defaultBranch: true });
+
+ let originalValue = defaultPreferences.get(prefName);
+ registerCleanupFunction(() => {
+ defaultPreferences.set(prefName, originalValue);
+ });
+
+ let firstValue, secondValue;
+ switch (type) {
+ case "string":
+ firstValue = "test value 1";
+ secondValue = "test value 2";
+ break;
+ case "number":
+ firstValue = 10;
+ secondValue = 100;
+ break;
+ case "boolean":
+ firstValue = false;
+ secondValue = true;
+ break;
+ default:
+ Assert.ok(
+ false,
+ `"type" parameter must be one of "string", "number", or "boolean"`
+ );
+ }
+
+ add_task(async function get() {
+ let ext = await loadExtension({ background });
+
+ defaultPreferences.set(prefName, firstValue);
+ ext.sendMessage("get", {});
+ let result = await ext.awaitMessage("done");
+ Assert.strictEqual(result.value, firstValue);
+
+ defaultPreferences.set(prefName, secondValue);
+ ext.sendMessage("get", {});
+ result = await ext.awaitMessage("done");
+ Assert.strictEqual(result.value, secondValue);
+
+ await ext.unload();
+ });
+
+ add_task(async function set() {
+ let ext = await loadExtension({ background });
+
+ defaultPreferences.set(prefName, firstValue);
+ ext.sendMessage("set", { value: secondValue });
+ let result = await ext.awaitMessage("done");
+ Assert.strictEqual(result, true);
+ Assert.strictEqual(defaultPreferences.get(prefName), secondValue);
+
+ ext.sendMessage("set", { value: firstValue });
+ result = await ext.awaitMessage("done");
+ Assert.strictEqual(result, true);
+ Assert.strictEqual(defaultPreferences.get(prefName), firstValue);
+
+ await ext.unload();
+ });
+
+ add_task(async function clear() {
+ // no set()
+ defaultPreferences.set(prefName, firstValue);
+ let ext = await loadExtension({ background });
+ ext.sendMessage("clear", {});
+ let result = await ext.awaitMessage("done");
+ Assert.strictEqual(result, false);
+ Assert.strictEqual(defaultPreferences.get(prefName), firstValue);
+ await ext.unload();
+
+ // firstValue -> secondValue
+ defaultPreferences.set(prefName, firstValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: secondValue });
+ await ext.awaitMessage("done");
+ ext.sendMessage("clear", {});
+ result = await ext.awaitMessage("done");
+ Assert.strictEqual(result, true);
+ Assert.strictEqual(defaultPreferences.get(prefName), firstValue);
+ await ext.unload();
+
+ // secondValue -> firstValue
+ defaultPreferences.set(prefName, secondValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: firstValue });
+ await ext.awaitMessage("done");
+ ext.sendMessage("clear", {});
+ result = await ext.awaitMessage("done");
+ Assert.strictEqual(result, true);
+ Assert.strictEqual(defaultPreferences.get(prefName), secondValue);
+ await ext.unload();
+
+ // firstValue -> firstValue
+ defaultPreferences.set(prefName, firstValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: firstValue });
+ await ext.awaitMessage("done");
+ ext.sendMessage("clear", {});
+ result = await ext.awaitMessage("done");
+ Assert.strictEqual(result, true);
+ Assert.strictEqual(defaultPreferences.get(prefName), firstValue);
+ await ext.unload();
+
+ // secondValue -> secondValue
+ defaultPreferences.set(prefName, secondValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: secondValue });
+ await ext.awaitMessage("done");
+ ext.sendMessage("clear", {});
+ result = await ext.awaitMessage("done");
+ Assert.strictEqual(result, true);
+ Assert.strictEqual(defaultPreferences.get(prefName), secondValue);
+ await ext.unload();
+ });
+
+ add_task(async function shutdown() {
+ // no set()
+ defaultPreferences.set(prefName, firstValue);
+ let ext = await loadExtension({ background });
+ await ext.unload();
+ Assert.strictEqual(defaultPreferences.get(prefName), firstValue);
+
+ // firstValue -> secondValue
+ defaultPreferences.set(prefName, firstValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: secondValue });
+ await ext.awaitMessage("done");
+ await ext.unload();
+ Assert.strictEqual(defaultPreferences.get(prefName), firstValue);
+
+ // secondValue -> firstValue
+ defaultPreferences.set(prefName, secondValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: firstValue });
+ await ext.awaitMessage("done");
+ await ext.unload();
+ Assert.strictEqual(defaultPreferences.get(prefName), secondValue);
+
+ // firstValue -> firstValue
+ defaultPreferences.set(prefName, firstValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: firstValue });
+ await ext.awaitMessage("done");
+ await ext.unload();
+ Assert.strictEqual(defaultPreferences.get(prefName), firstValue);
+
+ // secondValue -> secondValue
+ defaultPreferences.set(prefName, secondValue);
+ ext = await loadExtension({ background });
+ ext.sendMessage("set", { value: secondValue });
+ await ext.awaitMessage("done");
+ await ext.unload();
+ Assert.strictEqual(defaultPreferences.get(prefName), secondValue);
+ });
+}