summaryrefslogtreecommitdiffstats
path: root/browser/components/reportbrokensite/test/browser/head.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/reportbrokensite/test/browser/head.js')
-rw-r--r--browser/components/reportbrokensite/test/browser/head.js863
1 files changed, 863 insertions, 0 deletions
diff --git a/browser/components/reportbrokensite/test/browser/head.js b/browser/components/reportbrokensite/test/browser/head.js
new file mode 100644
index 0000000000..e3f4451b5b
--- /dev/null
+++ b/browser/components/reportbrokensite/test/browser/head.js
@@ -0,0 +1,863 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const { CustomizableUITestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/CustomizableUITestUtils.sys.mjs"
+);
+
+const { UrlClassifierTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/UrlClassifierTestUtils.sys.mjs"
+);
+
+const BASE_URL =
+ "https://example.com/browser/browser/components/reportbrokensite/test/browser/";
+
+const REPORTABLE_PAGE_URL = "https://example.com";
+
+const REPORTABLE_PAGE_URL2 = REPORTABLE_PAGE_URL.replace(".com", ".org");
+
+const REPORTABLE_PAGE_URL3 = `${BASE_URL}example_report_page.html`;
+
+const NEW_REPORT_ENDPOINT_TEST_URL = `${BASE_URL}sendMoreInfoTestEndpoint.html`;
+
+const PREFS = {
+ DATAREPORTING_ENABLED: "datareporting.healthreport.uploadEnabled",
+ REPORTER_ENABLED: "ui.new-webcompat-reporter.enabled",
+ REASON: "ui.new-webcompat-reporter.reason-dropdown",
+ SEND_MORE_INFO: "ui.new-webcompat-reporter.send-more-info-link",
+ NEW_REPORT_ENDPOINT: "ui.new-webcompat-reporter.new-report-endpoint",
+ REPORT_SITE_ISSUE_ENABLED: "extensions.webcompat-reporter.enabled",
+ PREFERS_CONTRAST_ENABLED: "layout.css.prefers-contrast.enabled",
+ USE_ACCESSIBILITY_THEME: "ui.useAccessibilityTheme",
+};
+
+function add_common_setup() {
+ add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [[PREFS.NEW_REPORT_ENDPOINT, NEW_REPORT_ENDPOINT_TEST_URL]],
+ });
+ registerCleanupFunction(function () {
+ for (const prefName of Object.values(PREFS)) {
+ Services.prefs.clearUserPref(prefName);
+ }
+ });
+ });
+}
+
+function areObjectsEqual(actual, expected, path = "") {
+ if (typeof expected == "function") {
+ try {
+ const passes = expected(actual);
+ if (!passes) {
+ info(`${path} not pass check function: ${actual}`);
+ }
+ return passes;
+ } catch (e) {
+ info(`${path} threw exception:
+ got: ${typeof actual}, ${actual}
+ expected: ${typeof expected}, ${expected}
+ exception: ${e.message}
+ ${e.stack}`);
+ return false;
+ }
+ }
+
+ if (typeof actual != typeof expected) {
+ info(`${path} types do not match:
+ got: ${typeof actual}, ${actual}
+ expected: ${typeof expected}, ${expected}`);
+ return false;
+ }
+ if (typeof actual != "object" || actual === null || expected === null) {
+ if (actual !== expected) {
+ info(`${path} does not match
+ got: ${typeof actual}, ${actual}
+ expected: ${typeof expected}, ${expected}`);
+ return false;
+ }
+ return true;
+ }
+ const prefix = path ? `${path}.` : path;
+ for (const [key, val] of Object.entries(actual)) {
+ if (!(key in expected)) {
+ info(`Extra ${prefix}${key}: ${val}`);
+ return false;
+ }
+ }
+ let result = true;
+ for (const [key, expectedVal] of Object.entries(expected)) {
+ if (key in actual) {
+ if (!areObjectsEqual(actual[key], expectedVal, `${prefix}${key}`)) {
+ result = false;
+ }
+ } else {
+ info(`Missing ${prefix}${key} (${expectedVal})`);
+ result = false;
+ }
+ }
+ return result;
+}
+
+function clickAndAwait(toClick, evt, target) {
+ const menuPromise = BrowserTestUtils.waitForEvent(target, evt);
+ EventUtils.synthesizeMouseAtCenter(toClick, {}, window);
+ return menuPromise;
+}
+
+async function openTab(url, win) {
+ const options = {
+ gBrowser:
+ win?.gBrowser ||
+ Services.wm.getMostRecentWindow("navigator:browser").gBrowser,
+ url,
+ };
+ return BrowserTestUtils.openNewForegroundTab(options);
+}
+
+async function changeTab(tab, url) {
+ BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, url);
+ await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+}
+
+function closeTab(tab) {
+ BrowserTestUtils.removeTab(tab);
+}
+
+function switchToWindow(win) {
+ const promises = [
+ BrowserTestUtils.waitForEvent(win, "focus"),
+ BrowserTestUtils.waitForEvent(win, "activate"),
+ ];
+ win.focus();
+ return Promise.all(promises);
+}
+
+function isSelectedTab(win, tab) {
+ const selectedTab = win.document.querySelector(".tabbrowser-tab[selected]");
+ is(selectedTab, tab);
+}
+
+function ensureReportBrokenSitePreffedOn() {
+ Services.prefs.setBoolPref(PREFS.DATAREPORTING_ENABLED, true);
+ Services.prefs.setBoolPref(PREFS.REPORTER_ENABLED, true);
+ ensureReasonDisabled();
+}
+
+function ensureReportBrokenSitePreffedOff() {
+ Services.prefs.setBoolPref(PREFS.REPORTER_ENABLED, false);
+}
+
+function ensureReportSiteIssuePreffedOn() {
+ Services.prefs.setBoolPref(PREFS.REPORT_SITE_ISSUE_ENABLED, true);
+}
+
+function ensureReportSiteIssuePreffedOff() {
+ Services.prefs.setBoolPref(PREFS.REPORT_SITE_ISSUE_ENABLED, false);
+}
+
+function ensureSendMoreInfoEnabled() {
+ Services.prefs.setBoolPref(PREFS.SEND_MORE_INFO, true);
+}
+
+function ensureSendMoreInfoDisabled() {
+ Services.prefs.setBoolPref(PREFS.SEND_MORE_INFO, false);
+}
+
+function ensureReasonDisabled() {
+ Services.prefs.setIntPref(PREFS.REASON, 0);
+}
+
+function ensureReasonOptional() {
+ Services.prefs.setIntPref(PREFS.REASON, 1);
+}
+
+function ensureReasonRequired() {
+ Services.prefs.setIntPref(PREFS.REASON, 2);
+}
+
+function isMenuItemEnabled(menuItem, itemDesc) {
+ ok(!menuItem.hidden, `${itemDesc} menu item is shown`);
+ ok(!menuItem.disabled, `${itemDesc} menu item is enabled`);
+}
+
+function isMenuItemHidden(menuItem, itemDesc) {
+ ok(
+ !menuItem || menuItem.hidden || !BrowserTestUtils.isVisible(menuItem),
+ `${itemDesc} menu item is hidden`
+ );
+}
+
+function isMenuItemDisabled(menuItem, itemDesc) {
+ ok(!menuItem.hidden, `${itemDesc} menu item is shown`);
+ ok(menuItem.disabled, `${itemDesc} menu item is disabled`);
+}
+
+class ReportBrokenSiteHelper {
+ sourceMenu = undefined;
+ win = undefined;
+
+ constructor(sourceMenu) {
+ this.sourceMenu = sourceMenu;
+ this.win = sourceMenu.win;
+ }
+
+ getViewNode(id) {
+ return PanelMultiView.getViewNode(this.win.document, id);
+ }
+
+ get mainView() {
+ return this.getViewNode("report-broken-site-popup-mainView");
+ }
+
+ get sentView() {
+ return this.getViewNode("report-broken-site-popup-reportSentView");
+ }
+
+ get openPanel() {
+ return this.mainView?.closest("panel");
+ }
+
+ get opened() {
+ return this.openPanel?.hasAttribute("panelopen");
+ }
+
+ async open(triggerMenuItem) {
+ const window = triggerMenuItem.ownerGlobal;
+ const shownPromise = BrowserTestUtils.waitForEvent(
+ this.mainView,
+ "ViewShown"
+ );
+ const focusPromise = BrowserTestUtils.waitForEvent(this.URLInput, "focus");
+ await EventUtils.synthesizeMouseAtCenter(triggerMenuItem, {}, window);
+ await shownPromise;
+ await focusPromise;
+ }
+
+ async #assertClickAndViewChanges(button, view, newView, newFocus) {
+ ok(view.closest("panel").hasAttribute("panelopen"), "Panel is open");
+ ok(BrowserTestUtils.isVisible(button), "Button is visible");
+ ok(!button.disabled, "Button is enabled");
+ const promises = [];
+ if (newView) {
+ if (newView.nodeName == "panel") {
+ promises.push(BrowserTestUtils.waitForEvent(newView, "popupshown"));
+ } else {
+ promises.push(BrowserTestUtils.waitForEvent(newView, "ViewShown"));
+ }
+ } else {
+ promises.push(BrowserTestUtils.waitForEvent(view, "ViewHiding"));
+ }
+ if (newFocus) {
+ promises.push(BrowserTestUtils.waitForEvent(newFocus, "focus"));
+ }
+ EventUtils.synthesizeMouseAtCenter(button, {}, this.win);
+ await Promise.all(promises);
+ }
+
+ async awaitReportSentViewOpened() {
+ await Promise.all([
+ BrowserTestUtils.waitForEvent(this.sentView, "ViewShown"),
+ BrowserTestUtils.waitForEvent(this.okayButton, "focus"),
+ ]);
+ }
+
+ async clickSend() {
+ await this.#assertClickAndViewChanges(
+ this.sendButton,
+ this.mainView,
+ this.sentView,
+ this.okayButton
+ );
+ }
+
+ waitForSendMoreInfoTab() {
+ return BrowserTestUtils.waitForNewTab(
+ this.win.gBrowser,
+ NEW_REPORT_ENDPOINT_TEST_URL
+ );
+ }
+
+ async clickSendMoreInfo() {
+ const newTabPromise = this.waitForSendMoreInfoTab();
+ EventUtils.synthesizeMouseAtCenter(this.sendMoreInfoLink, {}, this.win);
+ const newTab = await newTabPromise;
+ const receivedData = await SpecialPowers.spawn(
+ newTab.linkedBrowser,
+ [],
+ async function () {
+ await content.wrappedJSObject.messageArrived;
+ return content.wrappedJSObject.message;
+ }
+ );
+ this.win.gBrowser.removeCurrentTab();
+ return receivedData;
+ }
+
+ async clickCancel() {
+ await this.#assertClickAndViewChanges(this.cancelButton, this.mainView);
+ }
+
+ async clickOkay() {
+ await this.#assertClickAndViewChanges(this.okayButton, this.sentView);
+ }
+
+ async clickBack() {
+ await this.#assertClickAndViewChanges(
+ this.backButton,
+ this.sourceMenu.popup
+ );
+ }
+
+ isBackButtonEnabled() {
+ ok(BrowserTestUtils.isVisible(this.backButton), "Back button is visible");
+ ok(!this.backButton.disabled, "Back button is enabled");
+ }
+
+ close() {
+ if (this.opened) {
+ this.openPanel?.hidePopup(false);
+ }
+ this.sourceMenu?.close();
+ }
+
+ // UI element getters
+ get URLInput() {
+ return this.getViewNode("report-broken-site-popup-url");
+ }
+
+ get URLInvalidMessage() {
+ return this.getViewNode("report-broken-site-popup-invalid-url-msg");
+ }
+
+ get reasonInput() {
+ return this.getViewNode("report-broken-site-popup-reason");
+ }
+
+ get reasonDropdownPopup() {
+ return this.win.document.getElementById("ContentSelectDropdown").menupopup;
+ }
+
+ get reasonRequiredMessage() {
+ return this.getViewNode("report-broken-site-popup-missing-reason-msg");
+ }
+
+ get reasonLabelRequired() {
+ return this.getViewNode("report-broken-site-popup-reason-label");
+ }
+
+ get reasonLabelOptional() {
+ return this.getViewNode("report-broken-site-popup-reason-optional-label");
+ }
+
+ get descriptionTextarea() {
+ return this.getViewNode("report-broken-site-popup-description");
+ }
+
+ get sendMoreInfoLink() {
+ return this.getViewNode("report-broken-site-popup-send-more-info-link");
+ }
+
+ get backButton() {
+ return this.mainView.querySelector(".subviewbutton-back");
+ }
+
+ get sendButton() {
+ return this.getViewNode("report-broken-site-popup-send-button");
+ }
+
+ get cancelButton() {
+ return this.getViewNode("report-broken-site-popup-cancel-button");
+ }
+
+ get okayButton() {
+ return this.getViewNode("report-broken-site-popup-okay-button");
+ }
+
+ // Test helpers
+
+ #setInput(input, value) {
+ input.value = value;
+ input.dispatchEvent(
+ new UIEvent("input", { bubbles: true, view: this.win })
+ );
+ }
+
+ setURL(value) {
+ this.#setInput(this.URLInput, value);
+ }
+
+ chooseReason(value) {
+ const item = this.getViewNode(`report-broken-site-popup-reason-${value}`);
+ this.reasonInput.selectedIndex = item.index;
+ }
+
+ dismissDropdownPopup() {
+ const popup = this.reasonDropdownPopup;
+ const menuPromise = BrowserTestUtils.waitForPopupEvent(popup, "hidden");
+ popup.hidePopup();
+ return menuPromise;
+ }
+
+ setDescription(value) {
+ this.#setInput(this.descriptionTextarea, value);
+ }
+
+ isURL(expected) {
+ is(this.URLInput.value, expected);
+ }
+
+ isURLInvalidMessageShown() {
+ ok(
+ BrowserTestUtils.isVisible(this.URLInvalidMessage),
+ "'Please enter a valid URL' message is shown"
+ );
+ }
+
+ isURLInvalidMessageHidden() {
+ ok(
+ !BrowserTestUtils.isVisible(this.URLInvalidMessage),
+ "'Please enter a valid URL' message is hidden"
+ );
+ }
+
+ isReasonNeededMessageShown() {
+ ok(
+ BrowserTestUtils.isVisible(this.reasonRequiredMessage),
+ "'Please choose a reason' message is shown"
+ );
+ }
+
+ isReasonNeededMessageHidden() {
+ ok(
+ !BrowserTestUtils.isVisible(this.reasonRequiredMessage),
+ "'Please choose a reason' message is hidden"
+ );
+ }
+
+ isSendButtonEnabled() {
+ ok(BrowserTestUtils.isVisible(this.sendButton), "Send button is visible");
+ ok(!this.sendButton.disabled, "Send button is enabled");
+ }
+
+ isSendButtonDisabled() {
+ ok(BrowserTestUtils.isVisible(this.sendButton), "Send button is visible");
+ ok(this.sendButton.disabled, "Send button is disabled");
+ }
+
+ isSendMoreInfoShown() {
+ ok(
+ BrowserTestUtils.isVisible(this.sendMoreInfoLink),
+ "send more info is shown"
+ );
+ }
+
+ isSendMoreInfoHidden() {
+ ok(
+ !BrowserTestUtils.isVisible(this.sendMoreInfoLink),
+ "send more info is hidden"
+ );
+ }
+
+ isSendMoreInfoShownOrHiddenAppropriately() {
+ if (Services.prefs.getBoolPref(PREFS.SEND_MORE_INFO)) {
+ this.isSendMoreInfoShown();
+ } else {
+ this.isSendMoreInfoHidden();
+ }
+ }
+
+ isReasonHidden() {
+ ok(
+ !BrowserTestUtils.isVisible(this.reasonInput),
+ "reason drop-down is hidden"
+ );
+ ok(
+ !BrowserTestUtils.isVisible(this.reasonLabelOptional),
+ "optional reason label is hidden"
+ );
+ ok(
+ !BrowserTestUtils.isVisible(this.reasonLabelRequired),
+ "required reason label is hidden"
+ );
+ }
+
+ isReasonRequired() {
+ ok(
+ BrowserTestUtils.isVisible(this.reasonInput),
+ "reason drop-down is shown"
+ );
+ ok(
+ !BrowserTestUtils.isVisible(this.reasonLabelOptional),
+ "optional reason label is hidden"
+ );
+ ok(
+ BrowserTestUtils.isVisible(this.reasonLabelRequired),
+ "required reason label is shown"
+ );
+ }
+
+ isReasonOptional() {
+ ok(
+ BrowserTestUtils.isVisible(this.reasonInput),
+ "reason drop-down is shown"
+ );
+ ok(
+ BrowserTestUtils.isVisible(this.reasonLabelOptional),
+ "optional reason label is shown"
+ );
+ ok(
+ !BrowserTestUtils.isVisible(this.reasonLabelRequired),
+ "required reason label is hidden"
+ );
+ }
+
+ isReasonShownOrHiddenAppropriately() {
+ const pref = Services.prefs.getIntPref(PREFS.REASON);
+ if (pref == 2) {
+ this.isReasonOptional();
+ } else if (pref == 1) {
+ this.isReasonOptional();
+ } else {
+ this.isReasonHidden();
+ }
+ }
+
+ isDescription(expected) {
+ return this.descriptionTextarea.value == expected;
+ }
+
+ isMainViewResetToCurrentTab() {
+ this.isURL(this.win.gBrowser.selectedBrowser.currentURI.spec);
+ this.isDescription("");
+ this.isReasonShownOrHiddenAppropriately();
+ this.isSendMoreInfoShownOrHiddenAppropriately();
+ }
+}
+
+class MenuHelper {
+ menuDescription = undefined;
+
+ win = undefined;
+
+ constructor(win = window) {
+ this.win = win;
+ }
+
+ getViewNode(id) {
+ return PanelMultiView.getViewNode(this.win.document, id);
+ }
+
+ get showsBackButton() {
+ return true;
+ }
+
+ get reportBrokenSite() {}
+
+ get reportSiteIssue() {}
+
+ get popup() {}
+
+ get opened() {
+ return this.popup?.hasAttribute("panelopen");
+ }
+
+ async open() {}
+
+ async close() {}
+
+ isReportBrokenSiteDisabled() {
+ return isMenuItemDisabled(this.reportBrokenSite, this.menuDescription);
+ }
+
+ isReportBrokenSiteEnabled() {
+ return isMenuItemEnabled(this.reportBrokenSite, this.menuDescription);
+ }
+
+ isReportBrokenSiteHidden() {
+ return isMenuItemHidden(this.reportBrokenSite, this.menuDescription);
+ }
+
+ isReportSiteIssueDisabled() {
+ return isMenuItemDisabled(this.reportSiteIssue, this.menuDescription);
+ }
+
+ isReportSiteIssueEnabled() {
+ return isMenuItemEnabled(this.reportSiteIssue, this.menuDescription);
+ }
+
+ isReportSiteIssueHidden() {
+ return isMenuItemHidden(this.reportSiteIssue, this.menuDescription);
+ }
+
+ async openReportBrokenSite() {
+ if (!this.opened) {
+ await this.open();
+ }
+ isMenuItemEnabled(this.reportBrokenSite, this.menuDescription);
+ const rbs = new ReportBrokenSiteHelper(this);
+ await rbs.open(this.reportBrokenSite);
+ return rbs;
+ }
+
+ async openAndPrefillReportBrokenSite(url = null, description = "") {
+ let rbs = await this.openReportBrokenSite();
+ rbs.isMainViewResetToCurrentTab();
+ if (url) {
+ rbs.setURL(url);
+ }
+ if (description) {
+ rbs.setDescription(description);
+ }
+ return rbs;
+ }
+}
+
+class AppMenuHelper extends MenuHelper {
+ menuDescription = "AppMenu";
+
+ get reportBrokenSite() {
+ return this.getViewNode("appMenu-report-broken-site-button");
+ }
+
+ get reportSiteIssue() {
+ return undefined;
+ }
+
+ get popup() {
+ return this.win.document.getElementById("appMenu-popup");
+ }
+
+ async open() {
+ await new CustomizableUITestUtils(this.win).openMainMenu();
+ }
+
+ async close() {
+ if (this.opened) {
+ await new CustomizableUITestUtils(this.win).hideMainMenu();
+ }
+ }
+}
+
+class AppMenuHelpSubmenuHelper extends MenuHelper {
+ menuDescription = "AppMenu help sub-menu";
+
+ get reportBrokenSite() {
+ return this.getViewNode("appMenu_help_reportBrokenSite");
+ }
+
+ get reportSiteIssue() {
+ return this.getViewNode("appMenu_help_reportSiteIssue");
+ }
+
+ get popup() {
+ return this.win.document.getElementById("appMenu-popup");
+ }
+
+ async open() {
+ await new CustomizableUITestUtils(this.win).openMainMenu();
+
+ const anchor = this.win.document.getElementById("PanelUI-menu-button");
+ this.win.PanelUI.showHelpView(anchor);
+
+ const appMenuHelpSubview = this.getViewNode("PanelUI-helpView");
+ await BrowserTestUtils.waitForEvent(appMenuHelpSubview, "ViewShown");
+ }
+
+ async close() {
+ if (this.opened) {
+ await new CustomizableUITestUtils(this.win).hideMainMenu();
+ }
+ }
+}
+
+class HelpMenuHelper extends MenuHelper {
+ menuDescription = "Help Menu";
+
+ get showsBackButton() {
+ return false;
+ }
+
+ get reportBrokenSite() {
+ return this.win.document.getElementById("help_reportBrokenSite");
+ }
+
+ get reportSiteIssue() {
+ return this.win.document.getElementById("help_reportSiteIssue");
+ }
+
+ get popup() {
+ return this.getViewNode("PanelUI-helpView");
+ }
+
+ get helpMenu() {
+ return this.win.document.getElementById("menu_HelpPopup");
+ }
+
+ async openReportBrokenSite() {
+ // We can't actually open the Help menu properly in testing, so the best
+ // we can do to open its Report Broken Site panel is to force its DOM to be
+ // prepared, and then soft-click the Report Broken Site menuitem to open it.
+ await this.open();
+ const shownPromise = BrowserTestUtils.waitForEvent(
+ this.win,
+ "ViewShown",
+ true,
+ e => e.target.classList.contains("report-broken-site-view")
+ );
+ this.reportBrokenSite.click();
+ await shownPromise;
+ return new ReportBrokenSiteHelper(this);
+ }
+
+ async open() {
+ const { helpMenu } = this;
+ const promise = BrowserTestUtils.waitForEvent(helpMenu, "popupshown");
+
+ // This event-faking method was copied from browser_title_case_menus.js.
+ // We can't actually open the Help menu in testing, but this lets us
+ // force its DOM to be properly built.
+ helpMenu.dispatchEvent(new MouseEvent("popupshowing", { bubbles: true }));
+ helpMenu.dispatchEvent(new MouseEvent("popupshown", { bubbles: true }));
+
+ await promise;
+ }
+
+ async close() {
+ const { helpMenu } = this;
+ const promise = BrowserTestUtils.waitForPopupEvent(helpMenu, "hidden");
+
+ // (Also copied from browser_title_case_menus.js)
+ // Just for good measure, we'll fire the popuphiding/popuphidden events
+ // after we close the menupopups.
+ helpMenu.dispatchEvent(new MouseEvent("popuphiding", { bubbles: true }));
+ helpMenu.dispatchEvent(new MouseEvent("popuphidden", { bubbles: true }));
+
+ await promise;
+ }
+}
+
+class ProtectionsPanelHelper extends MenuHelper {
+ menuDescription = "Protections Panel";
+
+ get reportBrokenSite() {
+ this.win.gProtectionsHandler._initializePopup();
+ return this.getViewNode("protections-popup-report-broken-site-button");
+ }
+
+ get reportSiteIssue() {
+ return undefined;
+ }
+
+ get popup() {
+ this.win.gProtectionsHandler._initializePopup();
+ return this.win.document.getElementById("protections-popup");
+ }
+
+ async open() {
+ const promise = BrowserTestUtils.waitForEvent(
+ this.win,
+ "popupshown",
+ true,
+ e => e.target.id == "protections-popup"
+ );
+ this.win.gProtectionsHandler.showProtectionsPopup();
+ await promise;
+ }
+
+ async close() {
+ if (this.opened) {
+ const popup = this.popup;
+ const promise = BrowserTestUtils.waitForPopupEvent(popup, "hidden");
+ PanelMultiView.hidePopup(popup, false);
+ await promise;
+ }
+ }
+}
+
+function AppMenu(win = window) {
+ return new AppMenuHelper(win);
+}
+
+function AppMenuHelpSubmenu(win = window) {
+ return new AppMenuHelpSubmenuHelper(win);
+}
+
+function HelpMenu(win = window) {
+ return new HelpMenuHelper(win);
+}
+
+function ProtectionsPanel(win = window) {
+ return new ProtectionsPanelHelper(win);
+}
+
+function pressKeyAndAwait(event, key, config = {}) {
+ const win = config.window || window;
+ if (!event.then) {
+ event = BrowserTestUtils.waitForEvent(win, event, config.timeout || 200);
+ }
+ EventUtils.synthesizeKey(key, config, win);
+ return event;
+}
+
+async function pressKeyAndGetFocus(key, config = {}) {
+ return (await pressKeyAndAwait("focus", key, config)).target;
+}
+
+async function tabTo(match, win = window) {
+ const config = { window: win };
+ const { activeElement } = win.document;
+ if (activeElement?.matches(match)) {
+ return activeElement;
+ }
+ let initial = await pressKeyAndGetFocus("VK_TAB", config);
+ let target = initial;
+ do {
+ if (target.matches(match)) {
+ return target;
+ }
+ target = await pressKeyAndGetFocus("VK_TAB", config);
+ } while (target && target !== initial);
+ return undefined;
+}
+
+async function setupStrictETP(fn) {
+ await UrlClassifierTestUtils.addTestTrackers();
+ registerCleanupFunction(() => {
+ UrlClassifierTestUtils.cleanupTestTrackers();
+ });
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["security.mixed_content.block_active_content", true],
+ ["security.mixed_content.block_display_content", true],
+ ["security.mixed_content.upgrade_display_content", false],
+ [
+ "urlclassifier.trackingTable",
+ "content-track-digest256,mochitest2-track-simple",
+ ],
+ ],
+ });
+}
+
+// copied from browser/base/content/test/protectionsUI/head.js
+function waitForContentBlockingEvent(numChanges = 1, win = null) {
+ if (!win) {
+ win = window;
+ }
+ return new Promise(resolve => {
+ let n = 0;
+ let listener = {
+ onContentBlockingEvent(webProgress, request, event) {
+ n = n + 1;
+ info(
+ `Received onContentBlockingEvent event: ${event} (${n} of ${numChanges})`
+ );
+ if (n >= numChanges) {
+ win.gBrowser.removeProgressListener(listener);
+ resolve(n);
+ }
+ },
+ };
+ win.gBrowser.addProgressListener(listener);
+ });
+}