summaryrefslogtreecommitdiffstats
path: root/browser/components/firefoxview/tests/browser/browser_opentabs_pinned_tabs.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/firefoxview/tests/browser/browser_opentabs_pinned_tabs.js')
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_pinned_tabs.js481
1 files changed, 481 insertions, 0 deletions
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_pinned_tabs.js b/browser/components/firefoxview/tests/browser/browser_opentabs_pinned_tabs.js
new file mode 100644
index 0000000000..d74812bca5
--- /dev/null
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_pinned_tabs.js
@@ -0,0 +1,481 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let pageWithAlert =
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ "http://example.com/browser/browser/base/content/test/tabPrompts/openPromptOffTimeout.html";
+let pageWithSound =
+ "http://mochi.test:8888/browser/dom/base/test/file_audioLoop.html";
+
+function cleanup() {
+ // Cleanup
+ while (gBrowser.tabs.length > 1) {
+ BrowserTestUtils.removeTab(gBrowser.tabs[1]);
+ }
+}
+
+const arrowDown = async tabList => {
+ info("Arrow down");
+ EventUtils.synthesizeKey("KEY_ArrowDown", {});
+ await tabList.getUpdateComplete();
+};
+const arrowUp = async tabList => {
+ info("Arrow up");
+ EventUtils.synthesizeKey("KEY_ArrowUp", {});
+ await tabList.getUpdateComplete();
+};
+const arrowRight = async tabList => {
+ info("Arrow right");
+ EventUtils.synthesizeKey("KEY_ArrowRight", {});
+ await tabList.getUpdateComplete();
+};
+const arrowLeft = async tabList => {
+ info("Arrow left");
+ EventUtils.synthesizeKey("KEY_ArrowLeft", {});
+ await tabList.getUpdateComplete();
+};
+
+add_task(async function test_pin_unpin_open_tab() {
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToViewAndWait(document, "opentabs");
+
+ let openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ await openTabs.updateComplete;
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length
+ );
+ await openTabs.openTabsTarget.readyWindowsPromise;
+ let card = openTabs.viewCards[0];
+ let openTabEl = card.tabList.rowEls[0];
+ let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Pin tab
+ EventUtils.synthesizeMouseAtCenter(
+ openTabEl.secondaryButtonEl,
+ {},
+ content
+ );
+ await TestUtils.waitForCondition(() => card.tabContextMenu.panelList);
+ let panelList = card.tabContextMenu.panelList;
+ await BrowserTestUtils.waitForEvent(panelList, "shown");
+ info("The context menu is shown when clicking the tab's 'more' button");
+
+ let pinTabPanelItem = panelList.querySelector(
+ "panel-item[data-l10n-id=fxviewtabrow-pin-tab]"
+ );
+
+ await clearAllParentTelemetryEvents();
+ let contextMenuEvent = [
+ [
+ "firefoxview_next",
+ "context_menu",
+ "tabs",
+ undefined,
+ { menu_action: "pin-tab", data_type: "opentabs" },
+ ],
+ ];
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Unpin tab
+ EventUtils.synthesizeMouseAtCenter(pinTabPanelItem, {}, content);
+ info("Pin Tab context menu option clicked.");
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ let pinnedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(() =>
+ pinnedTab.indicators.includes("pinned")
+ );
+
+ // Check aria roles
+ let listWrapper = card.tabList.shadowRoot.querySelector(".fxview-tab-list");
+ ok(
+ Array.from(listWrapper.classList).includes("pinned"),
+ "The tab list has the 'pinned' class as expected."
+ );
+
+ Assert.strictEqual(
+ listWrapper.getAttribute("role"),
+ "tablist",
+ "The list wrapper has an aria-role of 'tablist'"
+ );
+ Assert.strictEqual(
+ pinnedTab.pinnedTabButtonEl.getAttribute("role"),
+ "tab",
+ "The pinned tab's button element has a role of 'tab'"
+ );
+
+ // Open context menu
+ EventUtils.synthesizeMouseAtCenter(
+ pinnedTab,
+ { type: "contextmenu" },
+ content
+ );
+ await TestUtils.waitForCondition(() => card.tabContextMenu.panelList);
+ panelList = card.tabContextMenu.panelList;
+ await BrowserTestUtils.waitForEvent(panelList, "shown");
+ info("The context menu is shown when right clicking the pinned tab");
+
+ let unpinTabPanelItem = panelList.querySelector(
+ "panel-item[data-l10n-id=fxviewtabrow-unpin-tab]"
+ );
+
+ await clearAllParentTelemetryEvents();
+ contextMenuEvent = [
+ [
+ "firefoxview_next",
+ "context_menu",
+ "tabs",
+ undefined,
+ { menu_action: "unpin-tab", data_type: "opentabs" },
+ ],
+ ];
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Unpin tab
+ EventUtils.synthesizeMouseAtCenter(unpinTabPanelItem, {}, content);
+ info("Unpin Tab context menu option clicked.");
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+ await telemetryEvent(contextMenuEvent);
+ });
+ cleanup();
+});
+
+add_task(async function test_indicator_pinned_tabs_with_keyboard() {
+ await add_new_tab(URLs[0]);
+ await add_new_tab(URLs[1]);
+ await add_new_tab(pageWithSound);
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToViewAndWait(document, "opentabs");
+
+ let openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ await openTabs.updateComplete;
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length
+ );
+ await openTabs.openTabsTarget.readyWindowsPromise;
+ setSortOption(openTabs, "tabStripOrder");
+ let card = openTabs.viewCards[0];
+
+ let openedTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ pageWithAlert,
+ true
+ );
+ let openedTabGotAttentionPromise = BrowserTestUtils.waitForAttribute(
+ "attention",
+ openedTab
+ );
+
+ await switchToFxViewTab();
+
+ await openedTabGotAttentionPromise;
+
+ let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Pin 2 of 5 tabs
+ browser.ownerGlobal.gBrowser.tabs.forEach((tab, i) => {
+ if (i > 2) {
+ browser.ownerGlobal.gBrowser.pinTab(tab);
+ }
+ });
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ let soundPlayingPinnedTab = card.tabList.rowEls[0];
+ let attentionPinnedTab = card.tabList.rowEls[1];
+ let firstUnpinnedTab = card.tabList.rowEls[2];
+ let secondUnpinnedTab = card.tabList.rowEls[3];
+
+ // Check soundplaying indicator
+ ok(
+ soundPlayingPinnedTab.indicators.includes("pinned") &&
+ soundPlayingPinnedTab.indicators.includes("soundplaying") &&
+ soundPlayingPinnedTab.mediaButtonEl,
+ "The first pinned tab has the 'sound playing' indicator."
+ );
+
+ soundPlayingPinnedTab.pinnedTabButtonEl.focus();
+ ok(
+ isActiveElement(soundPlayingPinnedTab.pinnedTabButtonEl),
+ "Focus should be on the first pinned tab's button element."
+ );
+ info("First pinned tab has focus");
+
+ // Test mute/unmute
+ EventUtils.synthesizeKey("m", { ctrlKey: true });
+ await TestUtils.waitForCondition(() =>
+ soundPlayingPinnedTab.indicators.includes("muted")
+ );
+ EventUtils.synthesizeKey("m", { ctrlKey: true });
+ await TestUtils.waitForCondition(
+ () => !soundPlayingPinnedTab.indicators.includes("muted")
+ );
+
+ await arrowRight(card.tabList);
+ ok(
+ isActiveElement(attentionPinnedTab.pinnedTabButtonEl),
+ "Focus should be on the second pinned tab's button element."
+ );
+
+ // Check notification dot indicator
+ ok(
+ attentionPinnedTab.indicators.includes("pinned") &&
+ attentionPinnedTab.indicators.includes("attention") &&
+ Array.from(
+ attentionPinnedTab.shadowRoot.querySelector(
+ ".fxview-tab-row-favicon-wrapper"
+ ).classList
+ ).includes("attention"),
+ "The second pinned tab has the 'attention' indicator."
+ );
+
+ await arrowDown(card.tabList);
+ ok(
+ isActiveElement(firstUnpinnedTab.mainEl),
+ "Focus should be on the first unpinned tab's main/link element."
+ );
+
+ await arrowRight(card.tabList);
+ ok(
+ isActiveElement(firstUnpinnedTab.secondaryButtonEl),
+ "Focus should be on the first unpinned tab's secondary/more button element."
+ );
+
+ await arrowUp(card.tabList);
+ ok(
+ isActiveElement(attentionPinnedTab.pinnedTabButtonEl),
+ "Focus should be on the second pinned tab's button element."
+ );
+
+ await arrowRight(card.tabList);
+ ok(
+ isActiveElement(firstUnpinnedTab.secondaryButtonEl),
+ "Focus should be on the first unpinned tab's secondary/more button element."
+ );
+
+ await arrowUp(card.tabList);
+ ok(
+ isActiveElement(attentionPinnedTab.pinnedTabButtonEl),
+ "Focus should be on the second pinned tab's button element."
+ );
+
+ await arrowLeft(card.tabList);
+ ok(
+ isActiveElement(soundPlayingPinnedTab.pinnedTabButtonEl),
+ "Focus should be on the first pinned tab's button element."
+ );
+
+ await arrowDown(card.tabList);
+ ok(
+ isActiveElement(firstUnpinnedTab.secondaryButtonEl),
+ "Focus should be on the first unpinned tab's secondary/more button element."
+ );
+
+ await arrowDown(card.tabList);
+ ok(
+ isActiveElement(secondUnpinnedTab.secondaryButtonEl),
+ "Focus should be on the second unpinned tab's secondary/more button element."
+ );
+
+ // Switch back to other tab to close prompt before cleanup
+ await BrowserTestUtils.switchTab(gBrowser, openedTab);
+ EventUtils.synthesizeKey("KEY_Enter", {});
+ });
+ cleanup();
+});
+
+add_task(async function test_mute_unmute_pinned_tab() {
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToViewAndWait(document, "opentabs");
+
+ let openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ await openTabs.updateComplete;
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length
+ );
+ await openTabs.openTabsTarget.readyWindowsPromise;
+ let card = openTabs.viewCards[0];
+ let openTabEl = card.tabList.rowEls[0];
+ let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Mute tab
+ // We intentionally turn off this a11y check, because the following click
+ // is purposefully targeting a not focusable button within a pinned tab
+ // control. A keyboard-only user could mute/unmute this pinned tab via the
+ // context menu, while we do not want to create an additional, unnecessary
+ // tabstop for this control, therefore this rule check shall be ignored by
+ // a11y_checks suite.
+ AccessibilityUtils.setEnv({ focusableRule: false });
+ EventUtils.synthesizeMouseAtCenter(openTabEl.mediaButtonEl, {}, content);
+ AccessibilityUtils.resetEnv();
+ info("Mute Tab button clicked.");
+
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ let mutedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(() =>
+ mutedTab.indicators.includes("muted")
+ );
+
+ // Unmute tab
+ // We intentionally turn off this a11y check, because the following click
+ // is purposefully targeting a not focusable button within a pinned tab
+ // control. A keyboard-only user could mute/unmute this pinned tab via the
+ // context menu, while we do not want to create an additional, unnecessary
+ // tabstop for this control, therefore this rule check shall be ignored by
+ // a11y_checks suite.
+ AccessibilityUtils.setEnv({ focusableRule: false });
+ EventUtils.synthesizeMouseAtCenter(openTabEl.mediaButtonEl, {}, content);
+ AccessibilityUtils.resetEnv();
+ info("Unmute Tab button clicked.");
+
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ let unmutedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(
+ () => !unmutedTab.indicators.includes("muted")
+ );
+ });
+ cleanup();
+});
+
+add_task(async function test_mute_unmute_with_context_menu() {
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToViewAndWait(document, "opentabs");
+
+ let openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ await openTabs.updateComplete;
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length
+ );
+ await openTabs.openTabsTarget.readyWindowsPromise;
+ let card = openTabs.viewCards[0];
+ let openTabEl = card.tabList.rowEls[0];
+ let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Mute tab
+ EventUtils.synthesizeMouseAtCenter(
+ openTabEl.pinnedTabButtonEl,
+ { type: "contextmenu" },
+ content
+ );
+ await TestUtils.waitForCondition(() => card.tabContextMenu.panelList);
+ let panelList = card.tabContextMenu.panelList;
+ await BrowserTestUtils.waitForEvent(panelList, "shown");
+ info("The context menu is shown when clicking the tab's 'more' button");
+
+ let pinTabPanelItem = panelList.querySelector(
+ "panel-item[data-l10n-id=fxviewtabrow-mute-tab]"
+ );
+
+ await clearAllParentTelemetryEvents();
+ let contextMenuEvent = [
+ [
+ "firefoxview_next",
+ "context_menu",
+ "tabs",
+ undefined,
+ { menu_action: "mute-tab", data_type: "opentabs" },
+ ],
+ ];
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Mute tab
+ EventUtils.synthesizeMouseAtCenter(pinTabPanelItem, {}, content);
+ info("Mute Tab context menu option clicked.");
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ let mutedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(() =>
+ mutedTab.indicators.includes("muted")
+ );
+
+ // Open context menu
+ EventUtils.synthesizeMouseAtCenter(
+ mutedTab,
+ { type: "contextmenu" },
+ content
+ );
+ await TestUtils.waitForCondition(() => card.tabContextMenu.panelList);
+ panelList = card.tabContextMenu.panelList;
+ await BrowserTestUtils.waitForEvent(panelList, "shown");
+ info("The context menu is shown when right clicking the pinned tab");
+
+ let unmuteTabPanelItem = panelList.querySelector(
+ "panel-item[data-l10n-id=fxviewtabrow-unmute-tab]"
+ );
+
+ await clearAllParentTelemetryEvents();
+ contextMenuEvent = [
+ [
+ "firefoxview_next",
+ "context_menu",
+ "tabs",
+ undefined,
+ { menu_action: "unmute-tab", data_type: "opentabs" },
+ ],
+ ];
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Unpin tab
+ EventUtils.synthesizeMouseAtCenter(unmuteTabPanelItem, {}, content);
+ info("Unmute Tab context menu option clicked.");
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+ await telemetryEvent(contextMenuEvent);
+
+ let unmutedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(
+ () => !unmutedTab.indicators.includes("muted")
+ );
+ });
+ cleanup();
+});