1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5from __future__ import absolute_import, print_function 6 7import contextlib 8import os 9 10from six.moves.urllib.parse import quote 11 12from marionette_driver import By, errors, expected, Wait 13from marionette_driver.keys import Keys 14from marionette_driver.marionette import Alert 15from marionette_harness import ( 16 MarionetteTestCase, 17 run_if_manage_instance, 18 skip_unless_browser_pref, 19 WindowManagerMixin, 20) 21 22here = os.path.abspath(os.path.dirname(__file__)) 23 24 25BLACK_PIXEL = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" # noqa 26RED_PIXEL = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=" # noqa 27 28 29def inline(doc): 30 return "data:text/html;charset=utf-8,%s" % quote(doc) 31 32 33def inline_image(data): 34 return "data:image/png;base64,%s" % data 35 36 37class BaseNavigationTestCase(WindowManagerMixin, MarionetteTestCase): 38 def setUp(self): 39 super(BaseNavigationTestCase, self).setUp() 40 41 file_path = os.path.join(here, "data", "test.html").replace("\\", "/") 42 43 self.test_page_file_url = "file:///{}".format(file_path) 44 self.test_page_frameset = self.marionette.absolute_url("frameset.html") 45 self.test_page_insecure = self.fixtures.where_is("test.html", on="https") 46 self.test_page_not_remote = "about:robots" 47 self.test_page_push_state = self.marionette.absolute_url( 48 "navigation_pushstate.html" 49 ) 50 self.test_page_remote = self.marionette.absolute_url("test.html") 51 self.test_page_slow_resource = self.marionette.absolute_url( 52 "slow_resource.html" 53 ) 54 55 if self.marionette.session_capabilities["platformName"] == "mac": 56 self.mod_key = Keys.META 57 else: 58 self.mod_key = Keys.CONTROL 59 60 # Always use a blank new tab for an empty history 61 self.new_tab = self.open_tab() 62 self.marionette.switch_to_window(self.new_tab) 63 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 64 lambda _: self.history_length == 1, 65 message="The newly opened tab doesn't have a browser history length of 1", 66 ) 67 68 def tearDown(self): 69 self.marionette.timeout.reset() 70 71 self.close_all_tabs() 72 73 super(BaseNavigationTestCase, self).tearDown() 74 75 @property 76 def history_length(self): 77 return self.marionette.execute_script("return window.history.length;") 78 79 @property 80 def is_remote_tab(self): 81 with self.marionette.using_context("chrome"): 82 # TODO: DO NOT USE MOST RECENT WINDOW BUT CURRENT ONE 83 return self.marionette.execute_script( 84 """ 85 Components.utils.import("resource://gre/modules/AppConstants.jsm"); 86 87 let win = null; 88 89 if (AppConstants.MOZ_APP_NAME == "fennec") { 90 Components.utils.import("resource://gre/modules/Services.jsm"); 91 win = Services.wm.getMostRecentWindow("navigator:browser"); 92 } else { 93 Components.utils.import("resource:///modules/BrowserWindowTracker.jsm"); 94 win = BrowserWindowTracker.getTopWindow(); 95 } 96 97 let tabBrowser = null; 98 99 // Fennec 100 if (win.BrowserApp) { 101 tabBrowser = win.BrowserApp.selectedBrowser; 102 103 // Firefox 104 } else if (win.gBrowser) { 105 tabBrowser = win.gBrowser.selectedBrowser; 106 107 } else { 108 return null; 109 } 110 111 return tabBrowser.isRemoteBrowser; 112 """ 113 ) 114 115 @property 116 def ready_state(self): 117 return self.marionette.execute_script( 118 "return window.document.readyState;", sandbox=None 119 ) 120 121 122class TestNavigate(BaseNavigationTestCase): 123 def test_set_location_through_execute_script(self): 124 # To avoid unexpected remoteness changes and a hang in any non-navigation 125 # command (bug 1519354) when navigating via the location bar, already 126 # pre-load a page which causes a remoteness change. 127 self.marionette.navigate(self.test_page_push_state) 128 129 self.marionette.execute_script( 130 "window.location.href = arguments[0];", 131 script_args=(self.test_page_remote,), 132 sandbox=None, 133 ) 134 135 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 136 expected.element_present(*(By.ID, "testh1")), 137 message="Target element 'testh1' has not been found", 138 ) 139 140 self.assertEqual(self.test_page_remote, self.marionette.get_url()) 141 142 def test_navigate_chrome_unsupported_error(self): 143 with self.marionette.using_context("chrome"): 144 self.assertRaises( 145 errors.UnsupportedOperationException, 146 self.marionette.navigate, 147 "about:blank", 148 ) 149 self.assertRaises( 150 errors.UnsupportedOperationException, self.marionette.go_back 151 ) 152 self.assertRaises( 153 errors.UnsupportedOperationException, self.marionette.go_forward 154 ) 155 self.assertRaises( 156 errors.UnsupportedOperationException, self.marionette.refresh 157 ) 158 159 def test_get_current_url_returns_top_level_browsing_context_url(self): 160 page_iframe = self.marionette.absolute_url("test_iframe.html") 161 162 self.marionette.navigate(page_iframe) 163 self.assertEqual(page_iframe, self.marionette.get_url()) 164 frame = self.marionette.find_element(By.CSS_SELECTOR, "#test_iframe") 165 self.marionette.switch_to_frame(frame) 166 self.assertEqual(page_iframe, self.marionette.get_url()) 167 168 def test_get_current_url(self): 169 self.marionette.navigate(self.test_page_remote) 170 self.assertEqual(self.test_page_remote, self.marionette.get_url()) 171 self.marionette.navigate("about:blank") 172 self.assertEqual("about:blank", self.marionette.get_url()) 173 174 def test_navigate_in_child_frame_changes_to_top(self): 175 self.marionette.navigate(self.test_page_frameset) 176 frame = self.marionette.find_element(By.NAME, "third") 177 self.marionette.switch_to_frame(frame) 178 self.assertRaises( 179 errors.NoSuchElementException, 180 self.marionette.find_element, 181 By.NAME, 182 "third", 183 ) 184 185 self.marionette.navigate(self.test_page_frameset) 186 self.marionette.find_element(By.NAME, "third") 187 188 def test_invalid_url(self): 189 with self.assertRaises(errors.MarionetteException): 190 self.marionette.navigate("foo") 191 with self.assertRaises(errors.MarionetteException): 192 self.marionette.navigate("thisprotocoldoesnotexist://") 193 194 def test_find_element_state_complete(self): 195 self.marionette.navigate(self.test_page_remote) 196 self.assertEqual("complete", self.ready_state) 197 self.assertTrue(self.marionette.find_element(By.ID, "mozLink")) 198 199 def test_navigate_timeout_error_no_remoteness_change(self): 200 is_remote_before_timeout = self.is_remote_tab 201 self.marionette.timeout.page_load = 0.5 202 with self.assertRaises(errors.TimeoutException): 203 self.marionette.navigate(self.marionette.absolute_url("slow")) 204 self.assertEqual(self.is_remote_tab, is_remote_before_timeout) 205 206 def test_navigate_timeout_error_remoteness_change(self): 207 self.assertTrue(self.is_remote_tab) 208 self.marionette.navigate("about:robots") 209 self.assertFalse(self.is_remote_tab) 210 211 self.marionette.timeout.page_load = 0.5 212 with self.assertRaises(errors.TimeoutException): 213 self.marionette.navigate(self.marionette.absolute_url("slow")) 214 215 def test_navigate_to_same_image_document_twice(self): 216 self.marionette.navigate(self.fixtures.where_is("black.png")) 217 self.assertIn("black.png", self.marionette.title) 218 self.marionette.navigate(self.fixtures.where_is("black.png")) 219 self.assertIn("black.png", self.marionette.title) 220 221 def test_navigate_hash_change(self): 222 doc = inline("<p id=foo>") 223 self.marionette.navigate(doc) 224 self.marionette.execute_script("window.visited = true", sandbox=None) 225 self.marionette.navigate("{}#foo".format(doc)) 226 self.assertTrue( 227 self.marionette.execute_script("return window.visited", sandbox=None) 228 ) 229 230 def test_navigate_hash_argument_identical(self): 231 test_page = "{}#foo".format(inline("<p id=foo>")) 232 233 self.marionette.navigate(test_page) 234 self.marionette.find_element(By.ID, "foo") 235 self.marionette.navigate(test_page) 236 self.marionette.find_element(By.ID, "foo") 237 238 def test_navigate_hash_argument_differnt(self): 239 test_page = "{}#Foo".format(inline("<p id=foo>")) 240 241 self.marionette.navigate(test_page) 242 self.marionette.find_element(By.ID, "foo") 243 self.marionette.navigate(test_page.lower()) 244 self.marionette.find_element(By.ID, "foo") 245 246 def test_navigate_history_pushstate(self): 247 target_page = self.marionette.absolute_url("navigation_pushstate_target.html") 248 249 self.marionette.navigate(self.test_page_push_state) 250 self.marionette.find_element(By.ID, "forward").click() 251 252 # By using pushState() the URL is updated but the target page is not loaded 253 # and as such the element is not displayed 254 self.assertEqual(self.marionette.get_url(), target_page) 255 with self.assertRaises(errors.NoSuchElementException): 256 self.marionette.find_element(By.ID, "target") 257 258 self.marionette.go_back() 259 self.assertEqual(self.marionette.get_url(), self.test_page_push_state) 260 261 # The target page still gets not loaded 262 self.marionette.go_forward() 263 self.assertEqual(self.marionette.get_url(), target_page) 264 with self.assertRaises(errors.NoSuchElementException): 265 self.marionette.find_element(By.ID, "target") 266 267 # Navigating to a different page, and returning to the injected 268 # page, it will be loaded. 269 self.marionette.navigate(self.test_page_remote) 270 self.assertEqual(self.marionette.get_url(), self.test_page_remote) 271 272 self.marionette.go_back() 273 self.assertEqual(self.marionette.get_url(), target_page) 274 self.marionette.find_element(By.ID, "target") 275 276 self.marionette.go_back() 277 self.assertEqual(self.marionette.get_url(), self.test_page_push_state) 278 279 def test_navigate_file_url(self): 280 self.marionette.navigate(self.test_page_file_url) 281 self.marionette.find_element(By.ID, "file-url") 282 self.marionette.navigate(self.test_page_remote) 283 284 def test_navigate_file_url_remoteness_change(self): 285 self.marionette.navigate("about:robots") 286 self.assertFalse(self.is_remote_tab) 287 288 self.marionette.navigate(self.test_page_file_url) 289 self.assertTrue(self.is_remote_tab) 290 self.marionette.find_element(By.ID, "file-url") 291 292 self.marionette.navigate("about:robots") 293 self.assertFalse(self.is_remote_tab) 294 295 def test_stale_element_after_remoteness_change(self): 296 self.marionette.navigate(self.test_page_file_url) 297 self.assertTrue(self.is_remote_tab) 298 elem = self.marionette.find_element(By.ID, "file-url") 299 300 self.marionette.navigate("about:robots") 301 self.assertFalse(self.is_remote_tab) 302 303 # Force a GC to get rid of the replaced browsing context. 304 with self.marionette.using_context("chrome"): 305 self.marionette.execute_async_script( 306 """ 307 const resolve = arguments[0]; 308 309 var memSrv = Cc["@mozilla.org/memory-reporter-manager;1"] 310 .getService(Ci.nsIMemoryReporterManager); 311 312 Services.obs.notifyObservers(null, "child-mmu-request", null); 313 memSrv.minimizeMemoryUsage(resolve); 314 """ 315 ) 316 317 with self.assertRaises(errors.StaleElementException): 318 elem.click() 319 320 def test_about_blank_for_new_docshell(self): 321 self.assertEqual(self.marionette.get_url(), "about:blank") 322 323 self.marionette.navigate("about:blank") 324 325 def test_about_newtab(self): 326 with self.marionette.using_prefs({"browser.newtabpage.enabled": True}): 327 self.marionette.navigate("about:newtab") 328 329 self.marionette.navigate(self.test_page_remote) 330 self.marionette.find_element(By.ID, "testDiv") 331 332 @run_if_manage_instance("Only runnable if Marionette manages the instance") 333 def test_focus_after_navigation(self): 334 self.marionette.restart() 335 336 self.marionette.navigate(inline("<input autofocus>")) 337 focus_el = self.marionette.find_element(By.CSS_SELECTOR, ":focus") 338 self.assertEqual(self.marionette.get_active_element(), focus_el) 339 340 def test_no_hang_when_navigating_after_closing_original_tab(self): 341 # Close the start tab 342 self.marionette.switch_to_window(self.start_tab) 343 self.marionette.close() 344 345 self.marionette.switch_to_window(self.new_tab) 346 self.marionette.navigate(self.test_page_remote) 347 348 def test_type_to_non_remote_tab(self): 349 self.marionette.navigate(self.test_page_not_remote) 350 self.assertFalse(self.is_remote_tab) 351 352 with self.marionette.using_context("chrome"): 353 urlbar = self.marionette.find_element(By.ID, "urlbar-input") 354 urlbar.send_keys(self.mod_key + "a") 355 urlbar.send_keys(self.mod_key + "x") 356 urlbar.send_keys("about:support" + Keys.ENTER) 357 358 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 359 lambda mn: mn.get_url() == "about:support", 360 message="'about:support' hasn't been loaded", 361 ) 362 self.assertFalse(self.is_remote_tab) 363 364 def test_type_to_remote_tab(self): 365 self.assertTrue(self.is_remote_tab) 366 367 with self.marionette.using_context("chrome"): 368 urlbar = self.marionette.find_element(By.ID, "urlbar-input") 369 urlbar.send_keys(self.mod_key + "a") 370 urlbar.send_keys(self.mod_key + "x") 371 urlbar.send_keys(self.test_page_remote + Keys.ENTER) 372 373 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 374 lambda mn: mn.get_url() == self.test_page_remote, 375 message="'{}' hasn't been loaded".format(self.test_page_remote), 376 ) 377 self.assertTrue(self.is_remote_tab) 378 379 380class TestBackForwardNavigation(BaseNavigationTestCase): 381 def run_bfcache_test(self, test_pages): 382 # Helper method to run simple back and forward testcases. 383 384 def check_page_status(page, expected_history_length): 385 if "alert_text" in page: 386 if page["alert_text"] is None: 387 # navigation auto-dismisses beforeunload prompt 388 with self.assertRaises(errors.NoAlertPresentException): 389 Alert(self.marionette).text 390 else: 391 self.assertEqual(Alert(self.marionette).text, page["alert_text"]) 392 393 self.assertEqual(self.marionette.get_url(), page["url"]) 394 self.assertEqual(self.history_length, expected_history_length) 395 396 if "is_remote" in page: 397 self.assertEqual( 398 page["is_remote"], 399 self.is_remote_tab, 400 "'{}' doesn't match expected remoteness state: {}".format( 401 page["url"], page["is_remote"] 402 ), 403 ) 404 405 if "callback" in page and callable(page["callback"]): 406 page["callback"]() 407 408 for index, page in enumerate(test_pages): 409 if "error" in page: 410 with self.assertRaises(page["error"]): 411 self.marionette.navigate(page["url"]) 412 else: 413 self.marionette.navigate(page["url"]) 414 415 check_page_status(page, index + 1) 416 417 # Now going back in history for all test pages by backward iterating 418 # through the list (-1) and skipping the first entry at the end (-2). 419 for page in test_pages[-2::-1]: 420 if "error" in page: 421 with self.assertRaises(page["error"]): 422 self.marionette.go_back() 423 else: 424 self.marionette.go_back() 425 426 check_page_status(page, len(test_pages)) 427 428 # Now going forward in history by skipping the first entry. 429 for page in test_pages[1::]: 430 if "error" in page: 431 with self.assertRaises(page["error"]): 432 self.marionette.go_forward() 433 else: 434 self.marionette.go_forward() 435 436 check_page_status(page, len(test_pages)) 437 438 def test_no_history_items(self): 439 # Both methods should not raise a failure if no navigation is possible 440 self.marionette.go_back() 441 self.marionette.go_forward() 442 443 def test_dismissed_beforeunload_prompt(self): 444 url_beforeunload = inline( 445 """ 446 <input type="text"> 447 <script> 448 window.addEventListener("beforeunload", function (event) { 449 event.preventDefault(); 450 }); 451 </script> 452 """ 453 ) 454 455 def modify_page(): 456 self.marionette.find_element(By.TAG_NAME, "input").send_keys("foo") 457 458 test_pages = [ 459 {"url": inline("<p>foobar</p>"), "alert_text": None}, 460 {"url": url_beforeunload, "callback": modify_page}, 461 {"url": inline("<p>foobar</p>"), "alert_text": None}, 462 ] 463 464 self.run_bfcache_test(test_pages) 465 466 def test_data_urls(self): 467 test_pages = [ 468 {"url": inline("<p>foobar</p>")}, 469 {"url": self.test_page_remote}, 470 {"url": inline("<p>foobar</p>")}, 471 ] 472 self.run_bfcache_test(test_pages) 473 474 def test_same_document_hash_change(self): 475 test_pages = [ 476 {"url": "{}#23".format(self.test_page_remote)}, 477 {"url": self.test_page_remote}, 478 {"url": "{}#42".format(self.test_page_remote)}, 479 ] 480 self.run_bfcache_test(test_pages) 481 482 def test_file_url(self): 483 test_pages = [ 484 {"url": self.test_page_remote}, 485 {"url": self.test_page_file_url}, 486 {"url": self.test_page_remote}, 487 ] 488 self.run_bfcache_test(test_pages) 489 490 def test_frameset(self): 491 test_pages = [ 492 {"url": self.marionette.absolute_url("frameset.html")}, 493 {"url": self.test_page_remote}, 494 {"url": self.marionette.absolute_url("frameset.html")}, 495 ] 496 self.run_bfcache_test(test_pages) 497 498 def test_frameset_after_navigating_in_frame(self): 499 test_element_locator = (By.ID, "email") 500 501 self.marionette.navigate(self.test_page_remote) 502 self.assertEqual(self.marionette.get_url(), self.test_page_remote) 503 self.assertEqual(self.history_length, 1) 504 page = self.marionette.absolute_url("frameset.html") 505 self.marionette.navigate(page) 506 self.assertEqual(self.marionette.get_url(), page) 507 self.assertEqual(self.history_length, 2) 508 frame = self.marionette.find_element(By.ID, "fifth") 509 self.marionette.switch_to_frame(frame) 510 link = self.marionette.find_element(By.ID, "linkId") 511 link.click() 512 513 # We cannot use get_url() to wait until the target page has been loaded, 514 # because it will return the URL of the top browsing context and doesn't 515 # wait for the page load to be complete. 516 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 517 expected.element_present(*test_element_locator), 518 message="Target element 'email' has not been found", 519 ) 520 self.assertEqual(self.history_length, 3) 521 522 # Go back to the frame the click navigated away from 523 self.marionette.go_back() 524 self.assertEqual(self.marionette.get_url(), page) 525 with self.assertRaises(errors.NoSuchElementException): 526 self.marionette.find_element(*test_element_locator) 527 528 # Go back to the non-frameset page 529 self.marionette.switch_to_parent_frame() 530 self.marionette.go_back() 531 self.assertEqual(self.marionette.get_url(), self.test_page_remote) 532 533 # Go forward to the frameset page 534 self.marionette.go_forward() 535 self.assertEqual(self.marionette.get_url(), page) 536 537 # Go forward to the frame the click navigated to 538 # TODO: See above for automatic browser context switches. Hard to do here 539 frame = self.marionette.find_element(By.ID, "fifth") 540 self.marionette.switch_to_frame(frame) 541 self.marionette.go_forward() 542 self.marionette.find_element(*test_element_locator) 543 self.assertEqual(self.marionette.get_url(), page) 544 545 def test_image_to_html_to_image(self): 546 test_pages = [ 547 {"url": self.marionette.absolute_url("black.png")}, 548 {"url": self.test_page_remote}, 549 {"url": self.marionette.absolute_url("white.png")}, 550 ] 551 self.run_bfcache_test(test_pages) 552 553 def test_image_to_image(self): 554 test_pages = [ 555 {"url": self.marionette.absolute_url("black.png")}, 556 {"url": self.marionette.absolute_url("white.png")}, 557 {"url": inline_image(RED_PIXEL)}, 558 {"url": inline_image(BLACK_PIXEL)}, 559 {"url": self.marionette.absolute_url("black.png")}, 560 ] 561 self.run_bfcache_test(test_pages) 562 563 def test_remoteness_change(self): 564 test_pages = [ 565 {"url": "about:robots", "is_remote": False}, 566 {"url": self.test_page_remote, "is_remote": True}, 567 {"url": "about:robots", "is_remote": False}, 568 ] 569 self.run_bfcache_test(test_pages) 570 571 def test_non_remote_about_pages(self): 572 test_pages = [ 573 {"url": "about:preferences", "is_remote": False}, 574 {"url": "about:robots", "is_remote": False}, 575 {"url": "about:support", "is_remote": False}, 576 ] 577 self.run_bfcache_test(test_pages) 578 579 def test_navigate_to_requested_about_page_after_error_page(self): 580 test_pages = [ 581 {"url": "about:neterror"}, 582 {"url": self.test_page_remote}, 583 {"url": "about:blocked"}, 584 ] 585 self.run_bfcache_test(test_pages) 586 587 def test_timeout_error(self): 588 urls = [ 589 self.marionette.absolute_url("slow?delay=3"), 590 self.test_page_remote, 591 self.marionette.absolute_url("slow?delay=4"), 592 ] 593 594 # First, load all pages completely to get them added to the cache 595 for index, url in enumerate(urls): 596 self.marionette.navigate(url) 597 self.assertEqual(url, self.marionette.get_url()) 598 self.assertEqual(self.history_length, index + 1) 599 600 self.marionette.go_back() 601 self.assertEqual(urls[1], self.marionette.get_url()) 602 603 # Force triggering a timeout error 604 self.marionette.timeout.page_load = 0.5 605 with self.assertRaises(errors.TimeoutException): 606 self.marionette.go_back() 607 self.marionette.timeout.reset() 608 609 delay = Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 610 expected.element_present(By.ID, "delay"), 611 message="Target element 'delay' has not been found after timeout in 'back'", 612 ) 613 self.assertEqual(delay.text, "3") 614 615 self.marionette.go_forward() 616 self.assertEqual(urls[1], self.marionette.get_url()) 617 618 # Force triggering a timeout error 619 self.marionette.timeout.page_load = 0.5 620 with self.assertRaises(errors.TimeoutException): 621 self.marionette.go_forward() 622 self.marionette.timeout.reset() 623 624 delay = Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 625 expected.element_present(By.ID, "delay"), 626 message="Target element 'delay' has not been found after timeout in 'forward'", 627 ) 628 self.assertEqual(delay.text, "4") 629 630 def test_certificate_error(self): 631 test_pages = [ 632 { 633 "url": self.test_page_insecure, 634 "error": errors.InsecureCertificateException, 635 }, 636 {"url": self.test_page_remote}, 637 { 638 "url": self.test_page_insecure, 639 "error": errors.InsecureCertificateException, 640 }, 641 ] 642 self.run_bfcache_test(test_pages) 643 644 645class TestRefresh(BaseNavigationTestCase): 646 def test_basic(self): 647 self.marionette.navigate(self.test_page_remote) 648 self.assertEqual(self.test_page_remote, self.marionette.get_url()) 649 650 self.marionette.execute_script( 651 """ 652 let elem = window.document.createElement('div'); 653 elem.id = 'someDiv'; 654 window.document.body.appendChild(elem); 655 """ 656 ) 657 self.marionette.find_element(By.ID, "someDiv") 658 659 self.marionette.refresh() 660 self.assertEqual(self.test_page_remote, self.marionette.get_url()) 661 with self.assertRaises(errors.NoSuchElementException): 662 self.marionette.find_element(By.ID, "someDiv") 663 664 def test_refresh_in_child_frame_navigates_to_top(self): 665 self.marionette.navigate(self.test_page_frameset) 666 self.assertEqual(self.test_page_frameset, self.marionette.get_url()) 667 668 frame = self.marionette.find_element(By.NAME, "third") 669 self.marionette.switch_to_frame(frame) 670 self.assertRaises( 671 errors.NoSuchElementException, 672 self.marionette.find_element, 673 By.NAME, 674 "third", 675 ) 676 677 self.marionette.refresh() 678 self.marionette.find_element(By.NAME, "third") 679 680 def test_file_url(self): 681 self.marionette.navigate(self.test_page_file_url) 682 self.assertEqual(self.test_page_file_url, self.marionette.get_url()) 683 684 self.marionette.refresh() 685 self.assertEqual(self.test_page_file_url, self.marionette.get_url()) 686 687 def test_dismissed_beforeunload_prompt(self): 688 self.marionette.navigate( 689 inline( 690 """ 691 <input type="text"> 692 <script> 693 window.addEventListener("beforeunload", function (event) { 694 event.preventDefault(); 695 }); 696 </script> 697 """ 698 ) 699 ) 700 self.marionette.find_element(By.TAG_NAME, "input").send_keys("foo") 701 self.marionette.refresh() 702 703 # navigation auto-dismisses beforeunload prompt 704 with self.assertRaises(errors.NoAlertPresentException): 705 Alert(self.marionette).text 706 707 def test_image(self): 708 image = self.marionette.absolute_url("black.png") 709 710 self.marionette.navigate(image) 711 self.assertEqual(image, self.marionette.get_url()) 712 713 self.marionette.refresh() 714 self.assertEqual(image, self.marionette.get_url()) 715 716 def test_history_pushstate(self): 717 target_page = self.marionette.absolute_url("navigation_pushstate_target.html") 718 719 self.marionette.navigate(self.test_page_push_state) 720 self.marionette.find_element(By.ID, "forward").click() 721 722 # By using pushState() the URL is updated but the target page is not loaded 723 # and as such the element is not displayed 724 self.assertEqual(self.marionette.get_url(), target_page) 725 with self.assertRaises(errors.NoSuchElementException): 726 self.marionette.find_element(By.ID, "target") 727 728 # Refreshing the target page will trigger a full page load. 729 self.marionette.refresh() 730 self.assertEqual(self.marionette.get_url(), target_page) 731 self.marionette.find_element(By.ID, "target") 732 733 self.marionette.go_back() 734 self.assertEqual(self.marionette.get_url(), self.test_page_push_state) 735 736 def test_timeout_error(self): 737 slow_page = self.marionette.absolute_url("slow?delay=3") 738 739 self.marionette.navigate(slow_page) 740 self.assertEqual(slow_page, self.marionette.get_url()) 741 742 self.marionette.timeout.page_load = 0.5 743 with self.assertRaises(errors.TimeoutException): 744 self.marionette.refresh() 745 self.assertEqual(slow_page, self.marionette.get_url()) 746 747 def test_insecure_error(self): 748 with self.assertRaises(errors.InsecureCertificateException): 749 self.marionette.navigate(self.test_page_insecure) 750 self.assertEqual(self.marionette.get_url(), self.test_page_insecure) 751 752 with self.assertRaises(errors.InsecureCertificateException): 753 self.marionette.refresh() 754 755 756class TestTLSNavigation(BaseNavigationTestCase): 757 insecure_tls = {"acceptInsecureCerts": True} 758 secure_tls = {"acceptInsecureCerts": False} 759 760 def setUp(self): 761 super(TestTLSNavigation, self).setUp() 762 763 self.test_page_insecure = self.fixtures.where_is("test.html", on="https") 764 765 self.marionette.delete_session() 766 self.capabilities = self.marionette.start_session(self.insecure_tls) 767 768 def tearDown(self): 769 try: 770 self.marionette.delete_session() 771 self.marionette.start_session() 772 except: 773 pass 774 775 super(TestTLSNavigation, self).tearDown() 776 777 @contextlib.contextmanager 778 def safe_session(self): 779 try: 780 self.capabilities = self.marionette.start_session(self.secure_tls) 781 self.assertFalse(self.capabilities["acceptInsecureCerts"]) 782 # Always use a blank new tab for an empty history 783 self.new_tab = self.open_tab() 784 self.marionette.switch_to_window(self.new_tab) 785 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 786 lambda _: self.history_length == 1, 787 message="The newly opened tab doesn't have a browser history length of 1", 788 ) 789 yield self.marionette 790 finally: 791 self.close_all_tabs() 792 self.marionette.delete_session() 793 794 @contextlib.contextmanager 795 def unsafe_session(self): 796 try: 797 self.capabilities = self.marionette.start_session(self.insecure_tls) 798 self.assertTrue(self.capabilities["acceptInsecureCerts"]) 799 # Always use a blank new tab for an empty history 800 self.new_tab = self.open_tab() 801 self.marionette.switch_to_window(self.new_tab) 802 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 803 lambda _: self.history_length == 1, 804 message="The newly opened tab doesn't have a browser history length of 1", 805 ) 806 yield self.marionette 807 finally: 808 self.close_all_tabs() 809 self.marionette.delete_session() 810 811 def test_navigate_by_command(self): 812 self.marionette.navigate(self.test_page_insecure) 813 self.assertIn("https", self.marionette.get_url()) 814 815 def test_navigate_by_click(self): 816 link_url = self.test_page_insecure 817 self.marionette.navigate( 818 inline("<a href=%s>https is the future</a>" % link_url) 819 ) 820 self.marionette.find_element(By.TAG_NAME, "a").click() 821 self.assertIn("https", self.marionette.get_url()) 822 823 def test_deactivation(self): 824 invalid_cert_url = self.test_page_insecure 825 826 self.marionette.delete_session() 827 828 print("with safe session") 829 with self.safe_session() as session: 830 with self.assertRaises(errors.InsecureCertificateException): 831 session.navigate(invalid_cert_url) 832 833 print("with unsafe session") 834 with self.unsafe_session() as session: 835 session.navigate(invalid_cert_url) 836 837 print("with safe session again") 838 with self.safe_session() as session: 839 with self.assertRaises(errors.InsecureCertificateException): 840 session.navigate(invalid_cert_url) 841 842 843class TestPageLoadStrategy(BaseNavigationTestCase): 844 def tearDown(self): 845 self.marionette.delete_session() 846 self.marionette.start_session() 847 848 super(TestPageLoadStrategy, self).tearDown() 849 850 def test_none(self): 851 self.marionette.delete_session() 852 self.marionette.start_session({"pageLoadStrategy": "none"}) 853 854 self.marionette.navigate(self.test_page_slow_resource) 855 Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( 856 lambda _: self.marionette.get_url() == self.test_page_slow_resource, 857 message="Target page has not been loaded", 858 ) 859 self.marionette.find_element(By.ID, "slow") 860 861 def test_none_with_new_session_waits_for_page_loaded(self): 862 self.marionette.delete_session() 863 self.marionette.start_session({"pageLoadStrategy": "none"}) 864 865 # Navigate will return immediately. 866 self.marionette.navigate(self.test_page_slow_resource) 867 868 # Make sure that when creating a new session right away it waits 869 # until the page has been finished loading. 870 self.marionette.delete_session() 871 self.marionette.start_session() 872 873 self.assertEqual(self.test_page_slow_resource, self.marionette.get_url()) 874 self.assertEqual("complete", self.ready_state) 875 self.marionette.find_element(By.ID, "slow") 876 877 def test_eager(self): 878 self.marionette.delete_session() 879 self.marionette.start_session({"pageLoadStrategy": "eager"}) 880 881 self.marionette.navigate(self.test_page_slow_resource) 882 self.assertEqual("interactive", self.ready_state) 883 self.assertEqual(self.test_page_slow_resource, self.marionette.get_url()) 884 self.marionette.find_element(By.ID, "slow") 885 886 def test_normal(self): 887 self.marionette.delete_session() 888 self.marionette.start_session({"pageLoadStrategy": "normal"}) 889 890 self.marionette.navigate(self.test_page_slow_resource) 891 self.assertEqual(self.test_page_slow_resource, self.marionette.get_url()) 892 self.assertEqual("complete", self.ready_state) 893 self.marionette.find_element(By.ID, "slow") 894 895 def test_strategy_after_remoteness_change(self): 896 """Bug 1378191 - Reset of capabilities after listener reload.""" 897 self.marionette.delete_session() 898 self.marionette.start_session({"pageLoadStrategy": "eager"}) 899 900 # Trigger a remoteness change which will reload the listener script 901 self.assertTrue( 902 self.is_remote_tab, "Initial tab doesn't have remoteness flag set" 903 ) 904 self.marionette.navigate("about:robots") 905 self.assertFalse(self.is_remote_tab, "Tab has remoteness flag set") 906 self.marionette.navigate(self.test_page_slow_resource) 907 self.assertEqual("interactive", self.ready_state) 908