Skip to content

Commit 3e547e9

Browse files
committed
wip
1 parent 2dcd937 commit 3e547e9

4 files changed

Lines changed: 39 additions & 21 deletions

File tree

‎playwright/_impl/_greenlets.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,13 @@ def wait_for_future(
6868
) -> None:
6969
__tracebackhide__ = True
7070
g_self = greenlet.getcurrent()
71+
waiting = True
7172

7273
def resume(_: "asyncio.Future") -> None:
73-
g_self.switch()
74+
# asyncio runs the callback in a later loop iteration, also when the future
75+
# is done already. By then the wait may be over and this greenlet elsewhere.
76+
if waiting:
77+
g_self.switch()
7478

7579
# The wait owns the callback that resumes this greenlet, so that it can
7680
# remove it again when the wait is abandoned. A callback left behind would
@@ -92,6 +96,7 @@ def resume(_: "asyncio.Future") -> None:
9296
future.cancel()
9397
raise
9498
finally:
99+
waiting = False
95100
# The loop is only running for as long as the dispatcher fiber is alive.
96101
# Also after a signal handler interrupted it: run_forever() cleared this
97102
# on its way out, but the dispatcher is going to run the loop again.

‎tests/async/library/test_browsertype_connect.py‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,8 @@ async def test_BT_046_should_send_extra_headers_with_connect_request(
493493
kind: str,
494494
connect: Callable[..., Awaitable[Browser]],
495495
server: Server,
496-
server_web_sockets: List[WebSocketProtocol],
497496
) -> None:
498-
server.once_web_socket_connection(server_web_sockets.append)
497+
request_future = server.wait_for_web_socket_connection_request()
499498
with suppress(Error):
500499
await connect(
501500
f"ws://localhost:{server.PORT}/ws",
@@ -505,9 +504,9 @@ async def test_BT_046_should_send_extra_headers_with_connect_request(
505504
},
506505
timeout=100,
507506
)
508-
request = server_web_sockets[0].http_headers
509-
assert request["user-agent"] == "Playwright"
510-
assert request["foo"] == "bar"
507+
request = await request_future
508+
assert request.headers["user-agent"] == "Playwright"
509+
assert request.headers["foo"] == "bar"
511510

512511

513512
@pytest.mark.parametrize("kind", KINDS)

‎tests/sync/legacy/test_sync.py‎

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -304,26 +304,39 @@ def test_expect_response_should_not_hang_when_predicate_throws(page: Page) -> No
304304
raise Exception("Oops!")
305305

306306

307-
def test_expect_response_should_not_switch_to_stale_greenlet_when_cancelled(
307+
def test_expect_event_should_not_switch_to_stale_greenlet(
308308
page: Page, server: Server
309309
) -> None:
310310
# Mimics frameworks like pytest-twisted that run the test body in a separate
311311
# greenlet which stays alive (suspended) after handing control back.
312312
main = greenlet.getcurrent()
313-
resumed: List[bool] = []
314313

315-
def body() -> None:
314+
def expect_not_resumed(action: Callable[[], None]) -> None:
315+
resumed: List[bool] = []
316+
317+
def body() -> None:
318+
action()
319+
main.switch()
320+
resumed.append(True)
321+
main.switch()
322+
323+
greenlet(body).switch()
324+
# Pumps the dispatcher, which runs the done callbacks of the futures.
325+
page.goto(server.EMPTY_PAGE)
326+
assert resumed == []
327+
328+
def cancel_wait() -> None:
316329
with pytest.raises(Exception, match="Oops!"):
317330
with page.expect_response("**/*"):
318331
raise Exception("Oops!")
319-
main.switch()
320-
resumed.append(True)
321-
main.switch()
322332

323-
greenlet(body).switch()
324-
# Pumps the dispatcher, which runs the cancelled future's done callbacks.
325-
page.goto(server.EMPTY_PAGE)
326-
assert resumed == []
333+
def wait_for_done_future() -> None:
334+
with page.expect_console_message() as message_info:
335+
page.evaluate("console.log('hello')")
336+
assert message_info.value.text == "hello"
337+
338+
expect_not_resumed(cancel_wait)
339+
expect_not_resumed(wait_for_done_future)
327340

328341

329342
def test_expect_response_should_use_context_timeout(

‎tests/sync/library/test_browsertype_connect.py‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,11 +506,11 @@ def test_BT_045_should_timeout_in_connect_while_connecting(
506506
@pytest.mark.parametrize("kind", KINDS)
507507
def test_BT_046_should_send_extra_headers_with_connect_request(
508508
kind: str,
509+
playwright: Playwright,
509510
connect: Callable[..., Browser],
510511
server: Server,
511-
server_web_sockets: List[WebSocketProtocol],
512512
) -> None:
513-
server.once_web_socket_connection(server_web_sockets.append)
513+
request_future = server.wait_for_web_socket_connection_request()
514514
with suppress(Error):
515515
connect(
516516
f"ws://localhost:{server.PORT}/ws",
@@ -520,9 +520,10 @@ def test_BT_046_should_send_extra_headers_with_connect_request(
520520
},
521521
timeout=100,
522522
)
523-
request = server_web_sockets[0].http_headers
524-
assert request["user-agent"] == "Playwright"
525-
assert request["foo"] == "bar"
523+
wait_for_future(playwright._loop, playwright._dispatcher_fiber, request_future)
524+
request = request_future.result()
525+
assert request.headers["user-agent"] == "Playwright"
526+
assert request.headers["foo"] == "bar"
526527

527528

528529
@pytest.mark.parametrize("kind", KINDS)

0 commit comments

Comments
 (0)