summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/browser/head_pageAction.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/extensions/test/browser/head_pageAction.js')
-rw-r--r--browser/components/extensions/test/browser/head_pageAction.js232
1 files changed, 232 insertions, 0 deletions
diff --git a/browser/components/extensions/test/browser/head_pageAction.js b/browser/components/extensions/test/browser/head_pageAction.js
new file mode 100644
index 0000000000..f80a6d3c98
--- /dev/null
+++ b/browser/components/extensions/test/browser/head_pageAction.js
@@ -0,0 +1,232 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+/* exported runTests */
+// This file is imported into the same scope as head.js.
+/* import-globals-from head.js */
+
+{
+ // At the moment extension language negotiation is tied to Firefox language
+ // negotiation result. That means that to test an extension in `es-ES`, we need
+ // to mock `es-ES` being available in Firefox and then request it.
+ //
+ // In the future, we should provide some way for tests to decouple their
+ // language selection from that of Firefox.
+ const avLocales = Services.locale.availableLocales;
+
+ Services.locale.availableLocales = ["en-US", "es-ES"];
+ registerCleanupFunction(() => {
+ Services.locale.availableLocales = avLocales;
+ });
+}
+
+async function runTests(options) {
+ function background(getTests) {
+ let tests;
+
+ // Gets the current details of the page action, and returns a
+ // promise that resolves to an object containing them.
+ async function getDetails(tabId) {
+ return {
+ title: await browser.pageAction.getTitle({ tabId }),
+ popup: await browser.pageAction.getPopup({ tabId }),
+ isShown: await browser.pageAction.isShown({ tabId }),
+ };
+ }
+
+ // Runs the next test in the `tests` array, checks the results,
+ // and passes control back to the outer test scope.
+ function nextTest() {
+ let test = tests.shift();
+
+ test(async expecting => {
+ let [tab] = await browser.tabs.query({
+ active: true,
+ currentWindow: true,
+ });
+ let { id: tabId, windowId, url } = tab;
+
+ browser.test.log(`Get details: tab={id: ${tabId}, url: ${url}}`);
+
+ // Check that the API returns the expected values, and then
+ // run the next test.
+ let details = await getDetails(tabId);
+ if (expecting) {
+ browser.test.assertEq(
+ expecting.title,
+ details.title,
+ "expected value from getTitle"
+ );
+
+ browser.test.assertEq(
+ expecting.popup,
+ details.popup,
+ "expected value from getPopup"
+ );
+ }
+
+ browser.test.assertEq(
+ !!expecting,
+ details.isShown,
+ "expected value from isShown"
+ );
+
+ // Check that the actual icon has the expected values, then
+ // run the next test.
+ browser.test.sendMessage("nextTest", expecting, windowId, tests.length);
+ });
+ }
+
+ async function runTests() {
+ let tabs = [];
+ let windows = [];
+ tests = getTests(tabs, windows);
+
+ let resultTabs = await browser.tabs.query({
+ active: true,
+ currentWindow: true,
+ });
+
+ tabs[0] = resultTabs[0].id;
+ windows[0] = resultTabs[0].windowId;
+
+ nextTest();
+ }
+
+ browser.test.onMessage.addListener(msg => {
+ if (msg == "runTests") {
+ runTests();
+ } else if (msg == "runNextTest") {
+ nextTest();
+ } else {
+ browser.test.fail(`Unexpected message: ${msg}`);
+ }
+ });
+
+ runTests();
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: options.manifest,
+
+ files: options.files || {},
+
+ background: `(${background})(${options.getTests})`,
+ });
+
+ let pageActionId;
+ let currentWindow = window;
+ let windows = [];
+
+ async function waitForDetails(details, windowId) {
+ function check() {
+ let { document } = Services.wm.getOuterWindowWithId(windowId);
+ let image = document.getElementById(pageActionId);
+ if (details == null) {
+ return image == null || image.getAttribute("disabled") == "true";
+ }
+ let title = details.title || options.manifest.name;
+ return (
+ !!image &&
+ getListStyleImage(image) == details.icon &&
+ image.getAttribute("tooltiptext") == title &&
+ image.getAttribute("aria-label") == title
+ );
+ // TODO: Popup URL. If this is updated, modify also checkDetails.
+ }
+
+ // eslint-disable-next-line no-async-promise-executor
+ return new Promise(async resolve => {
+ let maxCounter = 10;
+ while (!check() && --maxCounter > 0) {
+ info("checks left: " + maxCounter);
+ await promiseAnimationFrame(currentWindow);
+ }
+ resolve();
+ });
+ }
+
+ function checkDetails(details, windowId) {
+ let { document } = Services.wm.getOuterWindowWithId(windowId);
+ let image = document.getElementById(pageActionId);
+ if (details == null) {
+ ok(
+ image == null || image.getAttribute("disabled") == "true",
+ "image is disabled"
+ );
+ } else {
+ ok(image, "image exists");
+
+ is(getListStyleImage(image), details.icon, "icon URL is correct");
+
+ let title = details.title || options.manifest.name;
+ is(image.getAttribute("tooltiptext"), title, "image title is correct");
+ is(
+ image.getAttribute("aria-label"),
+ title,
+ "image aria-label is correct"
+ );
+ // TODO: Popup URL. If this is updated, modify also waitForDetails.
+ }
+ }
+
+ let testNewWindows = 1;
+
+ let awaitFinish = new Promise(resolve => {
+ extension.onMessage(
+ "nextTest",
+ async (expecting, windowId, testsRemaining) => {
+ if (!pageActionId) {
+ pageActionId = BrowserPageActions.urlbarButtonNodeIDForActionID(
+ makeWidgetId(extension.id)
+ );
+ }
+
+ await waitForDetails(expecting, windowId);
+
+ checkDetails(expecting, windowId);
+
+ if (testsRemaining) {
+ extension.sendMessage("runNextTest");
+ } else if (testNewWindows) {
+ testNewWindows--;
+
+ BrowserTestUtils.openNewBrowserWindow()
+ .then(window => {
+ windows.push(window);
+ currentWindow = window;
+ return focusWindow(window);
+ })
+ .then(() => {
+ extension.sendMessage("runTests");
+ });
+ } else {
+ resolve();
+ }
+ }
+ );
+ });
+
+ let reqLoc = Services.locale.requestedLocales;
+ Services.locale.requestedLocales = ["es-ES"];
+
+ await extension.startup();
+
+ await awaitFinish;
+
+ await extension.unload();
+
+ Services.locale.requestedLocales = reqLoc;
+
+ let node = document.getElementById(pageActionId);
+ is(node, null, "pageAction image removed from document");
+
+ currentWindow = null;
+ for (let win of windows.splice(0)) {
+ node = win.document.getElementById(pageActionId);
+ is(node, null, "pageAction image removed from second document");
+
+ await BrowserTestUtils.closeWindow(win);
+ }
+}