Bug 1380855 - Fix intermittency and speed up devtools panel webextension test. draft
authorLuca Greco <lgreco@mozilla.com>
Fri, 05 Jan 2018 19:16:53 +0100
changeset 717191 c781c5591afe3e95549d087dfc893d31136185c8
parent 717183 ca379fcca95b1f4a3744242ea8647004b99b3507
child 745181 38a3cc5e8a3044c4833d89451c06dacd4e0ff635
push id94592
push userluca.greco@alcacoop.it
push dateMon, 08 Jan 2018 11:36:10 +0000
bugs1380855
milestone59.0a1
Bug 1380855 - Fix intermittency and speed up devtools panel webextension test. MozReview-Commit-ID: 27DFuD9hYUa
browser/components/extensions/test/browser/browser_ext_devtools_panel.js
--- a/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
+++ b/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
@@ -35,16 +35,45 @@ async function testThemeSwitching(extens
          `The onThemeChanged event listener fired for the ${location}.`);
       is(await extension.awaitMessage(`current_theme_${location}`),
          newTheme,
          `The current theme is reported as expected for the ${location}.`);
     }
   }
 }
 
+add_task(async function setup_blank_panel() {
+  // Create a blank custom tool so that we don't need to wait the webconsole
+  // to be fully loaded/unloaded to prevent intermittent failures (related
+  // to a webconsole that is still loading when the test has been completed).
+  const testBlankPanel = {
+    id: "testBlankPanel",
+    url: "about:blank",
+    label: "Blank Tool",
+    isTargetSupported() {
+      return true;
+    },
+    build(iframeWindow, toolbox) {
+      return Promise.resolve({
+        target: toolbox.target,
+        toolbox: toolbox,
+        isReady: true,
+        panelDoc: iframeWindow.document,
+        destroy() {},
+      });
+    },
+  };
+
+  registerCleanupFunction(() => {
+    gDevTools.unregisterTool(testBlankPanel.id);
+  });
+
+  gDevTools.registerTool(testBlankPanel);
+});
+
 add_task(async function test_theme_name_no_panel() {
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
 
   async function devtools_page() {
     browser.devtools.panels.onThemeChanged.addListener(themeName => {
       browser.test.sendMessage("devtools_theme_changed_page", themeName);
       browser.test.sendMessage("current_theme_page", browser.devtools.panels.themeName);
     });
@@ -71,17 +100,17 @@ add_task(async function test_theme_name_
   });
 
   // Ensure that the initial value of the devtools theme is "light".
   await SpecialPowers.pushPrefEnv({set: [[DEVTOOLS_THEME_PREF, "light"]]});
 
   await extension.startup();
 
   let target = gDevTools.getTargetForTab(tab);
-  await gDevTools.showToolbox(target, "webconsole");
+  await gDevTools.showToolbox(target, "testBlankPanel");
   info("developer toolbox opened");
 
   is(await extension.awaitMessage("initial_theme"),
      "light",
      "The initial theme is reported as expected.");
 
   await testThemeSwitching(extension);
 
@@ -191,17 +220,17 @@ add_task(async function test_devtools_pa
 
   // Ensure that the initial value of the devtools theme is "light".
   Preferences.set(DEVTOOLS_THEME_PREF, "light");
 
   await extension.startup();
 
   let target = gDevTools.getTargetForTab(tab);
 
-  const toolbox = await gDevTools.showToolbox(target, "webconsole");
+  const toolbox = await gDevTools.showToolbox(target, "testBlankPanel");
   info("developer toolbox opened");
 
   await extension.awaitMessage("devtools_panel_created");
   is(await extension.awaitMessage("initial_theme_page"),
      "light",
      "The initial theme is reported as expected from a devtools page.");
 
   const toolboxAdditionalTools = toolbox.getAdditionalTools();
@@ -221,29 +250,29 @@ add_task(async function test_devtools_pa
      "Got the same devtools.inspectedWindow.tabId from devtools page and panel");
   is(await extension.awaitMessage("initial_theme_panel"),
      "light",
      "The initial theme is reported as expected from a devtools panel.");
   info("Addon Devtools Panel shown");
 
   await testThemeSwitching(extension, ["page", "panel"]);
 
-  await gDevTools.showToolbox(target, "webconsole");
+  await gDevTools.showToolbox(target, "testBlankPanel");
   const results = await extension.awaitMessage("devtools_panel_hidden");
   info("Addon Devtools Panel hidden");
 
   is(results.panelCreated, 1, "devtools.panel.create callback has been called once");
   is(results.panelShown, 1, "panel.onShown listener has been called once");
   is(results.panelHidden, 1, "panel.onHidden listener has been called once");
 
   await gDevTools.showToolbox(target, panelId);
   await extension.awaitMessage("devtools_panel_shown");
   info("Addon Devtools Panel shown - second cycle");
 
-  await gDevTools.showToolbox(target, "webconsole");
+  await gDevTools.showToolbox(target, "testBlankPanel");
   const secondCycleResults = await extension.awaitMessage("devtools_panel_hidden");
   info("Addon Devtools Panel hidden - second cycle");
 
   is(secondCycleResults.panelCreated, 1, "devtools.panel.create callback has been called once");
   is(secondCycleResults.panelShown, 2, "panel.onShown listener has been called twice");
   is(secondCycleResults.panelHidden, 2, "panel.onHidden listener has been called twice");
 
   // Turn off the addon devtools panel using the visibilityswitch.
@@ -286,17 +315,17 @@ add_task(async function test_devtools_pa
      "The initial theme is reported as expected from a devtools panel.");
   info("Addon Devtools Panel shown - after visibilityswitch toggled");
 
   info("Wait until the Addon Devtools Panel has been loaded - after visibilityswitch toggled");
   const panelTabIdAfterToggle = await extension.awaitMessage("devtools_panel_inspectedWindow_tabId");
   is(panelTabIdAfterToggle, devtoolsPageTabId,
      "Got the same devtools.inspectedWindow.tabId from devtools panel after visibility toggled");
 
-  await gDevTools.showToolbox(target, "webconsole");
+  await gDevTools.showToolbox(target, "testBlankPanel");
   const toolToggledResults = await extension.awaitMessage("devtools_panel_hidden");
   info("Addon Devtools Panel hidden - after visibilityswitch toggled");
 
   is(toolToggledResults.panelCreated, 1, "devtools.panel.create callback has been called once");
   is(toolToggledResults.panelShown, 3, "panel.onShown listener has been called three times");
   is(toolToggledResults.panelHidden, 3, "panel.onHidden listener has been called three times");
 
   await gDevTools.closeToolbox(target);
@@ -364,17 +393,17 @@ add_task(async function test_devtools_pa
     },
   });
 
   await extension.startup();
 
 
   let target = gDevTools.getTargetForTab(tab);
 
-  const toolbox = await gDevTools.showToolbox(target, "webconsole");
+  const toolbox = await gDevTools.showToolbox(target, "testBlankPanel");
   info("developer toolbox opened");
 
   await extension.awaitMessage("devtools_panel_created");
 
   const toolboxAdditionalTools = toolbox.getAdditionalTools();
 
   is(toolboxAdditionalTools.length, 1,
      "Got the expected number of toolbox specific panel registered.");
@@ -433,32 +462,38 @@ add_task(async function test_devtools_pa
 
 add_task(async function test_devtools_page_invalid_panel_urls() {
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
 
   async function devtools_page() {
     const matchInvalidPanelURL = /must be a relative URL/;
     const matchInvalidIconURL = /be one of \[""\], or match the format "strictRelativeUrl"/;
 
-    const test_cases = [
-      // Invalid panel urls (validated by the schema wrappers, throws on invalid urls).
+    // Invalid panel urls (validated by the schema wrappers, throws on invalid urls).
+    const invalid_panels = [
       {panel: "about:about", icon: "icon.png", expectError: matchInvalidPanelURL},
       {panel: "about:addons", icon: "icon.png", expectError: matchInvalidPanelURL},
       {panel: "http://mochi.test:8888", icon: "icon.png", expectError: matchInvalidPanelURL},
       // Invalid icon urls (validated inside the API method because of the empty icon string
       // which have to be resolved to the default icon, reject the returned promise).
       {panel: "panel.html", icon: "about:about", expectError: matchInvalidIconURL},
       {panel: "panel.html", icon: "http://mochi.test:8888", expectError: matchInvalidIconURL},
-      // Valid panel urls
+    ];
+
+    const valid_panels = [
       {panel: "panel.html", icon: "icon.png"},
       {panel: "./panel.html", icon: "icon.png"},
       {panel: "/panel.html", icon: "icon.png"},
       {panel: "/panel.html", icon: ""},
     ];
 
+    let valid_panels_length = valid_panels.length;
+
+    const test_cases = [].concat(invalid_panels, valid_panels);
+
     browser.test.onMessage.addListener(async msg => {
       if (msg !== "start_test_panel_create") {
         return;
       }
 
       for (let {panel, icon, expectError} of test_cases) {
         browser.test.log(`Testing devtools.panels.create for ${JSON.stringify({panel, icon})}`);
 
@@ -471,32 +506,36 @@ add_task(async function test_devtools_pa
             `panel url ${panel} and icon ${icon}`
           );
         } else {
           // Verify that with valid panel and icon urls the panel is created and loaded
           // as expected.
           try {
             const pane = await browser.devtools.panels.create("Test Panel", icon, panel);
 
+            valid_panels_length--;
+
             // Wait the panel to be loaded.
             const oncePanelLoaded = new Promise(resolve => {
               pane.onShown.addListener(paneWin => {
                 browser.test.assertTrue(
                   paneWin.location.href.endsWith("/panel.html"),
                   `The panel has loaded the expected extension URL with ${panel}`);
                 resolve();
               });
             });
 
             // Ask the privileged code to select the last created panel.
-            browser.test.sendMessage("select-devtools-panel");
+            const done = valid_panels_length === 0;
+            browser.test.sendMessage("select-devtools-panel", done);
             await oncePanelLoaded;
           } catch (err) {
             browser.test.fail("Unexpected failure on creating a devtools panel with " +
                               `panel url ${panel} and icon ${icon}`);
+            throw err;
           }
         }
       }
 
       browser.test.sendMessage("test_invalid_devtools_panel_urls_done");
     });
 
     browser.test.sendMessage("devtools_page_ready");
@@ -533,31 +572,37 @@ add_task(async function test_devtools_pa
       "default-icon.png": imageBuffer,
     },
   });
 
   await extension.startup();
 
   let target = gDevTools.getTargetForTab(tab);
 
-  let toolbox = await gDevTools.showToolbox(target, "webconsole");
-
-  extension.onMessage("select-devtools-panel", () => {
-    const toolboxAdditionalTools = toolbox.getAdditionalTools();
-    const lastTool = toolboxAdditionalTools[toolboxAdditionalTools.length - 1];
-
-    gDevTools.showToolbox(target, lastTool.id);
-  });
+  let toolbox = await gDevTools.showToolbox(target, "testBlankPanel");
 
   info("developer toolbox opened");
 
   await extension.awaitMessage("devtools_page_ready");
 
   extension.sendMessage("start_test_panel_create");
 
+  let done = false;
+
+  while (!done) {
+    info("Waiting test extension request to select the last created panel");
+    done = await extension.awaitMessage("select-devtools-panel");
+
+    const toolboxAdditionalTools = toolbox.getAdditionalTools();
+    const lastTool = toolboxAdditionalTools[toolboxAdditionalTools.length - 1];
+
+    gDevTools.showToolbox(target, lastTool.id);
+    info("Last created panel selected");
+  }
+
   await extension.awaitMessage("test_invalid_devtools_panel_urls_done");
 
   await gDevTools.closeToolbox(target);
   await target.destroy();
 
   await extension.unload();
 
   await BrowserTestUtils.removeTab(tab);