321 lines
10 KiB
Python
321 lines
10 KiB
Python
# 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
|
|
from typing import Optional
|
|
|
|
import pytest
|
|
|
|
from playwright.async_api import BrowserContext, Page
|
|
from tests.utils import must
|
|
|
|
from ..server import Server, TestServerRequest
|
|
|
|
|
|
async def test_console_event_should_work(page: Page) -> None:
|
|
[message, _] = await asyncio.gather(
|
|
page.context.wait_for_event("console"),
|
|
page.evaluate("() => console.log('hello')"),
|
|
)
|
|
assert message.text == "hello"
|
|
assert message.page == page
|
|
|
|
|
|
async def test_console_event_should_work_in_popup(page: Page) -> None:
|
|
[message, popup, _] = await asyncio.gather(
|
|
page.context.wait_for_event("console"),
|
|
page.wait_for_event("popup"),
|
|
page.evaluate(
|
|
"""() => {
|
|
const win = window.open('');
|
|
win.console.log('hello');
|
|
}"""
|
|
),
|
|
)
|
|
assert message.text == "hello"
|
|
assert message.page == popup
|
|
|
|
|
|
# console message from javascript: url is not reported at all
|
|
@pytest.mark.skip_browser("firefox")
|
|
async def test_console_event_should_work_in_popup_2(
|
|
page: Page, browser_name: str
|
|
) -> None:
|
|
[message, popup, _] = await asyncio.gather(
|
|
page.context.wait_for_event("console", lambda msg: msg.type == "log"),
|
|
page.context.wait_for_event("page"),
|
|
page.evaluate(
|
|
"""async () => {
|
|
const win = window.open('javascript:console.log("hello")');
|
|
await new Promise(f => setTimeout(f, 0));
|
|
win.close();
|
|
}"""
|
|
),
|
|
)
|
|
assert message.text == "hello"
|
|
assert message.page == popup
|
|
|
|
|
|
# console message from javascript: url is not reported at all
|
|
@pytest.mark.skip_browser("firefox")
|
|
async def test_console_event_should_work_in_immediately_closed_popup(
|
|
page: Page, browser_name: str
|
|
) -> None:
|
|
[message, popup, _] = await asyncio.gather(
|
|
page.context.wait_for_event("console"),
|
|
page.wait_for_event("popup"),
|
|
page.evaluate(
|
|
"""async () => {
|
|
const win = window.open();
|
|
win.console.log('hello');
|
|
win.close();
|
|
}"""
|
|
),
|
|
)
|
|
assert message.text == "hello"
|
|
assert message.page == popup
|
|
|
|
|
|
async def test_dialog_event_should_work1(page: Page) -> None:
|
|
prompt_task: Optional[asyncio.Future[str]] = None
|
|
|
|
async def open_dialog() -> None:
|
|
nonlocal prompt_task
|
|
prompt_task = asyncio.create_task(page.evaluate("() => prompt('hey?')"))
|
|
|
|
[dialog1, dialog2, _] = await asyncio.gather(
|
|
page.context.wait_for_event("dialog"),
|
|
page.wait_for_event("dialog"),
|
|
open_dialog(),
|
|
)
|
|
assert dialog1 == dialog2
|
|
assert dialog1.message == "hey?"
|
|
assert dialog1.page == page
|
|
await dialog1.accept("hello")
|
|
assert await must(prompt_task) == "hello"
|
|
|
|
|
|
async def test_dialog_event_should_work_in_popup(page: Page) -> None:
|
|
prompt_task: Optional[asyncio.Future[str]] = None
|
|
|
|
async def open_dialog() -> None:
|
|
nonlocal prompt_task
|
|
prompt_task = asyncio.create_task(
|
|
page.evaluate("() => window.open('').prompt('hey?')")
|
|
)
|
|
|
|
[dialog, popup, _] = await asyncio.gather(
|
|
page.context.wait_for_event("dialog"),
|
|
page.wait_for_event("popup"),
|
|
open_dialog(),
|
|
)
|
|
assert dialog.message == "hey?"
|
|
assert dialog.page == popup
|
|
await dialog.accept("hello")
|
|
assert await must(prompt_task) == "hello"
|
|
|
|
|
|
# console message from javascript: url is not reported at all
|
|
@pytest.mark.skip_browser("firefox")
|
|
async def test_dialog_event_should_work_in_popup_2(
|
|
page: Page, browser_name: str
|
|
) -> None:
|
|
promise = asyncio.create_task(
|
|
page.evaluate("() => window.open('javascript:prompt(\"hey?\")')")
|
|
)
|
|
dialog = await page.context.wait_for_event("dialog")
|
|
assert dialog.message == "hey?"
|
|
assert dialog.page is None
|
|
await dialog.accept("hello")
|
|
await promise
|
|
|
|
|
|
# console message from javascript: url is not reported at all
|
|
@pytest.mark.skip_browser("firefox")
|
|
async def test_dialog_event_should_work_in_immdiately_closed_popup(page: Page) -> None:
|
|
[message, popup, _] = await asyncio.gather(
|
|
page.context.wait_for_event("console"),
|
|
page.wait_for_event("popup"),
|
|
page.evaluate(
|
|
"""() => {
|
|
const win = window.open();
|
|
win.console.log('hello');
|
|
win.close();
|
|
}"""
|
|
),
|
|
)
|
|
assert message.text == "hello"
|
|
assert message.page == popup
|
|
|
|
|
|
async 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"""<script>window.result = prompt('hey?')</script>""")
|
|
request.finish()
|
|
|
|
server.set_route("/popup.html", handle_route)
|
|
await page.goto(server.EMPTY_PAGE)
|
|
await page.set_content("<a href='popup.html' target=_blank>Click me</a>")
|
|
|
|
promise = asyncio.create_task(page.click("a"))
|
|
[dialog, popup] = await asyncio.gather(
|
|
page.context.wait_for_event("dialog"),
|
|
page.wait_for_event("popup"),
|
|
)
|
|
|
|
assert dialog.message == "hey?"
|
|
assert dialog.page == popup
|
|
await dialog.accept("hello")
|
|
await promise
|
|
assert await popup.evaluate("window.result") == "hello"
|
|
|
|
|
|
async def test_console_event_should_work_with_context_manager(page: Page) -> None:
|
|
async with page.context.expect_console_message() as cm_info:
|
|
await page.evaluate("() => console.log('hello')")
|
|
message = await cm_info.value
|
|
assert message.text == "hello"
|
|
assert message.page == page
|
|
|
|
|
|
async def test_page_error_event_should_work(page: Page) -> None:
|
|
async with page.context.expect_event("weberror") as page_error_info:
|
|
await page.set_content('<script>throw new Error("boom")</script>')
|
|
page_error = await page_error_info.value
|
|
assert page_error.page == page
|
|
assert page_error.error.stack and "boom" in page_error.error.stack
|
|
|
|
|
|
async def test_weberror_event_should_work(context: BrowserContext, page: Page) -> None:
|
|
async with context.expect_event("weberror") as error_info:
|
|
await page.goto('data:text/html,<script>throw new Error("Test")</script>')
|
|
error = await error_info.value
|
|
assert error.page == page
|
|
assert error.error.message == "Test"
|
|
|
|
|
|
async 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'<script src="/error.js"></script>')
|
|
request.finish()
|
|
|
|
server.set_route("/error.js", handle_error_js)
|
|
server.set_route("/error.html", handle_error_html)
|
|
|
|
async with context.expect_event("weberror") as error_info:
|
|
await page.goto(server.PREFIX + "/error.html")
|
|
web_error = await error_info.value
|
|
location = web_error.location
|
|
assert location["url"] == f"{server.PREFIX}/error.js"
|
|
assert location["line"] == 2
|
|
assert location["column"] > 0
|
|
|
|
|
|
async def test_pageload_event_should_work(
|
|
context: BrowserContext, page: Page, server: Server
|
|
) -> None:
|
|
async with context.expect_event("pageload") as info:
|
|
await page.goto(server.EMPTY_PAGE)
|
|
event_page = await info.value
|
|
assert event_page == page
|
|
|
|
|
|
async def test_framenavigated_event_should_work(
|
|
context: BrowserContext, page: Page, server: Server
|
|
) -> None:
|
|
async with context.expect_event("framenavigated") as info:
|
|
await page.goto(server.EMPTY_PAGE)
|
|
frame = await info.value
|
|
assert frame == page.main_frame
|
|
assert frame.url == server.EMPTY_PAGE
|
|
|
|
|
|
async def test_pageclose_event_should_work(context: BrowserContext) -> None:
|
|
page = await context.new_page()
|
|
async with context.expect_event("pageclose") as info:
|
|
await page.close()
|
|
closed = await info.value
|
|
assert closed == page
|
|
|
|
|
|
async def test_frameattached_event_should_work(
|
|
context: BrowserContext, page: Page, server: Server
|
|
) -> None:
|
|
await page.goto(server.EMPTY_PAGE)
|
|
async with context.expect_event("frameattached") as info:
|
|
await page.evaluate(
|
|
"""() => {
|
|
const iframe = document.createElement('iframe');
|
|
iframe.src = 'about:blank';
|
|
document.body.appendChild(iframe);
|
|
}"""
|
|
)
|
|
frame = await info.value
|
|
assert frame.parent_frame == page.main_frame
|
|
|
|
|
|
async def test_framedetached_event_should_work(
|
|
context: BrowserContext, page: Page, server: Server
|
|
) -> None:
|
|
await page.goto(server.EMPTY_PAGE)
|
|
await page.evaluate(
|
|
"""() => {
|
|
const iframe = document.createElement('iframe');
|
|
iframe.id = 'x';
|
|
iframe.src = 'about:blank';
|
|
document.body.appendChild(iframe);
|
|
}"""
|
|
)
|
|
await page.wait_for_selector("iframe")
|
|
async with context.expect_event("framedetached") as info:
|
|
await page.evaluate("() => document.getElementById('x').remove()")
|
|
frame = await info.value
|
|
assert frame.parent_frame == page.main_frame
|
|
|
|
|
|
async 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)
|
|
await page.set_content(f'<a href="{server.PREFIX}/download">download</a>')
|
|
async with context.expect_event("download") as info:
|
|
await page.click("a")
|
|
download = await info.value
|
|
assert download.suggested_filename == "file.txt"
|
|
assert download.page == page
|