Skip to content

fix: support async predicates in page.expect_request/expect_response#3055

Merged
Skn0tt merged 3 commits intomicrosoft:mainfrom
Skn0tt:fix/async-predicate-expect-event
Apr 30, 2026
Merged

fix: support async predicates in page.expect_request/expect_response#3055
Skn0tt merged 3 commits intomicrosoft:mainfrom
Skn0tt:fix/async-predicate-expect-event

Conversation

@Skn0tt
Copy link
Copy Markdown
Member

@Skn0tt Skn0tt commented Apr 30, 2026

Closes #1545.

Async predicates passed to page.expect_request / page.expect_response were called but never awaited, so the returned coroutine evaluated truthy and the first matching event resolved the wait (with a RuntimeWarning: coroutine '...' was never awaited).

  • Waiter now detects coroutine results from predicates and awaits them in a tracked task; exceptions from predicates reject the waiter instead of being silently swallowed by pyee.
  • The async API's predicate parameter type is widened to Callable[[T], Union[bool, Awaitable[bool]]]. The sync API keeps Callable[[T], bool] — codegen was extended with a SYNC_API flag that strips the Awaitable arm from both signatures and docstrings for the sync generator.
  • Two tests added in tests/async/test_page.py covering the success path and exception propagation.

Closes microsoft#1545

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Skn0tt Skn0tt requested a review from dgozman April 30, 2026 12:01
try:
result = predicate(event_data)
except Exception as e:
self._reject(e)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line a separate bugfix? I don't see where we would reject after a sync predicate throws before this PR. Perhaps add a test for this as well?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — yes, this is a coupled bugfix. Previously sync predicates that threw were silently swallowed by pyee's listener machinery, leaving the expect_* call to hang until timeout. Pushed a test (test_expect_response_should_reject_when_sync_predicate_throws) covering it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-checked against JS waiter.ts's waitForEvent (packages/playwright-core/src/client/waiter.ts:113-124) — JS already awaits predicates and rejects on either sync or async predicate exceptions (try/catch wraps await predicate(eventArg)). This PR brings Python to parity.

Skn0tt and others added 2 commits April 30, 2026 14:14
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…roval

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Skn0tt Skn0tt merged commit 797946e into microsoft:main Apr 30, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Question]: how can I access async response's body in the predicate?

2 participants