diff options
Diffstat (limited to 'testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py')
-rw-r--r-- | testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py | 901 |
1 files changed, 901 insertions, 0 deletions
diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py b/testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py new file mode 100644 index 0000000000..ec1a8f1be0 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py @@ -0,0 +1,901 @@ +# 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 contextlib +import os + +from six.moves.urllib.parse import quote + +from marionette_driver import By, errors, expected, Wait +from marionette_driver.keys import Keys +from marionette_driver.marionette import Alert +from marionette_harness import ( + MarionetteTestCase, + run_if_manage_instance, + WindowManagerMixin, +) + +here = os.path.abspath(os.path.dirname(__file__)) + + +BLACK_PIXEL = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" # noqa +RED_PIXEL = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=" # noqa + + +def inline(doc): + return "data:text/html;charset=utf-8,%s" % quote(doc) + + +def inline_image(data): + return "data:image/png;base64,%s" % data + + +class BaseNavigationTestCase(WindowManagerMixin, MarionetteTestCase): + def setUp(self): + super(BaseNavigationTestCase, self).setUp() + + file_path = os.path.join(here, "data", "test.html").replace("\\", "/") + + self.test_page_file_url = "file:///{}".format(file_path) + self.test_page_frameset = self.marionette.absolute_url("frameset.html") + self.test_page_insecure = self.fixtures.where_is("test.html", on="https") + self.test_page_not_remote = "about:robots" + self.test_page_push_state = self.marionette.absolute_url( + "navigation_pushstate.html" + ) + self.test_page_remote = self.marionette.absolute_url("test.html") + + if self.marionette.session_capabilities["platformName"] == "mac": + self.mod_key = Keys.META + else: + self.mod_key = Keys.CONTROL + + # Always use a blank new tab for an empty history + self.new_tab = self.open_tab() + self.marionette.switch_to_window(self.new_tab) + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda _: self.history_length == 1, + message="The newly opened tab doesn't have a browser history length of 1", + ) + + def tearDown(self): + self.marionette.timeout.reset() + + self.close_all_tabs() + + super(BaseNavigationTestCase, self).tearDown() + + @property + def history_length(self): + return self.marionette.execute_script("return window.history.length;") + + @property + def is_remote_tab(self): + with self.marionette.using_context("chrome"): + # TODO: DO NOT USE MOST RECENT WINDOW BUT CURRENT ONE + return self.marionette.execute_script( + """ + const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" + ); + + let win = null; + + if (AppConstants.MOZ_APP_NAME == "fennec") { + win = Services.wm.getMostRecentWindow("navigator:browser"); + } else { + const { BrowserWindowTracker } = ChromeUtils.importESModule( + "resource:///modules/BrowserWindowTracker.sys.mjs" + ); + win = BrowserWindowTracker.getTopWindow(); + } + + let tabBrowser = null; + + // Fennec + if (win.BrowserApp) { + tabBrowser = win.BrowserApp.selectedBrowser; + + // Firefox + } else if (win.gBrowser) { + tabBrowser = win.gBrowser.selectedBrowser; + + } else { + return null; + } + + return tabBrowser.isRemoteBrowser; + """ + ) + + @property + def ready_state(self): + return self.marionette.execute_script( + "return window.document.readyState;", sandbox=None + ) + + +class TestNavigate(BaseNavigationTestCase): + def test_set_location_through_execute_script(self): + # To avoid unexpected remoteness changes and a hang in any non-navigation + # command (bug 1519354) when navigating via the location bar, already + # pre-load a page which causes a remoteness change. + self.marionette.navigate(self.test_page_push_state) + + self.marionette.execute_script( + "window.location.href = arguments[0];", + script_args=(self.test_page_remote,), + sandbox=None, + ) + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_present(*(By.ID, "testh1")), + message="Target element 'testh1' has not been found", + ) + + self.assertEqual(self.test_page_remote, self.marionette.get_url()) + + def test_navigate_chrome_unsupported_error(self): + with self.marionette.using_context("chrome"): + self.assertRaises( + errors.UnsupportedOperationException, + self.marionette.navigate, + "about:blank", + ) + self.assertRaises( + errors.UnsupportedOperationException, self.marionette.go_back + ) + self.assertRaises( + errors.UnsupportedOperationException, self.marionette.go_forward + ) + self.assertRaises( + errors.UnsupportedOperationException, self.marionette.refresh + ) + + def test_get_current_url_returns_top_level_browsing_context_url(self): + page_iframe = self.marionette.absolute_url("test_iframe.html") + + self.marionette.navigate(page_iframe) + self.assertEqual(page_iframe, self.marionette.get_url()) + frame = self.marionette.find_element(By.CSS_SELECTOR, "#test_iframe") + self.marionette.switch_to_frame(frame) + self.assertEqual(page_iframe, self.marionette.get_url()) + + def test_get_current_url(self): + self.marionette.navigate(self.test_page_remote) + self.assertEqual(self.test_page_remote, self.marionette.get_url()) + self.marionette.navigate("about:blank") + self.assertEqual("about:blank", self.marionette.get_url()) + + def test_navigate_in_child_frame_changes_to_top(self): + self.marionette.navigate(self.test_page_frameset) + frame = self.marionette.find_element(By.NAME, "third") + self.marionette.switch_to_frame(frame) + self.assertRaises( + errors.NoSuchElementException, + self.marionette.find_element, + By.NAME, + "third", + ) + + self.marionette.navigate(self.test_page_frameset) + self.marionette.find_element(By.NAME, "third") + + def test_invalid_url(self): + with self.assertRaises(errors.MarionetteException): + self.marionette.navigate("foo") + with self.assertRaises(errors.MarionetteException): + self.marionette.navigate("thisprotocoldoesnotexist://") + + def test_find_element_state_complete(self): + self.marionette.navigate(self.test_page_remote) + self.assertEqual("complete", self.ready_state) + self.assertTrue(self.marionette.find_element(By.ID, "mozLink")) + + def test_navigate_timeout_error_no_remoteness_change(self): + is_remote_before_timeout = self.is_remote_tab + self.marionette.timeout.page_load = 0.5 + with self.assertRaises(errors.TimeoutException): + self.marionette.navigate(self.marionette.absolute_url("slow")) + self.assertEqual(self.is_remote_tab, is_remote_before_timeout) + + def test_navigate_timeout_error_remoteness_change(self): + self.assertTrue(self.is_remote_tab) + self.marionette.navigate("about:robots") + self.assertFalse(self.is_remote_tab) + + self.marionette.timeout.page_load = 0.5 + with self.assertRaises(errors.TimeoutException): + self.marionette.navigate(self.marionette.absolute_url("slow")) + + def test_navigate_to_same_image_document_twice(self): + self.marionette.navigate(self.fixtures.where_is("black.png")) + self.assertIn("black.png", self.marionette.title) + self.marionette.navigate(self.fixtures.where_is("black.png")) + self.assertIn("black.png", self.marionette.title) + + def test_navigate_hash_change(self): + doc = inline("<p id=foo>") + self.marionette.navigate(doc) + self.marionette.execute_script("window.visited = true", sandbox=None) + self.marionette.navigate("{}#foo".format(doc)) + self.assertTrue( + self.marionette.execute_script("return window.visited", sandbox=None) + ) + + def test_navigate_hash_argument_identical(self): + test_page = "{}#foo".format(inline("<p id=foo>")) + + self.marionette.navigate(test_page) + self.marionette.find_element(By.ID, "foo") + self.marionette.navigate(test_page) + self.marionette.find_element(By.ID, "foo") + + def test_navigate_hash_argument_differnt(self): + test_page = "{}#Foo".format(inline("<p id=foo>")) + + self.marionette.navigate(test_page) + self.marionette.find_element(By.ID, "foo") + self.marionette.navigate(test_page.lower()) + self.marionette.find_element(By.ID, "foo") + + def test_navigate_history_pushstate(self): + target_page = self.marionette.absolute_url("navigation_pushstate_target.html") + + self.marionette.navigate(self.test_page_push_state) + self.marionette.find_element(By.ID, "forward").click() + + # By using pushState() the URL is updated but the target page is not loaded + # and as such the element is not displayed + self.assertEqual(self.marionette.get_url(), target_page) + with self.assertRaises(errors.NoSuchElementException): + self.marionette.find_element(By.ID, "target") + + self.marionette.go_back() + self.assertEqual(self.marionette.get_url(), self.test_page_push_state) + + # The target page still gets not loaded + self.marionette.go_forward() + self.assertEqual(self.marionette.get_url(), target_page) + with self.assertRaises(errors.NoSuchElementException): + self.marionette.find_element(By.ID, "target") + + # Navigating to a different page, and returning to the injected + # page, it will be loaded. + self.marionette.navigate(self.test_page_remote) + self.assertEqual(self.marionette.get_url(), self.test_page_remote) + + self.marionette.go_back() + self.assertEqual(self.marionette.get_url(), target_page) + self.marionette.find_element(By.ID, "target") + + self.marionette.go_back() + self.assertEqual(self.marionette.get_url(), self.test_page_push_state) + + def test_navigate_file_url(self): + self.marionette.navigate(self.test_page_file_url) + self.marionette.find_element(By.ID, "file-url") + self.marionette.navigate(self.test_page_remote) + + def test_navigate_file_url_remoteness_change(self): + self.marionette.navigate("about:robots") + self.assertFalse(self.is_remote_tab) + + self.marionette.navigate(self.test_page_file_url) + self.assertTrue(self.is_remote_tab) + self.marionette.find_element(By.ID, "file-url") + + self.marionette.navigate("about:robots") + self.assertFalse(self.is_remote_tab) + + def test_no_such_element_after_remoteness_change(self): + self.marionette.navigate(self.test_page_file_url) + self.assertTrue(self.is_remote_tab) + elem = self.marionette.find_element(By.ID, "file-url") + + self.marionette.navigate("about:robots") + self.assertFalse(self.is_remote_tab) + + with self.assertRaises(errors.StaleElementException): + elem.click() + + def test_about_blank_for_new_docshell(self): + self.assertEqual(self.marionette.get_url(), "about:blank") + + self.marionette.navigate("about:blank") + + def test_about_newtab(self): + with self.marionette.using_prefs({"browser.newtabpage.enabled": True}): + self.marionette.navigate("about:newtab") + + self.marionette.navigate(self.test_page_remote) + self.marionette.find_element(By.ID, "testDiv") + + @run_if_manage_instance("Only runnable if Marionette manages the instance") + def test_focus_after_navigation(self): + self.marionette.restart() + + self.marionette.navigate(inline("<input autofocus>")) + + # Per spec, autofocus candidates will be + # flushed by next paint, so we use rAF here to + # ensure the candidates are flushed. + self.marionette.execute_async_script( + """ + const callback = arguments[arguments.length - 1]; + window.requestAnimationFrame(function() { + window.requestAnimationFrame(callback); + }); + """ + ) + focus_el = self.marionette.find_element(By.CSS_SELECTOR, ":focus") + self.assertEqual(self.marionette.get_active_element(), focus_el) + + def test_no_hang_when_navigating_after_closing_original_tab(self): + # Close the start tab + self.marionette.switch_to_window(self.start_tab) + self.marionette.close() + + self.marionette.switch_to_window(self.new_tab) + self.marionette.navigate(self.test_page_remote) + + def test_type_to_non_remote_tab(self): + self.marionette.navigate(self.test_page_not_remote) + self.assertFalse(self.is_remote_tab) + + with self.marionette.using_context("chrome"): + urlbar = self.marionette.find_element(By.ID, "urlbar-input") + urlbar.send_keys(self.mod_key + "a") + urlbar.send_keys(self.mod_key + "x") + urlbar.send_keys("about:support" + Keys.ENTER) + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda mn: mn.get_url() == "about:support", + message="'about:support' hasn't been loaded", + ) + self.assertFalse(self.is_remote_tab) + + def test_type_to_remote_tab(self): + self.assertTrue(self.is_remote_tab) + + with self.marionette.using_context("chrome"): + urlbar = self.marionette.find_element(By.ID, "urlbar-input") + urlbar.send_keys(self.mod_key + "a") + urlbar.send_keys(self.mod_key + "x") + urlbar.send_keys(self.test_page_remote + Keys.ENTER) + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda mn: mn.get_url() == self.test_page_remote, + message="'{}' hasn't been loaded".format(self.test_page_remote), + ) + self.assertTrue(self.is_remote_tab) + + def test_navigate_after_deleting_session(self): + self.marionette.delete_session() + self.marionette.start_session() + + self.marionette.navigate(self.test_page_remote) + self.assertEqual(self.test_page_remote, self.marionette.get_url()) + + +class TestBackForwardNavigation(BaseNavigationTestCase): + def run_bfcache_test(self, test_pages): + # Helper method to run simple back and forward testcases. + + def check_page_status(page, expected_history_length): + if "alert_text" in page: + self.assertEqual(Alert(self.marionette).text, page["alert_text"]) + + self.assertEqual(self.marionette.get_url(), page["url"]) + self.assertEqual(self.history_length, expected_history_length) + + if "is_remote" in page: + self.assertEqual( + page["is_remote"], + self.is_remote_tab, + "'{}' doesn't match expected remoteness state: {}".format( + page["url"], page["is_remote"] + ), + ) + + if "callback" in page and callable(page["callback"]): + page["callback"]() + + for index, page in enumerate(test_pages): + if "error" in page: + with self.assertRaises(page["error"]): + self.marionette.navigate(page["url"]) + else: + self.marionette.navigate(page["url"]) + + check_page_status(page, index + 1) + + # Now going back in history for all test pages by backward iterating + # through the list (-1) and skipping the first entry at the end (-2). + for page in test_pages[-2::-1]: + if "error" in page: + with self.assertRaises(page["error"]): + self.marionette.go_back() + else: + self.marionette.go_back() + + check_page_status(page, len(test_pages)) + + # Now going forward in history by skipping the first entry. + for page in test_pages[1::]: + if "error" in page: + with self.assertRaises(page["error"]): + self.marionette.go_forward() + else: + self.marionette.go_forward() + + check_page_status(page, len(test_pages)) + + def test_no_history_items(self): + # Both methods should not raise a failure if no navigation is possible + self.marionette.go_back() + self.marionette.go_forward() + + def test_data_urls(self): + test_pages = [ + {"url": inline("<p>foobar</p>")}, + {"url": self.test_page_remote}, + {"url": inline("<p>foobar</p>")}, + ] + self.run_bfcache_test(test_pages) + + def test_same_document_hash_change(self): + test_pages = [ + {"url": "{}#23".format(self.test_page_remote)}, + {"url": self.test_page_remote}, + {"url": "{}#42".format(self.test_page_remote)}, + ] + self.run_bfcache_test(test_pages) + + def test_file_url(self): + test_pages = [ + {"url": self.test_page_remote}, + {"url": self.test_page_file_url}, + {"url": self.test_page_remote}, + ] + self.run_bfcache_test(test_pages) + + def test_frameset(self): + test_pages = [ + {"url": self.marionette.absolute_url("frameset.html")}, + {"url": self.test_page_remote}, + {"url": self.marionette.absolute_url("frameset.html")}, + ] + self.run_bfcache_test(test_pages) + + def test_frameset_after_navigating_in_frame(self): + test_element_locator = (By.ID, "email") + + self.marionette.navigate(self.test_page_remote) + self.assertEqual(self.marionette.get_url(), self.test_page_remote) + self.assertEqual(self.history_length, 1) + page = self.marionette.absolute_url("frameset.html") + self.marionette.navigate(page) + self.assertEqual(self.marionette.get_url(), page) + self.assertEqual(self.history_length, 2) + frame = self.marionette.find_element(By.ID, "fifth") + self.marionette.switch_to_frame(frame) + link = self.marionette.find_element(By.ID, "linkId") + link.click() + + # We cannot use get_url() to wait until the target page has been loaded, + # because it will return the URL of the top browsing context and doesn't + # wait for the page load to be complete. + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_present(*test_element_locator), + message="Target element 'email' has not been found", + ) + self.assertEqual(self.history_length, 3) + + # Go back to the frame the click navigated away from + self.marionette.go_back() + self.assertEqual(self.marionette.get_url(), page) + with self.assertRaises(errors.NoSuchElementException): + self.marionette.find_element(*test_element_locator) + + # Go back to the non-frameset page + self.marionette.switch_to_parent_frame() + self.marionette.go_back() + self.assertEqual(self.marionette.get_url(), self.test_page_remote) + + # Go forward to the frameset page + self.marionette.go_forward() + self.assertEqual(self.marionette.get_url(), page) + + # Go forward to the frame the click navigated to + # TODO: See above for automatic browser context switches. Hard to do here + frame = self.marionette.find_element(By.ID, "fifth") + self.marionette.switch_to_frame(frame) + self.marionette.go_forward() + self.marionette.find_element(*test_element_locator) + self.assertEqual(self.marionette.get_url(), page) + + def test_image_to_html_to_image(self): + test_pages = [ + {"url": self.marionette.absolute_url("black.png")}, + {"url": self.test_page_remote}, + {"url": self.marionette.absolute_url("white.png")}, + ] + self.run_bfcache_test(test_pages) + + def test_image_to_image(self): + test_pages = [ + {"url": self.marionette.absolute_url("black.png")}, + {"url": self.marionette.absolute_url("white.png")}, + {"url": inline_image(RED_PIXEL)}, + {"url": inline_image(BLACK_PIXEL)}, + {"url": self.marionette.absolute_url("black.png")}, + ] + self.run_bfcache_test(test_pages) + + def test_remoteness_change(self): + test_pages = [ + {"url": "about:robots", "is_remote": False}, + {"url": self.test_page_remote, "is_remote": True}, + {"url": "about:robots", "is_remote": False}, + ] + self.run_bfcache_test(test_pages) + + def test_non_remote_about_pages(self): + test_pages = [ + {"url": "about:preferences", "is_remote": False}, + {"url": "about:robots", "is_remote": False}, + {"url": "about:support", "is_remote": False}, + ] + self.run_bfcache_test(test_pages) + + def test_navigate_to_requested_about_page_after_error_page(self): + test_pages = [ + {"url": "about:neterror"}, + {"url": self.test_page_remote}, + {"url": "about:blocked"}, + ] + self.run_bfcache_test(test_pages) + + def test_timeout_error(self): + urls = [ + self.marionette.absolute_url("slow?delay=3"), + self.test_page_remote, + self.marionette.absolute_url("slow?delay=4"), + ] + + # First, load all pages completely to get them added to the cache + for index, url in enumerate(urls): + self.marionette.navigate(url) + self.assertEqual(url, self.marionette.get_url()) + self.assertEqual(self.history_length, index + 1) + + self.marionette.go_back() + self.assertEqual(urls[1], self.marionette.get_url()) + + # Force triggering a timeout error + self.marionette.timeout.page_load = 0.5 + with self.assertRaises(errors.TimeoutException): + self.marionette.go_back() + self.marionette.timeout.reset() + + delay = Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_present(By.ID, "delay"), + message="Target element 'delay' has not been found after timeout in 'back'", + ) + self.assertEqual(delay.text, "3") + + self.marionette.go_forward() + self.assertEqual(urls[1], self.marionette.get_url()) + + # Force triggering a timeout error + self.marionette.timeout.page_load = 0.5 + with self.assertRaises(errors.TimeoutException): + self.marionette.go_forward() + self.marionette.timeout.reset() + + delay = Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_present(By.ID, "delay"), + message="Target element 'delay' has not been found after timeout in 'forward'", + ) + self.assertEqual(delay.text, "4") + + def test_certificate_error(self): + test_pages = [ + { + "url": self.test_page_insecure, + "error": errors.InsecureCertificateException, + }, + {"url": self.test_page_remote}, + { + "url": self.test_page_insecure, + "error": errors.InsecureCertificateException, + }, + ] + self.run_bfcache_test(test_pages) + + +class TestRefresh(BaseNavigationTestCase): + def test_basic(self): + self.marionette.navigate(self.test_page_remote) + self.assertEqual(self.test_page_remote, self.marionette.get_url()) + + self.marionette.execute_script( + """ + let elem = window.document.createElement('div'); + elem.id = 'someDiv'; + window.document.body.appendChild(elem); + """ + ) + self.marionette.find_element(By.ID, "someDiv") + + self.marionette.refresh() + self.assertEqual(self.test_page_remote, self.marionette.get_url()) + with self.assertRaises(errors.NoSuchElementException): + self.marionette.find_element(By.ID, "someDiv") + + def test_refresh_in_child_frame_navigates_to_top(self): + self.marionette.navigate(self.test_page_frameset) + self.assertEqual(self.test_page_frameset, self.marionette.get_url()) + + frame = self.marionette.find_element(By.NAME, "third") + self.marionette.switch_to_frame(frame) + self.assertRaises( + errors.NoSuchElementException, + self.marionette.find_element, + By.NAME, + "third", + ) + + self.marionette.refresh() + self.marionette.find_element(By.NAME, "third") + + def test_file_url(self): + self.marionette.navigate(self.test_page_file_url) + self.assertEqual(self.test_page_file_url, self.marionette.get_url()) + + self.marionette.refresh() + self.assertEqual(self.test_page_file_url, self.marionette.get_url()) + + def test_image(self): + image = self.marionette.absolute_url("black.png") + + self.marionette.navigate(image) + self.assertEqual(image, self.marionette.get_url()) + + self.marionette.refresh() + self.assertEqual(image, self.marionette.get_url()) + + def test_history_pushstate(self): + target_page = self.marionette.absolute_url("navigation_pushstate_target.html") + + self.marionette.navigate(self.test_page_push_state) + self.marionette.find_element(By.ID, "forward").click() + + # By using pushState() the URL is updated but the target page is not loaded + # and as such the element is not displayed + self.assertEqual(self.marionette.get_url(), target_page) + with self.assertRaises(errors.NoSuchElementException): + self.marionette.find_element(By.ID, "target") + + # Refreshing the target page will trigger a full page load. + self.marionette.refresh() + self.assertEqual(self.marionette.get_url(), target_page) + self.marionette.find_element(By.ID, "target") + + self.marionette.go_back() + self.assertEqual(self.marionette.get_url(), self.test_page_push_state) + + def test_timeout_error(self): + slow_page = self.marionette.absolute_url("slow?delay=3") + + self.marionette.navigate(slow_page) + self.assertEqual(slow_page, self.marionette.get_url()) + + self.marionette.timeout.page_load = 0.5 + with self.assertRaises(errors.TimeoutException): + self.marionette.refresh() + self.assertEqual(slow_page, self.marionette.get_url()) + + def test_insecure_error(self): + with self.assertRaises(errors.InsecureCertificateException): + self.marionette.navigate(self.test_page_insecure) + self.assertEqual(self.marionette.get_url(), self.test_page_insecure) + + with self.assertRaises(errors.InsecureCertificateException): + self.marionette.refresh() + + +class TestTLSNavigation(BaseNavigationTestCase): + insecure_tls = {"acceptInsecureCerts": True} + secure_tls = {"acceptInsecureCerts": False} + + def setUp(self): + super(TestTLSNavigation, self).setUp() + + self.test_page_insecure = self.fixtures.where_is("test.html", on="https") + + self.marionette.delete_session() + self.capabilities = self.marionette.start_session(self.insecure_tls) + + def tearDown(self): + try: + self.marionette.delete_session() + self.marionette.start_session() + except: + pass + + super(TestTLSNavigation, self).tearDown() + + @contextlib.contextmanager + def safe_session(self): + try: + self.capabilities = self.marionette.start_session(self.secure_tls) + self.assertFalse(self.capabilities["acceptInsecureCerts"]) + # Always use a blank new tab for an empty history + self.new_tab = self.open_tab() + self.marionette.switch_to_window(self.new_tab) + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda _: self.history_length == 1, + message="The newly opened tab doesn't have a browser history length of 1", + ) + yield self.marionette + finally: + self.close_all_tabs() + self.marionette.delete_session() + + @contextlib.contextmanager + def unsafe_session(self): + try: + self.capabilities = self.marionette.start_session(self.insecure_tls) + self.assertTrue(self.capabilities["acceptInsecureCerts"]) + # Always use a blank new tab for an empty history + self.new_tab = self.open_tab() + self.marionette.switch_to_window(self.new_tab) + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda _: self.history_length == 1, + message="The newly opened tab doesn't have a browser history length of 1", + ) + yield self.marionette + finally: + self.close_all_tabs() + self.marionette.delete_session() + + def test_navigate_by_command(self): + self.marionette.navigate(self.test_page_insecure) + self.assertIn("https", self.marionette.get_url()) + + def test_navigate_by_click(self): + link_url = self.test_page_insecure + self.marionette.navigate( + inline("<a href=%s>https is the future</a>" % link_url) + ) + self.marionette.find_element(By.TAG_NAME, "a").click() + self.assertIn("https", self.marionette.get_url()) + + def test_deactivation(self): + invalid_cert_url = self.test_page_insecure + + self.marionette.delete_session() + + print("with safe session") + with self.safe_session() as session: + with self.assertRaises(errors.InsecureCertificateException): + session.navigate(invalid_cert_url) + + print("with unsafe session") + with self.unsafe_session() as session: + session.navigate(invalid_cert_url) + + print("with safe session again") + with self.safe_session() as session: + with self.assertRaises(errors.InsecureCertificateException): + session.navigate(invalid_cert_url) + + +class TestPageLoadStrategy(BaseNavigationTestCase): + def setUp(self): + super(TestPageLoadStrategy, self).setUp() + + # Test page that delays the response and as such the document to be + # loaded. It is used for testing the page load strategy "none". + self.test_page_slow = self.marionette.absolute_url("slow") + + # Similar to "slow" but additionally triggers a cross group navigation + # which triggers a replacement of the top-level browsing context. + self.test_page_slow_coop = self.marionette.absolute_url("slow-coop") + + # Test page that contains a slow loading <img> element which delays the + # "load" but not the "DOMContentLoaded" event. + self.test_page_slow_resource = self.marionette.absolute_url( + "slow_resource.html" + ) + + def tearDown(self): + self.marionette.delete_session() + self.marionette.start_session() + + super(TestPageLoadStrategy, self).tearDown() + + def test_none(self): + self.marionette.delete_session() + self.marionette.start_session({"pageLoadStrategy": "none"}) + + # Navigate will return immediately. As such wait for the target URL to + # be the current location, and the element to exist. + self.marionette.navigate(self.test_page_slow) + with self.assertRaises(errors.NoSuchElementException): + self.marionette.find_element(By.ID, "delay") + + Wait( + self.marionette, + ignored_exceptions=errors.NoSuchElementException, + timeout=self.marionette.timeout.page_load, + ).until(lambda _: self.marionette.find_element(By.ID, "delay")) + + self.assertEqual(self.marionette.get_url(), self.test_page_slow) + + def test_none_with_new_session_waits_for_page_loaded(self): + self.marionette.delete_session() + self.marionette.start_session({"pageLoadStrategy": "none"}) + + # Navigate will return immediately. + self.marionette.navigate(self.test_page_slow) + + # Make sure that when creating a new session right away it waits + # until the page has been finished loading. + self.marionette.delete_session() + self.marionette.start_session() + + self.assertEqual(self.marionette.get_url(), self.test_page_slow) + self.assertEqual(self.ready_state, "complete") + self.marionette.find_element(By.ID, "delay") + + def test_none_with_new_session_waits_for_page_loaded_remoteness_change(self): + self.marionette.delete_session() + self.marionette.start_session({"pageLoadStrategy": "none"}) + + # Navigate will return immediately. + self.marionette.navigate(self.test_page_slow_coop) + + # Make sure that when creating a new session right away it waits + # until the page has been finished loading. + self.marionette.delete_session() + self.marionette.start_session() + + self.assertEqual(self.marionette.get_url(), self.test_page_slow_coop) + self.assertEqual(self.ready_state, "complete") + self.marionette.find_element(By.ID, "delay") + + def test_eager(self): + self.marionette.delete_session() + self.marionette.start_session({"pageLoadStrategy": "eager"}) + + self.marionette.navigate(self.test_page_slow_resource) + self.assertEqual(self.ready_state, "interactive") + self.assertEqual(self.marionette.get_url(), self.test_page_slow_resource) + self.marionette.find_element(By.ID, "slow") + + def test_normal(self): + self.marionette.delete_session() + self.marionette.start_session({"pageLoadStrategy": "normal"}) + + self.marionette.navigate(self.test_page_slow_resource) + self.assertEqual(self.marionette.get_url(), self.test_page_slow_resource) + self.assertEqual(self.ready_state, "complete") + self.marionette.find_element(By.ID, "slow") + + def test_strategy_after_remoteness_change(self): + """Bug 1378191 - Reset of capabilities after listener reload.""" + self.marionette.delete_session() + self.marionette.start_session({"pageLoadStrategy": "eager"}) + + # Trigger a remoteness change which will reload the listener script + self.assertTrue( + self.is_remote_tab, "Initial tab doesn't have remoteness flag set" + ) + self.marionette.navigate("about:robots") + self.assertFalse(self.is_remote_tab, "Tab has remoteness flag set") + self.marionette.navigate(self.test_page_slow_resource) + self.assertEqual(self.ready_state, "interactive") |