# 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. from typing import Optional import pytest from playwright.sync_api import BrowserContext, Dialog, Page from ..server import Server, TestServerRequest def test_console_event_should_work(page: Page) -> None: with page.context.expect_console_message() as console_info: page.evaluate("() => console.log('hello')") message = console_info.value assert message.text == "hello" assert message.page == page def test_console_event_should_work_in_popup(page: Page) -> None: with page.context.expect_console_message() as console_info: with page.expect_popup() as popup_info: page.evaluate( """() => { const win = window.open(''); win.console.log('hello'); }""" ) message = console_info.value popup = popup_info.value assert message.text == "hello" assert message.page == popup # console message from javascript: url is not reported at all @pytest.mark.skip_browser("firefox") def test_console_event_should_work_in_popup_2(page: Page, browser_name: str) -> None: with page.context.expect_console_message( lambda msg: msg.type == "log" ) as console_info: with page.context.expect_page() as page_info: page.evaluate( """async () => { const win = window.open('javascript:console.log("hello")'); await new Promise(f => setTimeout(f, 0)); win.close(); }""" ) message = console_info.value popup = page_info.value assert message.text == "hello" assert message.page == popup # console message from javascript: url is not reported at all @pytest.mark.skip_browser("firefox") def test_console_event_should_work_in_immediately_closed_popup( page: Page, browser_name: str ) -> None: with page.context.expect_console_message( lambda msg: msg.type == "log" ) as console_info: with page.context.expect_page() as page_info: page.evaluate( """() => { const win = window.open(''); win.console.log('hello'); win.close(); }""" ) message = console_info.value popup = page_info.value assert message.text == "hello" assert message.page == popup def test_dialog_event_should_work1(page: Page) -> None: dialog1: Optional[Dialog] = None def handle_page_dialog(dialog: Dialog) -> None: nonlocal dialog1 dialog1 = dialog dialog.accept("hello") page.on("dialog", handle_page_dialog) dialog2: Optional[Dialog] = None def handle_context_dialog(dialog: Dialog) -> None: nonlocal dialog2 dialog2 = dialog page.context.on("dialog", handle_context_dialog) assert page.evaluate("() => prompt('hey?')") == "hello" assert dialog1 assert dialog1 == dialog2 assert dialog1.message == "hey?" assert dialog1.page == page def test_dialog_event_should_work_in_popup1(page: Page) -> None: dialog: Optional[Dialog] = None def handle_dialog(d: Dialog) -> None: nonlocal dialog dialog = d dialog.accept("hello") page.context.on("dialog", handle_dialog) with page.expect_popup() as popup_info: assert page.evaluate("() => window.open('').prompt('hey?')") == "hello" popup = popup_info.value assert dialog assert dialog.message == "hey?" assert dialog.page == popup # console message from javascript: url is not reported at all @pytest.mark.skip_browser("firefox") def test_dialog_event_should_work_in_popup_2(page: Page, browser_name: str) -> None: def handle_dialog(dialog: Dialog) -> None: assert dialog.message == "hey?" assert dialog.page is None dialog.accept("hello") page.context.on("dialog", handle_dialog) assert page.evaluate("() => window.open('javascript:prompt(\"hey?\")')") # console message from javascript: url is not reported at all @pytest.mark.skip_browser("firefox") def test_dialog_event_should_work_in_immdiately_closed_popup(page: Page) -> None: popup = None def handle_popup(p: Page) -> None: nonlocal popup popup = p page.on("popup", handle_popup) with page.context.expect_console_message() as console_info: page.evaluate( """() => { const win = window.open(); win.console.log('hello'); win.close(); }""" ) message = console_info.value assert message.text == "hello" assert message.page == popup def test_dialog_event_should_work_with_inline_script_tag( page: Page, server: Server ) -> None: def handle_route(request: TestServerRequest) -> None: request.setHeader("content-type", "text/html") request.write(b"") request.finish() server.set_route("/popup.html", handle_route) page.goto(server.EMPTY_PAGE) page.set_content("Click me") with ( page.context.expect_event("dialog") as dialog_info, page.expect_popup() as popup_info, ): page.click("a") dialog: Dialog = dialog_info.value popup: Page = popup_info.value assert dialog.message == "hey?" assert dialog.page == popup dialog.accept("hello") assert popup.evaluate("window.result") == "hello" def test_console_event_should_work_with_context_manager(page: Page) -> None: with page.context.expect_console_message() as cm_info: page.evaluate("() => console.log('hello')") message = cm_info.value assert message.text == "hello" assert message.page == page def test_weberror_event_should_work(context: BrowserContext, page: Page) -> None: with context.expect_event("weberror") as error_info: page.goto('data:text/html,') error = error_info.value assert error.page == page assert error.error.message == "Test" def test_weberror_event_should_include_location( context: BrowserContext, page: Page, server: Server ) -> None: def handle_error_js(request: TestServerRequest) -> None: request.setHeader("content-type", "application/javascript") request.write( b""" function foo() { throw new Error('boom'); } foo(); """ ) request.finish() def handle_error_html(request: TestServerRequest) -> None: request.setHeader("content-type", "text/html") request.write(b'') request.finish() server.set_route("/error.js", handle_error_js) server.set_route("/error.html", handle_error_html) with context.expect_event("weberror") as error_info: page.goto(server.PREFIX + "/error.html") web_error = error_info.value location = web_error.location assert location["url"] == f"{server.PREFIX}/error.js" assert location["line"] == 2 assert location["column"] > 0 def test_pageload_event_should_work( context: BrowserContext, page: Page, server: Server ) -> None: with context.expect_event("pageload") as info: page.goto(server.EMPTY_PAGE) assert info.value == page def test_framenavigated_event_should_work( context: BrowserContext, page: Page, server: Server ) -> None: with context.expect_event("framenavigated") as info: page.goto(server.EMPTY_PAGE) frame = info.value assert frame == page.main_frame assert frame.url == server.EMPTY_PAGE def test_pageclose_event_should_work(context: BrowserContext) -> None: page = context.new_page() with context.expect_event("pageclose") as info: page.close() assert info.value == page def test_frameattached_event_should_work( context: BrowserContext, page: Page, server: Server ) -> None: page.goto(server.EMPTY_PAGE) with context.expect_event("frameattached") as info: page.evaluate( """() => { const iframe = document.createElement('iframe'); iframe.src = 'about:blank'; document.body.appendChild(iframe); }""" ) assert info.value.parent_frame == page.main_frame def test_framedetached_event_should_work( context: BrowserContext, page: Page, server: Server ) -> None: page.goto(server.EMPTY_PAGE) page.evaluate( """() => { const iframe = document.createElement('iframe'); iframe.id = 'x'; iframe.src = 'about:blank'; document.body.appendChild(iframe); }""" ) page.wait_for_selector("iframe") with context.expect_event("framedetached") as info: page.evaluate("() => document.getElementById('x').remove()") assert info.value.parent_frame == page.main_frame def test_download_event_should_work( context: BrowserContext, page: Page, server: Server ) -> None: def handle_download(request: TestServerRequest) -> None: request.setHeader("Content-Type", "application/octet-stream") request.setHeader("Content-Disposition", "attachment; filename=file.txt") request.write(b"Hello world") request.finish() server.set_route("/download", handle_download) page.set_content(f'download') with context.expect_event("download") as info: page.click("a") download = info.value assert download.suggested_filename == "file.txt" assert download.page == page