Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions playwright/_impl/_browser_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,15 @@ def handle_transport_close(reason: Optional[str]) -> None:
for page in context.pages:
page._on_close()
context._on_close()
browser._on_close()
connection.cleanup(reason)
# TODO: Backport https://github.com/microsoft/playwright/commit/d8d5289e8692c9b1265d23ee66988d1ac5122f33
# Give a chance to any API call promises to reject upon page/context closure.
# This happens naturally when we receive page.onClose and browser.onClose from the server
# in separate tasks. However, upon pipe closure we used to dispatch them all synchronously
# here and promises did not have a chance to reject.
# The order of rejects vs closure is a part of the API contract and our test runner
# relies on it to attribute rejections to the right test.
if browser:
connection._loop.call_soon(browser._on_close)

transport.once("close", handle_transport_close)

Expand Down
51 changes: 51 additions & 0 deletions tests/async/test_browsertype_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,57 @@ async def test_browser_type_connect_should_reject_navigation_when_browser_closes
assert "has been closed" in exc_info.value.message


async def test_browser_type_connect_should_reject_wait_for_event_before_browser_close_finishes(
browser_type: BrowserType, launch_server: Callable[[], RemoteServer]
) -> None:
remote_server = launch_server()
browser = await browser_type.connect(remote_server.ws_endpoint)
page = await browser.new_page()

rejected = False

async def wait_for_download() -> None:
nonlocal rejected
try:
await page.wait_for_event("download")
except Error:
rejected = True

wait_task = asyncio.create_task(wait_for_download())
await asyncio.sleep(0)

await browser.close()
assert rejected is True
await wait_task


async def test_browser_type_connect_should_reject_wait_for_event_before_disconnected(
browser_type: BrowserType, launch_server: Callable[[], RemoteServer]
) -> None:
remote_server = launch_server()
browser = await browser_type.connect(remote_server.ws_endpoint)
page = await browser.new_page()
log = []

async def wait_for_download() -> None:
try:
await page.wait_for_event("download")
except Error:
log.append("rejected")

wait_task = asyncio.create_task(wait_for_download())
await asyncio.sleep(0)
browser.on("disconnected", lambda _: log.append("disconnected"))

remote_server.kill()
await wait_task
for _ in range(10):
if len(log) == 2:
break
await asyncio.sleep(0.1)
assert log == ["rejected", "disconnected"]


async def test_should_not_allow_getting_the_path(
browser_type: BrowserType, launch_server: Callable[[], RemoteServer], server: Server
) -> None:
Expand Down
Loading