summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/extensions/test/browser/browser_ext_devtools_panel.js')
-rw-r--r--browser/components/extensions/test/browser/browser_ext_devtools_panel.js812
1 files changed, 812 insertions, 0 deletions
diff --git a/browser/components/extensions/test/browser/browser_ext_devtools_panel.js b/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
new file mode 100644
index 0000000000..c9bf12b9fd
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_devtools_panel.js
@@ -0,0 +1,812 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+// Like most of the mochitest-browser devtools test,
+// on debug test machine, it takes about 50s to run the test.
+requestLongerTimeout(4);
+
+loadTestSubscript("head_devtools.js");
+
+ChromeUtils.defineESModuleGetters(this, {
+ Preferences: "resource://gre/modules/Preferences.sys.mjs",
+});
+
+const DEVTOOLS_THEME_PREF = "devtools.theme";
+
+/**
+ * This test file ensures that:
+ *
+ * - devtools.panels.themeName returns the correct value,
+ * both from a page and a panel.
+ * - devtools.panels.onThemeChanged fires for theme changes,
+ * both from a page and a panel.
+ * - devtools.panels.create is able to create a devtools panel.
+ */
+
+function createPage(jsScript, bodyText = "") {
+ return `<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body>
+ ${bodyText}
+ <script src="${jsScript}"></script>
+ </body>
+ </html>`;
+}
+
+async function test_theme_name(testWithPanel = false) {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "http://mochi.test:8888/"
+ );
+
+ function switchTheme(theme) {
+ const waitforThemeChanged = gDevTools.once("theme-changed");
+ Preferences.set(DEVTOOLS_THEME_PREF, theme);
+ return waitforThemeChanged;
+ }
+
+ async function testThemeSwitching(extension, locations = ["page"]) {
+ for (let newTheme of ["dark", "light"]) {
+ await switchTheme(newTheme);
+ for (let location of locations) {
+ is(
+ await extension.awaitMessage(`devtools_theme_changed_${location}`),
+ newTheme,
+ `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}.`
+ );
+ }
+ }
+ }
+
+ async function devtools_page(createPanel) {
+ if (createPanel) {
+ await browser.devtools.panels.create(
+ "Test Panel Theme",
+ "fake-icon.png",
+ "devtools_panel.html"
+ );
+ }
+
+ browser.devtools.panels.onThemeChanged.addListener(themeName => {
+ browser.test.sendMessage("devtools_theme_changed_page", themeName);
+ browser.test.sendMessage(
+ "current_theme_page",
+ browser.devtools.panels.themeName
+ );
+ });
+
+ browser.test.sendMessage(
+ "initial_theme_page",
+ browser.devtools.panels.themeName
+ );
+ }
+
+ async function devtools_panel() {
+ browser.devtools.panels.onThemeChanged.addListener(themeName => {
+ browser.test.sendMessage("devtools_theme_changed_panel", themeName);
+ browser.test.sendMessage(
+ "current_theme_panel",
+ browser.devtools.panels.themeName
+ );
+ });
+
+ browser.test.sendMessage(
+ "initial_theme_panel",
+ browser.devtools.panels.themeName
+ );
+ }
+
+ let files = {
+ "devtools_page.html": createPage("devtools_page.js"),
+ "devtools_page.js": `(${devtools_page})(${testWithPanel})`,
+ };
+
+ if (testWithPanel) {
+ files["devtools_panel.js"] = devtools_panel;
+ files["devtools_panel.html"] = createPage(
+ "devtools_panel.js",
+ "Test Panel Theme"
+ );
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ devtools_page: "devtools_page.html",
+ },
+ files,
+ });
+
+ // Ensure that the initial value of the devtools theme is "light".
+ await SpecialPowers.pushPrefEnv({ set: [[DEVTOOLS_THEME_PREF, "light"]] });
+ registerCleanupFunction(async function () {
+ await SpecialPowers.popPrefEnv();
+ });
+
+ await extension.startup();
+
+ const toolbox = await openToolboxForTab(tab);
+
+ info("Waiting initial theme from devtools_page");
+ is(
+ await extension.awaitMessage("initial_theme_page"),
+ "light",
+ "The initial theme is reported as expected."
+ );
+
+ if (testWithPanel) {
+ let toolboxAdditionalTools = toolbox.getAdditionalTools();
+ is(
+ toolboxAdditionalTools.length,
+ 1,
+ "Got the expected number of toolbox specific panel registered."
+ );
+
+ let panelId = toolboxAdditionalTools[0].id;
+
+ await gDevTools.showToolboxForTab(tab, { toolId: panelId });
+ is(
+ await extension.awaitMessage("initial_theme_panel"),
+ "light",
+ "The initial theme is reported as expected from a devtools panel."
+ );
+
+ await testThemeSwitching(extension, ["page", "panel"]);
+ } else {
+ await testThemeSwitching(extension);
+ }
+
+ await closeToolboxForTab(tab);
+
+ await extension.unload();
+
+ BrowserTestUtils.removeTab(tab);
+}
+
+add_task(async function test_devtools_page_theme() {
+ await test_theme_name(false);
+});
+
+add_task(async function test_devtools_panel_theme() {
+ await test_theme_name(true);
+});
+
+add_task(async function test_devtools_page_panels_create() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "http://mochi.test:8888/"
+ );
+
+ async function devtools_page() {
+ const result = {
+ devtoolsPageTabId: browser.devtools.inspectedWindow.tabId,
+ panelCreated: 0,
+ panelShown: 0,
+ panelHidden: 0,
+ };
+
+ try {
+ const panel = await browser.devtools.panels.create(
+ "Test Panel Create",
+ "fake-icon.png",
+ "devtools_panel.html"
+ );
+
+ result.panelCreated++;
+
+ panel.onShown.addListener(contentWindow => {
+ result.panelShown++;
+ browser.test.assertEq(
+ "complete",
+ contentWindow.document.readyState,
+ "Got the expected 'complete' panel document readyState"
+ );
+ browser.test.assertEq(
+ "test_panel_global",
+ contentWindow.TEST_PANEL_GLOBAL,
+ "Got the expected global in the panel contentWindow"
+ );
+ browser.test.sendMessage("devtools_panel_shown", result);
+ });
+
+ panel.onHidden.addListener(() => {
+ result.panelHidden++;
+
+ browser.test.sendMessage("devtools_panel_hidden", result);
+ });
+
+ browser.test.sendMessage("devtools_panel_created");
+ } catch (err) {
+ // Make the test able to fail fast when it is going to be a failure.
+ browser.test.sendMessage("devtools_panel_created");
+ throw err;
+ }
+ }
+
+ function devtools_panel() {
+ // Set a property in the global and check that it is defined
+ // and accessible from the devtools_page when the panel.onShown
+ // event has been received.
+ window.TEST_PANEL_GLOBAL = "test_panel_global";
+
+ browser.test.sendMessage(
+ "devtools_panel_inspectedWindow_tabId",
+ browser.devtools.inspectedWindow.tabId
+ );
+ }
+
+ const longPrefix = new Array(80).fill("x").join("");
+ // Extension ID includes "inspector" to verify Bug 1474379 doesn't regress.
+ const EXTENSION_ID = `${longPrefix}-inspector@create-devtools-panel.test`;
+
+ let extension = ExtensionTestUtils.loadExtension({
+ useAddonManager: "temporary",
+ manifest: {
+ devtools_page: "devtools_page.html",
+ browser_specific_settings: {
+ gecko: { id: EXTENSION_ID },
+ },
+ },
+ files: {
+ "devtools_page.html": createPage("devtools_page.js"),
+ "devtools_page.js": devtools_page,
+ "devtools_panel.html": createPage(
+ "devtools_panel.js",
+ "Test Panel Create"
+ ),
+ "devtools_panel.js": devtools_panel,
+ },
+ });
+
+ await extension.startup();
+
+ const extensionPrefBranch = `devtools.webextensions.${EXTENSION_ID}.`;
+ const extensionPrefName = `${extensionPrefBranch}enabled`;
+
+ let prefBranch = Services.prefs.getBranch(extensionPrefBranch);
+ ok(
+ prefBranch,
+ "The preference branch for the extension should have been created"
+ );
+ is(
+ prefBranch.getBoolPref("enabled", false),
+ true,
+ "The 'enabled' bool preference for the extension should be initially true"
+ );
+
+ // Get the devtools panel info for the first item in the toolbox additional tools array.
+ const getPanelInfo = toolbox => {
+ let toolboxAdditionalTools = toolbox.getAdditionalTools();
+ is(
+ toolboxAdditionalTools.length,
+ 1,
+ "Got the expected number of toolbox specific panel registered."
+ );
+ return toolboxAdditionalTools[0];
+ };
+
+ // Test the devtools panel shown and hide events.
+ const testPanelShowAndHide = async ({
+ tab,
+ panelId,
+ isFirstPanelLoad,
+ expectedResults,
+ }) => {
+ info("Wait Addon Devtools Panel to be shown");
+
+ await gDevTools.showToolboxForTab(tab, { toolId: panelId });
+ const { devtoolsPageTabId } = await extension.awaitMessage(
+ "devtools_panel_shown"
+ );
+
+ // If the panel is loaded for the first time, we expect to also
+ // receive the test messages and assert that both the page and the panel
+ // have the same devtools.inspectedWindow.tabId value.
+ if (isFirstPanelLoad) {
+ const devtoolsPanelTabId = await extension.awaitMessage(
+ "devtools_panel_inspectedWindow_tabId"
+ );
+ is(
+ devtoolsPanelTabId,
+ devtoolsPageTabId,
+ "Got the same devtools.inspectedWindow.tabId from devtools page and panel"
+ );
+ }
+
+ info("Wait Addon Devtools Panel to be shown");
+
+ await gDevTools.showToolboxForTab(tab, { toolId: "testBlankPanel" });
+ const results = await extension.awaitMessage("devtools_panel_hidden");
+
+ // We already checked the tabId, remove it from the results, so that we can check
+ // the remaining properties using a single Assert.deepEqual.
+ delete results.devtoolsPageTabId;
+
+ Assert.deepEqual(
+ results,
+ expectedResults,
+ "Got the expected number of created panels and shown/hidden events"
+ );
+ };
+
+ // Test the extension devtools_page enabling/disabling through the related
+ // about:config preference.
+ const testExtensionDevToolsPref = async ({
+ prefValue,
+ toolbox,
+ oldPanelId,
+ }) => {
+ if (!prefValue) {
+ // Test that the extension devtools_page is shutting down when the related
+ // about:config preference has been set to false, and the panel on its left
+ // is being selected.
+ info(
+ "Turning off the extension devtools page from its about:config preference"
+ );
+ let waitToolSelected = toolbox.once("select");
+ Services.prefs.setBoolPref(extensionPrefName, false);
+ const selectedTool = await waitToolSelected;
+ isnot(
+ selectedTool,
+ oldPanelId,
+ "Expect a different panel to be selected"
+ );
+
+ let toolboxAdditionalTools = toolbox.getAdditionalTools();
+ is(
+ toolboxAdditionalTools.length,
+ 0,
+ "Extension devtools panel unregistered"
+ );
+ is(
+ toolbox.visibleAdditionalTools.filter(toolId => toolId == oldPanelId)
+ .length,
+ 0,
+ "Removed panel should not be listed in the visible additional tools"
+ );
+ } else {
+ // Test that the extension devtools_page and panel are being created again when
+ // the related about:config preference has been set to true.
+ info(
+ "Turning on the extension devtools page from its about:config preference"
+ );
+ Services.prefs.setBoolPref(extensionPrefName, true);
+ await extension.awaitMessage("devtools_panel_created");
+
+ let toolboxAdditionalTools = toolbox.getAdditionalTools();
+ is(
+ toolboxAdditionalTools.length,
+ 1,
+ "Got one extension devtools panel registered"
+ );
+
+ let newPanelId = getPanelInfo(toolbox).id;
+ is(
+ toolbox.visibleAdditionalTools.filter(toolId => toolId == newPanelId)
+ .length,
+ 1,
+ "Extension panel is listed in the visible additional tools"
+ );
+ }
+ };
+
+ // Wait that the devtools_page has created its devtools panel and retrieve its
+ // panel id.
+ let toolbox = await openToolboxForTab(tab);
+ await extension.awaitMessage("devtools_panel_created");
+ let panelId = getPanelInfo(toolbox).id;
+
+ info("Test panel show and hide - first cycle");
+ await testPanelShowAndHide({
+ tab,
+ panelId,
+ isFirstPanelLoad: true,
+ expectedResults: {
+ panelCreated: 1,
+ panelShown: 1,
+ panelHidden: 1,
+ },
+ });
+
+ info("Test panel show and hide - second cycle");
+ await testPanelShowAndHide({
+ tab,
+ panelId,
+ isFirstPanelLoad: false,
+ expectedResults: {
+ panelCreated: 1,
+ panelShown: 2,
+ panelHidden: 2,
+ },
+ });
+
+ // Go back to the extension devtools panel.
+ await gDevTools.showToolboxForTab(tab, { toolId: panelId });
+ await extension.awaitMessage("devtools_panel_shown");
+
+ // Check that the aria-label has been set on the devtools panel.
+ const panelFrame = toolbox.doc.getElementById(
+ `toolbox-panel-iframe-${panelId}`
+ );
+ const panelInfo = getPanelInfo(toolbox);
+ ok(
+ panelInfo.panelLabel && !!panelInfo.panelLabel.length,
+ "Expect the registered panel to include a non empty panelLabel property"
+ );
+ is(
+ panelFrame && panelFrame.getAttribute("aria-label"),
+ panelInfo.panelLabel,
+ "Got the expected aria-label on the extension panel frame"
+ );
+
+ // Turn off the extension devtools page using the preference that enable/disable the
+ // devtools page for a given installed WebExtension.
+ await testExtensionDevToolsPref({
+ toolbox,
+ prefValue: false,
+ oldPanelId: panelId,
+ });
+
+ // Close and Re-open the toolbox to verify that the toolbox doesn't load the
+ // devtools_page and the devtools panel.
+ info("Re-open the toolbox and expect no extension devtools panel");
+ await closeToolboxForTab(tab);
+ toolbox = await openToolboxForTab(tab);
+
+ let toolboxAdditionalTools = toolbox.getAdditionalTools();
+ is(
+ toolboxAdditionalTools.length,
+ 0,
+ "Got no extension devtools panel on the opened toolbox as expected."
+ );
+
+ // Close and Re-open the toolbox to verify that the toolbox does load the
+ // devtools_page and the devtools panel again.
+ info("Restart the toolbox and enable the extension devtools panel");
+ await closeToolboxForTab(tab);
+ toolbox = await openToolboxForTab(tab);
+
+ // Turn the addon devtools panel back on using the preference that enable/disable the
+ // devtools page for a given installed WebExtension.
+ await testExtensionDevToolsPref({
+ toolbox,
+ prefValue: true,
+ });
+
+ // Test devtools panel is loaded correctly after being toggled and
+ // devtools panel events has been fired as expected.
+ panelId = getPanelInfo(toolbox).id;
+
+ info("Test panel show and hide - after disabling/enabling devtools_page");
+ await testPanelShowAndHide({
+ tab,
+ panelId,
+ isFirstPanelLoad: true,
+ expectedResults: {
+ panelCreated: 1,
+ panelShown: 1,
+ panelHidden: 1,
+ },
+ });
+
+ await closeToolboxForTab(tab);
+
+ await extension.unload();
+
+ // Verify that the extension preference branch has been removed once the extension
+ // has been uninstalled.
+ prefBranch = Services.prefs.getBranch(extensionPrefBranch);
+ is(
+ prefBranch.getPrefType("enabled"),
+ prefBranch.PREF_INVALID,
+ "The preference branch for the extension should have been removed"
+ );
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_devtools_page_panels_switch_toolbox_host() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "http://mochi.test:8888/"
+ );
+
+ function devtools_panel() {
+ const hasDevToolsAPINamespace = "devtools" in browser;
+
+ browser.test.sendMessage("devtools_panel_loaded", {
+ hasDevToolsAPINamespace,
+ panelLoadedURL: window.location.href,
+ });
+ }
+
+ async function devtools_page() {
+ const panel = await browser.devtools.panels.create(
+ "Test Panel Switch Host",
+ "fake-icon.png",
+ "devtools_panel.html"
+ );
+
+ panel.onShown.addListener(panelWindow => {
+ browser.test.sendMessage(
+ "devtools_panel_shown",
+ panelWindow.location.href
+ );
+ });
+
+ panel.onHidden.addListener(() => {
+ browser.test.sendMessage("devtools_panel_hidden");
+ });
+
+ browser.test.sendMessage("devtools_panel_created");
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ devtools_page: "devtools_page.html",
+ },
+ files: {
+ "devtools_page.html": createPage("devtools_page.js"),
+ "devtools_page.js": devtools_page,
+ "devtools_panel.html": createPage("devtools_panel.js", "DEVTOOLS PANEL"),
+ "devtools_panel.js": devtools_panel,
+ },
+ });
+
+ await extension.startup();
+
+ let toolbox = await openToolboxForTab(tab);
+ await extension.awaitMessage("devtools_panel_created");
+
+ const toolboxAdditionalTools = toolbox.getAdditionalTools();
+
+ is(
+ toolboxAdditionalTools.length,
+ 1,
+ "Got the expected number of toolbox specific panel registered."
+ );
+
+ const panelDef = toolboxAdditionalTools[0];
+ const panelId = panelDef.id;
+
+ info("Selecting the addon devtools panel");
+ await gDevTools.showToolboxForTab(tab, { toolId: panelId });
+
+ info("Wait for the panel to show and load for the first time");
+ const panelShownURL = await extension.awaitMessage("devtools_panel_shown");
+
+ const { panelLoadedURL, hasDevToolsAPINamespace } =
+ await extension.awaitMessage("devtools_panel_loaded");
+
+ is(
+ panelShownURL,
+ panelLoadedURL,
+ "Got the expected panel URL on the first load"
+ );
+ ok(
+ hasDevToolsAPINamespace,
+ "The devtools panel has the devtools API on the first load"
+ );
+
+ const originalToolboxHostType = toolbox.hostType;
+
+ info("Switch the toolbox from docked on bottom to docked on right");
+ toolbox.switchHost("right");
+
+ info(
+ "Wait for the panel to emit hide, show and load messages once docked on side"
+ );
+ await extension.awaitMessage("devtools_panel_hidden");
+ const dockedOnSideShownURL = await extension.awaitMessage(
+ "devtools_panel_shown"
+ );
+
+ is(
+ dockedOnSideShownURL,
+ panelShownURL,
+ "Got the expected panel url once the panel shown event has been emitted on toolbox host changed"
+ );
+
+ const dockedOnSideLoaded = await extension.awaitMessage(
+ "devtools_panel_loaded"
+ );
+
+ is(
+ dockedOnSideLoaded.panelLoadedURL,
+ panelShownURL,
+ "Got the expected panel url once the panel has been reloaded on toolbox host changed"
+ );
+ ok(
+ dockedOnSideLoaded.hasDevToolsAPINamespace,
+ "The devtools panel has the devtools API once the toolbox host has been changed"
+ );
+
+ info("Switch the toolbox from docked on bottom to the original dock mode");
+ toolbox.switchHost(originalToolboxHostType);
+
+ info(
+ "Wait for the panel test messages once toolbox dock mode has been restored"
+ );
+ await extension.awaitMessage("devtools_panel_hidden");
+ await extension.awaitMessage("devtools_panel_shown");
+ await extension.awaitMessage("devtools_panel_loaded");
+
+ await closeToolboxForTab(tab);
+
+ await extension.unload();
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+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"/;
+
+ // 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,
+ },
+ ];
+
+ 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,
+ })}`
+ );
+
+ if (expectError) {
+ // Verify that invalid panel urls throw.
+ browser.test.assertThrows(
+ () => browser.devtools.panels.create("Test Panel", icon, panel),
+ expectError,
+ "Got the expected rejection on creating a devtools panel with " +
+ `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.
+ 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");
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ devtools_page: "devtools_page.html",
+ icons: {
+ 32: "icon.png",
+ },
+ },
+ files: {
+ "devtools_page.html": createPage("devtools_page.js"),
+ "devtools_page.js": devtools_page,
+ "panel.html": createPage("panel.js", "DEVTOOLS PANEL"),
+ "panel.js": "",
+ "icon.png": imageBuffer,
+ "default-icon.png": imageBuffer,
+ },
+ });
+
+ await extension.startup();
+
+ let toolbox = await openToolboxForTab(tab);
+ 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.showToolboxForTab(tab, { toolId: lastTool.id });
+ info("Last created panel selected");
+ }
+
+ await extension.awaitMessage("test_invalid_devtools_panel_urls_done");
+
+ await closeToolboxForTab(tab);
+
+ await extension.unload();
+
+ BrowserTestUtils.removeTab(tab);
+});