diff options
Diffstat (limited to 'browser/components/sessionstore/test/marionette/test_persist_closed_tabs_restore_manually.py')
-rw-r--r-- | browser/components/sessionstore/test/marionette/test_persist_closed_tabs_restore_manually.py | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/browser/components/sessionstore/test/marionette/test_persist_closed_tabs_restore_manually.py b/browser/components/sessionstore/test/marionette/test_persist_closed_tabs_restore_manually.py new file mode 100644 index 0000000000..9aa2a3871f --- /dev/null +++ b/browser/components/sessionstore/test/marionette/test_persist_closed_tabs_restore_manually.py @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import sys + +# add this directory to the path +sys.path.append(os.path.dirname(__file__)) + +from marionette_driver import Wait, errors +from session_store_test_case import SessionStoreTestCase + + +def inline(title): + return "data:text/html;charset=utf-8,<html><head><title>{}</title></head><body></body></html>".format( + title + ) + + +class TestSessionRestoreClosedTabs(SessionStoreTestCase): + """ + Test that closed tabs persist between sessions and + that any previously open tabs are added to the recently + closed tab list. When a previous session is restored, + an open tab is restored and removed from the closed tabs list. + + If additional tabs are opened (and closed) before a previous + session is restored, those should be merged with the restored open + and closed tabs, preserving their state. + """ + + def setUp(self): + super(TestSessionRestoreClosedTabs, self).setUp( + startup_page=1, + include_private=False, + restore_on_demand=True, + test_windows=set( + [ + # Window 1 + ( + inline("lorem ipsom"), + inline("dolor"), + ), + ] + ), + ) + + def test_restore(self): + self.marionette.execute_script( + """ + Services.prefs.setBoolPref("browser.sessionstore.persist_closed_tabs_between_sessions", true); + """ + ) + + self.wait_for_windows( + self.all_windows, "Not all requested windows have been opened" + ) + # Close the second tab leaving the first tab open + self.marionette.execute_async_script( + """ + let resolve = arguments[0]; + let tab = gBrowser.tabs[1]; + gBrowser.removeTab(tab); + let { TabStateFlusher } = ChromeUtils.importESModule("resource:///modules/sessionstore/TabStateFlusher.sys.mjs"); + TabStateFlusher.flush(tab).then(resolve); + """ + ) + + self.marionette.quit() + self.marionette.start_session() + self.marionette.set_context("chrome") + + self.assertEqual( + self.marionette.execute_script( + """ + let { SessionStore } = ChromeUtils.importESModule("resource:///modules/sessionstore/SessionStore.sys.mjs"); + let state = JSON.parse(SessionStore.getBrowserState()); + return state.windows[0]._closedTabs.length; + """ + ), + 2, + msg="Should have 2 closed tabs after restart.", + ) + + self.assertEqual( + self.marionette.execute_script( + """ + let { SessionStore } = ChromeUtils.importESModule("resource:///modules/sessionstore/SessionStore.sys.mjs"); + let state = JSON.parse(SessionStore.getBrowserState()); + return state.windows[0]._closedTabs[0].removeAfterRestore; + """ + ), + True, + msg="Previously open tab that was added to closedTabs should have removeAfterRestore property.", + ) + + # open two new tabs, the second one will be closed + win = self.marionette.current_chrome_window_handle + self.open_tabs(win, (inline("sit"), inline("amet"))) + + self.assertEqual( + self.marionette.execute_script( + """ + return gBrowser.tabs[0].label + """ + ), + "sit", + msg="First open tab should now be sit", + ) + + self.assertEqual( + self.marionette.execute_script( + """ + return gBrowser.tabs[1].label + """ + ), + "amet", + msg="Second open tab should be amet", + ) + + self.assertEqual( + self.marionette.execute_script( + """ + return gBrowser.tabs.length + """ + ), + 2, + msg="should have 2 tabs open", + ) + + self.marionette.execute_async_script( + """ + let resolve = arguments[0]; + let tab = gBrowser.tabs[1]; + gBrowser.removeTab(tab); + let { TabStateFlusher } = ChromeUtils.importESModule("resource:///modules/sessionstore/TabStateFlusher.sys.mjs"); + TabStateFlusher.flush(tab).then(resolve); + """ + ) + + self.wait_for_tabcount(1, "Waiting for 1 tabs") + + # restore the previous session + self.assertEqual( + self.marionette.execute_script( + """ + const lazy = {}; + ChromeUtils.defineESModuleGetters(lazy, { + SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs", + }); + function observeClosedTabsChange() { + return new Promise(resolve => { + function observe(subject, topic, data) { + if (topic == "sessionstore-closed-objects-changed") { + Services.obs.removeObserver(this, "sessionstore-closed-objects-changed"); + resolve('observed closed objects changed'); + }; + } + Services.obs.addObserver(observe, "sessionstore-closed-objects-changed"); + }); + }; + + async function checkForClosedTabs() { + let closedTabsObserver = observeClosedTabsChange(); + lazy.SessionStore.restoreLastSession(); + await closedTabsObserver; + let state = JSON.parse(lazy.SessionStore.getBrowserState()); + return state.windows[0]._closedTabs.length; + } + return checkForClosedTabs(); + """ + ), + 2, + msg="Should have 2 closed tab after restoring session.", + ) + + self.wait_for_tabcount(2, "Waiting for 2 tabs") + + self.assertEqual( + self.marionette.execute_script( + """ + return gBrowser.tabs[0].label + """ + ), + "sit", + msg="Newly opened tab should still exist", + ) + + self.assertEqual( + self.marionette.execute_script( + """ + return gBrowser.tabs[1].label + """ + ), + "lorem ipsom", + msg="The open tab from the previous session should be restored", + ) + + # temporary until we remove this pref + self.marionette.execute_script( + """ + Services.prefs.clearUserPref("browser.sessionstore.persist_closed_tabs_between_sessions"); + """ + ) + + def wait_for_tabcount(self, expected_tabcount, message, timeout=5): + current_tabcount = None + + def check(_): + nonlocal current_tabcount + current_tabcount = self.marionette.execute_script( + "return gBrowser.tabs.length;" + ) + return current_tabcount == expected_tabcount + + try: + wait = Wait(self.marionette, timeout=timeout, interval=0.1) + wait.until(check, message=message) + except errors.TimeoutException as e: + # Update the message to include the most recent list of windows + message = ( + f"{e.message}. Expected {expected_tabcount}, got {current_tabcount}." + ) + raise errors.TimeoutException(message) |