# Copyright (c) Microsoft Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import asyncio import re import sys from pathlib import Path from typing import Any, List, Optional import pytest from playwright.async_api import ( BrowserContext, Error, Page, Request, Response, Route, TimeoutError, ) from tests.server import Server, TestServerRequest async def test_goto_should_work(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) assert page.url == server.EMPTY_PAGE async def test_goto_should_work_with_file_URL(page: Page, assetdir: Path) -> None: fileurl = (assetdir / "frames" / "two-frames.html").as_uri() await page.goto(fileurl) assert page.url.lower() == fileurl.lower() assert len(page.frames) == 3 async def test_goto_should_use_http_for_no_protocol(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE[7:]) assert page.url == server.EMPTY_PAGE async def test_goto_should_work_cross_process(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) assert page.url == server.EMPTY_PAGE url = server.CROSS_PROCESS_PREFIX + "/empty.html" request_frames = [] def on_request(r: Request) -> None: if r.url == url: request_frames.append(r.frame) page.on("request", on_request) response = await page.goto(url) assert response assert page.url == url assert response.frame == page.main_frame assert request_frames[0] == page.main_frame assert response.url == url async def test_goto_should_capture_iframe_navigation_request(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) assert page.url == server.EMPTY_PAGE request_frames = [] def on_request(r: Request) -> None: if r.url == server.PREFIX + "/frames/frame.html": request_frames.append(r.frame) page.on("request", on_request) response = await page.goto(server.PREFIX + "/frames/one-frame.html") assert response assert page.url == server.PREFIX + "/frames/one-frame.html" assert response.frame == page.main_frame assert response.url == server.PREFIX + "/frames/one-frame.html" assert len(page.frames) == 2 assert request_frames[0] == page.frames[1] async def test_goto_should_capture_cross_process_iframe_navigation_request( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) assert page.url == server.EMPTY_PAGE request_frames = [] def on_request(r: Request) -> None: if r.url == server.CROSS_PROCESS_PREFIX + "/frames/frame.html": request_frames.append(r.frame) page.on("request", on_request) response = await page.goto(server.CROSS_PROCESS_PREFIX + "/frames/one-frame.html") assert response assert page.url == server.CROSS_PROCESS_PREFIX + "/frames/one-frame.html" assert response.frame == page.main_frame assert response.url == server.CROSS_PROCESS_PREFIX + "/frames/one-frame.html" assert len(page.frames) == 2 assert request_frames[0] == page.frames[1] async def test_goto_should_work_with_anchor_navigation(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) assert page.url == server.EMPTY_PAGE await page.goto(server.EMPTY_PAGE + "#foo") assert page.url == server.EMPTY_PAGE + "#foo" await page.goto(server.EMPTY_PAGE + "#bar") assert page.url == server.EMPTY_PAGE + "#bar" async def test_goto_should_work_with_redirects(page: Page, server: Server) -> None: server.set_redirect("/redirect/1.html", "/redirect/2.html") server.set_redirect("/redirect/2.html", "/empty.html") response = await page.goto(server.PREFIX + "/redirect/1.html") assert response assert response.status == 200 assert page.url == server.EMPTY_PAGE async def test_goto_should_navigate_to_about_blank(page: Page, server: Server) -> None: response = await page.goto("about:blank") assert response is None async def test_goto_should_return_response_when_page_changes_its_url_after_load( page: Page, server: Server ) -> None: response = await page.goto(server.PREFIX + "/historyapi.html") assert response assert response.status == 200 @pytest.mark.skip_browser("firefox") async def test_goto_should_work_with_subframes_return_204(page: Page, server: Server) -> None: def handle(request: TestServerRequest) -> None: request.setResponseCode(204) request.finish() server.set_route("/frames/frame.html", handle) await page.goto(server.PREFIX + "/frames/one-frame.html") async def test_goto_should_fail_when_server_returns_204( page: Page, server: Server, is_chromium: bool, is_webkit: bool ) -> None: # WebKit just loads an empty page. def handle(request: TestServerRequest) -> None: request.setResponseCode(204) request.finish() server.set_route("/empty.html", handle) with pytest.raises(Error) as exc_info: await page.goto(server.EMPTY_PAGE) assert exc_info.value if is_chromium: assert "net::ERR_ABORTED" in exc_info.value.message elif is_webkit: assert "Aborted: 204 No Content" in exc_info.value.message else: assert "NS_BINDING_ABORTED" in exc_info.value.message async def test_goto_should_navigate_to_empty_page_with_domcontentloaded( page: Page, server: Server ) -> None: response = await page.goto(server.EMPTY_PAGE, wait_until="domcontentloaded") assert response assert response.status == 200 async def test_goto_should_work_when_page_calls_history_api_in_beforeunload( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) await page.evaluate( """() => { window.addEventListener('beforeunload', () => history.replaceState(null, 'initial', window.location.href), false) }""" ) response = await page.goto(server.PREFIX + "/grid.html") assert response assert response.status == 200 async def test_goto_should_fail_when_navigating_to_bad_url( page: Page, is_chromium: bool, is_webkit: bool ) -> None: with pytest.raises(Error) as exc_info: await page.goto("asdfasdf") if is_chromium or is_webkit: assert "Cannot navigate to invalid URL" in exc_info.value.message else: assert "Invalid url" in exc_info.value.message async def test_goto_should_fail_when_navigating_to_bad_ssl( page: Page, https_server: Server, browser_name: str ) -> None: with pytest.raises(Error) as exc_info: await page.goto(https_server.EMPTY_PAGE) expect_ssl_error(exc_info.value.message, browser_name) async def test_goto_should_fail_when_navigating_to_bad_ssl_after_redirects( page: Page, server: Server, https_server: Server, browser_name: str ) -> None: server.set_redirect("/redirect/1.html", "/redirect/2.html") server.set_redirect("/redirect/2.html", "/empty.html") with pytest.raises(Error) as exc_info: await page.goto(https_server.PREFIX + "/redirect/1.html") expect_ssl_error(exc_info.value.message, browser_name) async def test_goto_should_not_crash_when_navigating_to_bad_ssl_after_a_cross_origin_navigation( page: Page, server: Server, https_server: Server ) -> None: await page.goto(server.CROSS_PROCESS_PREFIX + "/empty.html") with pytest.raises(Error): await page.goto(https_server.EMPTY_PAGE) async def test_goto_should_throw_if_networkidle2_is_passed_as_an_option( page: Page, server: Server ) -> None: with pytest.raises(Error) as exc_info: await page.goto(server.EMPTY_PAGE, wait_until="networkidle2") # type: ignore assert ( "wait_until: expected one of (load|domcontentloaded|networkidle|commit)" in exc_info.value.message ) async def test_goto_should_fail_when_main_resources_failed_to_load( page: Page, is_chromium: bool, is_webkit: bool, is_win: bool ) -> None: with pytest.raises(Error) as exc_info: await page.goto("http://localhost:44123/non-existing-url") if is_chromium: assert "net::ERR_CONNECTION_REFUSED" in exc_info.value.message elif is_webkit and is_win: assert "Couldn't connect to server" in exc_info.value.message elif is_webkit: assert "Could not connect" in exc_info.value.message else: assert "NS_ERROR_CONNECTION_REFUSED" in exc_info.value.message async def test_goto_should_fail_when_exceeding_maximum_navigation_timeout( page: Page, server: Server ) -> None: # Hang for request to the empty.html server.set_route("/empty.html", lambda request: None) with pytest.raises(Error) as exc_info: await page.goto(server.PREFIX + "/empty.html", timeout=1) assert "Timeout 1ms exceeded" in exc_info.value.message assert server.PREFIX + "/empty.html" in exc_info.value.message assert isinstance(exc_info.value, TimeoutError) async def test_goto_should_fail_when_exceeding_default_maximum_navigation_timeout( page: Page, server: Server ) -> None: # Hang for request to the empty.html server.set_route("/empty.html", lambda request: None) page.context.set_default_navigation_timeout(2) page.set_default_navigation_timeout(1) with pytest.raises(Error) as exc_info: await page.goto(server.PREFIX + "/empty.html") assert "Timeout 1ms exceeded" in exc_info.value.message assert server.PREFIX + "/empty.html" in exc_info.value.message assert isinstance(exc_info.value, TimeoutError) async def test_goto_should_fail_when_exceeding_browser_context_navigation_timeout( page: Page, server: Server ) -> None: # Hang for request to the empty.html server.set_route("/empty.html", lambda request: None) page.context.set_default_navigation_timeout(2) with pytest.raises(Error) as exc_info: await page.goto(server.PREFIX + "/empty.html") assert "Timeout 2ms exceeded" in exc_info.value.message assert server.PREFIX + "/empty.html" in exc_info.value.message assert isinstance(exc_info.value, TimeoutError) async def test_goto_should_fail_when_exceeding_default_maximum_timeout( page: Page, server: Server ) -> None: # Hang for request to the empty.html server.set_route("/empty.html", lambda request: None) page.context.set_default_timeout(2) page.set_default_timeout(1) with pytest.raises(Error) as exc_info: await page.goto(server.PREFIX + "/empty.html") assert "Timeout 1ms exceeded" in exc_info.value.message assert server.PREFIX + "/empty.html" in exc_info.value.message assert isinstance(exc_info.value, TimeoutError) async def test_goto_should_fail_when_exceeding_browser_context_timeout( page: Page, server: Server ) -> None: # Hang for request to the empty.html server.set_route("/empty.html", lambda request: None) page.context.set_default_timeout(2) with pytest.raises(Error) as exc_info: await page.goto(server.PREFIX + "/empty.html") assert "Timeout 2ms exceeded" in exc_info.value.message assert server.PREFIX + "/empty.html" in exc_info.value.message assert isinstance(exc_info.value, TimeoutError) async def test_goto_should_prioritize_default_navigation_timeout_over_default_timeout( page: Page, server: Server ) -> None: # Hang for request to the empty.html server.set_route("/empty.html", lambda request: None) page.set_default_timeout(0) page.set_default_navigation_timeout(1) with pytest.raises(Error) as exc_info: await page.goto(server.PREFIX + "/empty.html") assert "Timeout 1ms exceeded" in exc_info.value.message assert server.PREFIX + "/empty.html" in exc_info.value.message assert isinstance(exc_info.value, TimeoutError) async def test_goto_should_disable_timeout_when_its_set_to_0(page: Page, server: Server) -> None: loaded: List[bool] = [] page.once("load", lambda _: loaded.append(True)) await page.goto(server.PREFIX + "/grid.html", timeout=0, wait_until="load") assert loaded == [True] async def test_goto_should_work_when_navigating_to_valid_url(page: Page, server: Server) -> None: response = await page.goto(server.EMPTY_PAGE) assert response assert response.ok async def test_goto_should_work_when_navigating_to_data_url(page: Page, server: Server) -> None: response = await page.goto("data:text/html,hello") assert response is None async def test_goto_should_work_when_navigating_to_404(page: Page, server: Server) -> None: response = await page.goto(server.PREFIX + "/not-found") assert response assert response.ok is False assert response.status == 404 async def test_goto_should_return_last_response_in_redirect_chain( page: Page, server: Server ) -> None: server.set_redirect("/redirect/1.html", "/redirect/2.html") server.set_redirect("/redirect/2.html", "/redirect/3.html") server.set_redirect("/redirect/3.html", server.EMPTY_PAGE) response = await page.goto(server.PREFIX + "/redirect/1.html") assert response assert response.ok assert response.url == server.EMPTY_PAGE async def test_goto_should_navigate_to_data_url_and_not_fire_dataURL_requests( page: Page, server: Server ) -> None: requests = [] page.on("request", lambda request: requests.append(request)) dataURL = "data:text/html,
yo
" response = await page.goto(dataURL) assert response is None assert requests == [] async def test_goto_should_navigate_to_url_with_hash_and_fire_requests_without_hash( page: Page, server: Server ) -> None: requests = [] page.on("request", lambda request: requests.append(request)) response = await page.goto(server.EMPTY_PAGE + "#hash") assert response assert response.status == 200 assert response.url == server.EMPTY_PAGE assert len(requests) == 1 assert requests[0].url == server.EMPTY_PAGE async def test_goto_should_work_with_self_requesting_page(page: Page, server: Server) -> None: response = await page.goto(server.PREFIX + "/self-request.html") assert response assert response.status == 200 assert "self-request.html" in response.url async def test_goto_should_fail_when_navigating_and_show_the_url_at_the_error_message( page: Page, https_server: Server ) -> None: url = https_server.PREFIX + "/redirect/1.html" with pytest.raises(Error) as exc_info: await page.goto(url) assert url in exc_info.value.message async def test_goto_should_be_able_to_navigate_to_a_page_controlled_by_service_worker( page: Page, server: Server ) -> None: await page.goto(server.PREFIX + "/serviceworkers/fetch/sw.html") await page.evaluate("window.activationPromise") await page.goto(server.PREFIX + "/serviceworkers/fetch/sw.html") async def test_goto_should_send_referer(page: Page, server: Server) -> None: [request1, request2, _] = await asyncio.gather( server.wait_for_request("/grid.html"), server.wait_for_request("/digits/1.png"), page.goto(server.PREFIX + "/grid.html", referer="http://google.com/"), ) assert request1.getHeader("referer") == "http://google.com/" # Make sure subresources do not inherit referer. assert request2.getHeader("referer") == server.PREFIX + "/grid.html" assert page.url == server.PREFIX + "/grid.html" async def test_goto_should_reject_referer_option_when_set_extra_http_headers_provides_referer( page: Page, server: Server ) -> None: await page.set_extra_http_headers({"referer": "http://microsoft.com/"}) with pytest.raises(Error) as exc_info: await page.goto(server.PREFIX + "/grid.html", referer="http://google.com/") assert '"referer" is already specified as extra HTTP header' in exc_info.value.message assert server.PREFIX + "/grid.html" in exc_info.value.message async def test_goto_should_work_with_commit(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE, wait_until="commit") assert page.url == server.EMPTY_PAGE async def test_network_idle_should_navigate_to_empty_page_with_networkidle( page: Page, server: Server ) -> None: response = await page.goto(server.EMPTY_PAGE, wait_until="networkidle") assert response assert response.status == 200 async def test_wait_for_nav_should_work(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) async with page.expect_navigation() as response_info: await page.evaluate("url => window.location.href = url", server.PREFIX + "/grid.html") response = await response_info.value assert response.ok assert "grid.html" in response.url async def test_wait_for_nav_should_respect_timeout(page: Page, server: Server) -> None: with pytest.raises(Error) as exc_info: async with page.expect_navigation(url="**/frame.html", timeout=2500): await page.goto(server.EMPTY_PAGE) assert "Timeout 2500ms exceeded" in exc_info.value.message async def test_wait_for_nav_should_work_with_both_domcontentloaded_and_load( page: Page, server: Server ) -> None: async with page.expect_navigation(wait_until="domcontentloaded"), page.expect_navigation( wait_until="load" ): await page.goto(server.PREFIX + "/one-style.html") async def test_wait_for_nav_should_work_with_clicking_on_anchor_links( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) await page.set_content('foobar') async with page.expect_navigation() as response_info: await page.click("a") response = await response_info.value assert response is None assert page.url == server.EMPTY_PAGE + "#foobar" async def test_wait_for_nav_should_work_with_clicking_on_links_which_do_not_commit_navigation( page: Page, server: Server, https_server: Server, browser_name: str ) -> None: await page.goto(server.EMPTY_PAGE) await page.set_content(f"foobar") with pytest.raises(Error) as exc_info: async with page.expect_navigation(): await page.click("a") expect_ssl_error(exc_info.value.message, browser_name) async def test_wait_for_nav_should_work_with_history_push_state(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) await page.set_content( """ SPA """ ) async with page.expect_navigation() as response_info: await page.click("a") response = await response_info.value assert response is None assert page.url == server.PREFIX + "/wow.html" async def test_wait_for_nav_should_work_with_history_replace_state( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) await page.set_content( """ SPA """ ) async with page.expect_navigation() as response_info: await page.click("a") response = await response_info.value assert response is None assert page.url == server.PREFIX + "/replaced.html" async def test_wait_for_nav_should_work_with_dom_history_back_forward( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) await page.set_content( """ back forward """ ) assert page.url == server.PREFIX + "/second.html" async with page.expect_navigation() as back_response_info: await page.click("a#back") back_response = await back_response_info.value assert back_response is None assert page.url == server.PREFIX + "/first.html" async with page.expect_navigation() as forward_response_info: await page.click("a#forward") forward_response = await forward_response_info.value assert forward_response is None assert page.url == server.PREFIX + "/second.html" @pytest.mark.skip_browser("webkit") # WebKit issues load event in some cases, but not always async def test_wait_for_nav_should_work_when_subframe_issues_window_stop( page: Page, server: Server, is_webkit: bool ) -> None: server.set_route("/frames/style.css", lambda _: None) done = False async def nav_and_mark_done() -> None: nonlocal done await page.goto(server.PREFIX + "/frames/one-frame.html") done = True task = asyncio.create_task(nav_and_mark_done()) await asyncio.sleep(0) async with page.expect_event("frameattached") as frame_info: pass frame = await frame_info.value async with page.expect_event("framenavigated", lambda f: f == frame): pass await frame.evaluate("() => window.stop()") await page.wait_for_timeout(2000) # give it some time to erroneously resolve assert done == (not is_webkit) # Chromium and Firefox issue load event in this case. if is_webkit: task.cancel() async def test_wait_for_nav_should_work_with_url_match(page: Page, server: Server) -> None: responses: List[Optional[Response]] = [None, None, None] async def wait_for_nav(url: Any, index: int) -> None: async with page.expect_navigation(url=url) as response_info: pass responses[index] = await response_info.value response0_promise = asyncio.create_task(wait_for_nav(re.compile(r"one-style\.html"), 0)) response1_promise = asyncio.create_task(wait_for_nav(re.compile(r"\/frame.html"), 1)) response2_promise = asyncio.create_task(wait_for_nav(lambda url: "foo=bar" in url, 2)) assert responses == [None, None, None] await page.goto(server.EMPTY_PAGE) assert responses == [None, None, None] await page.goto(server.PREFIX + "/frame.html") assert responses[0] is None await response1_promise assert responses[1] is not None assert responses[2] is None await page.goto(server.PREFIX + "/one-style.html") await response0_promise assert responses[0] is not None assert responses[1] is not None assert responses[2] is None await page.goto(server.PREFIX + "/frame.html?foo=bar") await response2_promise assert responses[0] is not None assert responses[1] is not None assert responses[2] is not None await page.goto(server.PREFIX + "/empty.html") assert responses[0].url == server.PREFIX + "/one-style.html" assert responses[1].url == server.PREFIX + "/frame.html" assert responses[2].url == server.PREFIX + "/frame.html?foo=bar" async def test_wait_for_nav_should_work_with_url_match_for_same_document_navigations( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) async with page.expect_navigation(url=re.compile(r"third\.html")) as response_info: assert not response_info.is_done() await page.evaluate("history.pushState({}, '', '/first.html')") assert not response_info.is_done() await page.evaluate("history.pushState({}, '', '/second.html')") assert not response_info.is_done() await page.evaluate("history.pushState({}, '', '/third.html')") assert response_info.is_done() async def test_wait_for_nav_should_work_for_cross_process_navigations( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) url = server.CROSS_PROCESS_PREFIX + "/empty.html" async with page.expect_navigation(wait_until="domcontentloaded") as response_info: await page.goto(url) response = await response_info.value assert response.url == url assert page.url == url assert await page.evaluate("document.location.href") == url async def test_expect_navigation_should_work_for_cross_process_navigations( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) url = server.CROSS_PROCESS_PREFIX + "/empty.html" async with page.expect_navigation(wait_until="domcontentloaded") as response_info: goto_task = asyncio.create_task(page.goto(url)) response = await response_info.value assert response.url == url assert page.url == url assert await page.evaluate("document.location.href") == url await goto_task async def test_wait_for_nav_should_work_with_commit(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) async with page.expect_navigation(wait_until="commit") as response_info: await page.evaluate("url => window.location.href = url", server.PREFIX + "/grid.html") response = await response_info.value assert response.ok assert "grid.html" in response.url async def test_wait_for_load_state_should_respect_timeout(page: Page, server: Server) -> None: requests = [] def handler(request: Any) -> None: requests.append(request) server.set_route("/one-style.css", handler) await page.goto(server.PREFIX + "/one-style.html", wait_until="domcontentloaded") with pytest.raises(Error) as exc_info: await page.wait_for_load_state("load", timeout=1) assert "Timeout 1ms exceeded." in exc_info.value.message async def test_wait_for_load_state_should_resolve_immediately_if_loaded( page: Page, server: Server ) -> None: await page.goto(server.PREFIX + "/one-style.html") await page.wait_for_load_state() async def test_wait_for_load_state_should_throw_for_bad_state(page: Page, server: Server) -> None: await page.goto(server.PREFIX + "/one-style.html") with pytest.raises(Error) as exc_info: await page.wait_for_load_state("bad") # type: ignore assert ( "state: expected one of (load|domcontentloaded|networkidle|commit)" in exc_info.value.message ) async def test_wait_for_load_state_should_resolve_immediately_if_load_state_matches( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) requests = [] def handler(request: Any) -> None: requests.append(request) server.set_route("/one-style.css", handler) await page.goto(server.PREFIX + "/one-style.html", wait_until="domcontentloaded") await page.wait_for_load_state("domcontentloaded") async def test_wait_for_load_state_networkidle(page: Page, server: Server) -> None: wait_for_network_idle_future = asyncio.create_task(page.wait_for_load_state("networkidle")) await page.goto(server.PREFIX + "/networkidle.html") await wait_for_network_idle_future async def test_wait_for_load_state_should_work_with_pages_that_have_loaded_before_being_connected_to( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) async with page.expect_popup() as popup_info: await page.evaluate("window._popup = window.open(document.location.href)") # The url is about:blank in FF. popup = await popup_info.value assert popup.url == server.EMPTY_PAGE await popup.wait_for_load_state() assert popup.url == server.EMPTY_PAGE async def test_wait_for_load_state_should_wait_for_load_state_of_empty_url_popup( page: Page, is_firefox: bool ) -> None: ready_state = [] async with page.expect_popup() as popup_info: ready_state.append( await page.evaluate( """() => { popup = window.open('') return popup.document.readyState }""" ) ) popup = await popup_info.value await popup.wait_for_load_state() assert ready_state == ["uninitialized"] if is_firefox else ["complete"] assert await popup.evaluate("() => document.readyState") == ready_state[0] async def test_wait_for_load_state_should_wait_for_load_state_of_about_blank_popup_( page: Page, ) -> None: async with page.expect_popup() as popup_info: await page.evaluate("window.open('about:blank') && 1") popup = await popup_info.value await popup.wait_for_load_state() assert await popup.evaluate("document.readyState") == "complete" async def test_wait_for_load_state_should_wait_for_load_state_of_about_blank_popup_with_noopener( page: Page, ) -> None: async with page.expect_popup() as popup_info: await page.evaluate("window.open('about:blank', null, 'noopener') && 1") popup = await popup_info.value await popup.wait_for_load_state() assert await popup.evaluate("document.readyState") == "complete" async def test_wait_for_load_state_should_wait_for_load_state_of_popup_with_network_url_( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) async with page.expect_popup() as popup_info: await page.evaluate("url => window.open(url) && 1", server.EMPTY_PAGE) popup = await popup_info.value await popup.wait_for_load_state() assert await popup.evaluate("document.readyState") == "complete" async def test_wait_for_load_state_should_wait_for_load_state_of_popup_with_network_url_and_noopener_( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) async with page.expect_popup() as popup_info: await page.evaluate("url => window.open(url, null, 'noopener') && 1", server.EMPTY_PAGE) popup = await popup_info.value await popup.wait_for_load_state() assert await popup.evaluate("document.readyState") == "complete" async def test_wait_for_load_state_should_work_with_clicking_target__blank( page: Page, server: Server ) -> None: await page.goto(server.EMPTY_PAGE) await page.set_content('yo') async with page.expect_popup() as popup_info: await page.click("a") popup = await popup_info.value await popup.wait_for_load_state() assert await popup.evaluate("document.readyState") == "complete" async def test_wait_for_load_state_should_wait_for_load_state_of_new_page( context: BrowserContext, ) -> None: async with context.expect_page() as page_info: await context.new_page() new_page = await page_info.value await new_page.wait_for_load_state() assert await new_page.evaluate("document.readyState") == "complete" async def test_wait_for_load_state_in_popup(context: BrowserContext, server: Server) -> None: page = await context.new_page() await page.goto(server.EMPTY_PAGE) css_requests = [] def handle_request(request: TestServerRequest) -> None: css_requests.append(request) request.write(b"body {}") request.finish() server.set_route("/one-style.css", handle_request) async with page.expect_popup() as popup_info: await page.evaluate( "url => window.popup = window.open(url)", server.PREFIX + "/one-style.html" ) popup = await popup_info.value await popup.wait_for_load_state() assert len(css_requests) async def test_go_back_should_work(page: Page, server: Server) -> None: assert await page.go_back() is None await page.goto(server.EMPTY_PAGE) await page.goto(server.PREFIX + "/grid.html") response = await page.go_back() assert response assert response.ok assert server.EMPTY_PAGE in response.url response = await page.go_forward() assert response assert response.ok assert "/grid.html" in response.url response = await page.go_forward() assert response is None async def test_go_back_should_work_with_history_api(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) await page.evaluate( """() => { history.pushState({}, '', '/first.html') history.pushState({}, '', '/second.html') }""" ) assert page.url == server.PREFIX + "/second.html" await page.go_back() assert page.url == server.PREFIX + "/first.html" await page.go_back() assert page.url == server.EMPTY_PAGE await page.go_forward() assert page.url == server.PREFIX + "/first.html" async def test_frame_goto_should_navigate_subframes(page: Page, server: Server) -> None: await page.goto(server.PREFIX + "/frames/one-frame.html") assert "/frames/one-frame.html" in page.frames[0].url assert "/frames/frame.html" in page.frames[1].url response = await page.frames[1].goto(server.EMPTY_PAGE) assert response assert response.ok assert response.frame == page.frames[1] async def test_frame_goto_should_reject_when_frame_detaches( page: Page, server: Server, browser_name: str ) -> None: await page.goto(server.PREFIX + "/frames/one-frame.html") server.set_route("/one-style.css", lambda _: None) wait_for_request_task = asyncio.create_task(server.wait_for_request("/one-style.css")) navigation_task = asyncio.create_task(page.frames[1].goto(server.PREFIX + "/one-style.html")) await wait_for_request_task await page.eval_on_selector("iframe", "frame => frame.remove()") with pytest.raises(Error) as exc_info: await navigation_task if browser_name == "chromium": assert "net::ERR_FAILED" in exc_info.value.message or ( "frame was detached" in exc_info.value.message.lower() ) else: assert "frame was detached" in exc_info.value.message.lower() async def test_frame_goto_should_continue_after_client_redirect(page: Page, server: Server) -> None: server.set_route("/frames/script.js", lambda _: None) url = server.PREFIX + "/frames/child-redirect.html" with pytest.raises(Error) as exc_info: await page.goto(url, timeout=5000, wait_until="networkidle") assert "Timeout 5000ms exceeded." in exc_info.value.message assert f'navigating to "{url}", waiting until "networkidle"' in exc_info.value.message async def test_frame_wait_for_nav_should_work(page: Page, server: Server) -> None: await page.goto(server.PREFIX + "/frames/one-frame.html") frame = page.frames[1] async with frame.expect_navigation() as response_info: await frame.evaluate("url => window.location.href = url", server.PREFIX + "/grid.html") response = await response_info.value assert response.ok assert "grid.html" in response.url assert response.frame == frame assert "/frames/one-frame.html" in page.url async def test_frame_wait_for_nav_should_fail_when_frame_detaches( page: Page, server: Server ) -> None: await page.goto(server.PREFIX + "/frames/one-frame.html") frame = page.frames[1] server.set_route("/empty.html", lambda _: None) server.set_route("/one-style.css", lambda _: None) with pytest.raises(Error) as exc_info: async with frame.expect_navigation(): async def after_it() -> None: await server.wait_for_request("/one-style.html") await page.eval_on_selector( "iframe", "frame => setTimeout(() => frame.remove(), 0)" ) await asyncio.gather( page.eval_on_selector( "iframe", "frame => frame.contentWindow.location.href = '/one-style.html'", ), after_it(), ) assert "frame was detached" in exc_info.value.message async def test_frame_wait_for_load_state_should_work(page: Page, server: Server) -> None: await page.goto(server.PREFIX + "/frames/one-frame.html") frame = page.frames[1] request_future: "asyncio.Future[Route]" = asyncio.Future() await page.route( server.PREFIX + "/one-style.css", lambda route, request: request_future.set_result(route), ) await frame.goto(server.PREFIX + "/one-style.html", wait_until="domcontentloaded") request = await request_future load_task = asyncio.create_task(frame.wait_for_load_state()) # give the promise a chance to resolve, even though it shouldn't await page.evaluate("1") assert not load_task.done() asyncio.create_task(request.continue_()) await load_task async def test_reload_should_work(page: Page, server: Server) -> None: await page.goto(server.EMPTY_PAGE) await page.evaluate("window._foo = 10") await page.reload() assert await page.evaluate("window._foo") is None async def test_reload_should_work_with_data_url(page: Page, server: Server) -> None: await page.goto("data:text/html,hello") assert "hello" in await page.content() assert await page.reload() is None assert "hello" in await page.content() async def test_should_work_with__blank_target(page: Page, server: Server) -> None: def handler(request: TestServerRequest) -> None: request.write(f'Click me'.encode()) request.finish() server.set_route("/empty.html", handler) await page.goto(server.EMPTY_PAGE) await page.click('"Click me"') async def test_should_work_with_cross_process__blank_target(page: Page, server: Server) -> None: def handler(request: TestServerRequest) -> None: request.write( f'Click me'.encode() ) request.finish() server.set_route("/empty.html", handler) await page.goto(server.EMPTY_PAGE) await page.click('"Click me"') def expect_ssl_error(error_message: str, browser_name: str) -> None: if browser_name == "chromium": assert "net::ERR_CERT_AUTHORITY_INVALID" in error_message elif browser_name == "webkit": if sys.platform == "darwin": assert "The certificate for this server is invalid" in error_message elif sys.platform == "win32": assert "SSL peer certificate or SSH remote key was not OK" in error_message else: assert "Unacceptable TLS certificate" in error_message else: assert "SSL_ERROR_UNKNOWN" in error_message