diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js')
-rw-r--r-- | browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js b/browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js new file mode 100644 index 0000000000..57d0f8d031 --- /dev/null +++ b/browser/components/firefoxview/tests/browser/browser_opentabs_firefoxview.js @@ -0,0 +1,423 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const TEST_URL1 = "about:robots"; +const TEST_URL2 = "https://example.org/"; +const TEST_URL3 = "about:mozilla"; + +const fxaDevicesWithCommands = [ + { + id: 1, + name: "My desktop device", + availableCommands: { "https://identity.mozilla.com/cmd/open-uri": "test" }, + lastAccessTime: Date.now(), + }, + { + id: 2, + name: "My mobile device", + availableCommands: { "https://identity.mozilla.com/cmd/open-uri": "boo" }, + lastAccessTime: Date.now() + 60000, // add 30min + }, +]; + +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); +} + +function getTabRowURLs(rows) { + return Array.from(rows).map(row => row.url); +} + +async function waitUntilRowsMatch(openTabs, cardIndex, expectedURLs) { + let card; + + info( + "moreMenuSetup: openTabs has openTabsTarget?:" + !!openTabs?.openTabsTarget + ); + //await openTabs.openTabsTarget.readyWindowsPromise; + info( + `waitUntilRowsMatch, wait for there to be at least ${cardIndex + 1} cards` + ); + await BrowserTestUtils.waitForCondition(() => { + if (!openTabs.initialWindowsReady) { + info("openTabs.initialWindowsReady isn't true"); + return false; + } + try { + card = getOpenTabsCards(openTabs)[cardIndex]; + } catch (ex) { + info("Calling getOpenTabsCards produced exception: " + ex.message); + } + return !!card; + }, "Waiting for openTabs to be ready and to get the cards"); + + const expectedURLsAsString = JSON.stringify(expectedURLs); + info(`Waiting for row URLs to match ${expectedURLs.join(", ")}`); + await BrowserTestUtils.waitForMutationCondition( + card.shadowRoot, + { characterData: true, childList: true, subtree: true }, + async () => { + let rows = await getRowsForCard(card); + return ( + rows.length == expectedURLs.length && + JSON.stringify(getTabRowURLs(rows)) == expectedURLsAsString + ); + } + ); +} + +async function getContextMenuPanelListForCard(card) { + let menuContainer = card.shadowRoot.querySelector( + "view-opentabs-contextmenu" + ); + ok(menuContainer, "Found the menuContainer for card"); + await TestUtils.waitForCondition( + () => menuContainer.panelList, + "Waiting for the context menu's panel-list to be rendered" + ); + ok( + menuContainer.panelList, + "Found the panelList in the card's view-opentabs-contextmenu" + ); + return menuContainer.panelList; +} + +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(); + // 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); + await BrowserTestUtils.waitForEvent(panelList, "shown"); + return panelList; +} + +async function moreMenuSetup() { + await add_new_tab(TEST_URL2); + await add_new_tab(TEST_URL3); + + // once we've opened a few tabs, navigate to the open tabs section in firefox view + await clickFirefoxViewButton(window); + const document = window.FirefoxViewHandler.tab.linkedBrowser.contentDocument; + + await navigateToCategoryAndWait(document, "opentabs"); + + let openTabs = document.querySelector("view-opentabs[name=opentabs]"); + setSortOption(openTabs, "tabStripOrder"); + await openTabs.openTabsTarget.readyWindowsPromise; + + info("waiting for openTabs' first card rows"); + await waitUntilRowsMatch(openTabs, 0, getVisibleTabURLs()); + + let cards = getOpenTabsCards(openTabs); + is(cards.length, 1, "There is one open window."); + + let rows = await getRowsForCard(cards[0]); + + let firstTab = rows[0]; + + firstTab.scrollIntoView(); + is( + isElInViewport(firstTab), + true, + "first tab list item is visible in viewport" + ); + + return [cards, rows]; +} + +add_task(async function test_more_menus() { + await withFirefoxView({}, async browser => { + let win = browser.ownerGlobal; + let shown, menuHidden; + + gBrowser.selectedTab = gBrowser.visibleTabs[0]; + Assert.equal( + gBrowser.selectedTab.linkedBrowser.currentURI.spec, + "about:blank", + "Selected tab is about:blank" + ); + + info(`Loading ${TEST_URL1} into the selected about:blank tab`); + let tabLoaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + + win.gURLBar.focus(); + win.gURLBar.value = TEST_URL1; + EventUtils.synthesizeKey("KEY_Enter", {}, win); + await tabLoaded; + + info("Waiting for moreMenuSetup to resolve"); + let [cards, rows] = await moreMenuSetup(); + Assert.deepEqual( + getVisibleTabURLs(), + [TEST_URL1, TEST_URL2, TEST_URL3], + "Prepared 3 open tabs" + ); + + 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]); + + // Move Tab submenu item + firstTab = rows[0]; + is(firstTab.url, TEST_URL2, `First tab list item is ${TEST_URL2}`); + + panelList = await openContextMenuForItem(firstTab, cards[0]); + let moveTabsPanelItem = panelList.querySelector( + "panel-item[data-l10n-id=fxviewtabrow-move-tab]" + ); + + let moveTabsSubmenuList = moveTabsPanelItem.shadowRoot.querySelector( + "panel-list[id=move-tab-menu]" + ); + ok(moveTabsSubmenuList, "Move tabs submenu panel list exists"); + + // navigate down 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 = [ + [ + "firefoxview_next", + "context_menu", + "tabs", + null, + { menu_action: "move-tab-end", data_type: "opentabs" }, + ], + ]; + + // 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( + NonPrivateTabs, + "TabChange" + ); + EventUtils.synthesizeKey("KEY_Enter", {}); + info("Waiting for result of moving a tab via the menu"); + await telemetryEvent(contextMenuEvent); + await menuHidden; + await tabChangeRaised; + + Assert.deepEqual( + getVisibleTabURLs(), + [TEST_URL3, TEST_URL2], + "The last tab became the first tab" + ); + + // this entire "move tabs" submenu test can be reordered above + // 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]); + + // 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( + "panel-item[data-l10n-id=fxviewtabrow-copy-link]" + ); + panelItemButton = panelItem.shadowRoot.querySelector( + "button[role=menuitem]" + ); + ok(panelItem, "Copy link panel item exists"); + ok( + panelItemButton, + "Copy link panel item button with role=menuitem exists" + ); + + await clearAllParentTelemetryEvents(); + contextMenuEvent = [ + [ + "firefoxview_next", + "context_menu", + "tabs", + null, + { menu_action: "copy-link", data_type: "opentabs" }, + ], + ]; + + menuHidden = BrowserTestUtils.waitForEvent(panelList, "hidden"); + panelItemButton.click(); + info("Waiting for menuHidden"); + await menuHidden; + info("Waiting for telemetryEvent"); + await telemetryEvent(contextMenuEvent); + + let copiedText = SpecialPowers.getClipboardData( + "text/plain", + Ci.nsIClipboard.kGlobalClipboard + ); + is(copiedText, TEST_URL3, "The correct url has been copied and pasted"); + + while (gBrowser.tabs.length > 1) { + BrowserTestUtils.removeTab(gBrowser.tabs[0]); + } + }); +}); + +add_task(async function test_send_device_submenu() { + const sandbox = setupMocks({ + state: UIState.STATUS_SIGNED_IN, + fxaDevices: [ + { + id: 1, + name: "This Device", + isCurrentDevice: true, + type: "desktop", + tabs: [], + }, + ], + }); + sandbox + .stub(gSync, "getSendTabTargets") + .callsFake(() => fxaDevicesWithCommands); + + await withFirefoxView({}, async browser => { + // TEST_URL2 is our only tab, left over from previous test + Assert.deepEqual( + getVisibleTabURLs(), + [TEST_URL2], + `We initially have a single ${TEST_URL2} tab` + ); + let shown; + + Services.obs.notifyObservers(null, UIState.ON_UPDATE); + let [cards, rows] = await moreMenuSetup(document); + + let firstTab = rows[0]; + let panelList = await openContextMenuForItem(firstTab, cards[0]); + + let sendTabPanelItem = panelList.querySelector( + "panel-item[data-l10n-id=fxviewtabrow-send-tab]" + ); + + ok(sendTabPanelItem, "Send tabs to device submenu panel item exists"); + + let sendTabSubmenuList = sendTabPanelItem.shadowRoot.querySelector( + "panel-list[id=send-tab-menu]" + ); + ok(sendTabSubmenuList, "Send tabs to device submenu panel list exists"); + + // 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", {}); + + shown = BrowserTestUtils.waitForEvent(sendTabSubmenuList, "shown"); + EventUtils.synthesizeKey("KEY_ArrowRight", {}); + await shown; + + let expectation = sandbox + .mock(gSync) + .expects("sendTabToDevice") + .once() + .withExactArgs( + TEST_URL2, + [fxaDevicesWithCommands[0]], + "mochitest index /" + ) + .returns(true); + + await clearAllParentTelemetryEvents(); + let contextMenuEvent = [ + [ + "firefoxview_next", + "context_menu", + "tabs", + null, + { menu_action: "send-tab-device", data_type: "opentabs" }, + ], + ]; + + // click on the first device and verify it was "sent" + let menuHidden = BrowserTestUtils.waitForEvent(panelList, "hidden"); + EventUtils.synthesizeKey("KEY_Enter", {}); + + expectation.verify(); + await telemetryEvent(contextMenuEvent); + await menuHidden; + + sandbox.restore(); + TabsSetupFlowManager.resetInternalState(); + while (gBrowser.tabs.length > 1) { + BrowserTestUtils.removeTab(gBrowser.tabs[0]); + } + }); +}); |