Bug 1500378 - Migrate browser_addons_debug_webextension_nobg to new aboutdebugging;r=daisuke
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 18 Jan 2019 09:58:15 +0000
changeset 511520 3b442a1b227d70bb7c3d28b763588a8962e52ea8
parent 511519 15a126eab0979e764c96c01c9083207b2c0aa9a0
child 511521 16ad98f608feb829110b74171b1c4cd70867c0cf
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaisuke
bugs1500378
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1500378 - Migrate browser_addons_debug_webextension_nobg to new aboutdebugging;r=daisuke Differential Revision: https://phabricator.services.mozilla.com/D16917
devtools/client/aboutdebugging-new/test/browser/browser.ini
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_debug_nobg.js
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_temporary_addon_buttons.js
devtools/client/aboutdebugging-new/test/browser/helper-addons.js
--- a/devtools/client/aboutdebugging-new/test/browser/browser.ini
+++ b/devtools/client/aboutdebugging-new/test/browser/browser.ini
@@ -18,16 +18,17 @@ support-files =
   resources/service-workers/*
   resources/test-adb-extension/*
   resources/test-temporary-extension/*
   test-tab-favicons.html
   !/devtools/client/shared/test/shared-head.js
   !/devtools/client/shared/test/shared-redux-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
 
+[browser_aboutdebugging_addons_debug_nobg.js]
 [browser_aboutdebugging_addons_manifest_url.js]
 skip-if = (os == 'linux' && bits == 32) # ADB start() fails on linux 32, see Bug 1499638
 [browser_aboutdebugging_addons_remote_runtime.js]
 [browser_aboutdebugging_addons_temporary_addon_buttons.js]
 [browser_aboutdebugging_connect_networklocations.js]
 [browser_aboutdebugging_connect_toggle_usb_devices.js]
 skip-if = (os == 'linux' && bits == 32) # ADB start() fails on linux 32, see Bug 1499638
 [browser_aboutdebugging_connection_prompt_setting.js]
copy from devtools/client/aboutdebugging/test/browser_addons_debug_webextension_nobg.js
copy to devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_debug_nobg.js
--- a/devtools/client/aboutdebugging/test/browser_addons_debug_webextension_nobg.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_debug_nobg.js
@@ -1,102 +1,124 @@
 /* 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 } = scopedCuImport("resource://testing-common/PromiseTestUtils.jsm");
 PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
 
-// Avoid test timeouts that can occur while waiting for the "addon-console-works" message.
-requestLongerTimeout(2);
-
 const ADDON_NOBG_ID = "test-devtools-webextension-nobg@mozilla.org";
 const ADDON_NOBG_NAME = "test-devtools-webextension-nobg";
 
 const {
   BrowserToolboxProcess,
 } = ChromeUtils.import("resource://devtools/client/framework/ToolboxProcess.jsm", {});
 
 /**
  * This test file ensures that the webextension addon developer toolbox:
  * - the webextension developer toolbox is connected to a fallback page when the
  *   background page is not available (and in the fallback page document body contains
  *   the expected message, which warns the user that the current page is not a real
  *   webextension context);
  */
 add_task(async function testWebExtensionsToolboxNoBackgroundPage() {
-  const addonFile = ExtensionTestCommon.generateXPI({
-    manifest: {
-      name: ADDON_NOBG_NAME,
-      applications: {
-        gecko: {id: ADDON_NOBG_ID},
+  await enableExtensionDebugging();
+  const { document, tab } = await openAboutDebugging();
+
+  const manifest = {
+    manifest_version: 2,
+    name: ADDON_NOBG_NAME,
+    version: "1.0",
+    applications: {
+      gecko: {
+        id: ADDON_NOBG_ID,
       },
     },
-  });
-  registerCleanupFunction(() => addonFile.remove(false));
-
-  const {
-    tab, document, debugBtn,
-  } = await setupTestAboutDebuggingWebExtension(ADDON_NOBG_NAME, addonFile);
+  };
+  await installTemporaryExtensionFromManifest(manifest, document);
 
-  // Be careful, this JS function is going to be executed in the addon toolbox,
-  // which lives in another process. So do not try to use any scope variable!
-  const env = Cc["@mozilla.org/process/environment;1"]
-        .getService(Ci.nsIEnvironment);
-  const testScript = function() {
-    /* eslint-disable no-undef */
-    // This is webextension toolbox process. So we can't access mochitest framework.
-    const waitUntil = async function(predicate, interval = 10) {
-      if (await predicate()) {
-        return true;
-      }
-      return new Promise(resolve => {
-        toolbox.win.setTimeout(function() {
-          waitUntil(predicate, interval).then(() => resolve(true));
-        }, interval);
-      });
-    };
-
-    toolbox.selectTool("inspector").then(async inspector => {
-      let nodeActor;
+  const target = findDebugTargetByText(ADDON_NOBG_NAME, document);
 
-      dump(`Wait the fallback window to be fully loaded\n`);
-      await waitUntil(async () => {
-        nodeActor = await inspector.walker.querySelector(inspector.walker.rootNode, "h1");
-        return nodeActor && nodeActor.inlineTextChild;
-      });
-
-      dump("Got a nodeActor with an inline text child\n");
-      const expectedValue = "Your addon does not have any document opened yet.";
-      const actualValue = nodeActor.inlineTextChild._form.nodeValue;
-
-      if (actualValue !== expectedValue) {
-        throw new Error(
-          `mismatched inlineTextchild value: "${actualValue}" !== "${expectedValue}"`
-        );
-      }
-
-      dump("Got the expected inline text content in the selected node\n");
-
-      await toolbox.destroy();
-    }).catch((error) => {
-      dump("Error while running code in the browser toolbox process:\n");
-      dump(error + "\n");
-      dump("stack:\n" + error.stack + "\n");
-    });
-    /* eslint-enable no-undef */
-  };
-  env.set("MOZ_TOOLBOX_TEST_SCRIPT", "new " + testScript);
+  info("Setup the toolbox test function as environment variable");
+  const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
+  env.set("MOZ_TOOLBOX_TEST_SCRIPT", "new " + toolboxTestScript);
+  env.set("MOZ_TOOLBOX_TEST_ADDON_NOBG_NAME", ADDON_NOBG_NAME);
   registerCleanupFunction(() => {
     env.set("MOZ_TOOLBOX_TEST_SCRIPT", "");
+    env.set("MOZ_TOOLBOX_TEST_ADDON_NOBG_NAME", "");
   });
 
+  info("Click inspect to open the addon toolbox, wait for toolbox close event");
   const onToolboxClose = BrowserToolboxProcess.once("close");
-  debugBtn.click();
+  const inspectButton = target.querySelector(".js-debug-target-inspect-button");
+  inspectButton.click();
   await onToolboxClose;
 
+  // The test script will not close the toolbox and will timeout if it fails, so reaching
+  // this point in the test is enough to assume the test was successful.
   ok(true, "Addon toolbox closed");
 
-  await uninstallAddon({document, id: ADDON_NOBG_ID, name: ADDON_NOBG_NAME});
-  await closeAboutDebugging(tab);
+  await removeTemporaryExtension(ADDON_NOBG_NAME, document);
+  await removeTab(tab);
 });
+
+// Be careful, this JS function is going to be executed in the addon toolbox,
+// which lives in another process. So do not try to use any scope variable!
+function toolboxTestScript() {
+  /* eslint-disable no-undef */
+  // This is webextension toolbox process. So we can't access mochitest framework.
+  const waitUntil = async function(predicate, interval = 10) {
+    if (await predicate()) {
+      return true;
+    }
+    return new Promise(resolve => {
+      toolbox.win.setTimeout(function() {
+        waitUntil(predicate, interval).then(() => resolve(true));
+      }, interval);
+    });
+  };
+
+  // We pass the expected target name as an environment variable because this method
+  // runs in a different process and cannot access the const defined in this test file.
+  const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
+  const expectedName = env.get("MOZ_TOOLBOX_TEST_ADDON_NOBG_NAME");
+
+  const targetName = toolbox.target.name;
+  const isAddonTarget = toolbox.target.isAddon;
+  if (!(isAddonTarget && targetName === expectedName)) {
+    dump(`Expected target name "${expectedName}", got ${targetName}`);
+    throw new Error("Toolbox doesn't have the expected target");
+  }
+
+  toolbox.selectTool("inspector").then(async inspector => {
+    let nodeActor;
+
+    dump(`Wait the fallback window to be fully loaded\n`);
+    await waitUntil(async () => {
+      nodeActor = await inspector.walker.querySelector(inspector.walker.rootNode, "h1");
+      return nodeActor && nodeActor.inlineTextChild;
+    });
+
+    dump("Got a nodeActor with an inline text child\n");
+    const expectedValue = "Your addon does not have any document opened yet.";
+    const actualValue = nodeActor.inlineTextChild._form.nodeValue;
+
+    if (actualValue !== expectedValue) {
+      throw new Error(
+        `mismatched inlineTextchild value: "${actualValue}" !== "${expectedValue}"`
+      );
+    }
+
+    dump("Got the expected inline text content in the selected node\n");
+
+    await toolbox.destroy();
+  }).catch((error) => {
+    dump("Error while running code in the browser toolbox process:\n");
+    dump(error + "\n");
+    dump("stack:\n" + error.stack + "\n");
+  });
+  /* eslint-enable no-undef */
+}
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_temporary_addon_buttons.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_temporary_addon_buttons.js
@@ -18,25 +18,17 @@ add_task(async function() {
     "name": ORIGINAL_EXTENSION_NAME,
     "version": "1.0",
     "applications": {
       "gecko": {
         "id": EXTENSION_ID,
       },
     },
   };
-
-  const tempExt = new TemporaryExtension(EXTENSION_ID);
-  tempExt.writeManifest(manifestBase);
-
-  info("Install a temporary extension (original)");
-  await AddonManager.installTemporaryAddon(tempExt.sourceDir);
-
-  info("Wait until a debug target item appears");
-  await waitUntil(() => findDebugTargetByText(ORIGINAL_EXTENSION_NAME, document));
+  const tempExt = await installTemporaryExtensionFromManifest(manifestBase, document);
 
   const originalTarget = findDebugTargetByText(ORIGINAL_EXTENSION_NAME, document);
   ok(!!originalTarget, "The temporary extension isinstalled with the expected name");
 
   info("Update the name of the temporary extension in the manifest");
   tempExt.writeManifest(Object.assign({}, manifestBase, {name: UPDATED_EXTENSION_NAME}));
 
   info("Click on the reload button for the temporary extension");
@@ -56,19 +48,16 @@ add_task(async function() {
   info("Click on the remove button for the temporary extension");
   const removeButton =
     updatedTarget.querySelector(".js-temporary-extension-remove-button");
   removeButton.click();
 
   info("Wait until the debug target with the updated extension name disappears");
   await waitUntil(() => !findDebugTargetByText(UPDATED_EXTENSION_NAME, document));
 
-  info("Remove the temporary web extension");
-  tempExt.remove();
-
   await removeTab(tab);
 });
 
 add_task(async function() {
   const PACKAGED_EXTENSION_ID = "packaged-extension@tests";
   const PACKAGED_EXTENSION_NAME = "Packaged extension";
 
   const { document, tab } = await openAboutDebugging();
--- a/devtools/client/aboutdebugging-new/test/browser/helper-addons.js
+++ b/devtools/client/aboutdebugging-new/test/browser/helper-addons.js
@@ -10,16 +10,27 @@ const { Management } = ChromeUtils.impor
 function _getSupportsFile(path) {
   const cr = Cc["@mozilla.org/chrome/chrome-registry;1"]
     .getService(Ci.nsIChromeRegistry);
   const uri = Services.io.newURI(CHROME_URL_ROOT + path);
   const fileurl = cr.convertChromeURL(uri);
   return fileurl.QueryInterface(Ci.nsIFileURL);
 }
 
+async function enableExtensionDebugging() {
+  // Force enabling of addons debugging
+  await pushPref("devtools.chrome.enabled", true);
+  await pushPref("devtools.debugger.remote-enabled", true);
+  // Disable security prompt
+  await pushPref("devtools.debugger.prompt-connection", false);
+  // Enable Browser toolbox test script execution via env variable
+  await pushPref("devtools.browser-toolbox.allow-unsafe-script", true);
+}
+/* exported enableExtensionDebugging */
+
 /**
  * Install a temporary extension at the provided path, with the provided name.
  * Will use a mock file picker to select the file.
  */
 async function installTemporaryExtension(path, name, document) {
   // Mock the file picker to select a test addon
   prepareMockFilePicker(path);
 
@@ -37,16 +48,36 @@ async function installTemporaryExtension
   // Trigger the file picker by clicking on the button
   document.querySelector(".js-temporary-extension-install-button").click();
 
   info("Wait for addon to be installed");
   await onAddonInstalled;
 }
 /* exported installTemporaryExtension */
 
+/**
+ * Install a fake temporary extension just using the manifest information.
+ * @return {TemporaryExtension} the temporary extension instance created
+ */
+async function installTemporaryExtensionFromManifest(manifest, document) {
+  const addonId = manifest.applications.gecko.id;
+  const temporaryExtension = new TemporaryExtension(addonId);
+  temporaryExtension.writeManifest(manifest);
+  registerCleanupFunction(() => temporaryExtension.remove(false));
+
+  info("Install a temporary extension");
+  await AddonManager.installTemporaryAddon(temporaryExtension.sourceDir);
+
+  info("Wait until the corresponding debug target item appears");
+  await waitUntil(() => findDebugTargetByText(manifest.name, document));
+
+  return temporaryExtension;
+}
+/* exported installTemporaryExtensionFromManifest */
+
 async function removeTemporaryExtension(name, document) {
   info(`Remove the temporary extension with name: '${name}'`);
   const temporaryExtensionItem = findDebugTargetByText(name, document);
   temporaryExtensionItem.querySelector(".js-temporary-extension-remove-button").click();
 
   info("Wait until the debug target item disappears");
   await waitUntil(() => !findDebugTargetByText(name, document));
 }