diff options
Diffstat (limited to 'browser/components/firefoxview/tests/browser/browser_opentabs_recency.js')
-rw-r--r-- | browser/components/firefoxview/tests/browser/browser_opentabs_recency.js | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js b/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js new file mode 100644 index 0000000000..e5beb4700a --- /dev/null +++ b/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js @@ -0,0 +1,408 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + This test checks the recent-browsing view of open tabs in about:firefoxview next + presents the correct tab data in the correct order. +*/ + +const tabURL1 = "data:,Tab1"; +const tabURL2 = "data:,Tab2"; +const tabURL3 = "data:,Tab3"; +const tabURL4 = "data:,Tab4"; + +let gInitialTab; +let gInitialTabURL; +const { NonPrivateTabs } = ChromeUtils.importESModule( + "resource:///modules/OpenTabs.sys.mjs" +); + +add_setup(function () { + gInitialTab = gBrowser.selectedTab; + gInitialTabURL = tabUrl(gInitialTab); +}); + +function tabUrl(tab) { + return tab.linkedBrowser.currentURI?.spec; +} + +async function minimizeWindow(win) { + let promiseSizeModeChange = BrowserTestUtils.waitForEvent( + win, + "sizemodechange" + ); + win.minimize(); + await promiseSizeModeChange; + ok( + !win.gBrowser.selectedTab.linkedBrowser.docShellIsActive, + "Docshell should be Inactive" + ); + ok(win.document.hidden, "Top level window should be hidden"); +} + +async function restoreWindow(win) { + ok(win.document.hidden, "Top level window should be hidden"); + let promiseSizeModeChange = BrowserTestUtils.waitForEvent( + win, + "sizemodechange" + ); + + // Check if we also need to wait for occlusion to be updated. + let promiseOcclusion; + let willWaitForOcclusion = win.isFullyOccluded; + if (willWaitForOcclusion) { + // Not only do we need to wait for the occlusionstatechange event, + // we also have to wait *one more event loop* to ensure that the + // other listeners to the occlusionstatechange events have fired. + // Otherwise, our browsing context might not have become active + // at the point where we receive the occlusionstatechange event. + promiseOcclusion = BrowserTestUtils.waitForEvent( + win, + "occlusionstatechange" + ).then(() => new Promise(resolve => SimpleTest.executeSoon(resolve))); + } else { + promiseOcclusion = Promise.resolve(); + } + + info("Calling window.restore"); + win.restore(); + // From browser/base/content/test/general/browser_minimize.js: + // On Ubuntu `window.restore` doesn't seem to work, use a timer to make the + // test fail faster and more cleanly than with a test timeout. + info( + `Waiting for sizemodechange ${ + willWaitForOcclusion ? "and occlusionstatechange " : "" + }event` + ); + let timer; + await Promise.race([ + Promise.all([promiseSizeModeChange, promiseOcclusion]), + new Promise((resolve, reject) => { + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + timer = setTimeout(() => { + reject( + `timed out waiting for sizemodechange sizemodechange ${ + willWaitForOcclusion ? "and occlusionstatechange " : "" + }event` + ); + }, 5000); + }), + ]); + clearTimeout(timer); + ok( + win.gBrowser.selectedTab.linkedBrowser.docShellIsActive, + "Docshell should be active again" + ); + ok(!win.document.hidden, "Top level window should be visible"); +} + +async function prepareOpenTabs(urls, win = window) { + const reusableTabURLs = ["about:newtab", "about:blank"]; + const gBrowser = win.gBrowser; + + for (let url of urls) { + if ( + gBrowser.visibleTabs.length == 1 && + reusableTabURLs.includes(gBrowser.selectedBrowser.currentURI.spec) + ) { + // we'll load into this tab rather than opening a new one + info( + `Loading ${url} into blank tab: ${gBrowser.selectedBrowser.currentURI.spec}` + ); + BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, null, url); + } else { + info(`Loading ${url} into new tab`); + await BrowserTestUtils.openNewForegroundTab(gBrowser, url); + } + await new Promise(res => win.requestAnimationFrame(res)); + } + Assert.equal( + gBrowser.visibleTabs.length, + urls.length, + `Prepared ${urls.length} tabs as expected` + ); + Assert.equal( + tabUrl(gBrowser.selectedTab), + urls[urls.length - 1], + "The selectedTab is the last of the URLs given as expected" + ); +} + +async function cleanup(...windowsToClose) { + await Promise.all( + windowsToClose.map(win => BrowserTestUtils.closeWindow(win)) + ); + + while (gBrowser.visibleTabs.length > 1) { + await SessionStoreTestUtils.closeTab(gBrowser.tabs.at(-1)); + } + if (gBrowser.selectedBrowser.currentURI.spec !== gInitialTabURL) { + BrowserTestUtils.startLoadingURIString( + gBrowser.selectedBrowser, + gInitialTabURL + ); + await BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser, + null, + gInitialTabURL + ); + } +} + +function getOpenTabsComponent(browser) { + return browser.contentDocument.querySelector( + "view-recentbrowsing view-opentabs" + ); +} + +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); + Assert.deepEqual( + actual, + expected, + "Tab list has items with URLs in the expected order" + ); +} + +add_task(async function test_single_window_tabs() { + await prepareOpenTabs([tabURL1, tabURL2]); + await openFirefoxViewTab(window).then(async viewTab => { + const browser = viewTab.linkedBrowser; + await checkTabList(browser, [tabURL2, tabURL1]); + + // switch to the first tab + let promiseHidden = BrowserTestUtils.waitForEvent( + browser.contentDocument, + "visibilitychange" + ); + + let tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + await BrowserTestUtils.switchTab(gBrowser, gBrowser.visibleTabs[0]); + await promiseHidden; + await tabChangeRaised; + }); + + // and check the results in the open tabs section of Recent Browsing + await openFirefoxViewTab(window).then(async viewTab => { + const browser = viewTab.linkedBrowser; + await checkTabList(browser, [tabURL1, tabURL2]); + }); + await cleanup(); +}); + +add_task(async function test_multiple_window_tabs() { + const fxViewURL = getFirefoxViewURL(); + const win1 = window; + let tabChangeRaised; + await prepareOpenTabs([tabURL1, tabURL2]); + const win2 = await BrowserTestUtils.openNewBrowserWindow(); + await prepareOpenTabs([tabURL3, tabURL4], win2); + + // to avoid confusing the results by activating different windows, + // check fxview in the current window - which is win2 + info("Switching to fxview tab in win2"); + await openFirefoxViewTab(win2).then(async viewTab => { + const browser = viewTab.linkedBrowser; + await checkTabList(browser, [tabURL4, tabURL3, tabURL2, tabURL1]); + + Assert.equal( + tabUrl(win2.gBrowser.selectedTab), + fxViewURL, + `The selected tab in window 2 is ${fxViewURL}` + ); + + info("Switching to first tab (tab3) in win2"); + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + let promiseHidden = BrowserTestUtils.waitForEvent( + browser.contentDocument, + "visibilitychange" + ); + await BrowserTestUtils.switchTab( + win2.gBrowser, + win2.gBrowser.visibleTabs[0] + ); + Assert.equal( + tabUrl(win2.gBrowser.selectedTab), + tabURL3, + `The selected tab in window 2 is ${tabURL3}` + ); + await tabChangeRaised; + await promiseHidden; + }); + + info("Opening fxview in win2 to confirm tab3 is most recent"); + await openFirefoxViewTab(win2).then(async viewTab => { + const browser = viewTab.linkedBrowser; + info("Check result of selecting 1ist tab in window 2"); + await checkTabList(browser, [tabURL3, tabURL4, tabURL2, tabURL1]); + }); + + info("Focusing win1, where tab2 should be selected"); + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + await SimpleTest.promiseFocus(win1); + await tabChangeRaised; + Assert.equal( + tabUrl(win1.gBrowser.selectedTab), + tabURL2, + `The selected tab in window 1 is ${tabURL2}` + ); + + info("Opening fxview in win1 to confirm tab2 is most recent"); + await openFirefoxViewTab(win1).then(async viewTab => { + const browser = viewTab.linkedBrowser; + info( + "In fxview, check result of activating window 1, where tab 2 is selected" + ); + await checkTabList(browser, [tabURL2, tabURL3, tabURL4, tabURL1]); + + let promiseHidden = BrowserTestUtils.waitForEvent( + browser.contentDocument, + "visibilitychange" + ); + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + info("Switching to first visible tab (tab1) in win1"); + await BrowserTestUtils.switchTab( + win1.gBrowser, + win1.gBrowser.visibleTabs[0] + ); + await promiseHidden; + await tabChangeRaised; + }); + + // check result in the fxview in the 1st window + info("Opening fxview in win1 to confirm tab1 is most recent"); + await openFirefoxViewTab(win1).then(async viewTab => { + const browser = viewTab.linkedBrowser; + info("Check result of selecting 1st tab in win1"); + await checkTabList(browser, [tabURL1, tabURL2, tabURL3, tabURL4]); + }); + + await cleanup(win2); +}); + +add_task(async function test_windows_activation() { + const win1 = window; + await prepareOpenTabs([tabURL1], win1); + let fxViewTab; + let tabChangeRaised; + info("switch to firefox-view and leave it selected"); + await openFirefoxViewTab(win1).then(tab => (fxViewTab = tab)); + + const win2 = await BrowserTestUtils.openNewBrowserWindow(); + await prepareOpenTabs([tabURL2], win2); + + const win3 = await BrowserTestUtils.openNewBrowserWindow(); + await prepareOpenTabs([tabURL3], win3); + await tabChangeRaised; + + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + await SimpleTest.promiseFocus(win1); + await tabChangeRaised; + + const browser = fxViewTab.linkedBrowser; + await checkTabList(browser, [tabURL3, tabURL2, tabURL1]); + + info("switch to win2 and confirm its selected tab becomes most recent"); + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + await SimpleTest.promiseFocus(win2); + await tabChangeRaised; + await checkTabList(browser, [tabURL2, tabURL3, tabURL1]); + await cleanup(win2, win3); +}); + +add_task(async function test_minimize_restore_windows() { + const win1 = window; + let tabChangeRaised; + await prepareOpenTabs([tabURL1, tabURL2]); + const win2 = await BrowserTestUtils.openNewBrowserWindow(); + await prepareOpenTabs([tabURL3, tabURL4], win2); + + // to avoid confusing the results by activating different windows, + // check fxview in the current window - which is win2 + info("Opening fxview in win2 to confirm tab4 is most recent"); + await openFirefoxViewTab(win2).then(async viewTab => { + const browser = viewTab.linkedBrowser; + await checkTabList(browser, [tabURL4, tabURL3, tabURL2, tabURL1]); + + let promiseHidden = BrowserTestUtils.waitForEvent( + browser.contentDocument, + "visibilitychange" + ); + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + info("Switching to the first tab (tab3) in 2nd window"); + await BrowserTestUtils.switchTab( + win2.gBrowser, + win2.gBrowser.visibleTabs[0] + ); + await promiseHidden; + await tabChangeRaised; + }); + + // then minimize the window, focusing the 1st window + info("Minimizing win2, leaving tab 3 selected"); + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + await minimizeWindow(win2); + info("Focusing win1, where tab2 is selected - making it most recent"); + await SimpleTest.promiseFocus(win1); + await tabChangeRaised; + + Assert.equal( + tabUrl(win1.gBrowser.selectedTab), + tabURL2, + `The selected tab in window 1 is ${tabURL2}` + ); + + info("Opening fxview in win1 to confirm tab2 is most recent"); + await openFirefoxViewTab(win1).then(async viewTab => { + const browser = viewTab.linkedBrowser; + await checkTabList(browser, [tabURL2, tabURL3, tabURL4, tabURL1]); + info( + "Restoring win2 and focusing it - which should make its selected tab most recent" + ); + tabChangeRaised = BrowserTestUtils.waitForEvent( + NonPrivateTabs, + "TabRecencyChange" + ); + await restoreWindow(win2); + await SimpleTest.promiseFocus(win2); + await tabChangeRaised; + + info( + "Checking tab order in fxview in win1, to confirm tab3 is most recent" + ); + await checkTabList(browser, [tabURL3, tabURL2, tabURL4, tabURL1]); + }); + + await cleanup(win2); +}); |