diff options
Diffstat (limited to '')
-rw-r--r-- | browser/components/customizableui/test/CustomizableUITestUtils.jsm | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/browser/components/customizableui/test/CustomizableUITestUtils.jsm b/browser/components/customizableui/test/CustomizableUITestUtils.jsm new file mode 100644 index 0000000000..89c32dbe08 --- /dev/null +++ b/browser/components/customizableui/test/CustomizableUITestUtils.jsm @@ -0,0 +1,167 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Shared functions generally available for tests involving PanelMultiView and + * the CustomizableUI elements in the browser window. + */ + +var EXPORTED_SYMBOLS = ["CustomizableUITestUtils"]; + +const { Assert } = ChromeUtils.importESModule( + "resource://testing-common/Assert.sys.mjs" +); +const { BrowserTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/BrowserTestUtils.sys.mjs" +); +const { TestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" +); + +const lazy = {}; + +ChromeUtils.defineModuleGetter( + lazy, + "CustomizableUI", + "resource:///modules/CustomizableUI.jsm" +); + +class CustomizableUITestUtils { + /** + * Constructs an instance that operates with the specified browser window. + */ + constructor(window) { + this.window = window; + this.document = window.document; + this.PanelUI = window.PanelUI; + } + + /** + * Opens a closed PanelMultiView via the specified function while waiting for + * the main view with the specified ID to become fully interactive. + */ + async openPanelMultiView(panel, mainView, openFn) { + if (panel.state == "open") { + // Some tests may intermittently leave the panel open. We report this, but + // don't fail so we don't introduce new intermittent test failures. + Assert.ok( + true, + "A previous test left the panel open. This should be" + + " fixed, but we can still do a best-effort recovery and" + + " assume that the requested view will be made visible." + ); + await openFn(); + return; + } + + if (panel.state == "hiding") { + // There may still be tests that don't wait after invoking a command that + // causes the main menu panel to close. Depending on timing, the panel may + // or may not be fully closed when the following test runs. We handle this + // case gracefully so we don't risk introducing new intermittent test + // failures that may show up at a later time. + Assert.ok( + true, + "A previous test requested the panel to close but" + + " didn't wait for the operation to complete. While" + + " the test should be fixed, we can still continue." + ); + } else { + Assert.equal(panel.state, "closed", "The panel is closed to begin with."); + } + + let promiseShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown"); + await openFn(); + await promiseShown; + } + + /** + * Closes an open PanelMultiView via the specified function while waiting for + * the operation to complete. + */ + async hidePanelMultiView(panel, closeFn) { + Assert.ok(panel.state == "open", "The panel is open to begin with."); + + let promiseHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden"); + await closeFn(); + await promiseHidden; + } + + /** + * Opens the main menu and waits for it to become fully interactive. + */ + async openMainMenu() { + await this.openPanelMultiView( + this.PanelUI.panel, + this.PanelUI.mainView, + () => this.PanelUI.show() + ); + } + + /** + * Closes the main menu and waits for the operation to complete. + */ + async hideMainMenu() { + await this.hidePanelMultiView(this.PanelUI.panel, () => + this.PanelUI.hide() + ); + } + + /** + * Add the search bar into the nav bar and verify it does not overflow. + * + * @returns {Promise} + * @resolves The search bar element. + * @rejects If search bar is not found, or overflows. + */ + async addSearchBar() { + lazy.CustomizableUI.addWidgetToArea( + "search-container", + lazy.CustomizableUI.AREA_NAVBAR, + lazy.CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1 + ); + + // addWidgetToArea adds the search bar into the nav bar first. If the + // search bar overflows, OverflowableToolbar for the nav bar moves the + // search bar into the overflow panel in its overflow event handler + // asynchronously. + // + // We should first wait for the layout flush to make sure either the search + // bar fits into the nav bar, or overflow event gets dispatched and the + // overflow event handler is called. + await this.window.promiseDocumentFlushed(() => {}); + + // Check if the OverflowableToolbar is handling the overflow event. + let navbar = this.window.document.getElementById( + lazy.CustomizableUI.AREA_NAVBAR + ); + await TestUtils.waitForCondition(() => { + return !navbar.overflowable.isHandlingOverflow(); + }); + + let searchbar = this.window.document.getElementById("searchbar"); + if (!searchbar) { + throw new Error("The search bar should exist."); + } + + // If the search bar overflows, it's placed inside the overflow panel. + // + // We cannot use navbar's property to check if overflow happens, since it + // can be different widget than the search bar that overflows. + if (searchbar.closest("#widget-overflow")) { + throw new Error( + "The search bar should not overflow from the nav bar. " + + "This test fails if the screen resolution is small and " + + "the search bar overflows from the nav bar." + ); + } + + return searchbar; + } + + removeSearchBar() { + lazy.CustomizableUI.removeWidgetFromArea("search-container"); + } +} |