summaryrefslogtreecommitdiffstats
path: root/devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_addons_debug_console.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_addons_debug_console.js')
-rw-r--r--devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_addons_debug_console.js440
1 files changed, 440 insertions, 0 deletions
diff --git a/devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_addons_debug_console.js b/devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_addons_debug_console.js
new file mode 100644
index 0000000000..1612cd545f
--- /dev/null
+++ b/devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_addons_debug_console.js
@@ -0,0 +1,440 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+/* import-globals-from helper-addons.js */
+Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-addons.js", this);
+
+// There are shutdown issues for which multiple rejections are left uncaught.
+// See bug 1018184 for resolving these issues.
+const { PromiseTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/PromiseTestUtils.sys.mjs"
+);
+PromiseTestUtils.allowMatchingRejectionsGlobally(/File closed/);
+
+// Avoid test timeouts that can occur while waiting for the "addon-console-works" message.
+requestLongerTimeout(2);
+
+const ADDON_ID = "test-devtools-webextension@mozilla.org";
+const ADDON_NAME = "base-test-devtools-webextension";
+
+const OTHER_ADDON_ID = "other-test-devtools-webextension@mozilla.org";
+const OTHER_ADDON_NAME = "other-test-devtools-webextension";
+
+const POPUPONLY_ADDON_ID = "popuponly-test-devtools-webextension@mozilla.org";
+const POPUPONLY_ADDON_NAME = "popuponly-test-devtools-webextension";
+
+const BACKGROUND_ADDON_ID = "background-test-devtools-webextension@mozilla.org";
+const BACKGROUND_ADDON_NAME = "background-test-devtools-webextension";
+
+/**
+ * This test file ensures that the webextension addon developer toolbox:
+ * - when the debug button is clicked on a webextension, the opened toolbox
+ * has a working webconsole with the background page as default target;
+ */
+add_task(async function testWebExtensionsToolboxWebConsole() {
+ await pushPref("devtools.webconsole.filter.css", true);
+ await enableExtensionDebugging();
+ const { document, tab, window } = await openAboutDebugging();
+ await selectThisFirefoxPage(document, window.AboutDebugging.store);
+
+ await installTemporaryExtensionFromXPI(
+ {
+ background() {
+ window.myWebExtensionAddonFunction = function () {
+ console.log(
+ "Background page function called",
+ this.browser.runtime.getManifest()
+ );
+ };
+
+ const style = document.createElement("style");
+ style.textContent = "* { color: error; }";
+ document.documentElement.appendChild(style);
+
+ throw new Error("Background page exception");
+ },
+ extraProperties: {
+ browser_action: {
+ default_title: "WebExtension Popup Debugging",
+ default_popup: "popup.html",
+ default_area: "navbar",
+ },
+ },
+ files: {
+ "popup.html": `<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ <script src="popup.js"></script>
+ </head>
+ <body>
+ Popup
+ </body>
+ </html>
+ `,
+ "popup.js": function () {
+ console.log("Popup log");
+
+ const style = document.createElement("style");
+ style.textContent = "* { color: popup-error; }";
+ document.documentElement.appendChild(style);
+
+ throw new Error("Popup exception");
+ },
+ },
+ id: ADDON_ID,
+ name: ADDON_NAME,
+ },
+ document
+ );
+
+ // Install another addon in order to ensure we don't get its logs
+ await installTemporaryExtensionFromXPI(
+ {
+ background() {
+ console.log("Other addon log");
+
+ const style = document.createElement("style");
+ style.textContent = "* { background-color: error; }";
+ document.documentElement.appendChild(style);
+
+ throw new Error("Other addon exception");
+ },
+ extraProperties: {
+ browser_action: {
+ default_title: "Other addon popup",
+ default_popup: "other-popup.html",
+ default_area: "navbar",
+ },
+ },
+ files: {
+ "other-popup.html": `<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ <script src="other-popup.js"></script>
+ </head>
+ <body>
+ Other popup
+ </body>
+ </html>
+ `,
+ "other-popup.js": function () {
+ console.log("Other popup log");
+
+ const style = document.createElement("style");
+ style.textContent = "* { background-color: popup-error; }";
+ document.documentElement.appendChild(style);
+
+ throw new Error("Other popup exception");
+ },
+ },
+ id: OTHER_ADDON_ID,
+ name: OTHER_ADDON_NAME,
+ },
+ document
+ );
+
+ const { devtoolsWindow } = await openAboutDevtoolsToolbox(
+ document,
+ tab,
+ window,
+ ADDON_NAME
+ );
+ const toolbox = getToolbox(devtoolsWindow);
+ const webconsole = await toolbox.selectTool("webconsole");
+ const { hud } = webconsole;
+
+ info("Trigger some code in the background page logging some stuff");
+ const onMessage = waitUntil(() => {
+ return !!findMessagesByType(hud, "Background page exception", ".error")
+ .length;
+ });
+ hud.ui.wrapper.dispatchEvaluateExpression("myWebExtensionAddonFunction()");
+ await onMessage;
+
+ info("Open the two add-ons popups to cover popups messages");
+ const onPopupMessage = waitUntil(() => {
+ return !!findMessagesByType(hud, "Popup exception", ".error").length;
+ });
+ clickOnAddonWidget(OTHER_ADDON_ID);
+ clickOnAddonWidget(ADDON_ID);
+ await onPopupMessage;
+
+ info("Wait a bit to catch unexpected duplicates or mixed up messages");
+ await wait(1000);
+
+ is(
+ findMessagesByType(hud, "Background page exception", ".error").length,
+ 1,
+ "We get the background page exception"
+ );
+ is(
+ findMessagesByType(hud, "Popup exception", ".error").length,
+ 1,
+ "We get the popup exception"
+ );
+ is(
+ findMessagesByType(
+ hud,
+ "Expected color but found ‘error’. Error in parsing value for ‘color’. Declaration dropped.",
+ ".warn"
+ ).length,
+ 1,
+ "We get the addon's background page CSS error message"
+ );
+ is(
+ findMessagesByType(
+ hud,
+ "Expected color but found ‘popup-error’. Error in parsing value for ‘color’. Declaration dropped.",
+ ".warn"
+ ).length,
+ 1,
+ "We get the addon's popup CSS error message"
+ );
+
+ // Verify that we don't get the other addon log and errors
+ ok(
+ !findMessageByType(hud, "Other addon log", ".console-api"),
+ "We don't get the other addon log"
+ );
+ ok(
+ !findMessageByType(hud, "Other addon exception", ".console-api"),
+ "We don't get the other addon exception"
+ );
+ ok(
+ !findMessageByType(hud, "Other popup log", ".console-api"),
+ "We don't get the other addon popup log"
+ );
+ ok(
+ !findMessageByType(hud, "Other popup exception", ".error"),
+ "We don't get the other addon popup exception"
+ );
+ ok(
+ !findMessageByType(
+ hud,
+ "Expected color but found ‘error’. Error in parsing value for ‘background-color’. Declaration dropped.",
+ ".warn"
+ ),
+ "We don't get the other addon's background page CSS error message"
+ );
+ ok(
+ !findMessageByType(
+ hud,
+ "Expected color but found ‘popup-error’. Error in parsing value for ‘background-color’. Declaration dropped.",
+ ".warn"
+ ),
+ "We don't get the other addon's popup CSS error message"
+ );
+
+ // Verify that console evaluations still work after reloading the page
+ info("Reload the webextension document");
+ const { onDomCompleteResource } =
+ await waitForNextTopLevelDomCompleteResource(toolbox.commands);
+ hud.ui.wrapper.dispatchEvaluateExpression("location.reload()");
+ await onDomCompleteResource;
+
+ info("Try to evaluate something after reload");
+
+ const onEvaluationResultAfterReload = waitUntil(() =>
+ findMessageByType(hud, "result:2", ".result")
+ );
+ const onMessageAfterReload = waitUntil(() =>
+ findMessageByType(hud, "message after reload", ".console-api")
+ );
+ hud.ui.wrapper.dispatchEvaluateExpression(
+ "console.log('message after reload'); 'result:' + (1 + 1)"
+ );
+ // Both cover that the console.log worked
+ await onMessageAfterReload;
+ // And we received the evaluation result
+ await onEvaluationResultAfterReload;
+
+ await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
+
+ // Note that it seems to be important to remove the addons in the reverse order
+ // from which they were installed...
+ await removeTemporaryExtension(OTHER_ADDON_NAME, document);
+ await removeTemporaryExtension(ADDON_NAME, document);
+ await removeTab(tab);
+});
+
+add_task(async function testWebExtensionNoBgScript() {
+ await pushPref("devtools.webconsole.filter.css", true);
+ await enableExtensionDebugging();
+ const { document, tab, window } = await openAboutDebugging();
+ await selectThisFirefoxPage(document, window.AboutDebugging.store);
+
+ await installTemporaryExtensionFromXPI(
+ {
+ extraProperties: {
+ browser_action: {
+ default_title: "WebExtension Popup Only",
+ default_popup: "popup.html",
+ default_area: "navbar",
+ },
+ },
+ files: {
+ "popup.html": `<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ <script src="popup.js"></script>
+ </head>
+ <body>
+ Popup
+ </body>
+ </html>
+ `,
+ "popup.js": function () {
+ console.log("Popup-only log");
+
+ const style = document.createElement("style");
+ style.textContent = "* { color: popup-only-error; }";
+ document.documentElement.appendChild(style);
+
+ throw new Error("Popup-only exception");
+ },
+ },
+ id: POPUPONLY_ADDON_ID,
+ name: POPUPONLY_ADDON_NAME,
+ },
+ document
+ );
+
+ const { devtoolsWindow } = await openAboutDevtoolsToolbox(
+ document,
+ tab,
+ window,
+ POPUPONLY_ADDON_NAME
+ );
+ const toolbox = getToolbox(devtoolsWindow);
+ const webconsole = await toolbox.selectTool("webconsole");
+ const { hud } = webconsole;
+
+ info("Open the add-on popup");
+ const onPopupMessage = waitUntil(() => {
+ return !!findMessagesByType(hud, "Popup-only exception", ".error").length;
+ });
+ clickOnAddonWidget(POPUPONLY_ADDON_ID);
+ await onPopupMessage;
+
+ info("Wait a bit to catch unexpected duplicates or mixed up messages");
+ await wait(1000);
+ is(
+ findMessagesByType(hud, "Popup-only exception", ".error").length,
+ 1,
+ "We get the popup exception"
+ );
+ is(
+ findMessagesByType(hud, "Popup-only log", ".console-api").length,
+ 1,
+ "We get the addon's popup log"
+ );
+ is(
+ findMessagesByType(
+ hud,
+ "Expected color but found ‘popup-only-error’. Error in parsing value for ‘color’. Declaration dropped.",
+ ".warn"
+ ).length,
+ 1,
+ "We get the addon's popup CSS error message"
+ );
+
+ await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
+ await removeTemporaryExtension(POPUPONLY_ADDON_NAME, document);
+ await removeTab(tab);
+});
+
+// Check that reloading the addon several times does not break the console,
+// see Bug 1778951.
+add_task(async function testWebExtensionTwoReloads() {
+ await enableExtensionDebugging();
+ const { document, tab, window } = await openAboutDebugging();
+ await selectThisFirefoxPage(document, window.AboutDebugging.store);
+
+ await installTemporaryExtensionFromXPI(
+ {
+ background() {
+ console.log("Background page log");
+ },
+ extraProperties: {
+ browser_action: {
+ default_title: "WebExtension with background script",
+ default_popup: "popup.html",
+ default_area: "navbar",
+ },
+ },
+ files: {
+ "popup.html": `<!DOCTYPE html>
+ <html>
+ <body>
+ Popup
+ </body>
+ </html>
+ `,
+ },
+ id: BACKGROUND_ADDON_ID,
+ name: BACKGROUND_ADDON_NAME,
+ },
+ document
+ );
+
+ // Retrieve the addonTarget element before calling `openAboutDevtoolsToolbox`,
+ // otherwise it will pick the about:devtools-toolbox tab with the same name
+ // instead.
+ const addonTarget = findDebugTargetByText(BACKGROUND_ADDON_NAME, document);
+
+ const { devtoolsWindow } = await openAboutDevtoolsToolbox(
+ document,
+ tab,
+ window,
+ BACKGROUND_ADDON_NAME
+ );
+ const toolbox = getToolbox(devtoolsWindow);
+ const webconsole = await toolbox.selectTool("webconsole");
+ const { hud } = webconsole;
+
+ // Verify that console evaluations still work after reloading the addon
+ info("Reload the webextension itself");
+ let { onDomCompleteResource } = await waitForNextTopLevelDomCompleteResource(
+ toolbox.commands
+ );
+ const reloadButton = addonTarget.querySelector(
+ ".qa-temporary-extension-reload-button"
+ );
+ reloadButton.click();
+ await onDomCompleteResource;
+
+ info("Try to evaluate something after 1st addon reload");
+ // Wait before evaluating the message, otherwise they might be cleaned up by
+ // the console UI.
+ info("Wait until the background script log is visible");
+ await waitUntil(() =>
+ findMessageByType(hud, "Background page log", ".message")
+ );
+
+ hud.ui.wrapper.dispatchEvaluateExpression("40+1");
+ await waitUntil(() => findMessageByType(hud, "41", ".result"));
+
+ info("Reload the extension a second time");
+ ({ onDomCompleteResource } = await waitForNextTopLevelDomCompleteResource(
+ toolbox.commands
+ ));
+ reloadButton.click();
+ await onDomCompleteResource;
+
+ info("Wait until the background script log is visible - after reload");
+ await waitUntil(() =>
+ findMessageByType(hud, "Background page log", ".message")
+ );
+
+ info("Try to evaluate something after 2nd addon reload");
+ hud.ui.wrapper.dispatchEvaluateExpression("40+2");
+ await waitUntil(() => findMessageByType(hud, "42", ".result"));
+
+ await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
+ await removeTemporaryExtension(BACKGROUND_ADDON_NAME, document);
+ await removeTab(tab);
+});