summaryrefslogtreecommitdiffstats
path: root/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js')
-rw-r--r--browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js747
1 files changed, 747 insertions, 0 deletions
diff --git a/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js
new file mode 100644
index 0000000000..8a3c63985b
--- /dev/null
+++ b/browser/components/firefoxview/tests/browser/browser_syncedtabs_firefoxview.js
@@ -0,0 +1,747 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_setup(async function () {
+ registerCleanupFunction(() => {
+ // reset internal state so it doesn't affect the next tests
+ TabsSetupFlowManager.resetInternalState();
+ });
+
+ // gSync.init() is called in a requestIdleCallback. Force its initialization.
+ gSync.init();
+
+ registerCleanupFunction(async function () {
+ await tearDown(gSandbox);
+ });
+});
+
+async function promiseTabListsUpdated({ tabLists }) {
+ for (const tabList of tabLists) {
+ await tabList.updateComplete;
+ }
+ await TestUtils.waitForTick();
+}
+
+add_task(async function test_unconfigured_initial_state() {
+ const sandbox = setupMocks({
+ state: UIState.STATUS_NOT_CONFIGURED,
+ syncEnabled: false,
+ });
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+
+ let emptyState =
+ syncedTabsComponent.shadowRoot.querySelector("fxview-empty-state");
+ ok(
+ emptyState.getAttribute("headerlabel").includes("syncedtabs-signin"),
+ "Signin message is shown"
+ );
+
+ // Test telemetry for signing into Firefox Accounts.
+ await clearAllParentTelemetryEvents();
+ EventUtils.synthesizeMouseAtCenter(
+ emptyState.querySelector(`button[data-action="sign-in"]`),
+ {},
+ browser.contentWindow
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
+ ).parent?.length >= 1,
+ "Waiting for fxa_continue firefoxview telemetry event.",
+ 200,
+ 100
+ );
+ TelemetryTestUtils.assertEvents(
+ [["firefoxview_next", "fxa_continue", "sync"]],
+ { category: "firefoxview_next" },
+ { clear: true, process: "parent" }
+ );
+ await BrowserTestUtils.removeTab(browser.ownerGlobal.gBrowser.selectedTab);
+ });
+ await tearDown(sandbox);
+});
+
+add_task(async function test_signed_in() {
+ const sandbox = setupMocks({
+ state: UIState.STATUS_SIGNED_IN,
+ fxaDevices: [
+ {
+ id: 1,
+ name: "This Device",
+ isCurrentDevice: true,
+ type: "desktop",
+ tabs: [],
+ },
+ ],
+ });
+
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+ let emptyState =
+ syncedTabsComponent.shadowRoot.querySelector("fxview-empty-state");
+ ok(
+ emptyState.getAttribute("headerlabel").includes("syncedtabs-adddevice"),
+ "Add device message is shown"
+ );
+
+ // Test telemetry for adding a device.
+ await clearAllParentTelemetryEvents();
+ EventUtils.synthesizeMouseAtCenter(
+ emptyState.querySelector(`button[data-action="add-device"]`),
+ {},
+ browser.contentWindow
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
+ ).parent?.length >= 1,
+ "Waiting for fxa_mobile firefoxview telemetry event.",
+ 200,
+ 100
+ );
+ TelemetryTestUtils.assertEvents(
+ [["firefoxview_next", "fxa_mobile", "sync"]],
+ { category: "firefoxview_next" },
+ { clear: true, process: "parent" }
+ );
+ await BrowserTestUtils.removeTab(browser.ownerGlobal.gBrowser.selectedTab);
+ });
+ await tearDown(sandbox);
+});
+
+add_task(async function test_no_synced_tabs() {
+ Services.prefs.setBoolPref("services.sync.engine.tabs", false);
+ const sandbox = setupMocks({
+ state: UIState.STATUS_SIGNED_IN,
+ fxaDevices: [
+ {
+ id: 1,
+ name: "This Device",
+ isCurrentDevice: true,
+ type: "desktop",
+ tabs: [],
+ },
+ {
+ id: 2,
+ name: "Other Device",
+ type: "desktop",
+ tabs: [],
+ },
+ ],
+ });
+
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+ let emptyState =
+ syncedTabsComponent.shadowRoot.querySelector("fxview-empty-state");
+ ok(
+ emptyState.getAttribute("headerlabel").includes("syncedtabs-synctabs"),
+ "Enable synced tabs message is shown"
+ );
+ });
+ await tearDown(sandbox);
+ Services.prefs.setBoolPref("services.sync.engine.tabs", true);
+});
+
+add_task(async function test_no_error_for_two_desktop() {
+ const sandbox = setupMocks({
+ state: UIState.STATUS_SIGNED_IN,
+ fxaDevices: [
+ {
+ id: 1,
+ name: "This Device",
+ isCurrentDevice: true,
+ type: "desktop",
+ tabs: [],
+ },
+ {
+ id: 2,
+ name: "Other Device",
+ type: "desktop",
+ tabs: [],
+ },
+ ],
+ });
+
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+ let emptyState =
+ syncedTabsComponent.shadowRoot.querySelector("fxview-empty-state");
+ is(emptyState, null, "No empty state should be shown");
+ let noTabs = syncedTabsComponent.shadowRoot.querySelectorAll(".notabs");
+ is(noTabs.length, 1, "Should be 1 empty device");
+ });
+ await tearDown(sandbox);
+});
+
+add_task(async function test_empty_state() {
+ const sandbox = setupMocks({
+ state: UIState.STATUS_SIGNED_IN,
+ fxaDevices: [
+ {
+ id: 1,
+ name: "This Device",
+ isCurrentDevice: true,
+ type: "desktop",
+ tabs: [],
+ },
+ {
+ id: 2,
+ name: "Other Desktop",
+ type: "desktop",
+ tabs: [],
+ },
+ {
+ id: 3,
+ name: "Other Mobile",
+ type: "phone",
+ tabs: [],
+ },
+ ],
+ });
+
+ await withFirefoxView({ openNewWindow: true }, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+ let noTabs = syncedTabsComponent.shadowRoot.querySelectorAll(".notabs");
+ is(noTabs.length, 2, "Should be 2 empty devices");
+
+ let headers =
+ syncedTabsComponent.shadowRoot.querySelectorAll("h3[slot=header]");
+ ok(
+ headers[0].textContent.includes("Other Desktop"),
+ "Text is correct (Desktop)"
+ );
+ ok(headers[0].innerHTML.includes("icon desktop"), "Icon should be desktop");
+ ok(
+ headers[1].textContent.includes("Other Mobile"),
+ "Text is correct (Mobile)"
+ );
+ ok(headers[1].innerHTML.includes("icon phone"), "Icon should be phone");
+ });
+ await tearDown(sandbox);
+});
+
+add_task(async function test_tabs() {
+ TabsSetupFlowManager.resetInternalState();
+
+ const sandbox = setupRecentDeviceListMocks();
+ const syncedTabsMock = sandbox.stub(SyncedTabs, "getRecentTabs");
+ let mockTabs1 = getMockTabData(syncedTabsData1);
+ let getRecentTabsResult = mockTabs1;
+ syncedTabsMock.callsFake(() => {
+ info(
+ `Stubbed SyncedTabs.getRecentTabs returning a promise that resolves to ${getRecentTabsResult.length} tabs\n`
+ );
+ return Promise.resolve(getRecentTabsResult);
+ });
+ sandbox.stub(SyncedTabs, "getTabClients").callsFake(() => {
+ return Promise.resolve(syncedTabsData1);
+ });
+
+ await withFirefoxView({ openNewWindow: true }, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+
+ let headers =
+ syncedTabsComponent.shadowRoot.querySelectorAll("h3[slot=header]");
+ ok(
+ headers[0].textContent.includes("My desktop"),
+ "Text is correct (My desktop)"
+ );
+ ok(headers[0].innerHTML.includes("icon desktop"), "Icon should be desktop");
+ ok(
+ headers[1].textContent.includes("My iphone"),
+ "Text is correct (My iphone)"
+ );
+ ok(headers[1].innerHTML.includes("icon phone"), "Icon should be phone");
+
+ let tabLists = syncedTabsComponent.tabLists;
+ await TestUtils.waitForCondition(() => {
+ return tabLists[0].rowEls.length;
+ });
+ let tabRow1 = tabLists[0].rowEls;
+ ok(
+ tabRow1[0].shadowRoot.textContent.includes,
+ "Internet for people, not profits - Mozilla"
+ );
+ ok(tabRow1[1].shadowRoot.textContent.includes, "Sandboxes - Sinon.JS");
+ is(tabRow1.length, 2, "Correct number of rows are displayed.");
+ let tabRow2 = tabLists[1].shadowRoot.querySelectorAll("fxview-tab-row");
+ is(tabRow2.length, 2, "Correct number of rows are dispayed.");
+ ok(tabRow1[0].shadowRoot.textContent.includes, "The Guardian");
+ ok(tabRow1[1].shadowRoot.textContent.includes, "The Times");
+
+ // Test telemetry for opening a tab.
+ await clearAllParentTelemetryEvents();
+ EventUtils.synthesizeMouseAtCenter(tabRow1[0], {}, browser.contentWindow);
+ await TestUtils.waitForCondition(
+ () =>
+ Services.telemetry.snapshotEvents(
+ Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS
+ ).parent?.length >= 1,
+ "Waiting for synced_tabs firefoxview telemetry event.",
+ 200,
+ 100
+ );
+ TelemetryTestUtils.assertEvents(
+ [
+ [
+ "firefoxview_next",
+ "synced_tabs",
+ "tabs",
+ null,
+ { page: "syncedtabs" },
+ ],
+ ],
+ { category: "firefoxview_next" },
+ { clear: true, process: "parent" }
+ );
+ });
+ await tearDown(sandbox);
+});
+
+add_task(async function test_empty_desktop_same_name() {
+ const sandbox = setupMocks({
+ state: UIState.STATUS_SIGNED_IN,
+ fxaDevices: [
+ {
+ id: 1,
+ name: "A Device",
+ isCurrentDevice: true,
+ type: "desktop",
+ tabs: [],
+ },
+ {
+ id: 2,
+ name: "A Device",
+ type: "desktop",
+ tabs: [],
+ },
+ ],
+ });
+
+ await withFirefoxView({ openNewWindow: true }, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+ let noTabs = syncedTabsComponent.shadowRoot.querySelectorAll(".notabs");
+ is(noTabs.length, 1, "Should be 1 empty devices");
+
+ let headers =
+ syncedTabsComponent.shadowRoot.querySelectorAll("h3[slot=header]");
+ ok(
+ headers[0].textContent.includes("A Device"),
+ "Text is correct (Desktop)"
+ );
+ });
+ await tearDown(sandbox);
+});
+
+add_task(async function test_empty_desktop_same_name_three() {
+ const sandbox = setupMocks({
+ state: UIState.STATUS_SIGNED_IN,
+ fxaDevices: [
+ {
+ id: 1,
+ name: "A Device",
+ isCurrentDevice: true,
+ type: "desktop",
+ tabs: [],
+ },
+ {
+ id: 2,
+ name: "A Device",
+ type: "desktop",
+ tabs: [],
+ },
+ {
+ id: 3,
+ name: "A Device",
+ type: "desktop",
+ tabs: [],
+ },
+ ],
+ });
+
+ await withFirefoxView({ openNewWindow: true }, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+ let noTabs = syncedTabsComponent.shadowRoot.querySelectorAll(".notabs");
+ is(noTabs.length, 2, "Should be 2 empty devices");
+
+ let headers =
+ syncedTabsComponent.shadowRoot.querySelectorAll("h3[slot=header]");
+ ok(
+ headers[0].textContent.includes("A Device"),
+ "Text is correct (Desktop)"
+ );
+ ok(
+ headers[1].textContent.includes("A Device"),
+ "Text is correct (Desktop)"
+ );
+ });
+ await tearDown(sandbox);
+});
+
+add_task(async function search_synced_tabs() {
+ TabsSetupFlowManager.resetInternalState();
+
+ const sandbox = setupRecentDeviceListMocks();
+ const syncedTabsMock = sandbox.stub(SyncedTabs, "getRecentTabs");
+ let mockTabs1 = getMockTabData(syncedTabsData1);
+ let getRecentTabsResult = mockTabs1;
+ syncedTabsMock.callsFake(() => {
+ info(
+ `Stubbed SyncedTabs.getRecentTabs returning a promise that resolves to ${getRecentTabsResult.length} tabs\n`
+ );
+ return Promise.resolve(getRecentTabsResult);
+ });
+ sandbox.stub(SyncedTabs, "getTabClients").callsFake(() => {
+ return Promise.resolve(syncedTabsData1);
+ });
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.firefox-view.search.enabled", true]],
+ });
+
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "syncedtabs");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ let syncedTabsComponent = document.querySelector(
+ "view-syncedtabs:not([slot=syncedtabs])"
+ );
+ await TestUtils.waitForCondition(() => syncedTabsComponent.fullyUpdated);
+
+ is(syncedTabsComponent.cardEls.length, 2, "There are two device cards.");
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length &&
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls
+ .length,
+ "The tab list has loaded for the first two cards."
+ );
+ let deviceOneTabs =
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls;
+ let deviceTwoTabs =
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls;
+
+ info("Input a search query.");
+ EventUtils.synthesizeMouseAtCenter(
+ syncedTabsComponent.searchTextbox,
+ {},
+ content
+ );
+ EventUtils.sendString("Mozilla", content);
+ await TestUtils.waitForCondition(
+ () => syncedTabsComponent.fullyUpdated,
+ "Synced Tabs component is done updating."
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length,
+ "The tab list has loaded for the first card."
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length === 1,
+ "There is one matching search result for the first device."
+ );
+ await TestUtils.waitForCondition(
+ () => !syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list"),
+ "There are no matching search results for the second device."
+ );
+
+ info("Clear the search query.");
+ EventUtils.synthesizeMouseAtCenter(
+ syncedTabsComponent.searchTextbox.clearButton,
+ {},
+ content
+ );
+ await TestUtils.waitForCondition(
+ () => syncedTabsComponent.fullyUpdated,
+ "Synced Tabs component is done updating."
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length &&
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls
+ .length,
+ "The tab list has loaded for the first two cards."
+ );
+ deviceOneTabs =
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls;
+ deviceTwoTabs =
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls;
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length === deviceOneTabs.length,
+ "The original device's list is restored."
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls
+ .length === deviceTwoTabs.length,
+ "The new devices's list is restored."
+ );
+ syncedTabsComponent.searchTextbox.blur();
+
+ info("Input a search query with keyboard.");
+ EventUtils.synthesizeKey("f", { accelKey: true }, content);
+ EventUtils.sendString("Mozilla", content);
+ await TestUtils.waitForCondition(
+ () => syncedTabsComponent.fullyUpdated,
+ "Synced Tabs component is done updating."
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length,
+ "The tab list has loaded for the first card."
+ );
+ await TestUtils.waitForCondition(() => {
+ return (
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length === 1
+ );
+ }, "There is one matching search result for the first device.");
+ await TestUtils.waitForCondition(
+ () => !syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list"),
+ "There are no matching search results for the second device."
+ );
+
+ info("Clear the search query with keyboard.");
+ is(
+ syncedTabsComponent.shadowRoot.activeElement,
+ syncedTabsComponent.searchTextbox,
+ "Search input is focused"
+ );
+ EventUtils.synthesizeKey("KEY_Tab", {}, content);
+ ok(
+ syncedTabsComponent.searchTextbox.clearButton.matches(":focus-visible"),
+ "Clear Search button is focused"
+ );
+ EventUtils.synthesizeKey("KEY_Enter", {}, content);
+ await TestUtils.waitForCondition(
+ () => syncedTabsComponent.fullyUpdated,
+ "Synced Tabs component is done updating."
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length &&
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list") &&
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls
+ .length,
+ "The tab list has loaded for the first two cards."
+ );
+ deviceOneTabs =
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls;
+ deviceTwoTabs =
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls;
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[0].querySelector("fxview-tab-list").rowEls
+ .length === deviceOneTabs.length,
+ "The original device's list is restored."
+ );
+ await TestUtils.waitForCondition(
+ () =>
+ syncedTabsComponent.cardEls[1].querySelector("fxview-tab-list").rowEls
+ .length === deviceTwoTabs.length,
+ "The new devices's list is restored."
+ );
+ });
+ await SpecialPowers.popPrefEnv();
+ await tearDown(sandbox);
+});
+
+add_task(async function search_synced_tabs_recent_browsing() {
+ const NUMBER_OF_TABS = 6;
+ TabsSetupFlowManager.resetInternalState();
+ const sandbox = setupRecentDeviceListMocks();
+ const tabClients = [
+ {
+ id: 1,
+ type: "client",
+ name: "My desktop",
+ clientType: "desktop",
+ tabs: Array(NUMBER_OF_TABS).fill({
+ type: "tab",
+ title: "Internet for people, not profits - Mozilla",
+ url: "https://www.mozilla.org/",
+ icon: "https://www.mozilla.org/media/img/favicons/mozilla/favicon.d25d81d39065.ico",
+ client: 1,
+ }),
+ },
+ {
+ id: 2,
+ type: "client",
+ name: "My iphone",
+ clientType: "phone",
+ tabs: [
+ {
+ type: "tab",
+ title: "Mount Everest - Wikipedia",
+ url: "https://en.wikipedia.org/wiki/Mount_Everest",
+ icon: "https://www.wikipedia.org/static/favicon/wikipedia.ico",
+ client: 2,
+ },
+ ],
+ },
+ ];
+ sandbox
+ .stub(SyncedTabs, "getRecentTabs")
+ .resolves(getMockTabData(tabClients));
+ sandbox.stub(SyncedTabs, "getTabClients").resolves(tabClients);
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.firefox-view.search.enabled", true]],
+ });
+ await withFirefoxView({}, async browser => {
+ const { document } = browser.contentWindow;
+ await navigateToCategoryAndWait(document, "recentbrowsing");
+ Services.obs.notifyObservers(null, UIState.ON_UPDATE);
+
+ const recentBrowsing = document.querySelector("view-recentbrowsing");
+ const slot = recentBrowsing.querySelector("[slot='syncedtabs']");
+
+ // Test that all tab lists repopulate when clearing out searched terms (Bug 1869895 & Bug 1873212)
+ info("Input a search query");
+ EventUtils.synthesizeMouseAtCenter(
+ recentBrowsing.searchTextbox,
+ {},
+ content
+ );
+ EventUtils.sendString("Mozilla", content);
+ await TestUtils.waitForCondition(
+ () => slot.fullyUpdated && slot.tabLists.length === 1,
+ "Synced Tabs component is done updating."
+ );
+ await promiseTabListsUpdated(slot);
+ info("Scroll first card into view.");
+ slot.tabLists[0].scrollIntoView();
+ await TestUtils.waitForCondition(
+ () => slot.tabLists[0].rowEls.length === 5,
+ "The first card is populated."
+ );
+ EventUtils.synthesizeMouseAtCenter(
+ recentBrowsing.searchTextbox,
+ {},
+ content
+ );
+ EventUtils.synthesizeKey("KEY_Backspace", { repeat: 5 });
+ await TestUtils.waitForCondition(
+ () => slot.fullyUpdated && slot.tabLists.length === 2,
+ "Synced Tabs component is done updating."
+ );
+ await promiseTabListsUpdated(slot);
+ info("Scroll second card into view.");
+ slot.tabLists[1].scrollIntoView();
+ await TestUtils.waitForCondition(
+ () =>
+ slot.tabLists[0].rowEls.length === 5 &&
+ slot.tabLists[1].rowEls.length === 1,
+ "Both cards are populated."
+ );
+ info("Clear the search query.");
+ EventUtils.synthesizeKey("KEY_Backspace", { repeat: 2 });
+
+ info("Input a search query");
+ EventUtils.synthesizeMouseAtCenter(
+ recentBrowsing.searchTextbox,
+ {},
+ content
+ );
+ EventUtils.sendString("Mozilla", content);
+ await TestUtils.waitForCondition(
+ () => slot.fullyUpdated && slot.tabLists.length === 2,
+ "Synced Tabs component is done updating."
+ );
+ await promiseTabListsUpdated(slot);
+ await TestUtils.waitForCondition(
+ () => slot.tabLists[0].rowEls.length === 5,
+ "Not all search results are shown yet."
+ );
+
+ info("Click the Show All link.");
+ const showAllLink = await TestUtils.waitForCondition(() =>
+ slot.shadowRoot.querySelector("[data-l10n-id='firefoxview-show-all']")
+ );
+ is(showAllLink.role, "link", "The show all control is a link.");
+ EventUtils.synthesizeMouseAtCenter(showAllLink, {}, content);
+ await TestUtils.waitForCondition(
+ () => slot.tabLists[0].rowEls.length === NUMBER_OF_TABS,
+ "All search results are shown."
+ );
+ ok(BrowserTestUtils.isHidden(showAllLink), "The show all link is hidden.");
+ });
+ await SpecialPowers.popPrefEnv();
+ await tearDown(sandbox);
+});