summaryrefslogtreecommitdiffstats
path: root/browser/components/firefoxview/tests/browser/browser_opentabs_recency.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/firefoxview/tests/browser/browser_opentabs_recency.js')
-rw-r--r--browser/components/firefoxview/tests/browser/browser_opentabs_recency.js408
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);
+});