mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1833522 - Share some of sessionstore's test helpers for use in recently-closed tab tests. r=sclements,fxview-reviewers,sessionstore-reviewers
* Move closeTab and openAndCloseTab to the helpers module and replace a couple of uses * Move waitForBrowserState/promiseBrowserState and replace a couple of uses Differential Revision: https://phabricator.services.mozilla.com/D187636
This commit is contained in:
parent
758b64ad63
commit
7878082e5c
@ -9,23 +9,11 @@
|
||||
* the current window.
|
||||
*/
|
||||
|
||||
const openedTabs = [];
|
||||
|
||||
async function closeTab(tab) {
|
||||
const sessionStoreChanged = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
await sessionStoreChanged;
|
||||
const idx = openedTabs.indexOf(tab);
|
||||
ok(idx >= 0, "Tab was found in the openedTabs array");
|
||||
openedTabs.splice(idx, 1);
|
||||
}
|
||||
|
||||
async function openTab(win = window, url) {
|
||||
const tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, url);
|
||||
openedTabs.push(tab);
|
||||
}
|
||||
const { SessionStoreTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/SessionStoreTestUtils.sys.mjs"
|
||||
);
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
SessionStoreTestUtils.init(this, window);
|
||||
|
||||
async function checkMenu(window, expected) {
|
||||
await SimpleTest.promiseFocus(window);
|
||||
@ -52,24 +40,11 @@ async function checkMenu(window, expected) {
|
||||
info("checkMenu:, menuHidden, returning");
|
||||
}
|
||||
|
||||
async function resetHistory() {
|
||||
function resetClosedTabsAndWindows() {
|
||||
// Clear the lists of closed windows and tabs.
|
||||
let sessionStoreChanged;
|
||||
while (SessionStore.getClosedWindowCount() > 0) {
|
||||
sessionStoreChanged = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
SessionStore.forgetClosedWindow(0);
|
||||
await sessionStoreChanged;
|
||||
}
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history");
|
||||
is(SessionStore.getClosedWindowCount(), 0, "Expect 0 closed windows");
|
||||
for (const win of BrowserWindowTracker.orderedWindows) {
|
||||
while (SessionStore.getClosedTabCountForWindow(win)) {
|
||||
sessionStoreChanged = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
SessionStore.forgetClosedTab(win, 0);
|
||||
await sessionStoreChanged;
|
||||
}
|
||||
is(
|
||||
SessionStore.getClosedTabCountForWindow(win),
|
||||
0,
|
||||
@ -79,16 +54,20 @@ async function resetHistory() {
|
||||
}
|
||||
|
||||
add_task(async function test_recently_closed_tabs_nonprivate() {
|
||||
await resetHistory();
|
||||
is(openedTabs.length, 0, "Got expected openedTabs length");
|
||||
await resetClosedTabsAndWindows();
|
||||
|
||||
const win1 = window;
|
||||
const win2 = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await openTab(win1, "https://example.com");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
win1.gBrowser,
|
||||
"https://example.com"
|
||||
);
|
||||
// we're going to close a tab and don't want to accidentally close the window when it has 0 tabs
|
||||
await openTab(win2, "about:about");
|
||||
await openTab(win2, "https://example.org");
|
||||
is(openedTabs.length, 3, "Got expected openedTabs length");
|
||||
await BrowserTestUtils.openNewForegroundTab(win2.gBrowser, "about:about");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
win2.gBrowser,
|
||||
"https://example.org"
|
||||
);
|
||||
|
||||
info("Checking the menuitem is initially disabled in both windows");
|
||||
for (let win of [win1, win2]) {
|
||||
@ -97,8 +76,7 @@ add_task(async function test_recently_closed_tabs_nonprivate() {
|
||||
});
|
||||
}
|
||||
|
||||
await closeTab(win2.gBrowser.selectedTab);
|
||||
is(openedTabs.length, 2, "Got expected openedTabs length");
|
||||
await SessionStoreTestUtils.closeTab(win2.gBrowser.selectedTab);
|
||||
is(
|
||||
SessionStore.getClosedTabCount(),
|
||||
1,
|
||||
@ -121,26 +99,31 @@ add_task(async function test_recently_closed_tabs_nonprivate() {
|
||||
|
||||
info("starting tab cleanup");
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
await closeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
await SessionStoreTestUtils.closeTab(
|
||||
gBrowser.tabs[gBrowser.tabs.length - 1]
|
||||
);
|
||||
}
|
||||
info("finished tab cleanup");
|
||||
openedTabs.length = 0;
|
||||
});
|
||||
|
||||
add_task(async function test_recently_closed_tabs_nonprivate_pref_off() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.sessionstore.closedTabsFromAllWindows", false]],
|
||||
});
|
||||
await resetHistory();
|
||||
is(openedTabs.length, 0, "Got expected openedTabs length");
|
||||
await resetClosedTabsAndWindows();
|
||||
|
||||
const win1 = window;
|
||||
const win2 = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await openTab(win1, "https://example.com");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
win1.gBrowser,
|
||||
"https://example.com"
|
||||
);
|
||||
// we're going to close a tab and don't want to accidentally close the window when it has 0 tabs
|
||||
await openTab(win2, "about:about");
|
||||
await openTab(win2, "https://example.org");
|
||||
is(openedTabs.length, 3, "Got expected openedTabs length");
|
||||
await BrowserTestUtils.openNewForegroundTab(win2.gBrowser, "about:about");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
win2.gBrowser,
|
||||
"https://example.org"
|
||||
);
|
||||
|
||||
info("Checking the menuitem is initially disabled in both windows");
|
||||
for (let win of [win1, win2]) {
|
||||
@ -148,10 +131,8 @@ add_task(async function test_recently_closed_tabs_nonprivate_pref_off() {
|
||||
menuItemDisabled: true,
|
||||
});
|
||||
}
|
||||
is(win2, BrowserWindowTracker.getTopWindow(), "Check topWindow");
|
||||
|
||||
await closeTab(win2.gBrowser.selectedTab);
|
||||
is(openedTabs.length, 2, "Got expected openedTabs length");
|
||||
await SimpleTest.promiseFocus(win2);
|
||||
await SessionStoreTestUtils.closeTab(win2.gBrowser.selectedTab);
|
||||
is(
|
||||
SessionStore.getClosedTabCount(),
|
||||
1,
|
||||
@ -175,31 +156,39 @@ add_task(async function test_recently_closed_tabs_nonprivate_pref_off() {
|
||||
|
||||
info("starting tab cleanup");
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
await closeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
await SessionStoreTestUtils.closeTab(
|
||||
gBrowser.tabs[gBrowser.tabs.length - 1]
|
||||
);
|
||||
}
|
||||
info("finished tab cleanup");
|
||||
openedTabs.length = 0;
|
||||
SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function test_recently_closed_tabs_mixed_private() {
|
||||
await resetHistory();
|
||||
is(openedTabs.length, 0, "Got expected openedTabs length");
|
||||
await resetClosedTabsAndWindows();
|
||||
is(
|
||||
SessionStore.getClosedTabCount(),
|
||||
0,
|
||||
"Expect closed tab count of 0 after reset"
|
||||
);
|
||||
|
||||
await openTab(window, "about:robots");
|
||||
await openTab(window, "https://example.com");
|
||||
await BrowserTestUtils.openNewForegroundTab(window.gBrowser, "about:robots");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
window.gBrowser,
|
||||
"https://example.com"
|
||||
);
|
||||
|
||||
const privateWin = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
await openTab(privateWin, "about:about");
|
||||
await openTab(privateWin, "https://example.org");
|
||||
is(openedTabs.length, 4, "Got expected openedTabs length");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
privateWin.gBrowser,
|
||||
"about:about"
|
||||
);
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
privateWin.gBrowser,
|
||||
"https://example.org"
|
||||
);
|
||||
|
||||
for (let win of [window, privateWin]) {
|
||||
await checkMenu(win, {
|
||||
@ -207,8 +196,7 @@ add_task(async function test_recently_closed_tabs_mixed_private() {
|
||||
});
|
||||
}
|
||||
|
||||
await closeTab(privateWin.gBrowser.selectedTab);
|
||||
is(openedTabs.length, 3, "Got expected openedTabs length");
|
||||
await SessionStoreTestUtils.closeTab(privateWin.gBrowser.selectedTab);
|
||||
is(
|
||||
SessionStore.getClosedTabCount(privateWin),
|
||||
1,
|
||||
@ -228,21 +216,16 @@ add_task(async function test_recently_closed_tabs_mixed_private() {
|
||||
menuItemDisabled: false,
|
||||
});
|
||||
|
||||
await resetHistory();
|
||||
is(
|
||||
SessionStore.getClosedTabCount(privateWin),
|
||||
0,
|
||||
"Expect 0 closed tab count after reset"
|
||||
);
|
||||
is(
|
||||
SessionStore.getClosedTabCount(window),
|
||||
0,
|
||||
"Expect 0 closed tab count after reset"
|
||||
);
|
||||
await resetClosedTabsAndWindows();
|
||||
await SimpleTest.promiseFocus(window);
|
||||
|
||||
info("closing tab in non-private window");
|
||||
await closeTab(window.gBrowser.selectedTab);
|
||||
is(openedTabs.length, 2, "Got expected openedTabs length");
|
||||
await SessionStoreTestUtils.closeTab(window.gBrowser.selectedTab);
|
||||
is(
|
||||
SessionStore.getClosedTabCount(window),
|
||||
1,
|
||||
"Expect 1 closed tab count after closing the a tab in the non-private window"
|
||||
);
|
||||
|
||||
// the menu should be enabled only for the non-private window
|
||||
await checkMenu(window, {
|
||||
@ -259,33 +242,36 @@ add_task(async function test_recently_closed_tabs_mixed_private() {
|
||||
|
||||
info("starting tab cleanup");
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
await closeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
await SessionStoreTestUtils.closeTab(
|
||||
gBrowser.tabs[gBrowser.tabs.length - 1]
|
||||
);
|
||||
}
|
||||
info("finished tab cleanup");
|
||||
openedTabs.length = 0;
|
||||
});
|
||||
|
||||
add_task(async function test_recently_closed_tabs_mixed_private_pref_off() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.sessionstore.closedTabsFromAllWindows", false]],
|
||||
});
|
||||
await resetHistory();
|
||||
is(openedTabs.length, 0, "Got expected openedTabs length");
|
||||
is(
|
||||
SessionStore.getClosedTabCount(),
|
||||
0,
|
||||
"Expect closed tab count of 0 after reset"
|
||||
);
|
||||
await resetClosedTabsAndWindows();
|
||||
|
||||
await openTab(window, "about:robots");
|
||||
await openTab(window, "https://example.com");
|
||||
await BrowserTestUtils.openNewForegroundTab(window.gBrowser, "about:robots");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
window.gBrowser,
|
||||
"https://example.com"
|
||||
);
|
||||
|
||||
const privateWin = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
await openTab(privateWin, "about:about");
|
||||
await openTab(privateWin, "https://example.org");
|
||||
is(openedTabs.length, 4, "Got expected openedTabs length");
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
privateWin.gBrowser,
|
||||
"about:about"
|
||||
);
|
||||
await BrowserTestUtils.openNewForegroundTab(
|
||||
privateWin.gBrowser,
|
||||
"https://example.org"
|
||||
);
|
||||
|
||||
for (let win of [window, privateWin]) {
|
||||
await checkMenu(win, {
|
||||
@ -293,8 +279,8 @@ add_task(async function test_recently_closed_tabs_mixed_private_pref_off() {
|
||||
});
|
||||
}
|
||||
|
||||
await closeTab(privateWin.gBrowser.selectedTab);
|
||||
is(openedTabs.length, 3, "Got expected openedTabs length");
|
||||
await SimpleTest.promiseFocus(privateWin);
|
||||
await SessionStoreTestUtils.closeTab(privateWin.gBrowser.selectedTab);
|
||||
is(
|
||||
SessionStore.getClosedTabCount(privateWin),
|
||||
1,
|
||||
@ -314,7 +300,7 @@ add_task(async function test_recently_closed_tabs_mixed_private_pref_off() {
|
||||
menuItemDisabled: false,
|
||||
});
|
||||
|
||||
await resetHistory();
|
||||
await resetClosedTabsAndWindows();
|
||||
is(
|
||||
SessionStore.getClosedTabCount(privateWin),
|
||||
0,
|
||||
@ -327,8 +313,8 @@ add_task(async function test_recently_closed_tabs_mixed_private_pref_off() {
|
||||
);
|
||||
|
||||
info("closing tab in non-private window");
|
||||
await closeTab(window.gBrowser.selectedTab);
|
||||
is(openedTabs.length, 2, "Got expected openedTabs length");
|
||||
await SimpleTest.promiseFocus(window);
|
||||
await SessionStoreTestUtils.closeTab(window.gBrowser.selectedTab);
|
||||
|
||||
// the menu should be enabled only for the non-private window
|
||||
await checkMenu(window, {
|
||||
@ -345,9 +331,10 @@ add_task(async function test_recently_closed_tabs_mixed_private_pref_off() {
|
||||
|
||||
info("starting tab cleanup");
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
await closeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
await SessionStoreTestUtils.closeTab(
|
||||
gBrowser.tabs[gBrowser.tabs.length - 1]
|
||||
);
|
||||
}
|
||||
info("finished tab cleanup");
|
||||
openedTabs.length = 0;
|
||||
SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
@ -4,23 +4,18 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { SessionStoreTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/SessionStoreTestUtils.sys.mjs"
|
||||
);
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
|
||||
SessionStoreTestUtils.init(this, window);
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
);
|
||||
|
||||
async function openTab(URL) {
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, URL);
|
||||
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
return tab;
|
||||
}
|
||||
|
||||
async function closeTab(tab) {
|
||||
const sessionStorePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab);
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
await sessionStorePromise;
|
||||
}
|
||||
|
||||
let panelMenuWidgetAdded = false;
|
||||
function prepareHistoryPanel() {
|
||||
if (panelMenuWidgetAdded) {
|
||||
@ -108,8 +103,10 @@ add_task(async function testRecentlyClosedDisabled() {
|
||||
await hideHistoryPanel();
|
||||
|
||||
gBrowser.selectedTab.focus();
|
||||
let tab = await openTab(TEST_PATH + "dummy_history_item.html");
|
||||
await closeTab(tab);
|
||||
await SessionStoreTestUtils.openAndCloseTab(
|
||||
window,
|
||||
TEST_PATH + "dummy_history_item.html"
|
||||
);
|
||||
|
||||
await openHistoryPanel();
|
||||
|
||||
@ -207,69 +204,85 @@ add_task(async function testRecentlyClosedRestoreAllTabs() {
|
||||
// We need to make sure the history is cleared before starting the test
|
||||
await Sanitizer.sanitize(["history"]);
|
||||
await resetClosedTabs();
|
||||
const initialTabCount = gBrowser.visibleTabs.length;
|
||||
|
||||
await BrowserTestUtils.withNewTab("about:mozilla", async browser => {
|
||||
const initialTabCount = gBrowser.visibleTabs.length;
|
||||
// Open and close a few of tabs
|
||||
const closedTabUrls = [
|
||||
"about:robots",
|
||||
"https://example.com/",
|
||||
"https://example.org/",
|
||||
];
|
||||
for (let url of closedTabUrls) {
|
||||
let tab = await openTab(url);
|
||||
await closeTab(tab);
|
||||
}
|
||||
is(
|
||||
gBrowser.visibleTabs.length,
|
||||
initialTabCount,
|
||||
"All the new tabs were closed"
|
||||
);
|
||||
// Open the "Recently closed tabs" panel.
|
||||
let closeTabsPanel = await openRecentlyClosedTabsMenu();
|
||||
|
||||
// Click the first toolbar button in the panel.
|
||||
let toolbarButton = closeTabsPanel.querySelector(
|
||||
".panel-subview-body toolbarbutton"
|
||||
);
|
||||
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, toolbarButton, window);
|
||||
|
||||
info("waiting for reopenedTab");
|
||||
let reopenedTab = await newTabPromise;
|
||||
is(
|
||||
reopenedTab.linkedBrowser.currentURI.spec,
|
||||
closedTabUrls[closedTabUrls.length - 1],
|
||||
"Opened correct URL"
|
||||
);
|
||||
info(`restored tab, total open tabs: ${gBrowser.tabs.length}`);
|
||||
await closeTab(reopenedTab);
|
||||
|
||||
await openRecentlyClosedTabsMenu();
|
||||
let restoreAllItem = closeTabsPanel.querySelector(".restoreallitem");
|
||||
ok(
|
||||
restoreAllItem && !restoreAllItem.hidden,
|
||||
"Restore all menu item is not hidden"
|
||||
);
|
||||
|
||||
// Click the restore-all toolbar button in the panel.
|
||||
EventUtils.sendMouseEvent({ type: "click" }, restoreAllItem, window);
|
||||
|
||||
info("waiting for restored tabs");
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => SessionStore.getClosedTabCount() === 0,
|
||||
"Waiting for all the closed tabs to be opened"
|
||||
);
|
||||
|
||||
is(
|
||||
gBrowser.tabs.length,
|
||||
initialTabCount + closedTabUrls.length,
|
||||
"The expected number of closed tabs were restored"
|
||||
);
|
||||
info(
|
||||
`restored ${closedTabUrls.length} tabs, total open tabs: ${gBrowser.tabs.length}`
|
||||
);
|
||||
const closedTabUrls = [
|
||||
"about:robots",
|
||||
"https://example.com/",
|
||||
"https://example.org/",
|
||||
];
|
||||
const windowState = {
|
||||
tabs: [
|
||||
{
|
||||
entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }],
|
||||
},
|
||||
],
|
||||
_closedTabs: closedTabUrls.map(url => {
|
||||
return {
|
||||
title: url,
|
||||
state: {
|
||||
entries: [
|
||||
{
|
||||
url,
|
||||
triggeringPrincipal_base64,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
await SessionStoreTestUtils.promiseBrowserState({
|
||||
windows: [windowState],
|
||||
});
|
||||
|
||||
is(gBrowser.visibleTabs.length, 1, "We start with one tab open");
|
||||
// Open the "Recently closed tabs" panel.
|
||||
let closeTabsPanel = await openRecentlyClosedTabsMenu();
|
||||
|
||||
// Click the first toolbar button in the panel.
|
||||
let toolbarButton = closeTabsPanel.querySelector(
|
||||
".panel-subview-body toolbarbutton"
|
||||
);
|
||||
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, toolbarButton, window);
|
||||
|
||||
info(
|
||||
"We should reopen the first of closedTabUrls: " +
|
||||
JSON.stringify(closedTabUrls)
|
||||
);
|
||||
let reopenedTab = await newTabPromise;
|
||||
is(
|
||||
reopenedTab.linkedBrowser.currentURI.spec,
|
||||
closedTabUrls[0],
|
||||
"Opened the first URL"
|
||||
);
|
||||
info(`restored tab, total open tabs: ${gBrowser.tabs.length}`);
|
||||
|
||||
info("waiting for closeTab");
|
||||
await SessionStoreTestUtils.closeTab(reopenedTab);
|
||||
|
||||
await openRecentlyClosedTabsMenu();
|
||||
let restoreAllItem = closeTabsPanel.querySelector(".restoreallitem");
|
||||
ok(
|
||||
restoreAllItem && !restoreAllItem.hidden,
|
||||
"Restore all menu item is not hidden"
|
||||
);
|
||||
|
||||
// Click the restore-all toolbar button in the panel.
|
||||
EventUtils.sendMouseEvent({ type: "click" }, restoreAllItem, window);
|
||||
|
||||
info("waiting for restored tabs");
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => SessionStore.getClosedTabCount() === 0,
|
||||
"Waiting for all the closed tabs to be opened"
|
||||
);
|
||||
|
||||
is(
|
||||
gBrowser.tabs.length,
|
||||
initialTabCount + closedTabUrls.length,
|
||||
"The expected number of closed tabs were restored"
|
||||
);
|
||||
|
||||
// clean up extra tabs
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
BrowserTestUtils.removeTab(gBrowser.tabs.at(-1));
|
||||
@ -279,6 +292,7 @@ add_task(async function testRecentlyClosedRestoreAllTabs() {
|
||||
add_task(async function testRecentlyClosedWindows() {
|
||||
// We need to make sure the history is cleared before starting the test
|
||||
await Sanitizer.sanitize(["history"]);
|
||||
await resetClosedTabs();
|
||||
|
||||
// Open and close a new window.
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
@ -290,7 +304,11 @@ add_task(async function testRecentlyClosedWindows() {
|
||||
"https://example.com"
|
||||
);
|
||||
await loadedPromise;
|
||||
let closedObjectsChangePromise = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
await closedObjectsChangePromise;
|
||||
|
||||
prepareHistoryPanel();
|
||||
await openHistoryPanel();
|
||||
@ -307,15 +325,16 @@ add_task(async function testRecentlyClosedWindows() {
|
||||
// Click the first toolbar button in the panel.
|
||||
let panelBody = winPanel.querySelector(".panel-subview-body");
|
||||
let toolbarButton = panelBody.querySelector("toolbarbutton");
|
||||
let newWindowPromise = BrowserTestUtils.waitForNewWindow();
|
||||
let newWindowPromise = BrowserTestUtils.waitForNewWindow({
|
||||
url: "https://example.com/",
|
||||
});
|
||||
closedObjectsChangePromise = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, toolbarButton, window);
|
||||
|
||||
newWin = await newWindowPromise;
|
||||
is(
|
||||
newWin.gBrowser.currentURI.spec,
|
||||
"https://example.com/",
|
||||
"Opened correct URL"
|
||||
);
|
||||
await closedObjectsChangePromise;
|
||||
is(gBrowser.tabs.length, 1, "Did not open new tabs");
|
||||
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
|
@ -30,6 +30,12 @@ const { TelemetryTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/TelemetryTestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
|
||||
const { SessionStoreTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/SessionStoreTestUtils.sys.mjs"
|
||||
);
|
||||
SessionStoreTestUtils.init(this, window);
|
||||
|
||||
ChromeUtils.defineESModuleGetters(this, {
|
||||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
|
||||
SyncedTabs: "resource://services-sync/SyncedTabs.sys.mjs",
|
||||
@ -537,18 +543,7 @@ class TelemetrySpy {
|
||||
* has been updated after closing the tab.
|
||||
*/
|
||||
async function open_then_close(url, win = window) {
|
||||
let { updatePromise } = await BrowserTestUtils.withNewTab(
|
||||
{ url, gBrowser: win.gBrowser },
|
||||
async browser => {
|
||||
return {
|
||||
updatePromise: BrowserTestUtils.waitForSessionStoreUpdate({
|
||||
linkedBrowser: browser,
|
||||
}),
|
||||
};
|
||||
}
|
||||
);
|
||||
await updatePromise;
|
||||
return TestUtils.topicObserved("sessionstore-closed-objects-changed");
|
||||
return SessionStoreTestUtils.openAndCloseTab(win, url);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,5 +29,9 @@ EXTRA_JS_MODULES.sessionstore = [
|
||||
"TabStateFlusher.sys.mjs",
|
||||
]
|
||||
|
||||
TESTING_JS_MODULES += [
|
||||
"test/SessionStoreTestUtils.sys.mjs",
|
||||
]
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Session Restore")
|
||||
|
@ -0,0 +1,186 @@
|
||||
const lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
BrowserTestUtils: "resource://testing-common/BrowserTestUtils.sys.mjs",
|
||||
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
|
||||
TabStateFlusher: "resource:///modules/sessionstore/TabStateFlusher.sys.mjs",
|
||||
TestUtils: "resource://testing-common/TestUtils.sys.mjs",
|
||||
});
|
||||
|
||||
export var SessionStoreTestUtils = {
|
||||
/**
|
||||
* Running this init allows helpers to access test scope helpers, like Assert
|
||||
* and SimpleTest.
|
||||
* Tests should call this init() before using the helpers which rely on properties assign here.
|
||||
*
|
||||
* @param {object} scope The global scope where tests are being run.
|
||||
* @param {DOmWindow} scope The global window object, for acessing gBrowser etc.
|
||||
*/
|
||||
init(scope, windowGlobal) {
|
||||
if (!scope) {
|
||||
throw new Error(
|
||||
"Must initialize SessionStoreTestUtils with a test scope"
|
||||
);
|
||||
}
|
||||
if (!windowGlobal) {
|
||||
throw new Error("this.windowGlobal must be defined when we init");
|
||||
}
|
||||
this.info = scope.info;
|
||||
this.registerCleanupFunction = scope.registerCleanupFunction;
|
||||
this.windowGlobal = windowGlobal;
|
||||
},
|
||||
|
||||
async closeTab(tab) {
|
||||
await lazy.TabStateFlusher.flush(tab.linkedBrowser);
|
||||
let sessionUpdatePromise =
|
||||
lazy.BrowserTestUtils.waitForSessionStoreUpdate(tab);
|
||||
lazy.BrowserTestUtils.removeTab(tab);
|
||||
await sessionUpdatePromise;
|
||||
},
|
||||
|
||||
async openAndCloseTab(window, url) {
|
||||
let { updatePromise } = await lazy.BrowserTestUtils.withNewTab(
|
||||
{ url, gBrowser: window.gBrowser },
|
||||
async browser => {
|
||||
return {
|
||||
updatePromise: lazy.BrowserTestUtils.waitForSessionStoreUpdate({
|
||||
linkedBrowser: browser,
|
||||
}),
|
||||
};
|
||||
}
|
||||
);
|
||||
await updatePromise;
|
||||
return lazy.TestUtils.topicObserved("sessionstore-closed-objects-changed");
|
||||
},
|
||||
|
||||
// This assumes that tests will at least have some state/entries
|
||||
waitForBrowserState(aState, aSetStateCallback) {
|
||||
if (typeof aState == "string") {
|
||||
aState = JSON.parse(aState);
|
||||
}
|
||||
if (typeof aState != "object") {
|
||||
throw new TypeError(
|
||||
"Argument must be an object or a JSON representation of an object"
|
||||
);
|
||||
}
|
||||
if (!this.windowGlobal) {
|
||||
throw new Error(
|
||||
"no windowGlobal defined, please call init() first with the scope and window object"
|
||||
);
|
||||
}
|
||||
let windows = [this.windowGlobal];
|
||||
let tabsRestored = 0;
|
||||
let expectedTabsRestored = 0;
|
||||
let expectedWindows = aState.windows.length;
|
||||
let windowsOpen = 1;
|
||||
let listening = false;
|
||||
let windowObserving = false;
|
||||
let restoreHiddenTabs = Services.prefs.getBoolPref(
|
||||
"browser.sessionstore.restore_hidden_tabs"
|
||||
);
|
||||
// This should match the |restoreTabsLazily| value that
|
||||
// SessionStore.restoreWindow() uses.
|
||||
let restoreTabsLazily =
|
||||
Services.prefs.getBoolPref("browser.sessionstore.restore_on_demand") &&
|
||||
Services.prefs.getBoolPref("browser.sessionstore.restore_tabs_lazily");
|
||||
|
||||
aState.windows.forEach(function (winState) {
|
||||
winState.tabs.forEach(function (tabState) {
|
||||
if (!restoreTabsLazily && (restoreHiddenTabs || !tabState.hidden)) {
|
||||
expectedTabsRestored++;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// If there are only hidden tabs and restoreHiddenTabs = false, we still
|
||||
// expect one of them to be restored because it gets shown automatically.
|
||||
// Otherwise if lazy tab restore there will only be one tab restored per window.
|
||||
if (!expectedTabsRestored) {
|
||||
expectedTabsRestored = 1;
|
||||
} else if (restoreTabsLazily) {
|
||||
expectedTabsRestored = aState.windows.length;
|
||||
}
|
||||
|
||||
function onSSTabRestored(aEvent) {
|
||||
if (++tabsRestored == expectedTabsRestored) {
|
||||
// Remove the event listener from each window
|
||||
windows.forEach(function (win) {
|
||||
win.gBrowser.tabContainer.removeEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
});
|
||||
listening = false;
|
||||
SessionStoreTestUtils.info("running " + aSetStateCallback.name);
|
||||
lazy.TestUtils.executeSoon(aSetStateCallback);
|
||||
}
|
||||
}
|
||||
|
||||
// Used to add our listener to further windows so we can catch SSTabRestored
|
||||
// coming from them when creating a multi-window state.
|
||||
function windowObserver(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowopened") {
|
||||
let newWindow = aSubject;
|
||||
newWindow.addEventListener(
|
||||
"load",
|
||||
function () {
|
||||
if (++windowsOpen == expectedWindows) {
|
||||
Services.ww.unregisterNotification(windowObserver);
|
||||
windowObserving = false;
|
||||
}
|
||||
|
||||
// Track this window so we can remove the progress listener later
|
||||
windows.push(newWindow);
|
||||
// Add the progress listener
|
||||
newWindow.gBrowser.tabContainer.addEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to register the notification if we expect more than 1 window
|
||||
if (expectedWindows > 1) {
|
||||
this.registerCleanupFunction(function () {
|
||||
if (windowObserving) {
|
||||
Services.ww.unregisterNotification(windowObserver);
|
||||
}
|
||||
});
|
||||
windowObserving = true;
|
||||
Services.ww.registerNotification(windowObserver);
|
||||
}
|
||||
|
||||
this.registerCleanupFunction(function () {
|
||||
if (listening) {
|
||||
windows.forEach(function (win) {
|
||||
win.gBrowser.tabContainer.removeEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
// Add the event listener for this window as well.
|
||||
listening = true;
|
||||
this.windowGlobal.gBrowser.tabContainer.addEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
|
||||
// Ensure setBrowserState() doesn't remove the initial tab.
|
||||
this.windowGlobal.gBrowser.selectedTab = this.windowGlobal.gBrowser.tabs[0];
|
||||
|
||||
// Finally, call setBrowserState
|
||||
lazy.SessionStore.setBrowserState(JSON.stringify(aState));
|
||||
},
|
||||
|
||||
promiseBrowserState(aState) {
|
||||
return new Promise(resolve => this.waitForBrowserState(aState, resolve));
|
||||
},
|
||||
};
|
@ -64,57 +64,8 @@ const multiWindowState = {
|
||||
],
|
||||
};
|
||||
|
||||
async function setupWithBrowserState(browserState) {
|
||||
let numTabs = browserState.windows.reduce((count, winData) => {
|
||||
return count + winData.tabs.length;
|
||||
}, 0);
|
||||
let loadCount = 0;
|
||||
let windowOpenedCount = 1; // pre-count the first window
|
||||
let promiseRestoringTabs = new Promise(resolve => {
|
||||
gProgressListener.setCallback(function (
|
||||
aBrowser,
|
||||
aNeedRestore,
|
||||
aRestoring,
|
||||
aRestored
|
||||
) {
|
||||
if (++loadCount == numTabs) {
|
||||
// We don't actually care about load order in this test, just that they all
|
||||
// do load.
|
||||
is(loadCount, numTabs, "all tabs were restored");
|
||||
is(aNeedRestore, 0, "there are no tabs left needing restore");
|
||||
|
||||
gProgressListener.unsetCallback();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// We also want to catch the 2nd window, so we need to observe domwindowopened
|
||||
Services.ww.registerNotification(function observer(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowopened") {
|
||||
let win = aSubject;
|
||||
win.addEventListener(
|
||||
"load",
|
||||
function () {
|
||||
if (++windowOpenedCount == browserState.windows.length) {
|
||||
Services.ww.unregisterNotification(observer);
|
||||
win.gBrowser.addTabsProgressListener(gProgressListener);
|
||||
}
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const stateRestored = TestUtils.topicObserved(
|
||||
"sessionstore-browser-state-restored"
|
||||
);
|
||||
await ss.setBrowserState(JSON.stringify(browserState));
|
||||
await stateRestored;
|
||||
await promiseRestoringTabs;
|
||||
}
|
||||
add_setup(async function testSetup() {
|
||||
await setupWithBrowserState(multiWindowState);
|
||||
await SessionStoreTestUtils.promiseBrowserState(multiWindowState);
|
||||
});
|
||||
|
||||
add_task(async function test_ClosedTabMethods() {
|
||||
|
@ -29,7 +29,12 @@ const { TabState } = ChromeUtils.importESModule(
|
||||
const { TabStateFlusher } = ChromeUtils.importESModule(
|
||||
"resource:///modules/sessionstore/TabStateFlusher.sys.mjs"
|
||||
);
|
||||
const { SessionStoreTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/SessionStoreTestUtils.sys.mjs"
|
||||
);
|
||||
|
||||
const ss = SessionStore;
|
||||
SessionStoreTestUtils.init(this, window);
|
||||
|
||||
// Some tests here assume that all restored tabs are loaded without waiting for
|
||||
// the user to bring them to the foreground. We ensure this by resetting the
|
||||
@ -81,129 +86,11 @@ function provideWindow(aCallback, aURL, aFeatures) {
|
||||
|
||||
// This assumes that tests will at least have some state/entries
|
||||
function waitForBrowserState(aState, aSetStateCallback) {
|
||||
if (typeof aState == "string") {
|
||||
aState = JSON.parse(aState);
|
||||
}
|
||||
if (typeof aState != "object") {
|
||||
throw new TypeError(
|
||||
"Argument must be an object or a JSON representation of an object"
|
||||
);
|
||||
}
|
||||
let windows = [window];
|
||||
let tabsRestored = 0;
|
||||
let expectedTabsRestored = 0;
|
||||
let expectedWindows = aState.windows.length;
|
||||
let windowsOpen = 1;
|
||||
let listening = false;
|
||||
let windowObserving = false;
|
||||
let restoreHiddenTabs = Services.prefs.getBoolPref(
|
||||
"browser.sessionstore.restore_hidden_tabs"
|
||||
);
|
||||
// This should match the |restoreTabsLazily| value that
|
||||
// SessionStore.restoreWindow() uses.
|
||||
let restoreTabsLazily =
|
||||
Services.prefs.getBoolPref("browser.sessionstore.restore_on_demand") &&
|
||||
Services.prefs.getBoolPref("browser.sessionstore.restore_tabs_lazily");
|
||||
|
||||
aState.windows.forEach(function (winState) {
|
||||
winState.tabs.forEach(function (tabState) {
|
||||
if (!restoreTabsLazily && (restoreHiddenTabs || !tabState.hidden)) {
|
||||
expectedTabsRestored++;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// If there are only hidden tabs and restoreHiddenTabs = false, we still
|
||||
// expect one of them to be restored because it gets shown automatically.
|
||||
// Otherwise if lazy tab restore there will only be one tab restored per window.
|
||||
if (!expectedTabsRestored) {
|
||||
expectedTabsRestored = 1;
|
||||
} else if (restoreTabsLazily) {
|
||||
expectedTabsRestored = aState.windows.length;
|
||||
}
|
||||
|
||||
function onSSTabRestored(aEvent) {
|
||||
if (++tabsRestored == expectedTabsRestored) {
|
||||
// Remove the event listener from each window
|
||||
windows.forEach(function (win) {
|
||||
win.gBrowser.tabContainer.removeEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
});
|
||||
listening = false;
|
||||
info("running " + aSetStateCallback.name);
|
||||
executeSoon(aSetStateCallback);
|
||||
}
|
||||
}
|
||||
|
||||
// Used to add our listener to further windows so we can catch SSTabRestored
|
||||
// coming from them when creating a multi-window state.
|
||||
function windowObserver(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowopened") {
|
||||
let newWindow = aSubject;
|
||||
newWindow.addEventListener(
|
||||
"load",
|
||||
function () {
|
||||
if (++windowsOpen == expectedWindows) {
|
||||
Services.ww.unregisterNotification(windowObserver);
|
||||
windowObserving = false;
|
||||
}
|
||||
|
||||
// Track this window so we can remove the progress listener later
|
||||
windows.push(newWindow);
|
||||
// Add the progress listener
|
||||
newWindow.gBrowser.tabContainer.addEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to register the notification if we expect more than 1 window
|
||||
if (expectedWindows > 1) {
|
||||
registerCleanupFunction(function () {
|
||||
if (windowObserving) {
|
||||
Services.ww.unregisterNotification(windowObserver);
|
||||
}
|
||||
});
|
||||
windowObserving = true;
|
||||
Services.ww.registerNotification(windowObserver);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
if (listening) {
|
||||
windows.forEach(function (win) {
|
||||
win.gBrowser.tabContainer.removeEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
// Add the event listener for this window as well.
|
||||
listening = true;
|
||||
gBrowser.tabContainer.addEventListener(
|
||||
"SSTabRestored",
|
||||
onSSTabRestored,
|
||||
true
|
||||
);
|
||||
|
||||
// Ensure setBrowserState() doesn't remove the initial tab.
|
||||
gBrowser.selectedTab = gBrowser.tabs[0];
|
||||
|
||||
// Finally, call setBrowserState
|
||||
ss.setBrowserState(JSON.stringify(aState));
|
||||
return SessionStoreTestUtils.waitForBrowserState(aState, aSetStateCallback);
|
||||
}
|
||||
|
||||
function promiseBrowserState(aState) {
|
||||
return new Promise(resolve => waitForBrowserState(aState, resolve));
|
||||
return SessionStoreTestUtils.promiseBrowserState(aState);
|
||||
}
|
||||
|
||||
function promiseTabState(tab, state) {
|
||||
@ -751,11 +638,8 @@ function addNonCoopTask(aFile, aTest, aUrlRoot) {
|
||||
add_task(taskToBeAdded);
|
||||
}
|
||||
|
||||
async function openAndCloseTab(window, url) {
|
||||
let tab = BrowserTestUtils.addTab(window.gBrowser, url);
|
||||
await promiseBrowserLoaded(tab.linkedBrowser, true, url);
|
||||
await TabStateFlusher.flush(tab.linkedBrowser);
|
||||
await promiseRemoveTabAndSessionState(tab);
|
||||
function openAndCloseTab(window, url) {
|
||||
return SessionStoreTestUtils.openAndCloseTab(window, url);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user