summaryrefslogtreecommitdiffstats
path: root/browser/components/firefoxview/tests
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/firefoxview/tests')
-rw-r--r--browser/components/firefoxview/tests/browser/FirefoxViewTestUtils.sys.mjs17
-rw-r--r--browser/components/firefoxview/tests/browser/browser.toml45
-rw-r--r--browser/components/firefoxview/tests/browser/browser_dragDrop_after_opening_fxViewTab.js1
-rw-r--r--browser/components/firefoxview/tests/browser/browser_firefoxview.js5
-rw-r--r--browser/components/firefoxview/tests/browser/browser_firefoxview_general_telemetry.js42
-rw-r--r--browser/components/firefoxview/tests/browser/browser_firefoxview_navigation.js54
-rw-r--r--browser/components/firefoxview/tests/browser/browser_firefoxview_paused.js106
-rw-r--r--browser/components/firefoxview/tests/browser/browser_firefoxview_search_telemetry.js18
-rw-r--r--browser/components/firefoxview/tests/browser/browser_firefoxview_tab.js6
-rw-r--r--browser/components/firefoxview/tests/browser/browser_firefoxview_virtual_list.js2
-rw-r--r--browser/components/firefoxview/tests/browser/browser_history_firefoxview.js75
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_cards.js431
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_changes.js7
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js159
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_more.js151
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_pinned_tabs.js481
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_recency.js31
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_search.js161
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_tab_indicators.js128
-rw-r--r--browser/components/firefoxview/tests/browser/browser_recentlyclosed_firefoxview.js18
-rw-r--r--browser/components/firefoxview/tests/browser/browser_syncedtabs_errors_firefoxview.js4
-rw-r--r--browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js20
-rw-r--r--browser/components/firefoxview/tests/browser/browser_tab_list_keyboard_navigation.js334
-rw-r--r--browser/components/firefoxview/tests/browser/head.js83
-rw-r--r--browser/components/firefoxview/tests/chrome/chrome.toml2
-rw-r--r--browser/components/firefoxview/tests/chrome/test_fxview_category_navigation.html322
-rw-r--r--browser/components/firefoxview/tests/chrome/test_fxview_tab_list.html4
27 files changed, 1759 insertions, 948 deletions
diff --git a/browser/components/firefoxview/tests/browser/FirefoxViewTestUtils.sys.mjs b/browser/components/firefoxview/tests/browser/FirefoxViewTestUtils.sys.mjs
index 3fd2bf95e3..e1285c0396 100644
--- a/browser/components/firefoxview/tests/browser/FirefoxViewTestUtils.sys.mjs
+++ b/browser/components/firefoxview/tests/browser/FirefoxViewTestUtils.sys.mjs
@@ -21,6 +21,20 @@ function getFirefoxViewURL() {
return "about:firefoxview";
}
+/**
+ * Make the given window focused and active
+ */
+async function switchToWindow(win) {
+ await testScope.SimpleTest.promiseFocus(win);
+ if (Services.focus.activeWindow !== win) {
+ testScope.info("switchToWindow, waiting for activate event on the window");
+ await BrowserTestUtils.waitForEvent(win, "activate");
+ } else {
+ testScope.info("switchToWindow, win is already the activeWindow");
+ }
+ testScope.info("switchToWindow, done");
+}
+
function assertFirefoxViewTab(win) {
Assert.ok(win.FirefoxViewHandler.tab, "Firefox View tab exists");
Assert.ok(win.FirefoxViewHandler.tab?.hidden, "Firefox View tab is hidden");
@@ -48,7 +62,7 @@ async function openFirefoxViewTab(win) {
"Must initialize FirefoxViewTestUtils with a test scope which has a SimpleTest property"
);
}
- await testScope.SimpleTest.promiseFocus(win);
+ await switchToWindow(win);
let fxviewTab = win.FirefoxViewHandler.tab;
let alreadyLoaded =
fxviewTab?.linkedBrowser.currentURI.spec.includes(getFirefoxViewURL()) &&
@@ -167,6 +181,7 @@ function isFirefoxViewTabSelectedInWindow(win) {
export {
init,
+ switchToWindow,
withFirefoxView,
assertFirefoxViewTab,
assertFirefoxViewTabSelected,
diff --git a/browser/components/firefoxview/tests/browser/browser.toml b/browser/components/firefoxview/tests/browser/browser.toml
index 8e2005760b..9f9c1c0176 100644
--- a/browser/components/firefoxview/tests/browser/browser.toml
+++ b/browser/components/firefoxview/tests/browser/browser.toml
@@ -27,48 +27,57 @@ skip-if = ["true"] # Bug 1869605 and # Bug 1870296
["browser_firefoxview.js"]
-["browser_firefoxview_tab.js"]
-
-["browser_notification_dot.js"]
-skip-if = ["true"] # Bug 1851453
-
-["browser_opentabs_changes.js"]
-
-["browser_reload_firefoxview.js"]
-
-["browser_tab_close_last_tab.js"]
-
-["browser_tab_on_close_warning.js"]
-
-["browser_firefoxview_paused.js"]
-
["browser_firefoxview_general_telemetry.js"]
["browser_firefoxview_navigation.js"]
+["browser_firefoxview_paused.js"]
+
["browser_firefoxview_search_telemetry.js"]
+["browser_firefoxview_tab.js"]
+
["browser_firefoxview_virtual_list.js"]
["browser_history_firefoxview.js"]
-skip-if = ["true"] # Bug 1877594
-["browser_opentabs_firefoxview.js"]
+["browser_notification_dot.js"]
+skip-if = ["true"] # Bug 1851453
["browser_opentabs_cards.js"]
+
+["browser_opentabs_changes.js"]
+
+["browser_opentabs_firefoxview.js"]
+
+["browser_opentabs_more.js"]
fail-if = ["a11y_checks"] # Bugs 1858041, 1854625, and 1872174 clicked Show all link is not accessible because it is "hidden" when clicked
+skip-if = ["verify"] # Bug 1886017
+
+["browser_opentabs_pinned_tabs.js"]
["browser_opentabs_recency.js"]
skip-if = [
"os == 'win'",
"os == 'mac' && verify",
"os == 'linux'"
-] # macos times out, see bug 1857293, skipped for windows, see bug 1858460, skipped for linux, see bug 1875877
+] # macos times out, see bug 1857293, skipped for windows, see bug 1858460, Bug 1875877 - frequent fails on linux.
+
+["browser_opentabs_search.js"]
+fail-if = ["a11y_checks"] # Bug 1850591 clicked moz-page-nav-button button is not focusable
["browser_opentabs_tab_indicators.js"]
["browser_recentlyclosed_firefoxview.js"]
+["browser_reload_firefoxview.js"]
+
["browser_syncedtabs_errors_firefoxview.js"]
["browser_syncedtabs_firefoxview.js"]
+
+["browser_tab_close_last_tab.js"]
+
+["browser_tab_list_keyboard_navigation.js"]
+
+["browser_tab_on_close_warning.js"]
diff --git a/browser/components/firefoxview/tests/browser/browser_dragDrop_after_opening_fxViewTab.js b/browser/components/firefoxview/tests/browser/browser_dragDrop_after_opening_fxViewTab.js
index 9ce547238a..0376a3886d 100644
--- a/browser/components/firefoxview/tests/browser/browser_dragDrop_after_opening_fxViewTab.js
+++ b/browser/components/firefoxview/tests/browser/browser_dragDrop_after_opening_fxViewTab.js
@@ -15,6 +15,7 @@ add_task(async function () {
// window.RTL_UI doesn't update in existing windows when this pref is changed,
// so we need to test in a new window.
let win = await BrowserTestUtils.openNewBrowserWindow();
+ await switchToWindow(win);
const TEST_ROOT = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
diff --git a/browser/components/firefoxview/tests/browser/browser_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_firefoxview.js
index 33467941a4..1a51d61f42 100644
--- a/browser/components/firefoxview/tests/browser/browser_firefoxview.js
+++ b/browser/components/firefoxview/tests/browser/browser_firefoxview.js
@@ -6,10 +6,7 @@ add_task(async function about_firefoxview_smoke_test() {
const { document } = browser.contentWindow;
// sanity check the important regions exist on this page
- ok(
- document.querySelector("fxview-category-navigation"),
- "fxview-category-navigation element exists"
- );
+ ok(document.querySelector("moz-page-nav"), "moz-page-nav element exists");
ok(document.querySelector("named-deck"), "named-deck element exists");
});
});
diff --git a/browser/components/firefoxview/tests/browser/browser_firefoxview_general_telemetry.js b/browser/components/firefoxview/tests/browser/browser_firefoxview_general_telemetry.js
index 51d5caa032..b70e6b938e 100644
--- a/browser/components/firefoxview/tests/browser/browser_firefoxview_general_telemetry.js
+++ b/browser/components/firefoxview/tests/browser/browser_firefoxview_general_telemetry.js
@@ -39,7 +39,7 @@ add_task(async function firefox_view_entered_telemetry() {
enteredTelemetry[4] = { page: "recentlyclosed" };
enteredAndTabSelectedEvents = [tabSelectedTelemetry, enteredTelemetry];
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
await clearAllParentTelemetryEvents();
await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
is(
@@ -107,9 +107,9 @@ add_task(async function test_change_page_telemetry() {
],
];
await clearAllParentTelemetryEvents();
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
await telemetryEvent(changePageEvent);
- navigateToCategory(document, "recentbrowsing");
+ await navigateToViewAndWait(document, "recentbrowsing");
let openTabsComponent = document.querySelector(
"view-opentabs[slot=opentabs]"
@@ -189,7 +189,7 @@ add_task(async function test_context_menu_new_window_telemetry() {
);
// Test history context menu options
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
let historyComponent = document.querySelector("view-history");
await TestUtils.waitForCondition(() => historyComponent.fullyUpdated);
await TestUtils.waitForCondition(
@@ -198,7 +198,11 @@ add_task(async function test_context_menu_new_window_telemetry() {
let firstTabList = historyComponent.lists[0];
let firstItem = firstTabList.rowEls[0];
let panelList = historyComponent.panelList;
- EventUtils.synthesizeMouseAtCenter(firstItem.buttonEl, {}, content);
+ EventUtils.synthesizeMouseAtCenter(
+ firstItem.secondaryButtonEl,
+ {},
+ content
+ );
await BrowserTestUtils.waitForEvent(panelList, "shown");
await clearAllParentTelemetryEvents();
let panelItems = Array.from(panelList.children).filter(
@@ -245,7 +249,7 @@ add_task(async function test_context_menu_private_window_telemetry() {
);
// Test history context menu options
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
let historyComponent = document.querySelector("view-history");
await TestUtils.waitForCondition(() => historyComponent.fullyUpdated);
await TestUtils.waitForCondition(
@@ -254,14 +258,22 @@ add_task(async function test_context_menu_private_window_telemetry() {
let firstTabList = historyComponent.lists[0];
let firstItem = firstTabList.rowEls[0];
let panelList = historyComponent.panelList;
- EventUtils.synthesizeMouseAtCenter(firstItem.buttonEl, {}, content);
+ EventUtils.synthesizeMouseAtCenter(
+ firstItem.secondaryButtonEl,
+ {},
+ content
+ );
await BrowserTestUtils.waitForEvent(panelList, "shown");
await clearAllParentTelemetryEvents();
let panelItems = Array.from(panelList.children).filter(
panelItem => panelItem.nodeName === "PANEL-ITEM"
);
- EventUtils.synthesizeMouseAtCenter(firstItem.buttonEl, {}, content);
+ EventUtils.synthesizeMouseAtCenter(
+ firstItem.secondaryButtonEl,
+ {},
+ content
+ );
info("Context menu button clicked.");
await BrowserTestUtils.waitForEvent(panelList, "shown");
info("Context menu shown.");
@@ -314,7 +326,7 @@ add_task(async function test_context_menu_delete_from_history_telemetry() {
);
// Test history context menu options
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
let historyComponent = document.querySelector("view-history");
await TestUtils.waitForCondition(() => historyComponent.fullyUpdated);
await TestUtils.waitForCondition(
@@ -323,14 +335,22 @@ add_task(async function test_context_menu_delete_from_history_telemetry() {
let firstTabList = historyComponent.lists[0];
let firstItem = firstTabList.rowEls[0];
let panelList = historyComponent.panelList;
- EventUtils.synthesizeMouseAtCenter(firstItem.buttonEl, {}, content);
+ EventUtils.synthesizeMouseAtCenter(
+ firstItem.secondaryButtonEl,
+ {},
+ content
+ );
await BrowserTestUtils.waitForEvent(panelList, "shown");
await clearAllParentTelemetryEvents();
let panelItems = Array.from(panelList.children).filter(
panelItem => panelItem.nodeName === "PANEL-ITEM"
);
- EventUtils.synthesizeMouseAtCenter(firstItem.buttonEl, {}, content);
+ EventUtils.synthesizeMouseAtCenter(
+ firstItem.secondaryButtonEl,
+ {},
+ content
+ );
info("Context menu button clicked.");
await BrowserTestUtils.waitForEvent(panelList, "shown");
info("Context menu shown.");
diff --git a/browser/components/firefoxview/tests/browser/browser_firefoxview_navigation.js b/browser/components/firefoxview/tests/browser/browser_firefoxview_navigation.js
index 80206dd945..281d969b39 100644
--- a/browser/components/firefoxview/tests/browser/browser_firefoxview_navigation.js
+++ b/browser/components/firefoxview/tests/browser/browser_firefoxview_navigation.js
@@ -3,15 +3,15 @@
const URL_BASE = `${getFirefoxViewURL()}#`;
-function assertCorrectPage(document, name, event) {
+function assertCorrectPage(document, view, event) {
is(
document.location.hash,
- `#${name}`,
- `Navigation button for ${name} navigates to ${URL_BASE + name} on ${event}.`
+ `#${view}`,
+ `Navigation button for ${view} navigates to ${URL_BASE + view} on ${event}.`
);
is(
document.querySelector("named-deck").selectedViewName,
- name,
+ view,
"The correct deck child is selected"
);
}
@@ -22,21 +22,21 @@ add_task(async function test_side_component_navigation_by_click() {
const { document } = browser.contentWindow;
let win = browser.ownerGlobal;
- const categoryButtons = document.querySelectorAll("fxview-category-button");
+ const pageNavButtons = document.querySelectorAll("moz-page-nav-button");
- for (let element of categoryButtons) {
- const name = element.name;
+ for (let element of pageNavButtons) {
+ const view = element.view;
let buttonClicked = BrowserTestUtils.waitForEvent(
element.buttonEl,
"click",
win
);
- info(`Clicking navigation button for ${name}`);
+ info(`Clicking navigation button for ${view}`);
EventUtils.synthesizeMouseAtCenter(element.buttonEl, {}, content);
await buttonClicked;
- assertCorrectPage(document, name, "click");
+ assertCorrectPage(document, view, "click");
}
});
});
@@ -47,49 +47,49 @@ add_task(async function test_side_component_navigation_by_keyboard() {
const { document } = browser.contentWindow;
let win = browser.ownerGlobal;
- const categoryButtons = document.querySelectorAll("fxview-category-button");
- const firstButton = categoryButtons[0];
+ const pageNavButtons = document.querySelectorAll("moz-page-nav-button");
+ const firstButton = pageNavButtons[0].buttonEl;
firstButton.focus();
is(
- document.activeElement,
+ document.activeElement.shadowRoot.activeElement,
firstButton,
- "The first category button has focus"
+ "The first page nav button has focus"
);
- for (let element of Array.from(categoryButtons).slice(1)) {
- const name = element.name;
+ for (let element of Array.from(pageNavButtons).slice(1)) {
+ const view = element.view;
let buttonFocused = BrowserTestUtils.waitForEvent(element, "focus", win);
- info(`Focus is on ${document.activeElement.name}`);
- info(`Arrow down on navigation to ${name}`);
+ info(`Focus is on ${document.activeElement.view}`);
+ info(`Arrow down on navigation to ${view}`);
EventUtils.synthesizeKey("KEY_ArrowDown", {}, win);
await buttonFocused;
- assertCorrectPage(document, name, "key press");
+ assertCorrectPage(document, view, "key press");
}
});
});
-add_task(async function test_direct_navigation_to_correct_category() {
+add_task(async function test_direct_navigation_to_correct_view() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- const categoryButtons = document.querySelectorAll("fxview-category-button");
+ const pageNavButtons = document.querySelectorAll("moz-page-nav-button");
const namedDeck = document.querySelector("named-deck");
- for (let element of categoryButtons) {
- const name = element.name;
+ for (let element of pageNavButtons) {
+ const view = element.view;
- info(`Navigating to ${URL_BASE + name}`);
- document.location.assign(URL_BASE + name);
+ info(`Navigating to ${URL_BASE + view}`);
+ document.location.assign(URL_BASE + view);
await BrowserTestUtils.waitForCondition(() => {
- return namedDeck.selectedViewName === name;
+ return namedDeck.selectedViewName === view;
}, "Wait for navigation to complete");
is(
namedDeck.selectedViewName,
- name,
- `The correct deck child for category ${name} is selected`
+ view,
+ `The correct deck child for view ${view} is selected`
);
}
});
diff --git a/browser/components/firefoxview/tests/browser/browser_firefoxview_paused.js b/browser/components/firefoxview/tests/browser/browser_firefoxview_paused.js
index c95ac4fcf5..e61b48b472 100644
--- a/browser/components/firefoxview/tests/browser/browser_firefoxview_paused.js
+++ b/browser/components/firefoxview/tests/browser/browser_firefoxview_paused.js
@@ -5,9 +5,6 @@ const tabURL1 = "data:,Tab1";
const tabURL2 = "data:,Tab2";
const tabURL3 = "data:,Tab3";
-const { NonPrivateTabs } = ChromeUtils.importESModule(
- "resource:///modules/OpenTabs.sys.mjs"
-);
const TestTabs = {};
function getTopLevelViewElements(document) {
@@ -194,6 +191,42 @@ async function checkFxRenderCalls(browser, elements, selectedView) {
sandbox.restore();
}
+function dragAndDrop(
+ tab1,
+ tab2,
+ initialWindow = window,
+ destWindow = window,
+ afterTab = true,
+ context
+) {
+ let rect = tab2.getBoundingClientRect();
+ let event = {
+ ctrlKey: false,
+ altKey: false,
+ clientX: rect.left + rect.width / 2 + 10 * (afterTab ? 1 : -1),
+ clientY: rect.top + rect.height / 2,
+ };
+
+ if (destWindow != initialWindow) {
+ // Make sure that both tab1 and tab2 are visible
+ initialWindow.focus();
+ initialWindow.moveTo(rect.left, rect.top + rect.height * 3);
+ }
+
+ EventUtils.synthesizeDrop(
+ tab1,
+ tab2,
+ null,
+ "move",
+ initialWindow,
+ destWindow,
+ event
+ );
+
+ // Ensure dnd suppression is cleared.
+ EventUtils.synthesizeMouseAtCenter(tab2, { type: "mouseup" }, context);
+}
+
add_task(async function test_recentbrowsing() {
await setupOpenAndClosedTabs();
@@ -322,7 +355,7 @@ add_task(async function test_opentabs() {
const document = browser.contentDocument;
const { openTabsView } = getTopLevelViewElements(document);
- await navigateToCategoryAndWait(document, "opentabs");
+ await navigateToViewAndWait(document, "opentabs");
const { openTabsList } = await getElements(document);
ok(openTabsView, "Found the open tabs view");
@@ -387,7 +420,7 @@ add_task(async function test_recentlyclosed() {
await withFirefoxView({}, async browser => {
const document = browser.contentDocument;
const { recentlyClosedView } = getTopLevelViewElements(document);
- await navigateToCategoryAndWait(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
const { recentlyClosedList } = await getElements(document);
ok(recentlyClosedView, "Found the recently-closed view");
@@ -405,3 +438,66 @@ add_task(async function test_recentlyclosed() {
});
await BrowserTestUtils.removeTab(TestTabs.tab2);
});
+
+add_task(async function test_drag_drop_pinned_tab() {
+ await setupOpenAndClosedTabs();
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ let win1 = browser.ownerGlobal;
+ 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 tabRows = card.tabList.rowEls;
+ let tabChangeRaised;
+
+ // Pin first two tabs
+ for (var i = 0; i < 2; i++) {
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+ let currentTabEl = tabRows[i];
+ let currentTab = currentTabEl.tabElement;
+ info(`Pinning tab ${i + 1} with label: ${currentTab.label}`);
+ win1.gBrowser.pinTab(currentTab);
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+ tabRows = card.tabList.rowEls;
+ currentTabEl = tabRows[i];
+
+ await TestUtils.waitForCondition(
+ () => currentTabEl.indicators.includes("pinned"),
+ `Tab ${i + 1} is pinned.`
+ );
+ }
+
+ info(`First two tabs are pinned.`);
+
+ let win2 = await BrowserTestUtils.openNewBrowserWindow();
+
+ await openTabs.updateComplete;
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards.length === 2,
+ "Two windows are shown for Open Tabs in in Fx View."
+ );
+
+ let pinnedTab = win1.gBrowser.visibleTabs[0];
+ let newWindowTab = win2.gBrowser.visibleTabs[0];
+
+ dragAndDrop(newWindowTab, pinnedTab, win2, win1, true, content);
+
+ await switchToFxViewTab();
+ await openTabs.updateComplete;
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards.length === 1,
+ "One window is shown for Open Tabs in in Fx View."
+ );
+ });
+ cleanupTabs();
+});
diff --git a/browser/components/firefoxview/tests/browser/browser_firefoxview_search_telemetry.js b/browser/components/firefoxview/tests/browser/browser_firefoxview_search_telemetry.js
index 2ea2429c15..c76a11d3ad 100644
--- a/browser/components/firefoxview/tests/browser/browser_firefoxview_search_telemetry.js
+++ b/browser/components/firefoxview/tests/browser/browser_firefoxview_search_telemetry.js
@@ -56,7 +56,7 @@ add_task(async function test_search_initiated_telemetry() {
EventUtils.sendString("example.com", content);
await telemetryEvent(searchEvent("recentbrowsing"));
- await navigateToCategoryAndWait(document, "opentabs");
+ await navigateToViewAndWait(document, "opentabs");
await clearAllParentTelemetryEvents();
is(document.location.hash, "#opentabs", "Searching within open tabs.");
const openTabs = document.querySelector("named-deck > view-opentabs");
@@ -65,7 +65,7 @@ add_task(async function test_search_initiated_telemetry() {
EventUtils.sendString("example.com", content);
await telemetryEvent(searchEvent("opentabs"));
- await navigateToCategoryAndWait(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
await clearAllParentTelemetryEvents();
is(
document.location.hash,
@@ -84,7 +84,7 @@ add_task(async function test_search_initiated_telemetry() {
EventUtils.sendString("example.com", content);
await telemetryEvent(searchEvent("recentlyclosed"));
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
await clearAllParentTelemetryEvents();
is(document.location.hash, "#syncedtabs", "Searching within synced tabs.");
const syncedTabs = document.querySelector("named-deck > view-syncedtabs");
@@ -93,7 +93,7 @@ add_task(async function test_search_initiated_telemetry() {
EventUtils.sendString("example.com", content);
await telemetryEvent(searchEvent("syncedtabs"));
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
await clearAllParentTelemetryEvents();
is(document.location.hash, "#history", "Searching within history.");
const history = document.querySelector("named-deck > view-history");
@@ -316,7 +316,7 @@ add_task(async function test_sort_history_search_telemetry() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
const historyComponent = document.querySelector("view-history");
const searchTextbox = await TestUtils.waitForCondition(
@@ -432,7 +432,7 @@ add_task(async function test_cumulative_searches_recently_closed_telemetry() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
is(
document.location.hash,
"#recentlyclosed",
@@ -477,7 +477,7 @@ add_task(async function test_cumulative_searches_open_tabs_telemetry() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "opentabs");
+ await navigateToViewAndWait(document, "opentabs");
is(document.location.hash, "#opentabs", "Searching within open tabs.");
const openTabs = document.querySelector("named-deck > view-opentabs");
@@ -523,7 +523,7 @@ add_task(async function test_cumulative_searches_history_telemetry() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
is(document.location.hash, "#history", "Searching within history.");
const history = document.querySelector("named-deck > view-history");
const searchTextbox = await TestUtils.waitForCondition(() => {
@@ -585,7 +585,7 @@ add_task(async function test_cumulative_searches_syncedtabs_telemetry() {
const { document } = browser.contentWindow;
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
is(document.location.hash, "#syncedtabs", "Searching within synced tabs.");
let syncedTabs = document.querySelector(
"view-syncedtabs:not([slot=syncedtabs])"
diff --git a/browser/components/firefoxview/tests/browser/browser_firefoxview_tab.js b/browser/components/firefoxview/tests/browser/browser_firefoxview_tab.js
index f1ac7d6742..037729ea7d 100644
--- a/browser/components/firefoxview/tests/browser/browser_firefoxview_tab.js
+++ b/browser/components/firefoxview/tests/browser/browser_firefoxview_tab.js
@@ -55,12 +55,6 @@ function triggerClickOn(target, options) {
return promise;
}
-async function add_new_tab(URL) {
- let tab = BrowserTestUtils.addTab(gBrowser, URL);
- await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
- return tab;
-}
-
add_task(async function aria_attributes() {
let win = await BrowserTestUtils.openNewBrowserWindow();
is(
diff --git a/browser/components/firefoxview/tests/browser/browser_firefoxview_virtual_list.js b/browser/components/firefoxview/tests/browser/browser_firefoxview_virtual_list.js
index 501deb8e68..bf53796ef7 100644
--- a/browser/components/firefoxview/tests/browser/browser_firefoxview_virtual_list.js
+++ b/browser/components/firefoxview/tests/browser/browser_firefoxview_virtual_list.js
@@ -29,7 +29,7 @@ add_task(async function test_max_render_count_on_win_resize() {
"Firefox View is loaded to the Recent Browsing page."
);
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
let historyComponent = document.querySelector("view-history");
let tabList = historyComponent.lists[0];
diff --git a/browser/components/firefoxview/tests/browser/browser_history_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_history_firefoxview.js
index a6c697e398..c4c096acff 100644
--- a/browser/components/firefoxview/tests/browser/browser_history_firefoxview.js
+++ b/browser/components/firefoxview/tests/browser/browser_history_firefoxview.js
@@ -15,8 +15,8 @@ const HISTORY_EVENT = [["firefoxview_next", "history", "visits", undefined]];
const SHOW_ALL_HISTORY_EVENT = [
["firefoxview_next", "show_all_history", "tabs", undefined],
];
-
const NEVER_REMEMBER_HISTORY_PREF = "browser.privatebrowsing.autostart";
+
const DAY_MS = 24 * 60 * 60 * 1000;
const today = new Date();
const yesterday = new Date(Date.now() - DAY_MS);
@@ -24,6 +24,14 @@ const twoDaysAgo = new Date(Date.now() - DAY_MS * 2);
const threeDaysAgo = new Date(Date.now() - DAY_MS * 3);
const fourDaysAgo = new Date(Date.now() - DAY_MS * 4);
const oneMonthAgo = new Date(today);
+const dates = [
+ today,
+ yesterday,
+ twoDaysAgo,
+ threeDaysAgo,
+ fourDaysAgo,
+ oneMonthAgo,
+];
// Set the date for the first day of the last month
oneMonthAgo.setDate(1);
@@ -47,13 +55,14 @@ function isElInViewport(element) {
);
}
-async function historyComponentReady(historyComponent) {
+async function historyComponentReady(historyComponent, expectedHistoryItems) {
await TestUtils.waitForCondition(
() =>
[...historyComponent.allHistoryItems.values()].reduce(
(acc, { length }) => acc + length,
0
- ) === 24
+ ) === expectedHistoryItems,
+ "History component ready"
);
let expected = historyComponent.historyMapByDate.length;
@@ -148,6 +157,18 @@ async function addHistoryItems(dateAdded) {
});
}
+function createHistoryEntries() {
+ let historyEntries = [];
+ for (let i = 0; i < 4; i++) {
+ historyEntries.push({
+ url: URLs[i],
+ title: `Example Domain ${i}`,
+ visits: dates.map(date => [{ date }]),
+ });
+ }
+ return historyEntries;
+}
+
add_setup(async () => {
await SpecialPowers.pushPrefEnv({
set: [["browser.firefox-view.search.enabled", true]],
@@ -160,21 +181,20 @@ add_setup(async () => {
add_task(async function test_list_ordering() {
await PlacesUtils.history.clear();
- await addHistoryItems(today);
- await addHistoryItems(yesterday);
- await addHistoryItems(twoDaysAgo);
- await addHistoryItems(threeDaysAgo);
- await addHistoryItems(fourDaysAgo);
- await addHistoryItems(oneMonthAgo);
+ const historyEntries = createHistoryEntries();
+ await PlacesUtils.history.insertMany(historyEntries);
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
- let historyComponent = document.querySelector("view-history");
+ let historyComponent = await TestUtils.waitForCondition(
+ () => document.querySelector("view-history"),
+ "History component rendered"
+ );
historyComponent.profileAge = 8;
- await historyComponentReady(historyComponent);
+ await historyComponentReady(historyComponent, historyEntries.length);
let firstCard = historyComponent.cards[0];
@@ -262,7 +282,7 @@ add_task(async function test_empty_states() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
let historyComponent = document.querySelector("view-history");
historyComponent.profileAge = 8;
@@ -350,7 +370,7 @@ add_task(async function test_observers_removed_when_view_is_hidden() {
);
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
const historyComponent = document.querySelector("view-history");
historyComponent.profileAge = 8;
let visitList = await TestUtils.waitForCondition(() =>
@@ -390,20 +410,16 @@ add_task(async function test_observers_removed_when_view_is_hidden() {
add_task(async function test_show_all_history_telemetry() {
await PlacesUtils.history.clear();
- await addHistoryItems(today);
- await addHistoryItems(yesterday);
- await addHistoryItems(twoDaysAgo);
- await addHistoryItems(threeDaysAgo);
- await addHistoryItems(fourDaysAgo);
- await addHistoryItems(oneMonthAgo);
+ const historyEntries = createHistoryEntries();
+ await PlacesUtils.history.insertMany(historyEntries);
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
let historyComponent = document.querySelector("view-history");
historyComponent.profileAge = 8;
- await historyComponentReady(historyComponent);
+ await historyComponentReady(historyComponent, historyEntries.length);
await clearAllParentTelemetryEvents();
let showAllHistoryBtn = historyComponent.showAllHistoryBtn;
@@ -422,12 +438,15 @@ add_task(async function test_show_all_history_telemetry() {
});
add_task(async function test_search_history() {
+ await PlacesUtils.history.clear();
+ const historyEntries = createHistoryEntries();
+ await PlacesUtils.history.insertMany(historyEntries);
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
const historyComponent = document.querySelector("view-history");
historyComponent.profileAge = 8;
- await historyComponentReady(historyComponent);
+ await historyComponentReady(historyComponent, historyEntries.length);
const searchTextbox = await TestUtils.waitForCondition(
() => historyComponent.searchTextbox,
"The search textbox is displayed."
@@ -447,7 +466,7 @@ add_task(async function test_search_history() {
);
await TestUtils.waitForCondition(() => {
const { rowEls } = historyComponent.lists[0];
- return rowEls.length === 1 && rowEls[0].mainEl.href === URLs[0];
+ return rowEls.length === 1 && rowEls[0].mainEl.href === URLs[1];
}, "There is one matching search result.");
info("Input a bogus search query.");
@@ -504,7 +523,7 @@ add_task(async function test_persist_collapse_card_after_view_change() {
await addHistoryItems(today);
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "history");
const historyComponent = document.querySelector("view-history");
historyComponent.profileAge = 8;
await TestUtils.waitForCondition(
@@ -529,8 +548,8 @@ add_task(async function test_persist_collapse_card_after_view_change() {
);
// Switch to a new view and then back to History
- await navigateToCategoryAndWait(document, "syncedtabs");
- await navigateToCategoryAndWait(document, "history");
+ await navigateToViewAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "history");
// Check that first history card is still collapsed after changing view
ok(
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_cards.js b/browser/components/firefoxview/tests/browser/browser_opentabs_cards.js
index d57aa3cad1..d4de3ae5a9 100644
--- a/browser/components/firefoxview/tests/browser/browser_opentabs_cards.js
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_cards.js
@@ -7,36 +7,16 @@ const ROW_DATE_ID = "fxview-tab-row-date";
let gInitialTab;
let gInitialTabURL;
-const { NonPrivateTabs } = ChromeUtils.importESModule(
- "resource:///modules/OpenTabs.sys.mjs"
-);
add_setup(function () {
// This test opens a lot of windows and tabs and might run long on slower configurations
- requestLongerTimeout(2);
+ requestLongerTimeout(3);
gInitialTab = gBrowser.selectedTab;
gInitialTabURL = gBrowser.selectedBrowser.currentURI.spec;
});
-async function navigateToOpenTabs(browser) {
- const document = browser.contentDocument;
- if (document.querySelector("named-deck").selectedViewName != "opentabs") {
- await navigateToCategoryAndWait(browser.contentDocument, "opentabs");
- }
-}
-
-function getOpenTabsComponent(browser) {
- return browser.contentDocument.querySelector("named-deck > view-opentabs");
-}
-
-function getCards(browser) {
- return getOpenTabsComponent(browser).shadowRoot.querySelectorAll(
- "view-opentabs-card"
- );
-}
-
async function cleanup() {
- await SimpleTest.promiseFocus(window);
+ await switchToWindow(window);
await promiseAllButPrimaryWindowClosed();
await BrowserTestUtils.switchTab(gBrowser, gInitialTab);
await closeFirefoxViewTab(window);
@@ -58,11 +38,6 @@ async function cleanup() {
);
}
-async function getRowsForCard(card) {
- await TestUtils.waitForCondition(() => card.tabList.rowEls.length);
- return card.tabList.rowEls;
-}
-
/**
* Verify that there are the expected number of cards, and that each card has
* the expected URLs in order.
@@ -73,10 +48,10 @@ async function getRowsForCard(card) {
* The expected URLs for each card.
*/
async function checkTabLists(browser, expected) {
- const cards = getCards(browser);
+ const cards = getOpenTabsCards(getOpenTabsComponent(browser));
is(cards.length, expected.length, `There are ${expected.length} windows.`);
for (let i = 0; i < cards.length; i++) {
- const tabItems = await getRowsForCard(cards[i]);
+ const tabItems = await getTabRowsForCard(cards[i]);
const actual = Array.from(tabItems).map(({ url }) => url);
Assert.deepEqual(
actual,
@@ -87,11 +62,12 @@ async function checkTabLists(browser, expected) {
}
add_task(async function open_tab_same_window() {
+ let tabChangeRaised;
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
await navigateToOpenTabs(browser);
const openTabs = getOpenTabsComponent(browser);
- await openTabs.openTabsTarget.readyWindowsPromise;
+ await NonPrivateTabs.readyWindowsPromise;
await openTabs.updateComplete;
await checkTabLists(browser, [[gInitialTabURL]]);
@@ -99,7 +75,7 @@ add_task(async function open_tab_same_window() {
browser.contentDocument,
"visibilitychange"
);
- let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
@@ -114,7 +90,7 @@ add_task(async function open_tab_same_window() {
const browser = viewTab.linkedBrowser;
const openTabs = getOpenTabsComponent(browser);
setSortOption(openTabs, "tabStripOrder");
- await openTabs.openTabsTarget.readyWindowsPromise;
+ await NonPrivateTabs.readyWindowsPromise;
await openTabs.updateComplete;
await checkTabLists(browser, [[gInitialTabURL, TEST_URL]]);
@@ -122,8 +98,8 @@ add_task(async function open_tab_same_window() {
browser.contentDocument,
"visibilitychange"
);
- const cards = getCards(browser);
- const tabItems = await getRowsForCard(cards[0]);
+ const cards = getOpenTabsCards(openTabs);
+ const tabItems = await getTabRowsForCard(cards[0]);
tabItems[0].mainEl.click();
await promiseHidden;
});
@@ -135,8 +111,11 @@ add_task(async function open_tab_same_window() {
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
- const cards = getCards(browser);
- let tabItems = await getRowsForCard(cards[0]);
+ const openTabs = getOpenTabsComponent(browser);
+ await openTabs.updateComplete;
+
+ const cards = getOpenTabsCards(openTabs);
+ let tabItems = await getTabRowsForCard(cards[0]);
let promiseHidden = BrowserTestUtils.waitForEvent(
browser.contentDocument,
@@ -154,7 +133,13 @@ add_task(async function open_tab_same_window() {
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
- let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ const openTabs = getOpenTabsComponent(browser);
+ await openTabs.updateComplete;
+
+ // sanity-check current tab order before we change it
+ await checkTabLists(browser, [[gInitialTabURL, TEST_URL]]);
+
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
@@ -162,18 +147,24 @@ add_task(async function open_tab_same_window() {
info("Bring the new tab to the front.");
gBrowser.moveTabTo(newTab, 0);
+ info("Waiting for tabChangeRaised to resolve from the tab move");
await tabChangeRaised;
+ await openTabs.updateComplete;
+
await checkTabLists(browser, [[TEST_URL, gInitialTabURL]]);
tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
+ info("Remove the new tab");
await BrowserTestUtils.removeTab(newTab);
+ info("Waiting for tabChangeRaised to resolve from removing the tab");
await tabChangeRaised;
+ await openTabs.updateComplete;
await checkTabLists(browser, [[gInitialTabURL]]);
- const [card] = getCards(browser);
- const [row] = await getRowsForCard(card);
+ const [card] = getOpenTabsCards(getOpenTabsComponent(browser));
+ const [row] = await getTabRowsForCard(card);
ok(
!row.shadowRoot.getElementById("fxview-tab-row-url").hidden,
"The URL is displayed, since we have one window."
@@ -188,25 +179,29 @@ add_task(async function open_tab_same_window() {
});
add_task(async function open_tab_new_window() {
- const win = await BrowserTestUtils.openNewBrowserWindow();
- let winFocused;
- await BrowserTestUtils.openNewForegroundTab(win.gBrowser, TEST_URL);
+ const win2 = await BrowserTestUtils.openNewBrowserWindow();
+ let winBecameActive;
+ let tabChangeRaised;
+ await switchToWindow(win2);
+ await NonPrivateTabs.readyWindowsPromise;
+
+ await BrowserTestUtils.openNewForegroundTab(win2.gBrowser, TEST_URL);
info("Open fxview in new window");
- await openFirefoxViewTab(win).then(async viewTab => {
+ await openFirefoxViewTab(win2).then(async viewTab => {
const browser = viewTab.linkedBrowser;
await navigateToOpenTabs(browser);
const openTabs = getOpenTabsComponent(browser);
setSortOption(openTabs, "tabStripOrder");
- await openTabs.openTabsTarget.readyWindowsPromise;
+ await NonPrivateTabs.readyWindowsPromise;
await openTabs.updateComplete;
await checkTabLists(browser, [
[gInitialTabURL, TEST_URL],
[gInitialTabURL],
]);
- const cards = getCards(browser);
- const originalWinRows = await getRowsForCard(cards[1]);
+ const cards = getOpenTabsCards(openTabs);
+ const originalWinRows = await getTabRowsForCard(cards[1]);
const [row] = originalWinRows;
ok(
row.shadowRoot.getElementById("fxview-tab-row-url").hidden,
@@ -217,47 +212,60 @@ add_task(async function open_tab_new_window() {
"The date is hidden, since we have two windows."
);
info("Select a tab from the original window.");
- let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabRecencyChange"
);
- winFocused = BrowserTestUtils.waitForEvent(window, "focus", true);
- originalWinRows[0].mainEl.click();
+ winBecameActive = Promise.all([
+ BrowserTestUtils.waitForEvent(window, "focus", true),
+ BrowserTestUtils.waitForEvent(window, "activate"),
+ ]);
+ ok(row.tabElement, "The row has a tabElement property");
+ is(
+ row.tabElement.ownerGlobal,
+ window,
+ "The tabElement's ownerGlobal is our original window"
+ );
+ info(`Clicking on row with URL: ${row.url}`);
+ row.mainEl.click();
+ info("Waiting for TabRecencyChange event");
await tabChangeRaised;
});
- info("Wait for the original window to be focused");
- await winFocused;
+ info("Wait for the original window to be focused & active");
+ await winBecameActive;
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
await navigateToOpenTabs(browser);
const openTabs = getOpenTabsComponent(browser);
- await openTabs.openTabsTarget.readyWindowsPromise;
+ await NonPrivateTabs.readyWindowsPromise;
await openTabs.updateComplete;
- const cards = getCards(browser);
+ const cards = getOpenTabsCards(openTabs);
is(cards.length, 2, "There are two windows.");
- const newWinRows = await getRowsForCard(cards[1]);
+ const newWinRows = await getTabRowsForCard(cards[1]);
info("Select a tab from the new window.");
- winFocused = BrowserTestUtils.waitForEvent(win, "focus", true);
- let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ winBecameActive = Promise.all([
+ BrowserTestUtils.waitForEvent(win2, "focus", true),
+ BrowserTestUtils.waitForEvent(win2, "activate"),
+ ]);
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabRecencyChange"
);
newWinRows[0].mainEl.click();
await tabChangeRaised;
});
- info("Wait for the new window to be focused");
- await winFocused;
+ info("Wait for the new window to be focused & active");
+ await winBecameActive;
await cleanup();
});
add_task(async function open_tab_new_private_window() {
await BrowserTestUtils.openNewBrowserWindow({ private: true });
- await SimpleTest.promiseFocus(window);
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
await navigateToOpenTabs(browser);
@@ -265,7 +273,7 @@ add_task(async function open_tab_new_private_window() {
await openTabs.openTabsTarget.readyWindowsPromise;
await openTabs.updateComplete;
- const cards = getCards(browser);
+ const cards = getOpenTabsCards(openTabs);
is(cards.length, 1, "The private window is not displayed.");
});
await cleanup();
@@ -274,6 +282,7 @@ add_task(async function open_tab_new_private_window() {
add_task(async function open_tab_new_window_sort_by_recency() {
info("Open new tabs in a new window.");
const newWindow = await BrowserTestUtils.openNewBrowserWindow();
+ await switchToWindow(newWindow);
const tabs = [
newWindow.gBrowser.selectedTab,
await BrowserTestUtils.openNewForegroundTab(newWindow.gBrowser, URLs[0]),
@@ -285,7 +294,7 @@ add_task(async function open_tab_new_window_sort_by_recency() {
await navigateToOpenTabs(linkedBrowser);
const openTabs = getOpenTabsComponent(linkedBrowser);
setSortOption(openTabs, "recency");
- await openTabs.openTabsTarget.readyWindowsPromise;
+ await NonPrivateTabs.readyWindowsPromise;
await openTabs.updateComplete;
await checkTabLists(linkedBrowser, [
@@ -293,13 +302,13 @@ add_task(async function open_tab_new_window_sort_by_recency() {
[URLs[1], URLs[0], gInitialTabURL],
]);
info("Select tabs in the new window to trigger recency changes.");
- await SimpleTest.promiseFocus(newWindow);
+ await switchToWindow(newWindow);
await BrowserTestUtils.switchTab(newWindow.gBrowser, tabs[1]);
await BrowserTestUtils.switchTab(newWindow.gBrowser, tabs[0]);
- await SimpleTest.promiseFocus(window);
+ await switchToWindow(window);
await TestUtils.waitForCondition(async () => {
- const [, secondCard] = getCards(linkedBrowser);
- const tabItems = await getRowsForCard(secondCard);
+ const [, secondCard] = getOpenTabsCards(openTabs);
+ const tabItems = await getTabRowsForCard(secondCard);
return tabItems[0].url === gInitialTabURL;
});
await checkTabLists(linkedBrowser, [
@@ -311,12 +320,13 @@ add_task(async function open_tab_new_window_sort_by_recency() {
});
add_task(async function styling_for_multiple_windows() {
+ let tabChangeRaised;
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
await navigateToOpenTabs(browser);
const openTabs = getOpenTabsComponent(browser);
setSortOption(openTabs, "tabStripOrder");
- await openTabs.openTabsTarget.readyWindowsPromise;
+ await NonPrivateTabs.readyWindowsPromise;
await openTabs.updateComplete;
ok(
@@ -325,13 +335,10 @@ add_task(async function styling_for_multiple_windows() {
);
});
- await BrowserTestUtils.openNewBrowserWindow();
- let tabChangeRaised = BrowserTestUtils.waitForEvent(
- NonPrivateTabs,
- "TabChange"
- );
+ let win2 = await BrowserTestUtils.openNewBrowserWindow();
+ info("Switching to new window");
+ await switchToWindow(win2);
await NonPrivateTabs.readyWindowsPromise;
- await tabChangeRaised;
is(
NonPrivateTabs.currentWindows.length,
2,
@@ -339,290 +346,54 @@ add_task(async function styling_for_multiple_windows() {
);
info("switch to firefox view in the first window");
- SimpleTest.promiseFocus(window);
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
const openTabs = getOpenTabsComponent(browser);
- await openTabs.openTabsTarget.readyWindowsPromise;
- await openTabs.updateComplete;
+ const cardContainer = openTabs.shadowRoot.querySelector(
+ ".view-opentabs-card-container"
+ );
+ info("waiting for card-count to reflect 2 windows");
+ await BrowserTestUtils.waitForCondition(() => {
+ return cardContainer.getAttribute("card-count") == "two";
+ });
is(
openTabs.openTabsTarget.currentWindows.length,
2,
"There should be 2 current windows"
);
- ok(
- openTabs.shadowRoot.querySelector("[card-count=two]"),
- "The container shows two columns when two windows are open."
+ is(
+ cardContainer.getAttribute("card-count"),
+ "two",
+ "The container shows two columns when two windows are open"
);
});
- await BrowserTestUtils.openNewBrowserWindow();
+
tabChangeRaised = BrowserTestUtils.waitForEvent(NonPrivateTabs, "TabChange");
+ let win3 = await BrowserTestUtils.openNewBrowserWindow();
+ await switchToWindow(win3);
await NonPrivateTabs.readyWindowsPromise;
await tabChangeRaised;
is(
NonPrivateTabs.currentWindows.length,
3,
- "NonPrivateTabs now has 2 currentWindows"
+ "NonPrivateTabs now has 3 currentWindows"
);
- SimpleTest.promiseFocus(window);
- await openFirefoxViewTab(window).then(async viewTab => {
- const browser = viewTab.linkedBrowser;
- const openTabs = getOpenTabsComponent(browser);
- await openTabs.openTabsTarget.readyWindowsPromise;
- await openTabs.updateComplete;
-
- ok(
- openTabs.shadowRoot.querySelector("[card-count=three-or-more]"),
- "The container shows three columns when three windows are open."
- );
- });
- await cleanup();
-});
-
-add_task(async function toggle_show_more_link() {
- const tabEntry = url => ({
- entries: [{ url, triggeringPrincipal_base64 }],
- });
- const NUMBER_OF_WINDOWS = 4;
- const NUMBER_OF_TABS = 42;
- const browserState = { windows: [] };
- for (let windowIndex = 0; windowIndex < NUMBER_OF_WINDOWS; windowIndex++) {
- const winData = { tabs: [] };
- let tabCount = windowIndex == NUMBER_OF_WINDOWS - 1 ? NUMBER_OF_TABS : 1;
- for (let i = 0; i < tabCount; i++) {
- winData.tabs.push(tabEntry(`data:,Window${windowIndex}-Tab${i}`));
- }
- winData.selected = winData.tabs.length;
- browserState.windows.push(winData);
- }
- // use Session restore to batch-open windows and tabs
- await SessionStoreTestUtils.promiseBrowserState(browserState);
- // restoring this state requires an update to the initial tab globals
- // so cleanup expects the right thing
- gInitialTab = gBrowser.selectedTab;
- gInitialTabURL = gBrowser.selectedBrowser.currentURI.spec;
-
- const windows = Array.from(Services.wm.getEnumerator("navigator:browser"));
- is(windows.length, NUMBER_OF_WINDOWS, "There are four browser windows.");
-
- const tab = (win = window) => {
- info("Tab");
- EventUtils.synthesizeKey("KEY_Tab", {}, win);
- };
-
- const enter = (win = window) => {
- info("Enter");
- EventUtils.synthesizeKey("KEY_Enter", {}, win);
- };
-
- let lastCard;
-
- SimpleTest.promiseFocus(window);
+ // switch back to the original window
await openFirefoxViewTab(window).then(async viewTab => {
const browser = viewTab.linkedBrowser;
- await navigateToOpenTabs(browser);
const openTabs = getOpenTabsComponent(browser);
- await openTabs.openTabsTarget.readyWindowsPromise;
- await openTabs.updateComplete;
-
- const cards = getCards(browser);
- is(cards.length, NUMBER_OF_WINDOWS, "There are four windows.");
- lastCard = cards[NUMBER_OF_WINDOWS - 1];
- });
-
- await openFirefoxViewTab(window).then(async viewTab => {
- const browser = viewTab.linkedBrowser;
- const openTabs = getOpenTabsComponent(browser);
- await openTabs.openTabsTarget.readyWindowsPromise;
- await openTabs.updateComplete;
- Assert.less(
- (await getRowsForCard(lastCard)).length,
- NUMBER_OF_TABS,
- "Not all tabs are shown yet."
- );
- info("Toggle the Show More link.");
- lastCard.shadowRoot.querySelector("div[slot=footer]").click();
- await BrowserTestUtils.waitForMutationCondition(
- lastCard.shadowRoot,
- { childList: true, subtree: true },
- async () => (await getRowsForCard(lastCard)).length === NUMBER_OF_TABS
+ const cardContainer = openTabs.shadowRoot.querySelector(
+ ".view-opentabs-card-container"
);
- info("Toggle the Show Less link.");
- lastCard.shadowRoot.querySelector("div[slot=footer]").click();
- await BrowserTestUtils.waitForMutationCondition(
- lastCard.shadowRoot,
- { childList: true, subtree: true },
- async () => (await getRowsForCard(lastCard)).length < NUMBER_OF_TABS
- );
-
- // Setting this pref allows the test to run as expected with a keyboard on MacOS
- await SpecialPowers.pushPrefEnv({
- set: [["accessibility.tabfocus", 7]],
+ await BrowserTestUtils.waitForCondition(() => {
+ return cardContainer.getAttribute("card-count") == "three-or-more";
});
-
- info("Toggle the Show More link with keyboard.");
- lastCard.shadowRoot.querySelector("card-container").summaryEl.focus();
- // Tab to first item in the list
- tab();
- // Tab to the footer
- tab();
- enter();
- await BrowserTestUtils.waitForMutationCondition(
- lastCard.shadowRoot,
- { childList: true, subtree: true },
- async () => (await getRowsForCard(lastCard)).length === NUMBER_OF_TABS
- );
-
- info("Toggle the Show Less link with keyboard.");
- lastCard.shadowRoot.querySelector("card-container").summaryEl.focus();
- // Tab to first item in the list
- tab();
- // Tab to the footer
- tab();
- enter();
- await BrowserTestUtils.waitForMutationCondition(
- lastCard.shadowRoot,
- { childList: true, subtree: true },
- async () => (await getRowsForCard(lastCard)).length < NUMBER_OF_TABS
- );
-
- await SpecialPowers.popPrefEnv();
- });
- await cleanup();
-});
-
-add_task(async function search_open_tabs() {
- // Open a new window and navigate to TEST_URL. Then, when we search for
- // TEST_URL, it should show a search result in the new window's card.
- const win = await BrowserTestUtils.openNewBrowserWindow();
- await BrowserTestUtils.openNewForegroundTab(win.gBrowser, TEST_URL);
-
- await SpecialPowers.pushPrefEnv({
- set: [["browser.firefox-view.search.enabled", true]],
- });
- await openFirefoxViewTab(window).then(async viewTab => {
- const browser = viewTab.linkedBrowser;
- await navigateToOpenTabs(browser);
- const openTabs = getOpenTabsComponent(browser);
- await openTabs.openTabsTarget.readyWindowsPromise;
- await openTabs.updateComplete;
-
- const cards = getCards(browser);
- is(cards.length, 2, "There are two windows.");
- const winTabs = await getRowsForCard(cards[0]);
- const newWinTabs = await getRowsForCard(cards[1]);
-
- info("Input a search query.");
- EventUtils.synthesizeMouseAtCenter(openTabs.searchTextbox, {}, content);
- EventUtils.sendString(TEST_URL, content);
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[0].tabList.rowEls.length === 0,
- "There are no matching search results in the original window."
- );
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[1].tabList.rowEls.length === 1,
- "There is one matching search result in the new window."
- );
-
- info("Clear the search query.");
- EventUtils.synthesizeMouseAtCenter(
- openTabs.searchTextbox.clearButton,
- {},
- content
- );
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[0].tabList.rowEls.length === winTabs.length,
- "The original window's list is restored."
- );
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[1].tabList.rowEls.length === newWinTabs.length,
- "The new window's list is restored."
- );
- openTabs.searchTextbox.blur();
-
- info("Input a search query with keyboard.");
- EventUtils.synthesizeKey("f", { accelKey: true }, content);
- EventUtils.sendString(TEST_URL, content);
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[0].tabList.rowEls.length === 0,
- "There are no matching search results in the original window."
- );
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[1].tabList.rowEls.length === 1,
- "There is one matching search result in the new window."
- );
-
- info("Clear the search query with keyboard.");
- is(
- openTabs.shadowRoot.activeElement,
- openTabs.searchTextbox,
- "Search input is focused"
- );
- EventUtils.synthesizeKey("KEY_Tab", {}, content);
ok(
- openTabs.searchTextbox.clearButton.matches(":focus-visible"),
- "Clear Search button is focused"
- );
- EventUtils.synthesizeKey("KEY_Enter", {}, content);
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[0].tabList.rowEls.length === winTabs.length,
- "The original window's list is restored."
- );
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[1].tabList.rowEls.length === newWinTabs.length,
- "The new window's list is restored."
- );
- });
-
- await SpecialPowers.popPrefEnv();
- await cleanup();
-});
-
-add_task(async function search_open_tabs_recent_browsing() {
- const NUMBER_OF_TABS = 6;
- const win = await BrowserTestUtils.openNewBrowserWindow();
- for (let i = 0; i < NUMBER_OF_TABS; i++) {
- await BrowserTestUtils.openNewForegroundTab(win.gBrowser, TEST_URL);
- }
- await SpecialPowers.pushPrefEnv({
- set: [["browser.firefox-view.search.enabled", true]],
- });
- await openFirefoxViewTab(window).then(async viewTab => {
- const browser = viewTab.linkedBrowser;
- await navigateToCategoryAndWait(browser.contentDocument, "recentbrowsing");
- const recentBrowsing = browser.contentDocument.querySelector(
- "view-recentbrowsing"
- );
-
- info("Input a search query.");
- EventUtils.synthesizeMouseAtCenter(
- recentBrowsing.searchTextbox,
- {},
- content
- );
- EventUtils.sendString(TEST_URL, content);
- const slot = recentBrowsing.querySelector("[slot='opentabs']");
- await TestUtils.waitForCondition(
- () => slot.viewCards[0].tabList.rowEls.length === 5,
- "Not all search results are shown yet."
+ openTabs.shadowRoot.querySelector("[card-count=three-or-more]"),
+ "The container shows three columns when three windows are open."
);
-
- info("Click the Show All link.");
- const showAllLink = await TestUtils.waitForCondition(() => {
- const elt = slot.viewCards[0].shadowRoot.querySelector(
- "[data-l10n-id='firefoxview-show-all']"
- );
- EventUtils.synthesizeMouseAtCenter(elt, {}, content);
- if (slot.viewCards[0].tabList.rowEls.length === NUMBER_OF_TABS) {
- return elt;
- }
- return false;
- }, "All search results are shown.");
- is(showAllLink.role, "link", "The show all control is a link.");
- ok(BrowserTestUtils.isHidden(showAllLink), "The show all link is hidden.");
});
- await SpecialPowers.popPrefEnv();
await cleanup();
});
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_changes.js b/browser/components/firefoxview/tests/browser/browser_opentabs_changes.js
index c293afa8cd..15aba26d74 100644
--- a/browser/components/firefoxview/tests/browser/browser_opentabs_changes.js
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_changes.js
@@ -1,4 +1,4 @@
-const { NonPrivateTabs, getTabsTargetForWindow } = ChromeUtils.importESModule(
+const { getTabsTargetForWindow } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
let privateTabsChanges;
@@ -505,8 +505,9 @@ add_task(async function test_tabsFromPrivateWindows() {
});
const private2TabsChanges = getTabsTargetForWindow(private2Win);
private2TabsChanges.addEventListener("TabChange", private2Listener);
- ok(
- privateTabsChanges !== getTabsTargetForWindow(private2Win),
+ Assert.notStrictEqual(
+ privateTabsChanges,
+ getTabsTargetForWindow(private2Win),
"getTabsTargetForWindow creates a distinct instance for a different private window"
);
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js
index 57d0f8d031..955c2363d7 100644
--- a/browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js
@@ -1,6 +1,9 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
+// Test regularly times out - especially with verify
+requestLongerTimeout(2);
+
const TEST_URL1 = "about:robots";
const TEST_URL2 = "https://example.org/";
const TEST_URL3 = "about:mozilla";
@@ -20,27 +23,6 @@ const fxaDevicesWithCommands = [
},
];
-const { NonPrivateTabs } = ChromeUtils.importESModule(
- "resource:///modules/OpenTabs.sys.mjs"
-);
-
-async function getRowsForCard(card) {
- await TestUtils.waitForCondition(() => card.tabList.rowEls.length);
- return card.tabList.rowEls;
-}
-
-async function add_new_tab(URL) {
- let tabChangeRaised = BrowserTestUtils.waitForEvent(
- NonPrivateTabs,
- "TabChange"
- );
- let tab = BrowserTestUtils.addTab(gBrowser, URL);
- // wait so we can reliably compare the tab URL
- await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
- await tabChangeRaised;
- return tab;
-}
-
function getVisibleTabURLs(win = window) {
return win.gBrowser.visibleTabs.map(tab => tab.linkedBrowser.currentURI.spec);
}
@@ -78,7 +60,7 @@ async function waitUntilRowsMatch(openTabs, cardIndex, expectedURLs) {
card.shadowRoot,
{ characterData: true, childList: true, subtree: true },
async () => {
- let rows = await getRowsForCard(card);
+ let rows = await getTabRowsForCard(card);
return (
rows.length == expectedURLs.length &&
JSON.stringify(getTabRowURLs(rows)) == expectedURLsAsString
@@ -106,7 +88,7 @@ async function getContextMenuPanelListForCard(card) {
async function openContextMenuForItem(tabItem, card) {
// click on the item's button element (more menu)
// and wait for the panel list to be shown
- tabItem.buttonEl.click();
+ tabItem.secondaryButtonEl.click();
// NOTE: menu must populate with devices data before it can be rendered
// so the creation of the panel-list can be async
let panelList = await getContextMenuPanelListForCard(card);
@@ -122,7 +104,7 @@ async function moreMenuSetup() {
await clickFirefoxViewButton(window);
const document = window.FirefoxViewHandler.tab.linkedBrowser.contentDocument;
- await navigateToCategoryAndWait(document, "opentabs");
+ await navigateToViewAndWait(document, "opentabs");
let openTabs = document.querySelector("view-opentabs[name=opentabs]");
setSortOption(openTabs, "tabStripOrder");
@@ -134,7 +116,7 @@ async function moreMenuSetup() {
let cards = getOpenTabsCards(openTabs);
is(cards.length, 1, "There is one open window.");
- let rows = await getRowsForCard(cards[0]);
+ let rows = await getTabRowsForCard(cards[0]);
let firstTab = rows[0];
@@ -148,6 +130,44 @@ async function moreMenuSetup() {
return [cards, rows];
}
+add_task(async function test_close_open_tab() {
+ await withFirefoxView({}, async browser => {
+ const [cards, rows] = await moreMenuSetup();
+ const firstTab = rows[0];
+ const tertiaryButtonEl = firstTab.tertiaryButtonEl;
+
+ ok(tertiaryButtonEl, "Dismiss button exists");
+
+ await clearAllParentTelemetryEvents();
+ let closeTabEvent = [
+ ["firefoxview_next", "close_open_tab", "tabs", undefined],
+ ];
+
+ let tabsUpdated = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+ EventUtils.synthesizeMouseAtCenter(tertiaryButtonEl, {}, content);
+ await tabsUpdated;
+ Assert.deepEqual(
+ getVisibleTabURLs(),
+ [TEST_URL2, TEST_URL3],
+ "First tab successfully removed"
+ );
+
+ await telemetryEvent(closeTabEvent);
+
+ const openTabs = cards[0].ownerDocument.querySelector(
+ "view-opentabs[name=opentabs]"
+ );
+ await waitUntilRowsMatch(openTabs, 0, [TEST_URL2, TEST_URL3]);
+
+ while (gBrowser.tabs.length > 1) {
+ BrowserTestUtils.removeTab(gBrowser.tabs[0]);
+ }
+ });
+});
+
add_task(async function test_more_menus() {
await withFirefoxView({}, async browser => {
let win = browser.ownerGlobal;
@@ -156,11 +176,11 @@ add_task(async function test_more_menus() {
gBrowser.selectedTab = gBrowser.visibleTabs[0];
Assert.equal(
gBrowser.selectedTab.linkedBrowser.currentURI.spec,
- "about:blank",
- "Selected tab is about:blank"
+ "about:mozilla",
+ "Selected tab is about:mozilla"
);
- info(`Loading ${TEST_URL1} into the selected about:blank tab`);
+ info(`Loading ${TEST_URL1} into the selected about:mozilla tab`);
let tabLoaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
win.gURLBar.focus();
@@ -176,64 +196,18 @@ add_task(async function test_more_menus() {
"Prepared 3 open tabs"
);
+ // Move Tab submenu item
let firstTab = rows[0];
// Open the panel list (more menu) from the first list item
let panelList = await openContextMenuForItem(firstTab, cards[0]);
- // Close Tab menu item
- info("Panel list shown. Clicking on panel-item");
- let panelItem = panelList.querySelector(
- "panel-item[data-l10n-id=fxviewtabrow-close-tab]"
- );
- let panelItemButton = panelItem.shadowRoot.querySelector(
- "button[role=menuitem]"
- );
- ok(panelItem, "Close Tab panel item exists");
- ok(
- panelItemButton,
- "Close Tab panel item button with role=menuitem exists"
- );
-
- await clearAllParentTelemetryEvents();
- let contextMenuEvent = [
- [
- "firefoxview_next",
- "context_menu",
- "tabs",
- undefined,
- { menu_action: "close-tab", data_type: "opentabs" },
- ],
- ];
-
- // close a tab via the menu
- let tabChangeRaised = BrowserTestUtils.waitForEvent(
- NonPrivateTabs,
- "TabChange"
- );
- menuHidden = BrowserTestUtils.waitForEvent(panelList, "hidden");
- panelItemButton.click();
- info("Waiting for result of closing a tab via the menu");
- await tabChangeRaised;
- await cards[0].getUpdateComplete();
- await menuHidden;
- await telemetryEvent(contextMenuEvent);
-
- Assert.deepEqual(
- getVisibleTabURLs(),
- [TEST_URL2, TEST_URL3],
- "Got the expected 2 open tabs"
- );
-
let openTabs = cards[0].ownerDocument.querySelector(
"view-opentabs[name=opentabs]"
);
- await waitUntilRowsMatch(openTabs, 0, [TEST_URL2, TEST_URL3]);
+ await waitUntilRowsMatch(openTabs, 0, [TEST_URL1, TEST_URL2, TEST_URL3]);
- // Move Tab submenu item
- firstTab = rows[0];
- is(firstTab.url, TEST_URL2, `First tab list item is ${TEST_URL2}`);
+ is(firstTab.url, TEST_URL1, `First tab list item is ${TEST_URL1}`);
- panelList = await openContextMenuForItem(firstTab, cards[0]);
let moveTabsPanelItem = panelList.querySelector(
"panel-item[data-l10n-id=fxviewtabrow-move-tab]"
);
@@ -243,15 +217,14 @@ add_task(async function test_more_menus() {
);
ok(moveTabsSubmenuList, "Move tabs submenu panel list exists");
- // navigate down to the "Move tabs" submenu option, and
+ // navigate to the "Move tabs" submenu option, and
// open it with the right arrow key
- EventUtils.synthesizeKey("KEY_ArrowDown", {});
shown = BrowserTestUtils.waitForEvent(moveTabsSubmenuList, "shown");
EventUtils.synthesizeKey("KEY_ArrowRight", {});
await shown;
await clearAllParentTelemetryEvents();
- contextMenuEvent = [
+ let contextMenuEvent = [
[
"firefoxview_next",
"context_menu",
@@ -264,7 +237,7 @@ add_task(async function test_more_menus() {
// click on the first option, which should be "Move to the end" since
// this is the first tab
menuHidden = BrowserTestUtils.waitForEvent(panelList, "hidden");
- tabChangeRaised = BrowserTestUtils.waitForEvent(
+ let tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
@@ -276,7 +249,7 @@ add_task(async function test_more_menus() {
Assert.deepEqual(
getVisibleTabURLs(),
- [TEST_URL3, TEST_URL2],
+ [TEST_URL2, TEST_URL3, TEST_URL1],
"The last tab became the first tab"
);
@@ -284,15 +257,15 @@ add_task(async function test_more_menus() {
// closing a tab since it very clearly reveals the issues
// outlined in bug 1852622 when there are 3 or more tabs open
// and one is moved via the more menus.
- await waitUntilRowsMatch(openTabs, 0, [TEST_URL3, TEST_URL2]);
+ await waitUntilRowsMatch(openTabs, 0, [TEST_URL2, TEST_URL3, TEST_URL1]);
// Copy Link menu item (copyLink function that's called is a member of Viewpage.mjs)
panelList = await openContextMenuForItem(firstTab, cards[0]);
firstTab = rows[0];
- panelItem = panelList.querySelector(
+ let panelItem = panelList.querySelector(
"panel-item[data-l10n-id=fxviewtabrow-copy-link]"
);
- panelItemButton = panelItem.shadowRoot.querySelector(
+ let panelItemButton = panelItem.shadowRoot.querySelector(
"button[role=menuitem]"
);
ok(panelItem, "Copy link panel item exists");
@@ -323,7 +296,7 @@ add_task(async function test_more_menus() {
"text/plain",
Ci.nsIClipboard.kGlobalClipboard
);
- is(copiedText, TEST_URL3, "The correct url has been copied and pasted");
+ is(copiedText, TEST_URL2, "The correct url has been copied and pasted");
while (gBrowser.tabs.length > 1) {
BrowserTestUtils.removeTab(gBrowser.tabs[0]);
@@ -349,11 +322,11 @@ add_task(async function test_send_device_submenu() {
.callsFake(() => fxaDevicesWithCommands);
await withFirefoxView({}, async browser => {
- // TEST_URL2 is our only tab, left over from previous test
+ // TEST_URL1 is our only tab, left over from previous test
Assert.deepEqual(
getVisibleTabURLs(),
- [TEST_URL2],
- `We initially have a single ${TEST_URL2} tab`
+ [TEST_URL1],
+ `We initially have a single ${TEST_URL1} tab`
);
let shown;
@@ -376,9 +349,7 @@ add_task(async function test_send_device_submenu() {
// navigate down to the "Send tabs" submenu option, and
// open it with the right arrow key
- EventUtils.synthesizeKey("KEY_ArrowDown", {});
- EventUtils.synthesizeKey("KEY_ArrowDown", {});
- EventUtils.synthesizeKey("KEY_ArrowDown", {});
+ EventUtils.synthesizeKey("KEY_ArrowDown", { repeat: 4 });
shown = BrowserTestUtils.waitForEvent(sendTabSubmenuList, "shown");
EventUtils.synthesizeKey("KEY_ArrowRight", {});
@@ -389,9 +360,9 @@ add_task(async function test_send_device_submenu() {
.expects("sendTabToDevice")
.once()
.withExactArgs(
- TEST_URL2,
+ TEST_URL1,
[fxaDevicesWithCommands[0]],
- "mochitest index /"
+ "Gort! Klaatu barada nikto!"
)
.returns(true);
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_more.js b/browser/components/firefoxview/tests/browser/browser_opentabs_more.js
new file mode 100644
index 0000000000..fd25348699
--- /dev/null
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_more.js
@@ -0,0 +1,151 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let gInitialTab;
+let gInitialTabURL;
+
+// This test opens many tabs and regularly times out - especially with verify
+requestLongerTimeout(2);
+
+add_setup(function () {
+ gInitialTab = gBrowser.selectedTab;
+ gInitialTabURL = gBrowser.selectedBrowser.currentURI.spec;
+});
+
+async function cleanup() {
+ await SimpleTest.promiseFocus(window);
+ await promiseAllButPrimaryWindowClosed();
+ await BrowserTestUtils.switchTab(gBrowser, gInitialTab);
+ await closeFirefoxViewTab(window);
+
+ // clean up extra tabs
+ while (gBrowser.tabs.length > 1) {
+ BrowserTestUtils.removeTab(gBrowser.tabs.at(-1));
+ }
+
+ is(
+ BrowserWindowTracker.orderedWindows.length,
+ 1,
+ "One window at the end of test cleanup"
+ );
+ Assert.deepEqual(
+ gBrowser.tabs.map(tab => tab.linkedBrowser.currentURI.spec),
+ [gInitialTabURL],
+ "One about:blank tab open at the end up test cleanup"
+ );
+}
+
+add_task(async function toggle_show_more_link() {
+ const tabEntry = url => ({
+ entries: [{ url, triggeringPrincipal_base64 }],
+ });
+ const NUMBER_OF_WINDOWS = 4;
+ const NUMBER_OF_TABS = 42;
+ const browserState = { windows: [] };
+ for (let windowIndex = 0; windowIndex < NUMBER_OF_WINDOWS; windowIndex++) {
+ const winData = { tabs: [] };
+ let tabCount = windowIndex == NUMBER_OF_WINDOWS - 1 ? NUMBER_OF_TABS : 1;
+ for (let i = 0; i < tabCount; i++) {
+ winData.tabs.push(tabEntry(`data:,Window${windowIndex}-Tab${i}`));
+ }
+ winData.selected = winData.tabs.length;
+ browserState.windows.push(winData);
+ }
+ // use Session restore to batch-open windows and tabs
+ info(`Restoring to browserState: ${JSON.stringify(browserState, null, 2)}`);
+ await SessionStoreTestUtils.promiseBrowserState(browserState);
+ info("Windows and tabs opened, waiting for readyWindowsPromise");
+ await NonPrivateTabs.readyWindowsPromise;
+ info("readyWindowsPromise resolved");
+
+ // restoring this state requires an update to the initial tab globals
+ // so cleanup expects the right thing
+ gInitialTab = gBrowser.selectedTab;
+ gInitialTabURL = gBrowser.selectedBrowser.currentURI.spec;
+
+ const windows = Array.from(Services.wm.getEnumerator("navigator:browser"));
+ is(windows.length, NUMBER_OF_WINDOWS, "There are four browser windows.");
+
+ const tab = (win = window) => {
+ info("Tab");
+ EventUtils.synthesizeKey("KEY_Tab", {}, win);
+ };
+
+ const enter = (win = window) => {
+ info("Enter");
+ EventUtils.synthesizeKey("KEY_Enter", {}, win);
+ };
+
+ let lastCard;
+
+ await openFirefoxViewTab(window).then(async viewTab => {
+ const browser = viewTab.linkedBrowser;
+ await navigateToOpenTabs(browser);
+ const openTabs = getOpenTabsComponent(browser);
+ await openTabs.updateComplete;
+
+ let cards;
+ info(`Waiting for ${NUMBER_OF_WINDOWS} of window cards`);
+ await BrowserTestUtils.waitForCondition(() => {
+ cards = getOpenTabsCards(openTabs);
+ return cards.length == NUMBER_OF_WINDOWS;
+ });
+ is(cards.length, NUMBER_OF_WINDOWS, "There are four windows.");
+ lastCard = cards[NUMBER_OF_WINDOWS - 1];
+
+ Assert.less(
+ (await getTabRowsForCard(lastCard)).length,
+ NUMBER_OF_TABS,
+ "Not all tabs are shown yet."
+ );
+ info("Toggle the Show More link.");
+ lastCard.shadowRoot.querySelector("div[slot=footer]").click();
+ await BrowserTestUtils.waitForMutationCondition(
+ lastCard.shadowRoot,
+ { childList: true, subtree: true },
+ async () => (await getTabRowsForCard(lastCard)).length === NUMBER_OF_TABS
+ );
+
+ info("Toggle the Show Less link.");
+ lastCard.shadowRoot.querySelector("div[slot=footer]").click();
+ await BrowserTestUtils.waitForMutationCondition(
+ lastCard.shadowRoot,
+ { childList: true, subtree: true },
+ async () => (await getTabRowsForCard(lastCard)).length < NUMBER_OF_TABS
+ );
+
+ // Setting this pref allows the test to run as expected with a keyboard on MacOS
+ await SpecialPowers.pushPrefEnv({
+ set: [["accessibility.tabfocus", 7]],
+ });
+
+ info("Toggle the Show More link with keyboard.");
+ lastCard.shadowRoot.querySelector("card-container").summaryEl.focus();
+ // Tab to first item in the list
+ tab();
+ // Tab to the footer
+ tab();
+ enter();
+ await BrowserTestUtils.waitForMutationCondition(
+ lastCard.shadowRoot,
+ { childList: true, subtree: true },
+ async () => (await getTabRowsForCard(lastCard)).length === NUMBER_OF_TABS
+ );
+
+ info("Toggle the Show Less link with keyboard.");
+ lastCard.shadowRoot.querySelector("card-container").summaryEl.focus();
+ // Tab to first item in the list
+ tab();
+ // Tab to the footer
+ tab();
+ enter();
+ await BrowserTestUtils.waitForMutationCondition(
+ lastCard.shadowRoot,
+ { childList: true, subtree: true },
+ async () => (await getTabRowsForCard(lastCard)).length < NUMBER_OF_TABS
+ );
+
+ await SpecialPowers.popPrefEnv();
+ });
+ await cleanup();
+});
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();
+});
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js b/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js
index e5beb4700a..ee3f9981e1 100644
--- a/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js
@@ -13,9 +13,6 @@ const tabURL4 = "data:,Tab4";
let gInitialTab;
let gInitialTabURL;
-const { NonPrivateTabs } = ChromeUtils.importESModule(
- "resource:///modules/OpenTabs.sys.mjs"
-);
add_setup(function () {
gInitialTab = gBrowser.selectedTab;
@@ -158,12 +155,12 @@ function getOpenTabsComponent(browser) {
async function checkTabList(browser, expected) {
const tabsView = getOpenTabsComponent(browser);
- const openTabsCard = tabsView.shadowRoot.querySelector("view-opentabs-card");
- await tabsView.getUpdateComplete();
- const tabList = openTabsCard.shadowRoot.querySelector("fxview-tab-list");
- Assert.ok(tabList, "Found the tab list element");
- await TestUtils.waitForCondition(() => tabList.rowEls.length);
- let actual = Array.from(tabList.rowEls).map(row => row.url);
+ const [openTabsCard] = getOpenTabsCards(tabsView);
+ await openTabsCard.updateComplete;
+
+ const tabListRows = await getTabRowsForCard(openTabsCard);
+ Assert.ok(tabListRows, "Found the tab list element");
+ let actual = Array.from(tabListRows).map(row => row.url);
Assert.deepEqual(
actual,
expected,
@@ -255,7 +252,7 @@ add_task(async function test_multiple_window_tabs() {
NonPrivateTabs,
"TabRecencyChange"
);
- await SimpleTest.promiseFocus(win1);
+ await switchToWindow(win1);
await tabChangeRaised;
Assert.equal(
tabUrl(win1.gBrowser.selectedTab),
@@ -308,17 +305,20 @@ add_task(async function test_windows_activation() {
await openFirefoxViewTab(win1).then(tab => (fxViewTab = tab));
const win2 = await BrowserTestUtils.openNewBrowserWindow();
+ await switchToWindow(win2);
await prepareOpenTabs([tabURL2], win2);
const win3 = await BrowserTestUtils.openNewBrowserWindow();
+ await switchToWindow(win3);
await prepareOpenTabs([tabURL3], win3);
- await tabChangeRaised;
tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabRecencyChange"
);
- await SimpleTest.promiseFocus(win1);
+ info("Switching back to win 1");
+ await switchToWindow(win1);
+ info("Waiting for tabChangeRaised to resolve");
await tabChangeRaised;
const browser = fxViewTab.linkedBrowser;
@@ -329,7 +329,7 @@ add_task(async function test_windows_activation() {
NonPrivateTabs,
"TabRecencyChange"
);
- await SimpleTest.promiseFocus(win2);
+ await switchToWindow(win2);
await tabChangeRaised;
await checkTabList(browser, [tabURL2, tabURL3, tabURL1]);
await cleanup(win2, win3);
@@ -341,6 +341,7 @@ add_task(async function test_minimize_restore_windows() {
await prepareOpenTabs([tabURL1, tabURL2]);
const win2 = await BrowserTestUtils.openNewBrowserWindow();
await prepareOpenTabs([tabURL3, tabURL4], win2);
+ await NonPrivateTabs.readyWindowsPromise;
// to avoid confusing the results by activating different windows,
// check fxview in the current window - which is win2
@@ -374,7 +375,7 @@ add_task(async function test_minimize_restore_windows() {
);
await minimizeWindow(win2);
info("Focusing win1, where tab2 is selected - making it most recent");
- await SimpleTest.promiseFocus(win1);
+ await switchToWindow(win1);
await tabChangeRaised;
Assert.equal(
@@ -395,7 +396,7 @@ add_task(async function test_minimize_restore_windows() {
"TabRecencyChange"
);
await restoreWindow(win2);
- await SimpleTest.promiseFocus(win2);
+ await switchToWindow(win2);
await tabChangeRaised;
info(
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_search.js b/browser/components/firefoxview/tests/browser/browser_opentabs_search.js
new file mode 100644
index 0000000000..173bf1a623
--- /dev/null
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_search.js
@@ -0,0 +1,161 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URL = "about:robots";
+let gInitialTab;
+let gInitialTabURL;
+
+add_setup(function () {
+ gInitialTab = gBrowser.selectedTab;
+ gInitialTabURL = gBrowser.selectedBrowser.currentURI.spec;
+});
+
+async function cleanup() {
+ await SimpleTest.promiseFocus(window);
+ await promiseAllButPrimaryWindowClosed();
+ await BrowserTestUtils.switchTab(gBrowser, gInitialTab);
+ await closeFirefoxViewTab(window);
+
+ // clean up extra tabs
+ while (gBrowser.tabs.length > 1) {
+ BrowserTestUtils.removeTab(gBrowser.tabs.at(-1));
+ }
+}
+
+add_task(async function search_open_tabs() {
+ // Open a new window and navigate to TEST_URL. Then, when we search for
+ // TEST_URL, it should show a search result in the new window's card.
+ const win2 = await BrowserTestUtils.openNewBrowserWindow();
+ await switchToWindow(win2);
+ await NonPrivateTabs.readyWindowsPromise;
+ await BrowserTestUtils.openNewForegroundTab(win2.gBrowser, TEST_URL);
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.firefox-view.search.enabled", true]],
+ });
+ await openFirefoxViewTab(window).then(async viewTab => {
+ const browser = viewTab.linkedBrowser;
+ await navigateToOpenTabs(browser);
+ const openTabs = getOpenTabsComponent(browser);
+ await openTabs.updateComplete;
+
+ const cards = getOpenTabsCards(openTabs);
+ is(cards.length, 2, "There are two windows.");
+ const winTabs = await getTabRowsForCard(cards[0]);
+ const newWinTabs = await getTabRowsForCard(cards[1]);
+
+ info("Input a search query.");
+ EventUtils.synthesizeMouseAtCenter(openTabs.searchTextbox, {}, content);
+ EventUtils.sendString(TEST_URL, content);
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length === 0,
+ "There are no matching search results in the original window."
+ );
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[1].tabList.rowEls.length === 1,
+ "There is one matching search result in the new window."
+ );
+
+ info("Clear the search query.");
+ EventUtils.synthesizeMouseAtCenter(
+ openTabs.searchTextbox.clearButton,
+ {},
+ content
+ );
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length === winTabs.length,
+ "The original window's list is restored."
+ );
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[1].tabList.rowEls.length === newWinTabs.length,
+ "The new window's list is restored."
+ );
+ openTabs.searchTextbox.blur();
+
+ info("Input a search query with keyboard.");
+ EventUtils.synthesizeKey("f", { accelKey: true }, content);
+ EventUtils.sendString(TEST_URL, content);
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length === 0,
+ "There are no matching search results in the original window."
+ );
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[1].tabList.rowEls.length === 1,
+ "There is one matching search result in the new window."
+ );
+
+ info("Clear the search query with keyboard.");
+ is(
+ openTabs.shadowRoot.activeElement,
+ openTabs.searchTextbox,
+ "Search input is focused"
+ );
+ EventUtils.synthesizeKey("KEY_Tab", {}, content);
+ ok(
+ openTabs.searchTextbox.clearButton.matches(":focus-visible"),
+ "Clear Search button is focused"
+ );
+ EventUtils.synthesizeKey("KEY_Enter", {}, content);
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length === winTabs.length,
+ "The original window's list is restored."
+ );
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[1].tabList.rowEls.length === newWinTabs.length,
+ "The new window's list is restored."
+ );
+ });
+
+ await SpecialPowers.popPrefEnv();
+ await cleanup();
+});
+
+add_task(async function search_open_tabs_recent_browsing() {
+ const NUMBER_OF_TABS = 6;
+ const win2 = await BrowserTestUtils.openNewBrowserWindow();
+ await switchToWindow(win2);
+ await NonPrivateTabs.readyWindowsPromise;
+
+ for (let i = 0; i < NUMBER_OF_TABS; i++) {
+ await BrowserTestUtils.openNewForegroundTab(win2.gBrowser, TEST_URL);
+ }
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.firefox-view.search.enabled", true]],
+ });
+ await openFirefoxViewTab(window).then(async viewTab => {
+ const browser = viewTab.linkedBrowser;
+ await navigateToViewAndWait(browser.contentDocument, "recentbrowsing");
+ const recentBrowsing = browser.contentDocument.querySelector(
+ "view-recentbrowsing"
+ );
+
+ info("Input a search query.");
+ EventUtils.synthesizeMouseAtCenter(
+ recentBrowsing.searchTextbox,
+ {},
+ content
+ );
+ EventUtils.sendString(TEST_URL, content);
+ const slot = recentBrowsing.querySelector("[slot='opentabs']");
+ await TestUtils.waitForCondition(
+ () => slot.viewCards[0].tabList.rowEls.length === 5,
+ "Not all search results are shown yet."
+ );
+
+ info("Click the Show All link.");
+ const showAllLink = await TestUtils.waitForCondition(() => {
+ const elt = slot.viewCards[0].shadowRoot.querySelector(
+ "[data-l10n-id='firefoxview-show-all']"
+ );
+ EventUtils.synthesizeMouseAtCenter(elt, {}, content);
+ if (slot.viewCards[0].tabList.rowEls.length === NUMBER_OF_TABS) {
+ return elt;
+ }
+ return false;
+ }, "All search results are shown.");
+ is(showAllLink.role, "link", "The show all control is a link.");
+ ok(BrowserTestUtils.isHidden(showAllLink), "The show all link is hidden.");
+ });
+ await SpecialPowers.popPrefEnv();
+ await cleanup();
+});
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_tab_indicators.js b/browser/components/firefoxview/tests/browser/browser_opentabs_tab_indicators.js
index 1375052125..78fab976ed 100644
--- a/browser/components/firefoxview/tests/browser/browser_opentabs_tab_indicators.js
+++ b/browser/components/firefoxview/tests/browser/browser_opentabs_tab_indicators.js
@@ -1,9 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
-const { NonPrivateTabs } = ChromeUtils.importESModule(
- "resource:///modules/OpenTabs.sys.mjs"
-);
+requestLongerTimeout(2);
let pageWithAlert =
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
@@ -11,18 +9,12 @@ let pageWithAlert =
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[0]);
- }
-}
-
add_task(async function test_notification_dot_indicator() {
+ clearHistory();
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
let win = browser.ownerGlobal;
- await navigateToCategoryAndWait(document, "opentabs");
+ await navigateToViewAndWait(document, "opentabs");
// load page that opens prompt when page is hidden
let openedTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
@@ -47,9 +39,10 @@ add_task(async function test_notification_dot_indicator() {
await tabChangeRaised;
await openTabs.updateComplete;
- await TestUtils.waitForCondition(
- () => openTabs.viewCards[0].tabList.rowEls[1].attention,
- "The opened tab doesn't have the attention property, so no notification dot is shown."
+ await TestUtils.waitForCondition(() =>
+ Array.from(openTabs.viewCards[0].tabList.rowEls).some(rowEl => {
+ return rowEl.indicators.includes("attention");
+ })
);
info("The newly opened tab has a notification dot.");
@@ -58,11 +51,12 @@ add_task(async function test_notification_dot_indicator() {
await BrowserTestUtils.switchTab(gBrowser, openedTab);
EventUtils.synthesizeKey("KEY_Enter", {}, win);
- cleanup();
+ cleanupTabs();
});
});
add_task(async function test_container_indicator() {
+ clearHistory();
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
let win = browser.ownerGlobal;
@@ -79,7 +73,7 @@ add_task(async function test_container_indicator() {
URLs[0]
);
- await navigateToCategoryAndWait(document, "opentabs");
+ await navigateToViewAndWait(document, "opentabs");
let openTabs = document.querySelector("view-opentabs[name=opentabs]");
@@ -95,10 +89,14 @@ add_task(async function test_container_indicator() {
);
info("openTabs component has finished updating.");
- let containerTabElem = openTabs.viewCards[0].tabList.rowEls[1];
+ let containerTabElem;
await TestUtils.waitForCondition(
- () => containerTabElem.containerObj,
+ () =>
+ Array.from(openTabs.viewCards[0].tabList.rowEls).some(rowEl => {
+ containerTabElem = rowEl;
+ return rowEl.containerObj;
+ }),
"The container tab element isn't marked in Fx View."
);
@@ -111,14 +109,15 @@ add_task(async function test_container_indicator() {
info("The newly opened tab is marked as a container tab.");
- cleanup();
+ cleanupTabs();
});
});
add_task(async function test_sound_playing_muted_indicator() {
+ clearHistory();
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "opentabs");
+ await navigateToViewAndWait(document, "opentabs");
// Load a page in a container tab
let soundTab = await BrowserTestUtils.openNewForegroundTab(
@@ -146,9 +145,13 @@ add_task(async function test_sound_playing_muted_indicator() {
"The tab list hasn't rendered."
);
- let soundPlayingTabElem = openTabs.viewCards[0].tabList.rowEls[1];
-
- await TestUtils.waitForCondition(() => soundPlayingTabElem.soundPlaying);
+ let soundPlayingTabElem;
+ await TestUtils.waitForCondition(() =>
+ Array.from(openTabs.viewCards[0].tabList.rowEls).some(rowEl => {
+ soundPlayingTabElem = rowEl;
+ return rowEl.indicators.includes("soundplaying");
+ })
+ );
ok(
soundPlayingTabElem.mediaButtonEl,
@@ -174,7 +177,9 @@ add_task(async function test_sound_playing_muted_indicator() {
await tabChangeRaised;
await openTabs.updateComplete;
- await TestUtils.waitForCondition(() => soundPlayingTabElem.muted);
+ await TestUtils.waitForCondition(() =>
+ soundPlayingTabElem.indicators.includes("muted")
+ );
ok(
soundPlayingTabElem.mediaButtonEl,
@@ -185,7 +190,9 @@ add_task(async function test_sound_playing_muted_indicator() {
soundTab.toggleMuteAudio();
await tabChangeRaised;
await openTabs.updateComplete;
- await TestUtils.waitForCondition(() => soundPlayingTabElem.soundPlaying);
+ await TestUtils.waitForCondition(() =>
+ soundPlayingTabElem.indicators.includes("soundplaying")
+ );
ok(
soundPlayingTabElem.mediaButtonEl,
@@ -195,13 +202,80 @@ add_task(async function test_sound_playing_muted_indicator() {
soundTab.toggleMuteAudio();
await tabChangeRaised;
await openTabs.updateComplete;
- await TestUtils.waitForCondition(() => soundPlayingTabElem.muted);
+ await TestUtils.waitForCondition(() =>
+ soundPlayingTabElem.indicators.includes("muted")
+ );
ok(
soundPlayingTabElem.mediaButtonEl,
"The tab has the unmute button showing."
);
- cleanup();
+ cleanupTabs();
+ });
+});
+
+add_task(async function test_bookmark_indicator() {
+ const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URLs[0]);
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToViewAndWait(document, "opentabs");
+ const openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ setSortOption(openTabs, "recency");
+ let rowEl = await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0]?.tabList.rowEls[0]
+ );
+
+ info("Bookmark a tab while Firefox View is active.");
+ let bookmark = await PlacesUtils.bookmarks.insert({
+ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
+ url: URLs[0],
+ });
+ await TestUtils.waitForCondition(
+ () => rowEl.shadowRoot.querySelector(".bookmark"),
+ "Tab shows the bookmark star."
+ );
+ await PlacesUtils.bookmarks.update({
+ guid: bookmark.guid,
+ url: URLs[1],
+ });
+ await TestUtils.waitForCondition(
+ () => !rowEl.shadowRoot.querySelector(".bookmark"),
+ "The bookmark star is removed."
+ );
+ bookmark = await PlacesUtils.bookmarks.insert({
+ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
+ url: URLs[0],
+ });
+ await TestUtils.waitForCondition(
+ () => rowEl.shadowRoot.querySelector(".bookmark"),
+ "The bookmark star is restored."
+ );
+ await PlacesUtils.bookmarks.remove(bookmark.guid);
+ await TestUtils.waitForCondition(
+ () => !rowEl.shadowRoot.querySelector(".bookmark"),
+ "The bookmark star is removed again."
+ );
+
+ info("Bookmark a tab while Firefox View is inactive.");
+ await BrowserTestUtils.switchTab(gBrowser, tab);
+ bookmark = await PlacesUtils.bookmarks.insert({
+ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
+ url: URLs[0],
+ });
+ await switchToFxViewTab();
+ await TestUtils.waitForCondition(
+ () => rowEl.shadowRoot.querySelector(".bookmark"),
+ "Tab shows the bookmark star."
+ );
+ await BrowserTestUtils.switchTab(gBrowser, tab);
+ await PlacesUtils.bookmarks.remove(bookmark.guid);
+ await switchToFxViewTab();
+ await TestUtils.waitForCondition(
+ () => !rowEl.shadowRoot.querySelector(".bookmark"),
+ "The bookmark star is removed."
+ );
});
+ await cleanupTabs();
+ await PlacesUtils.bookmarks.eraseEverything();
});
diff --git a/browser/components/firefoxview/tests/browser/browser_recentlyclosed_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_recentlyclosed_firefoxview.js
index 313d86416e..fcfcf20562 100644
--- a/browser/components/firefoxview/tests/browser/browser_recentlyclosed_firefoxview.js
+++ b/browser/components/firefoxview/tests/browser/browser_recentlyclosed_firefoxview.js
@@ -196,7 +196,7 @@ add_task(async function test_initial_closed_tab() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
is(document.location.href, getFirefoxViewURL());
- await navigateToCategoryAndWait(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
let { cleanup } = await prepareSingleClosedTab();
await switchToFxViewTab(window);
let [listItems] = await waitForRecentlyClosedTabsList(document);
@@ -220,7 +220,7 @@ add_task(async function test_list_ordering() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
await clearAllParentTelemetryEvents();
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
let [cardMainSlotNode, listItems] = await waitForRecentlyClosedTabsList(
document
);
@@ -248,7 +248,7 @@ add_task(async function test_list_updates() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
let [listElem, listItems] = await waitForRecentlyClosedTabsList(document);
Assert.deepEqual(
@@ -321,7 +321,7 @@ add_task(async function test_restore_tab() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
let [listElem, listItems] = await waitForRecentlyClosedTabsList(document);
Assert.deepEqual(
@@ -365,7 +365,7 @@ add_task(async function test_dismiss_tab() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
let [listElem, listItems] = await waitForRecentlyClosedTabsList(document);
await clearAllParentTelemetryEvents();
@@ -429,7 +429,7 @@ add_task(async function test_empty_states() {
const { document } = browser.contentWindow;
is(document.location.href, "about:firefoxview");
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
let recentlyClosedComponent = document.querySelector(
"view-recentlyclosed:not([slot=recentlyclosed])"
);
@@ -479,7 +479,7 @@ add_task(async function test_observers_removed_when_view_is_hidden() {
await withFirefoxView({}, async function (browser) {
const { document } = browser.contentWindow;
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
const [listElem] = await waitForRecentlyClosedTabsList(document);
is(listElem.rowEls.length, 1);
@@ -510,7 +510,7 @@ add_task(async function test_search() {
let { cleanup, expectedURLs } = await prepareClosedTabs();
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- navigateToCategory(document, "recentlyclosed");
+ await navigateToViewAndWait(document, "recentlyclosed");
const [listElem] = await waitForRecentlyClosedTabsList(document);
const recentlyClosedComponent = document.querySelector(
"view-recentlyclosed:not([slot=recentlyclosed])"
@@ -569,7 +569,7 @@ add_task(async function test_search_recent_browsing() {
const { document } = browser.contentWindow;
info("Input a search query.");
- await navigateToCategoryAndWait(document, "recentbrowsing");
+ await navigateToViewAndWait(document, "recentbrowsing");
const recentBrowsing = document.querySelector("view-recentbrowsing");
EventUtils.synthesizeMouseAtCenter(
recentBrowsing.searchTextbox,
diff --git a/browser/components/firefoxview/tests/browser/browser_syncedtabs_errors_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_syncedtabs_errors_firefoxview.js
index 15dba68551..86e4d9cdee 100644
--- a/browser/components/firefoxview/tests/browser/browser_syncedtabs_errors_firefoxview.js
+++ b/browser/components/firefoxview/tests/browser/browser_syncedtabs_errors_firefoxview.js
@@ -56,7 +56,7 @@ add_task(async function test_network_offline() {
sandbox.spy(TabsSetupFlowManager, "tryToClearError");
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
Services.obs.notifyObservers(
@@ -112,7 +112,7 @@ add_task(async function test_sync_error() {
const sandbox = await setupWithDesktopDevices();
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
Services.obs.notifyObservers(null, "weave:service:sync:error");
diff --git a/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js
index 8a3c63985b..11f135cd52 100644
--- a/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js
+++ b/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js
@@ -29,7 +29,7 @@ add_task(async function test_unconfigured_initial_state() {
});
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -85,7 +85,7 @@ add_task(async function test_signed_in() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -148,7 +148,7 @@ add_task(async function test_no_synced_tabs() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -188,7 +188,7 @@ add_task(async function test_no_error_for_two_desktop() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -232,7 +232,7 @@ add_task(async function test_empty_state() {
await withFirefoxView({ openNewWindow: true }, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -277,7 +277,7 @@ add_task(async function test_tabs() {
await withFirefoxView({ openNewWindow: true }, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -365,7 +365,7 @@ add_task(async function test_empty_desktop_same_name() {
await withFirefoxView({ openNewWindow: true }, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -413,7 +413,7 @@ add_task(async function test_empty_desktop_same_name_three() {
await withFirefoxView({ openNewWindow: true }, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -459,7 +459,7 @@ add_task(async function search_synced_tabs() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "syncedtabs");
+ await navigateToViewAndWait(document, "syncedtabs");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
let syncedTabsComponent = document.querySelector(
@@ -666,7 +666,7 @@ add_task(async function search_synced_tabs_recent_browsing() {
});
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
- await navigateToCategoryAndWait(document, "recentbrowsing");
+ await navigateToViewAndWait(document, "recentbrowsing");
Services.obs.notifyObservers(null, UIState.ON_UPDATE);
const recentBrowsing = document.querySelector("view-recentbrowsing");
diff --git a/browser/components/firefoxview/tests/browser/browser_tab_list_keyboard_navigation.js b/browser/components/firefoxview/tests/browser/browser_tab_list_keyboard_navigation.js
new file mode 100644
index 0000000000..d83c1056e0
--- /dev/null
+++ b/browser/components/firefoxview/tests/browser/browser_tab_list_keyboard_navigation.js
@@ -0,0 +1,334 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function test_open_tab_row_navigation() {
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ let win = browser.ownerGlobal;
+
+ await navigateToViewAndWait(document, "opentabs");
+ const openTabs = document.querySelector("view-opentabs[name=opentabs]");
+
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList?.rowEls.length === 1,
+ "The tab list hasn't rendered"
+ );
+
+ // Focus tab row
+ let tabRow = openTabs.viewCards[0].tabList.rowEls[0];
+ let tabRowFocused = BrowserTestUtils.waitForEvent(tabRow, "focus", win);
+ tabRow.focus();
+ await tabRowFocused;
+ info("The tab row main element has focus.");
+
+ // Navigate right to context menu button
+ let secondaryButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.secondaryButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ await secondaryButtonFocused;
+ info("The context menu button has focus.");
+
+ // Navigate right to close button
+ let tertiaryButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.tertiaryButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ await tertiaryButtonFocused;
+ info("The close button has focus");
+
+ // Navigate left to context menu button
+ secondaryButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.secondaryButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowLeft", {}, win);
+ await secondaryButtonFocused;
+ info("The context menu button has focus.");
+
+ // Navigate left to tab row main element
+ tabRowFocused = BrowserTestUtils.waitForEvent(tabRow.mainEl, "focus", win);
+ EventUtils.synthesizeKey("KEY_ArrowLeft", {}, win);
+ await tabRowFocused;
+ info("The tab row main element has focus.");
+ });
+
+ cleanupTabs();
+});
+
+add_task(async function test_focus_moves_after_unmute() {
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ let win = browser.ownerGlobal;
+ await navigateToViewAndWait(document, "opentabs");
+ let openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ await openTabs.updateComplete;
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList.rowEls.length,
+ "The tab list has rendered."
+ );
+ await openTabs.openTabsTarget.readyWindowsPromise;
+ let card = openTabs.viewCards[0];
+ let openTabEl = card.tabList.rowEls[0];
+ let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+
+ // Mute tab
+ openTabEl.muteOrUnmuteTab();
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ let mutedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(
+ () => mutedTab.indicators.includes("muted"),
+ "The tab has been muted."
+ );
+
+ // Unmute using keyboard
+ card.tabList.currentActiveElementId = mutedTab.focusMediaButton();
+ isActiveElement(mutedTab.mediaButtonEl);
+ info("The media button has focus.");
+
+ tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+ EventUtils.synthesizeKey("KEY_Enter", {}, win);
+
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ let unmutedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(
+ () => !unmutedTab.indicators.includes("muted"),
+ "The tab is no longer muted."
+ );
+ isActiveElement(unmutedTab.secondaryButtonEl);
+ info(
+ "Focus should be on the tab's secondary button element after unmuting."
+ );
+
+ // Mute tab again and check that only Enter keys will toggle it
+ unmutedTab.muteOrUnmuteTab();
+ await TestUtils.waitForCondition(
+ () => mutedTab.indicators.includes("muted"),
+ "The tab has been muted."
+ );
+ mutedTab = card.tabList.rowEls[0];
+
+ card.tabList.currentActiveElementId = mutedTab.focusLink();
+ isActiveElement(mutedTab.mainEl);
+ info("The 'main' element has focus.");
+
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ isActiveElement(mutedTab.mediaButtonEl);
+ info("The media button has focus.");
+
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ isActiveElement(mutedTab.secondaryButtonEl);
+ info("The secondary/more button has focus.");
+
+ ok(
+ mutedTab.indicators.includes("muted"),
+ "The muted tab is still muted after arrowing past it."
+ );
+
+ EventUtils.synthesizeKey("KEY_ArrowLeft", {}, win);
+ isActiveElement(mutedTab.mediaButtonEl);
+ info("The media button has focus.");
+
+ EventUtils.synthesizeKey("KEY_Enter", {}, win);
+ await tabChangeRaised;
+ await openTabs.updateComplete;
+
+ unmutedTab = card.tabList.rowEls[0];
+ await TestUtils.waitForCondition(
+ () => !unmutedTab.indicators.includes("muted"),
+ "The tab is no longer muted."
+ );
+ isActiveElement(unmutedTab.secondaryButtonEl);
+ info(
+ "Focus should be on the tab's secondary button element after unmuting."
+ );
+ });
+
+ cleanupTabs();
+});
+
+add_task(async function test_open_tab_row_with_sound_navigation() {
+ const tabWithSound = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "http://mochi.test:8888/browser/dom/base/test/file_audioLoop.html",
+ true
+ );
+ const tabsUpdated = await BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ let win = browser.ownerGlobal;
+
+ await navigateToViewAndWait(document, "opentabs");
+ const openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ await TestUtils.waitForCondition(
+ () => tabWithSound.hasAttribute("soundplaying"),
+ "Tab is playing sound"
+ );
+ await tabsUpdated;
+ await openTabs.updateComplete;
+
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList?.rowEls.length === 2,
+ "The tab list has rendered."
+ );
+
+ // Focus tab row with sound playing
+ let tabRow;
+ for (const rowEl of openTabs.viewCards[0].tabList.rowEls) {
+ if (rowEl.indicators.includes("soundplaying")) {
+ tabRow = rowEl;
+ break;
+ }
+ }
+ ok(tabRow, "Found a tab row with sound playing.");
+ let tabRowFocused = BrowserTestUtils.waitForEvent(tabRow, "focus", win);
+ tabRow.focus();
+ await tabRowFocused;
+ info("The tab row main element has focus.");
+
+ // Navigate right to media button
+ let mediaButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.mediaButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ await mediaButtonFocused;
+ info("The media button has focus.");
+
+ // Navigate right to context menu button
+ let secondaryButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.secondaryButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ await secondaryButtonFocused;
+ info("The context menu button has focus.");
+
+ // Navigate right to close button
+ let tertiaryButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.tertiaryButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ await tertiaryButtonFocused;
+ info("The close button has focus");
+
+ // Navigate left to context menuo button
+ secondaryButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.secondaryButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowLeft", {}, win);
+ await secondaryButtonFocused;
+ info("The context menu button has focus.");
+
+ // Navigate left to media button
+ mediaButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.mediaButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowLeft", {}, win);
+ await mediaButtonFocused;
+ info("The media button has focus.");
+
+ // Navigate left to main element of tab row
+ tabRowFocused = BrowserTestUtils.waitForEvent(tabRow.mainEl, "focus", win);
+ EventUtils.synthesizeKey("KEY_ArrowLeft", {}, win);
+ await tabRowFocused;
+ info("The tab row main element has focus.");
+ });
+
+ cleanupTabs();
+});
+
+add_task(async function test_open_tab_row_with_sound_mute_and_unmute() {
+ const tabWithSound = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "http://mochi.test:8888/browser/dom/base/test/file_audioLoop.html",
+ true
+ );
+ const tabsUpdated = await BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ let win = browser.ownerGlobal;
+
+ await navigateToViewAndWait(document, "opentabs");
+ const openTabs = document.querySelector("view-opentabs[name=opentabs]");
+ await TestUtils.waitForCondition(
+ () => tabWithSound.hasAttribute("soundplaying"),
+ "Tab is playing sound"
+ );
+ await tabsUpdated;
+ await openTabs.updateComplete;
+
+ await TestUtils.waitForCondition(
+ () => openTabs.viewCards[0].tabList?.rowEls.length === 2,
+ "The tab list has rendered."
+ );
+
+ // Focus tab row with sound playing
+ let tabRow;
+ for (const rowEl of openTabs.viewCards[0].tabList.rowEls) {
+ if (rowEl.indicators.includes("soundplaying")) {
+ tabRow = rowEl;
+ break;
+ }
+ }
+ ok(tabRow, "Found a tab row with sound playing.");
+ let tabRowFocused = BrowserTestUtils.waitForEvent(tabRow, "focus", win);
+ tabRow.focus();
+ await tabRowFocused;
+ info("The tab row main element has focus.");
+
+ // Navigate right to media button
+ let mediaButtonFocused = BrowserTestUtils.waitForEvent(
+ tabRow.mediaButtonEl,
+ "focus",
+ win
+ );
+ EventUtils.synthesizeKey("KEY_ArrowRight", {}, win);
+ await mediaButtonFocused;
+ info("The media button has focus.");
+
+ EventUtils.synthesizeKey("KEY_Enter", {}, win);
+ await TestUtils.waitForCondition(
+ () => tabRow.indicators.includes("muted"),
+ "Tab has been muted"
+ );
+
+ EventUtils.synthesizeKey("KEY_Enter", {}, win);
+ await TestUtils.waitForCondition(
+ () => tabRow.indicators.includes("soundplaying"),
+ "Tab has been unmuted"
+ );
+ });
+
+ cleanupTabs();
+});
diff --git a/browser/components/firefoxview/tests/browser/head.js b/browser/components/firefoxview/tests/browser/head.js
index b0b41b759d..302f19071c 100644
--- a/browser/components/firefoxview/tests/browser/head.js
+++ b/browser/components/firefoxview/tests/browser/head.js
@@ -3,6 +3,7 @@
const {
getFirefoxViewURL,
+ switchToWindow,
withFirefoxView,
assertFirefoxViewTab,
assertFirefoxViewTabSelected,
@@ -31,6 +32,11 @@ const { FeatureCalloutMessages } = ChromeUtils.importESModule(
const { TelemetryTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/TelemetryTestUtils.sys.mjs"
);
+const { NonPrivateTabs } = ChromeUtils.importESModule(
+ "resource:///modules/OpenTabs.sys.mjs"
+);
+// shut down the open tabs module after each test so we don't get debounced events bleeding into the next
+registerCleanupFunction(() => NonPrivateTabs.stop());
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
const { SessionStoreTestUtils } = ChromeUtils.importESModule(
@@ -548,31 +554,19 @@ registerCleanupFunction(() => {
gSandbox?.restore();
});
-function navigateToCategory(document, category) {
- const navigation = document.querySelector("fxview-category-navigation");
- let navButton = Array.from(navigation.categoryButtons).filter(
- categoryButton => {
- return categoryButton.name === category;
- }
- )[0];
- navButton.buttonEl.click();
-}
-
-async function navigateToCategoryAndWait(document, category) {
- info(`navigateToCategoryAndWait, for ${category}`);
- const navigation = document.querySelector("fxview-category-navigation");
+async function navigateToViewAndWait(document, view) {
+ info(`navigateToViewAndWait, for ${view}`);
+ const navigation = document.querySelector("moz-page-nav");
const win = document.ownerGlobal;
SimpleTest.promiseFocus(win);
- let navButton = Array.from(navigation.categoryButtons).find(
- categoryButton => {
- return categoryButton.name === category;
- }
- );
+ let navButton = Array.from(navigation.pageNavButtons).find(pageNavButton => {
+ return pageNavButton.view === view;
+ });
const namedDeck = document.querySelector("named-deck");
await BrowserTestUtils.waitForCondition(
() => navButton.getBoundingClientRect().height,
- `Waiting for ${category} button to be clickable`
+ `Waiting for ${view} button to be clickable`
);
EventUtils.synthesizeMouseAtCenter(navButton, {}, win);
@@ -582,10 +576,10 @@ async function navigateToCategoryAndWait(document, category) {
child => child.slot == "selected"
);
return (
- namedDeck.selectedViewName == category &&
+ namedDeck.selectedViewName == view &&
selectedView?.getBoundingClientRect().height
);
- }, `Waiting for ${category} to be visible`);
+ }, `Waiting for ${view} to be visible`);
}
/**
@@ -597,6 +591,7 @@ async function navigateToCategoryAndWait(document, category) {
* The tab switched to.
*/
async function switchToFxViewTab(win = window) {
+ await switchToWindow(win);
return BrowserTestUtils.switchTab(win.gBrowser, win.FirefoxViewHandler.tab);
}
@@ -657,10 +652,32 @@ function setSortOption(component, value) {
EventUtils.synthesizeMouseAtCenter(el, {}, el.ownerGlobal);
}
+/**
+ * Select the Open Tabs view-page in the Firefox View tab.
+ */
+async function navigateToOpenTabs(browser) {
+ const document = browser.contentDocument;
+ if (document.querySelector("named-deck").selectedViewName != "opentabs") {
+ await navigateToViewAndWait(browser.contentDocument, "opentabs");
+ }
+}
+
function getOpenTabsCards(openTabs) {
return openTabs.shadowRoot.querySelectorAll("view-opentabs-card");
}
+function getOpenTabsComponent(browser) {
+ return browser.contentDocument.querySelector("named-deck > view-opentabs");
+}
+
+async function getTabRowsForCard(card) {
+ await TestUtils.waitForCondition(
+ () => card.tabList.rowEls.length,
+ "Wait for the card's tab list to have rows"
+ );
+ return card.tabList.rowEls;
+}
+
async function click_recently_closed_tab_item(itemElem, itemProperty = "") {
// Make sure the firefoxview tab still has focus
is(
@@ -675,7 +692,7 @@ async function click_recently_closed_tab_item(itemElem, itemProperty = "") {
let clickTarget;
switch (itemProperty) {
case "dismiss":
- clickTarget = itemElem.buttonEl;
+ clickTarget = itemElem.secondaryButtonEl;
break;
default:
clickTarget = itemElem.mainEl;
@@ -706,3 +723,25 @@ async function waitForRecentlyClosedTabsList(doc) {
});
return [cardMainSlotNode, cardMainSlotNode.rowEls];
}
+
+async function add_new_tab(URL) {
+ let tabChangeRaised = BrowserTestUtils.waitForEvent(
+ NonPrivateTabs,
+ "TabChange"
+ );
+ let tab = BrowserTestUtils.addTab(gBrowser, URL);
+ // wait so we can reliably compare the tab URL
+ await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ await tabChangeRaised;
+ return tab;
+}
+
+function isActiveElement(expectedLinkEl) {
+ return expectedLinkEl.getRootNode().activeElement == expectedLinkEl;
+}
+
+function cleanupTabs() {
+ while (gBrowser.tabs.length > 1) {
+ BrowserTestUtils.removeTab(gBrowser.tabs[0]);
+ }
+}
diff --git a/browser/components/firefoxview/tests/chrome/chrome.toml b/browser/components/firefoxview/tests/chrome/chrome.toml
index b1677430b2..3edeefd4a9 100644
--- a/browser/components/firefoxview/tests/chrome/chrome.toml
+++ b/browser/components/firefoxview/tests/chrome/chrome.toml
@@ -2,6 +2,4 @@
["test_card_container.html"]
-["test_fxview_category_navigation.html"]
-
["test_fxview_tab_list.html"]
diff --git a/browser/components/firefoxview/tests/chrome/test_fxview_category_navigation.html b/browser/components/firefoxview/tests/chrome/test_fxview_category_navigation.html
deleted file mode 100644
index 0ea0a94baf..0000000000
--- a/browser/components/firefoxview/tests/chrome/test_fxview_category_navigation.html
+++ /dev/null
@@ -1,322 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <meta charset="utf-8">
- <title>FxviewCategoryNavigation Tests</title>
- <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
- <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
- <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
- <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
- <script type="module" src="chrome://browser/content/firefoxview/fxview-category-navigation.mjs"></script>
-</head>
-<style>
-body {
- display: flex;
-}
-#navigation {
- width: var(--in-content-sidebar-width);
-}
-fxview-category-button[name="category-one"]::part(icon) {
- background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
-}
-fxview-category-button[name="category-two"]::part(icon) {
- background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
-}
-fxview-category-button[name="category-three"]::part(icon) {
- background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
-}
-fxview-category-button[name="category-four"]::part(icon) {
- background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
-}
-fxview-category-button[name="category-five"]::part(icon) {
- background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
-}
-</style>
-<body>
- <p id="display"></p>
- <div id="content">
- <div id="navigation">
- <fxview-category-navigation>
- <h2 slot="category-nav-header">Header</h2>
- <fxview-category-button class="category" slot="category-button" name="category-one">
- <span class="category-name">Category 1</span>
- </fxview-category-button>
- <fxview-category-button class="category" slot="category-button" name="category-two">
- <span class="category-name">Category 2</span>
- </fxview-category-button>
- <fxview-category-button class="category" slot="category-button" name="category-three">
- <span class="category-name">Category 3</span>
- </fxview-category-button>
- <fxview-category-button class="category" slot="category-button" name="category-four">
- <span class="category-name">Category 4</span>
- </fxview-category-button>
- <fxview-category-button class="category" slot="category-button" name="category-five">
- <span class="category-name">Category 5</span>
- </fxview-category-button>
- </fxview-category-navigation>
- </div>
- </div>
-<pre id="test"></pre>
-<script>
- Services.scriptloader.loadSubScript(
- "chrome://browser/content/utilityOverlay.js",
- this
- );
- const { BrowserTestUtils } = ChromeUtils.importESModule(
- "resource://testing-common/BrowserTestUtils.sys.mjs"
- );
-
-const fxviewCategoryNav = document.querySelector("fxview-category-navigation");
-
-function isActiveElement(expectedActiveEl) {
- return expectedActiveEl.getRootNode().activeElement == expectedActiveEl;
- }
-
- /**
- * Tests that the first category is selected by default
- */
- add_task(async function test_first_item_selected_by_default() {
- is(
- fxviewCategoryNav.categoryButtons.length,
- 5,
- "Five category buttons are in the navigation"
- );
-
- ok(
- fxviewCategoryNav.categoryButtons[0].name === fxviewCategoryNav.currentCategory,
- "The first category button is selected by default"
- )
- });
-
- /**
- * Tests that categories are selected when clicked
- */
- add_task(async function test_select_category() {
- let gBrowser = BrowserWindowTracker.getTopWindow().top.gBrowser;
- let secondCategory = fxviewCategoryNav.categoryButtons[1];
- let categoryChanged = BrowserTestUtils.waitForEvent(
- gBrowser,
- "change-category"
- );
-
- secondCategory.buttonEl.click();
- await categoryChanged;
-
- ok(
- secondCategory.name === fxviewCategoryNav.currentCategory,
- "The second category button is selected"
- )
-
- let thirdCategory = fxviewCategoryNav.categoryButtons[2];
- categoryChanged = BrowserTestUtils.waitForEvent(
- gBrowser,
- "change-category"
- );
-
- thirdCategory.buttonEl.click();
- await categoryChanged;
-
- ok(
- thirdCategory.name === fxviewCategoryNav.currentCategory,
- "The third category button is selected"
- )
-
- let firstCategory = fxviewCategoryNav.categoryButtons[0];
- categoryChanged = BrowserTestUtils.waitForEvent(
- gBrowser,
- "change-category"
- );
-
- firstCategory.buttonEl.click();
- await categoryChanged;
-
- ok(
- firstCategory.name === fxviewCategoryNav.currentCategory,
- "The first category button is selected"
- )
- });
-
- /**
- * Tests that categories are keyboard-navigable
- */
- add_task(async function test_keyboard_navigation() {
- const arrowDown = async () => {
- info("Arrow down");
- synthesizeKey("KEY_ArrowDown", {});
- await fxviewCategoryNav.getUpdateComplete();
- };
- const arrowUp = async () => {
- info("Arrow up");
- synthesizeKey("KEY_ArrowUp", {});
- await fxviewCategoryNav.getUpdateComplete();
- };
- const arrowLeft = async () => {
- info("Arrow left");
- synthesizeKey("KEY_ArrowLeft", {});
- await fxviewCategoryNav.getUpdateComplete();
- };
- const arrowRight = async () => {
- info("Arrow right");
- synthesizeKey("KEY_ArrowRight", {});
- await fxviewCategoryNav.getUpdateComplete();
- };
-
- // Setting this pref allows the test to run as expected with a keyboard on MacOS
- await SpecialPowers.pushPrefEnv({
- set: [["accessibility.tabfocus", 7]],
- });
-
- let firstCategory = fxviewCategoryNav.categoryButtons[0];
- let secondCategory = fxviewCategoryNav.categoryButtons[1];
- let thirdCategory = fxviewCategoryNav.categoryButtons[2];
- let fourthCategory = fxviewCategoryNav.categoryButtons[3];
- let fifthCategory = fxviewCategoryNav.categoryButtons[4];
-
- is(
- firstCategory.name,
- fxviewCategoryNav.currentCategory,
- "The first category button is selected"
- )
- firstCategory.focus();
- await arrowDown();
- ok(
- isActiveElement(secondCategory),
- "The second category button is the active element after first arrow down"
- );
- is(
- secondCategory.name,
- fxviewCategoryNav.currentCategory,
- "The second category button is selected"
- )
- await arrowDown();
- is(
- thirdCategory.name,
- fxviewCategoryNav.currentCategory,
- "The third category button is selected"
- )
- await arrowDown();
- is(
- fourthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fourth category button is selected"
- )
- await arrowDown();
- is(
- fifthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fifth category button is selected"
- )
- await arrowDown();
- is(
- fifthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fifth category button is still selected"
- )
- await arrowUp();
- is(
- fourthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fourth category button is selected"
- )
- await arrowUp();
- is(
- thirdCategory.name,
- fxviewCategoryNav.currentCategory,
- "The third category button is selected"
- )
- await arrowUp();
- is(
- secondCategory.name,
- fxviewCategoryNav.currentCategory,
- "The second category button is selected"
- )
- await arrowUp();
- is(
- firstCategory.name,
- fxviewCategoryNav.currentCategory,
- "The first category button is selected"
- )
- await arrowUp();
- is(
- firstCategory.name,
- fxviewCategoryNav.currentCategory,
- "The first category button is still selected"
- )
-
- // Test navigation with arrow left/right keys
- is(
- firstCategory.name,
- fxviewCategoryNav.currentCategory,
- "The first category button is selected"
- )
- firstCategory.focus();
- await arrowRight();
- ok(
- isActiveElement(secondCategory),
- "The second category button is the active element after first arrow right"
- );
- is(
- secondCategory.name,
- fxviewCategoryNav.currentCategory,
- "The second category button is selected"
- )
- await arrowRight();
- is(
- thirdCategory.name,
- fxviewCategoryNav.currentCategory,
- "The third category button is selected"
- )
- await arrowRight();
- is(
- fourthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fourth category button is selected"
- )
- await arrowRight();
- is(
- fifthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fifth category button is selected"
- )
- await arrowRight();
- is(
- fifthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fifth category button is still selected"
- )
- await arrowLeft();
- is(
- fourthCategory.name,
- fxviewCategoryNav.currentCategory,
- "The fourth category button is selected"
- )
- await arrowLeft();
- is(
- thirdCategory.name,
- fxviewCategoryNav.currentCategory,
- "The third category button is selected"
- )
- await arrowLeft();
- is(
- secondCategory.name,
- fxviewCategoryNav.currentCategory,
- "The second category button is selected"
- )
- await arrowLeft();
- is(
- firstCategory.name,
- fxviewCategoryNav.currentCategory,
- "The first category button is selected"
- )
- await arrowLeft();
- is(
- firstCategory.name,
- fxviewCategoryNav.currentCategory,
- "The first category button is still selected"
- )
-
- await SpecialPowers.popPrefEnv();
- });
-</script>
-</body>
-</html>
diff --git a/browser/components/firefoxview/tests/chrome/test_fxview_tab_list.html b/browser/components/firefoxview/tests/chrome/test_fxview_tab_list.html
index 22f04acab2..e48f776592 100644
--- a/browser/components/firefoxview/tests/chrome/test_fxview_tab_list.html
+++ b/browser/components/firefoxview/tests/chrome/test_fxview_tab_list.html
@@ -308,12 +308,12 @@
);
await arrowRight();
ok(
- isActiveElement(tabItems[0].buttonEl),
+ isActiveElement(tabItems[0].secondaryButtonEl),
"Focus should be on the first row's context menu button element of the list"
);
await arrowDown();
ok(
- isActiveElement(tabItems[1].buttonEl),
+ isActiveElement(tabItems[1].secondaryButtonEl),
"Focus should be on the second row's context menu button element of the list"
);
await arrowLeft();