diff --git a/playwright/_impl/_async_base.py b/playwright/_impl/_async_base.py
index 4d678f668..8c15f6944 100644
--- a/playwright/_impl/_async_base.py
+++ b/playwright/_impl/_async_base.py
@@ -15,7 +15,7 @@
import asyncio
import traceback
from types import TracebackType
-from typing import Any, Awaitable, Callable, Generic, Type, TypeVar, Union
+from typing import Any, Awaitable, Callable, Generic, Type, TypeVar
from playwright._impl._impl_to_api_mapping import ImplToApiMapping, ImplWrapper
@@ -73,19 +73,17 @@ def _wrap_handler(self, handler: Any) -> Callable[..., None]:
return mapping.wrap_handler(handler)
return handler
- def on(self, event: str, f: Callable[..., Union[Awaitable[None], None]]) -> None:
+ def on(self, event: Any, f: Any) -> None:
"""Registers the function ``f`` to the event name ``event``."""
self._impl_obj.on(event, self._wrap_handler(f))
- def once(self, event: str, f: Callable[..., Union[Awaitable[None], None]]) -> None:
+ def once(self, event: Any, f: Any) -> None:
"""The same as ``self.on``, except that the listener is automatically
removed after being called.
"""
self._impl_obj.once(event, self._wrap_handler(f))
- def remove_listener(
- self, event: str, f: Callable[..., Union[Awaitable[None], None]]
- ) -> None:
+ def remove_listener(self, event: Any, f: Any) -> None:
"""Removes the function ``f`` from ``event``."""
self._impl_obj.remove_listener(event, self._wrap_handler(f))
diff --git a/playwright/_impl/_sync_base.py b/playwright/_impl/_sync_base.py
index 4e0272420..93d0784f1 100644
--- a/playwright/_impl/_sync_base.py
+++ b/playwright/_impl/_sync_base.py
@@ -115,17 +115,17 @@ def _wrap_handler(self, handler: Any) -> Callable[..., None]:
return mapping.wrap_handler(handler)
return handler
- def on(self, event: str, f: Callable[..., None]) -> None:
+ def on(self, event: Any, f: Any) -> None:
"""Registers the function ``f`` to the event name ``event``."""
self._impl_obj.on(event, self._wrap_handler(f))
- def once(self, event: str, f: Callable[..., None]) -> None:
+ def once(self, event: Any, f: Any) -> None:
"""The same as ``self.on``, except that the listener is automatically
removed after being called.
"""
self._impl_obj.once(event, self._wrap_handler(f))
- def remove_listener(self, event: str, f: Callable[..., None]) -> None:
+ def remove_listener(self, event: Any, f: Any) -> None:
"""Removes the function ``f`` from ``event``."""
self._impl_obj.remove_listener(event, self._wrap_handler(f))
diff --git a/playwright/async_api/_generated.py b/playwright/async_api/_generated.py
index 2d45f1e0a..20097f446 100644
--- a/playwright/async_api/_generated.py
+++ b/playwright/async_api/_generated.py
@@ -40,6 +40,7 @@
StorageState,
ViewportSize,
)
+from playwright._impl._api_types import Error
from playwright._impl._async_base import (
AsyncBase,
AsyncContextManager,
@@ -693,6 +694,100 @@ async def handle(route, request):
class WebSocket(AsyncBase):
+ @typing.overload
+ def on(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[["WebSocket"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Fired when the websocket closes."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["framereceived"],
+ f: typing.Callable[
+ ["typing.Dict"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Fired when the websocket receives a frame."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["framesent"],
+ f: typing.Callable[
+ ["typing.Dict"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Fired when the websocket sends a frame."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["socketerror"],
+ f: typing.Callable[["str"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Fired when the websocket has an error."""
+
+ def on(
+ self,
+ event: str,
+ f: typing.Callable[..., typing.Union[typing.Awaitable[None], None]],
+ ) -> None:
+ return super().on(event=event, f=f)
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[["WebSocket"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Fired when the websocket closes."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["framereceived"],
+ f: typing.Callable[
+ ["typing.Dict"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Fired when the websocket receives a frame."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["framesent"],
+ f: typing.Callable[
+ ["typing.Dict"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Fired when the websocket sends a frame."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["socketerror"],
+ f: typing.Callable[["str"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Fired when the websocket has an error."""
+
+ def once(
+ self,
+ event: str,
+ f: typing.Callable[..., typing.Union[typing.Awaitable[None], None]],
+ ) -> None:
+ return super().once(event=event, f=f)
+
@property
def url(self) -> str:
"""WebSocket.url
@@ -5001,6 +5096,24 @@ async def set_checked(
class Worker(AsyncBase):
+ def on(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[["Worker"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is terminated."""
+ return super().on(event=event, f=f)
+
+ def once(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[["Worker"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is terminated."""
+ return super().once(event=event, f=f)
+
@property
def url(self) -> str:
"""Worker.url
@@ -5446,6 +5559,504 @@ async def delete(self) -> NoneType:
class Page(AsyncContextManager):
+ @typing.overload
+ def on(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the page closes."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["console"],
+ f: typing.Callable[
+ ["ConsoleMessage"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also
+ emitted if the page throws an error or a warning.
+
+ The arguments passed into `console.log` appear as arguments on the event handler.
+
+ An example of handling `console` event:
+
+ ```py
+ async def print_args(msg):
+ for arg in msg.args:
+ print(await arg.json_value())
+
+ page.on(\"console\", print_args)
+ await page.evaluate(\"console.log('hello', 5, {foo: 'bar'})\")
+ ```"""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["crash"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page crashes,
+ ongoing and subsequent operations will throw.
+
+ The most common way to deal with crashes is to catch an exception:
+
+ ```py
+ try:
+ # crash might happen during a click.
+ await page.click(\"button\")
+ # or while waiting for an event.
+ await page.wait_for_event(\"popup\")
+ except Error as e:
+ # when the page crashes, exception message contains \"crash\".
+ ```"""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["dialog"],
+ f: typing.Callable[["Dialog"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ either `dialog.accept()` or `dialog.dismiss()` the dialog - otherwise the page will
+ [freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking) waiting for the dialog, and
+ actions like click will never finish.
+
+ > NOTE: When no `page.on('dialog')` listeners are present, all dialogs are automatically dismissed."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["domcontentloaded"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the JavaScript [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded)
+ event is dispatched."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["download"],
+ f: typing.Callable[["Download"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when attachment download started. User can access basic file operations on downloaded content via the passed
+ `Download` instance.
+
+ > NOTE: Browser context **must** be created with the `acceptDownloads` set to `true` when user needs access to the
+ downloaded content. If `acceptDownloads` is not set, download events are emitted, but the actual download is not
+ performed and user has no access to the downloaded files."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["filechooser"],
+ f: typing.Callable[
+ ["FileChooser"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Emitted when a file chooser is supposed to appear, such as after clicking the ``. Playwright can
+ respond to it via setting the input files using `file_chooser.set_files()` that can be uploaded after that.
+
+ ```py
+ page.on(\"filechooser\", lambda file_chooser: file_chooser.set_files(\"/tmp/myfile.pdf\"))
+ ```"""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["frameattached"],
+ f: typing.Callable[["Frame"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a frame is attached."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["framedetached"],
+ f: typing.Callable[["Frame"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a frame is detached."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["framenavigated"],
+ f: typing.Callable[["Frame"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a frame is navigated to a new url."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["load"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/Web/Events/load) event is dispatched."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["pageerror"],
+ f: typing.Callable[["Error"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when an uncaught exception happens within the page."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["popup"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the page opens a new tab or window. This event is emitted in addition to the
+ `browser_context.on('page')`, but only for popups relevant to this page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ async with page.expect_event(\"popup\") as page_info:
+ page.evaluate(\"window.open('https://example.com')\")
+ popup = await page_info.value
+ print(await popup.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["request"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a page issues a request. The [request] object is read-only. In order to intercept and mutate requests, see
+ `page.route()` or `browser_context.route()`."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["requestfailed"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `page.on('request_finished')` event and not with `page.on('request_failed')`. A request will only be
+ considered failed when the client cannot get an HTTP response from the server, e.g. due to network error
+ net::ERR_FAILED."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["requestfinished"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["response"],
+ f: typing.Callable[["Response"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["websocket"],
+ f: typing.Callable[["WebSocket"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when `WebSocket` request is sent."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["worker"],
+ f: typing.Callable[["Worker"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is spawned by the
+ page."""
+
+ def on(
+ self,
+ event: str,
+ f: typing.Callable[..., typing.Union[typing.Awaitable[None], None]],
+ ) -> None:
+ return super().on(event=event, f=f)
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the page closes."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["console"],
+ f: typing.Callable[
+ ["ConsoleMessage"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also
+ emitted if the page throws an error or a warning.
+
+ The arguments passed into `console.log` appear as arguments on the event handler.
+
+ An example of handling `console` event:
+
+ ```py
+ async def print_args(msg):
+ for arg in msg.args:
+ print(await arg.json_value())
+
+ page.on(\"console\", print_args)
+ await page.evaluate(\"console.log('hello', 5, {foo: 'bar'})\")
+ ```"""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["crash"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page crashes,
+ ongoing and subsequent operations will throw.
+
+ The most common way to deal with crashes is to catch an exception:
+
+ ```py
+ try:
+ # crash might happen during a click.
+ await page.click(\"button\")
+ # or while waiting for an event.
+ await page.wait_for_event(\"popup\")
+ except Error as e:
+ # when the page crashes, exception message contains \"crash\".
+ ```"""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["dialog"],
+ f: typing.Callable[["Dialog"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ either `dialog.accept()` or `dialog.dismiss()` the dialog - otherwise the page will
+ [freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking) waiting for the dialog, and
+ actions like click will never finish.
+
+ > NOTE: When no `page.on('dialog')` listeners are present, all dialogs are automatically dismissed."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["domcontentloaded"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the JavaScript [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded)
+ event is dispatched."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["download"],
+ f: typing.Callable[["Download"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when attachment download started. User can access basic file operations on downloaded content via the passed
+ `Download` instance.
+
+ > NOTE: Browser context **must** be created with the `acceptDownloads` set to `true` when user needs access to the
+ downloaded content. If `acceptDownloads` is not set, download events are emitted, but the actual download is not
+ performed and user has no access to the downloaded files."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["filechooser"],
+ f: typing.Callable[
+ ["FileChooser"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Emitted when a file chooser is supposed to appear, such as after clicking the ``. Playwright can
+ respond to it via setting the input files using `file_chooser.set_files()` that can be uploaded after that.
+
+ ```py
+ page.on(\"filechooser\", lambda file_chooser: file_chooser.set_files(\"/tmp/myfile.pdf\"))
+ ```"""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["frameattached"],
+ f: typing.Callable[["Frame"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a frame is attached."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["framedetached"],
+ f: typing.Callable[["Frame"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a frame is detached."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["framenavigated"],
+ f: typing.Callable[["Frame"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a frame is navigated to a new url."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["load"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/Web/Events/load) event is dispatched."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["pageerror"],
+ f: typing.Callable[["Error"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when an uncaught exception happens within the page."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["popup"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when the page opens a new tab or window. This event is emitted in addition to the
+ `browser_context.on('page')`, but only for popups relevant to this page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ async with page.expect_event(\"popup\") as page_info:
+ page.evaluate(\"window.open('https://example.com')\")
+ popup = await page_info.value
+ print(await popup.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["request"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a page issues a request. The [request] object is read-only. In order to intercept and mutate requests, see
+ `page.route()` or `browser_context.route()`."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["requestfailed"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `page.on('request_finished')` event and not with `page.on('request_failed')`. A request will only be
+ considered failed when the client cannot get an HTTP response from the server, e.g. due to network error
+ net::ERR_FAILED."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["requestfinished"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["response"],
+ f: typing.Callable[["Response"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["websocket"],
+ f: typing.Callable[["WebSocket"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when `WebSocket` request is sent."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["worker"],
+ f: typing.Callable[["Worker"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is spawned by the
+ page."""
+
+ def once(
+ self,
+ event: str,
+ f: typing.Callable[..., typing.Union[typing.Awaitable[None], None]],
+ ) -> None:
+ return super().once(event=event, f=f)
+
@property
def accessibility(self) -> "Accessibility":
"""Page.accessibility
@@ -9015,6 +9626,242 @@ async def set_checked(
class BrowserContext(AsyncContextManager):
+ @typing.overload
+ def on(
+ self,
+ event: Literal["backgroundpage"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ > NOTE: Only works with Chromium browser's persistent context.
+
+ Emitted when new background page is created in the context.
+
+ ```py
+ background_page = await context.wait_for_event(\"backgroundpage\")
+ ```"""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[
+ ["BrowserContext"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Emitted when Browser context gets closed. This might happen because of one of the following:
+ - Browser context is closed.
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["page"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ The event is emitted when a new Page is created in the BrowserContext. The page may still be loading. The event will
+ also fire for popup pages. See also `page.on('popup')` to receive events about popups relevant to a specific page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ async with context.expect_page() as page_info:
+ await page.click(\"a[target=_blank]\"),
+ page = await page_info.value
+ print(await page.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["request"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To only
+ listen for requests from a particular page, use `page.on('request')`.
+
+ In order to intercept and mutate requests, see `browser_context.route()` or `page.route()`."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["requestfailed"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out. To only listen for failed requests from a particular page, use
+ `page.on('request_failed')`.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `browser_context.on('request_finished')` event and not with `browser_context.on('request_failed')`."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["requestfinished"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`. To listen for successful requests from a particular
+ page, use `page.on('request_finished')`."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["response"],
+ f: typing.Callable[["Response"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`. To listen for response events from a particular page, use
+ `page.on('response')`."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["serviceworker"],
+ f: typing.Callable[["Worker"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ > NOTE: Service workers are only supported on Chromium-based browsers.
+
+ Emitted when new service worker is created in the context."""
+
+ def on(
+ self,
+ event: str,
+ f: typing.Callable[..., typing.Union[typing.Awaitable[None], None]],
+ ) -> None:
+ return super().on(event=event, f=f)
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["backgroundpage"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ > NOTE: Only works with Chromium browser's persistent context.
+
+ Emitted when new background page is created in the context.
+
+ ```py
+ background_page = await context.wait_for_event(\"backgroundpage\")
+ ```"""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["close"],
+ f: typing.Callable[
+ ["BrowserContext"], "typing.Union[typing.Awaitable[None], None]"
+ ],
+ ) -> None:
+ """
+ Emitted when Browser context gets closed. This might happen because of one of the following:
+ - Browser context is closed.
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["page"],
+ f: typing.Callable[["Page"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ The event is emitted when a new Page is created in the BrowserContext. The page may still be loading. The event will
+ also fire for popup pages. See also `page.on('popup')` to receive events about popups relevant to a specific page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ async with context.expect_page() as page_info:
+ await page.click(\"a[target=_blank]\"),
+ page = await page_info.value
+ print(await page.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["request"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To only
+ listen for requests from a particular page, use `page.on('request')`.
+
+ In order to intercept and mutate requests, see `browser_context.route()` or `page.route()`."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["requestfailed"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out. To only listen for failed requests from a particular page, use
+ `page.on('request_failed')`.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `browser_context.on('request_finished')` event and not with `browser_context.on('request_failed')`."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["requestfinished"],
+ f: typing.Callable[["Request"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`. To listen for successful requests from a particular
+ page, use `page.on('request_finished')`."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["response"],
+ f: typing.Callable[["Response"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`. To listen for response events from a particular page, use
+ `page.on('response')`."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["serviceworker"],
+ f: typing.Callable[["Worker"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ > NOTE: Service workers are only supported on Chromium-based browsers.
+
+ Emitted when new service worker is created in the context."""
+
+ def once(
+ self,
+ event: str,
+ f: typing.Callable[..., typing.Union[typing.Awaitable[None], None]],
+ ) -> None:
+ return super().once(event=event, f=f)
+
@property
def pages(self) -> typing.List["Page"]:
"""BrowserContext.pages
@@ -9815,6 +10662,28 @@ async def detach(self) -> NoneType:
class Browser(AsyncContextManager):
+ def on(
+ self,
+ event: Literal["disconnected"],
+ f: typing.Callable[["Browser"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when Browser gets disconnected from the browser application. This might happen because of one of the following:
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+ return super().on(event=event, f=f)
+
+ def once(
+ self,
+ event: Literal["disconnected"],
+ f: typing.Callable[["Browser"], "typing.Union[typing.Awaitable[None], None]"],
+ ) -> None:
+ """
+ Emitted when Browser gets disconnected from the browser application. This might happen because of one of the following:
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+ return super().once(event=event, f=f)
+
@property
def contexts(self) -> typing.List["BrowserContext"]:
"""Browser.contexts
diff --git a/playwright/sync_api/_generated.py b/playwright/sync_api/_generated.py
index 9c51ef92f..f77db5ef6 100644
--- a/playwright/sync_api/_generated.py
+++ b/playwright/sync_api/_generated.py
@@ -40,6 +40,7 @@
StorageState,
ViewportSize,
)
+from playwright._impl._api_types import Error
from playwright._impl._browser import Browser as BrowserImpl
from playwright._impl._browser_context import BrowserContext as BrowserContextImpl
from playwright._impl._browser_type import BrowserType as BrowserTypeImpl
@@ -689,6 +690,72 @@ def handle(route, request):
class WebSocket(SyncBase):
+ @typing.overload
+ def on(
+ self, event: Literal["close"], f: typing.Callable[["WebSocket"], "None"]
+ ) -> None:
+ """
+ Fired when the websocket closes."""
+
+ @typing.overload
+ def on(
+ self,
+ event: Literal["framereceived"],
+ f: typing.Callable[["typing.Dict"], "None"],
+ ) -> None:
+ """
+ Fired when the websocket receives a frame."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["framesent"], f: typing.Callable[["typing.Dict"], "None"]
+ ) -> None:
+ """
+ Fired when the websocket sends a frame."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["socketerror"], f: typing.Callable[["str"], "None"]
+ ) -> None:
+ """
+ Fired when the websocket has an error."""
+
+ def on(self, event: str, f: typing.Callable[..., None]) -> None:
+ return super().on(event=event, f=f)
+
+ @typing.overload
+ def once(
+ self, event: Literal["close"], f: typing.Callable[["WebSocket"], "None"]
+ ) -> None:
+ """
+ Fired when the websocket closes."""
+
+ @typing.overload
+ def once(
+ self,
+ event: Literal["framereceived"],
+ f: typing.Callable[["typing.Dict"], "None"],
+ ) -> None:
+ """
+ Fired when the websocket receives a frame."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["framesent"], f: typing.Callable[["typing.Dict"], "None"]
+ ) -> None:
+ """
+ Fired when the websocket sends a frame."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["socketerror"], f: typing.Callable[["str"], "None"]
+ ) -> None:
+ """
+ Fired when the websocket has an error."""
+
+ def once(self, event: str, f: typing.Callable[..., None]) -> None:
+ return super().once(event=event, f=f)
+
@property
def url(self) -> str:
"""WebSocket.url
@@ -4974,6 +5041,20 @@ def set_checked(
class Worker(SyncBase):
+ def on(
+ self, event: Literal["close"], f: typing.Callable[["Worker"], "None"]
+ ) -> None:
+ """
+ Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is terminated."""
+ return super().on(event=event, f=f)
+
+ def once(
+ self, event: Literal["close"], f: typing.Callable[["Worker"], "None"]
+ ) -> None:
+ """
+ Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is terminated."""
+ return super().once(event=event, f=f)
+
@property
def url(self) -> str:
"""Worker.url
@@ -5409,6 +5490,404 @@ def delete(self) -> NoneType:
class Page(SyncContextManager):
+ @typing.overload
+ def on(self, event: Literal["close"], f: typing.Callable[["Page"], "None"]) -> None:
+ """
+ Emitted when the page closes."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["console"], f: typing.Callable[["ConsoleMessage"], "None"]
+ ) -> None:
+ """
+ Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also
+ emitted if the page throws an error or a warning.
+
+ The arguments passed into `console.log` appear as arguments on the event handler.
+
+ An example of handling `console` event:
+
+ ```py
+ def print_args(msg):
+ for arg in msg.args:
+ print(arg.json_value())
+
+ page.on(\"console\", print_args)
+ page.evaluate(\"console.log('hello', 5, {foo: 'bar'})\")
+ ```"""
+
+ @typing.overload
+ def on(self, event: Literal["crash"], f: typing.Callable[["Page"], "None"]) -> None:
+ """
+ Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page crashes,
+ ongoing and subsequent operations will throw.
+
+ The most common way to deal with crashes is to catch an exception:
+
+ ```py
+ try:
+ # crash might happen during a click.
+ page.click(\"button\")
+ # or while waiting for an event.
+ page.wait_for_event(\"popup\")
+ except Error as e:
+ # when the page crashes, exception message contains \"crash\".
+ ```"""
+
+ @typing.overload
+ def on(
+ self, event: Literal["dialog"], f: typing.Callable[["Dialog"], "None"]
+ ) -> None:
+ """
+ Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ either `dialog.accept()` or `dialog.dismiss()` the dialog - otherwise the page will
+ [freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking) waiting for the dialog, and
+ actions like click will never finish.
+
+ > NOTE: When no `page.on('dialog')` listeners are present, all dialogs are automatically dismissed."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["domcontentloaded"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ Emitted when the JavaScript [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded)
+ event is dispatched."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["download"], f: typing.Callable[["Download"], "None"]
+ ) -> None:
+ """
+ Emitted when attachment download started. User can access basic file operations on downloaded content via the passed
+ `Download` instance.
+
+ > NOTE: Browser context **must** be created with the `acceptDownloads` set to `true` when user needs access to the
+ downloaded content. If `acceptDownloads` is not set, download events are emitted, but the actual download is not
+ performed and user has no access to the downloaded files."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["filechooser"], f: typing.Callable[["FileChooser"], "None"]
+ ) -> None:
+ """
+ Emitted when a file chooser is supposed to appear, such as after clicking the ``. Playwright can
+ respond to it via setting the input files using `file_chooser.set_files()` that can be uploaded after that.
+
+ ```py
+ page.on(\"filechooser\", lambda file_chooser: file_chooser.set_files(\"/tmp/myfile.pdf\"))
+ ```"""
+
+ @typing.overload
+ def on(
+ self, event: Literal["frameattached"], f: typing.Callable[["Frame"], "None"]
+ ) -> None:
+ """
+ Emitted when a frame is attached."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["framedetached"], f: typing.Callable[["Frame"], "None"]
+ ) -> None:
+ """
+ Emitted when a frame is detached."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["framenavigated"], f: typing.Callable[["Frame"], "None"]
+ ) -> None:
+ """
+ Emitted when a frame is navigated to a new url."""
+
+ @typing.overload
+ def on(self, event: Literal["load"], f: typing.Callable[["Page"], "None"]) -> None:
+ """
+ Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/Web/Events/load) event is dispatched."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["pageerror"], f: typing.Callable[["Error"], "None"]
+ ) -> None:
+ """
+ Emitted when an uncaught exception happens within the page."""
+
+ @typing.overload
+ def on(self, event: Literal["popup"], f: typing.Callable[["Page"], "None"]) -> None:
+ """
+ Emitted when the page opens a new tab or window. This event is emitted in addition to the
+ `browser_context.on('page')`, but only for popups relevant to this page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ with page.expect_event(\"popup\") as page_info:
+ page.evaluate(\"window.open('https://example.com')\")
+ popup = page_info.value
+ print(popup.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["request"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a page issues a request. The [request] object is read-only. In order to intercept and mutate requests, see
+ `page.route()` or `browser_context.route()`."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["requestfailed"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `page.on('request_finished')` event and not with `page.on('request_failed')`. A request will only be
+ considered failed when the client cannot get an HTTP response from the server, e.g. due to network error
+ net::ERR_FAILED."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["requestfinished"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["response"], f: typing.Callable[["Response"], "None"]
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["websocket"], f: typing.Callable[["WebSocket"], "None"]
+ ) -> None:
+ """
+ Emitted when `WebSocket` request is sent."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["worker"], f: typing.Callable[["Worker"], "None"]
+ ) -> None:
+ """
+ Emitted when a dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is spawned by the
+ page."""
+
+ def on(self, event: str, f: typing.Callable[..., None]) -> None:
+ return super().on(event=event, f=f)
+
+ @typing.overload
+ def once(
+ self, event: Literal["close"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ Emitted when the page closes."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["console"], f: typing.Callable[["ConsoleMessage"], "None"]
+ ) -> None:
+ """
+ Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also
+ emitted if the page throws an error or a warning.
+
+ The arguments passed into `console.log` appear as arguments on the event handler.
+
+ An example of handling `console` event:
+
+ ```py
+ def print_args(msg):
+ for arg in msg.args:
+ print(arg.json_value())
+
+ page.on(\"console\", print_args)
+ page.evaluate(\"console.log('hello', 5, {foo: 'bar'})\")
+ ```"""
+
+ @typing.overload
+ def once(
+ self, event: Literal["crash"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page crashes,
+ ongoing and subsequent operations will throw.
+
+ The most common way to deal with crashes is to catch an exception:
+
+ ```py
+ try:
+ # crash might happen during a click.
+ page.click(\"button\")
+ # or while waiting for an event.
+ page.wait_for_event(\"popup\")
+ except Error as e:
+ # when the page crashes, exception message contains \"crash\".
+ ```"""
+
+ @typing.overload
+ def once(
+ self, event: Literal["dialog"], f: typing.Callable[["Dialog"], "None"]
+ ) -> None:
+ """
+ Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ either `dialog.accept()` or `dialog.dismiss()` the dialog - otherwise the page will
+ [freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking) waiting for the dialog, and
+ actions like click will never finish.
+
+ > NOTE: When no `page.on('dialog')` listeners are present, all dialogs are automatically dismissed."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["domcontentloaded"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ Emitted when the JavaScript [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded)
+ event is dispatched."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["download"], f: typing.Callable[["Download"], "None"]
+ ) -> None:
+ """
+ Emitted when attachment download started. User can access basic file operations on downloaded content via the passed
+ `Download` instance.
+
+ > NOTE: Browser context **must** be created with the `acceptDownloads` set to `true` when user needs access to the
+ downloaded content. If `acceptDownloads` is not set, download events are emitted, but the actual download is not
+ performed and user has no access to the downloaded files."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["filechooser"], f: typing.Callable[["FileChooser"], "None"]
+ ) -> None:
+ """
+ Emitted when a file chooser is supposed to appear, such as after clicking the ``. Playwright can
+ respond to it via setting the input files using `file_chooser.set_files()` that can be uploaded after that.
+
+ ```py
+ page.on(\"filechooser\", lambda file_chooser: file_chooser.set_files(\"/tmp/myfile.pdf\"))
+ ```"""
+
+ @typing.overload
+ def once(
+ self, event: Literal["frameattached"], f: typing.Callable[["Frame"], "None"]
+ ) -> None:
+ """
+ Emitted when a frame is attached."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["framedetached"], f: typing.Callable[["Frame"], "None"]
+ ) -> None:
+ """
+ Emitted when a frame is detached."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["framenavigated"], f: typing.Callable[["Frame"], "None"]
+ ) -> None:
+ """
+ Emitted when a frame is navigated to a new url."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["load"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/Web/Events/load) event is dispatched."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["pageerror"], f: typing.Callable[["Error"], "None"]
+ ) -> None:
+ """
+ Emitted when an uncaught exception happens within the page."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["popup"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ Emitted when the page opens a new tab or window. This event is emitted in addition to the
+ `browser_context.on('page')`, but only for popups relevant to this page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ with page.expect_event(\"popup\") as page_info:
+ page.evaluate(\"window.open('https://example.com')\")
+ popup = page_info.value
+ print(popup.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["request"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a page issues a request. The [request] object is read-only. In order to intercept and mutate requests, see
+ `page.route()` or `browser_context.route()`."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["requestfailed"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `page.on('request_finished')` event and not with `page.on('request_failed')`. A request will only be
+ considered failed when the client cannot get an HTTP response from the server, e.g. due to network error
+ net::ERR_FAILED."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["requestfinished"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["response"], f: typing.Callable[["Response"], "None"]
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["websocket"], f: typing.Callable[["WebSocket"], "None"]
+ ) -> None:
+ """
+ Emitted when `WebSocket` request is sent."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["worker"], f: typing.Callable[["Worker"], "None"]
+ ) -> None:
+ """
+ Emitted when a dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is spawned by the
+ page."""
+
+ def once(self, event: str, f: typing.Callable[..., None]) -> None:
+ return super().once(event=event, f=f)
+
@property
def accessibility(self) -> "Accessibility":
"""Page.accessibility
@@ -8959,6 +9438,196 @@ def set_checked(
class BrowserContext(SyncContextManager):
+ @typing.overload
+ def on(
+ self, event: Literal["backgroundpage"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ > NOTE: Only works with Chromium browser's persistent context.
+
+ Emitted when new background page is created in the context.
+
+ ```py
+ background_page = context.wait_for_event(\"backgroundpage\")
+ ```"""
+
+ @typing.overload
+ def on(
+ self, event: Literal["close"], f: typing.Callable[["BrowserContext"], "None"]
+ ) -> None:
+ """
+ Emitted when Browser context gets closed. This might happen because of one of the following:
+ - Browser context is closed.
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+
+ @typing.overload
+ def on(self, event: Literal["page"], f: typing.Callable[["Page"], "None"]) -> None:
+ """
+ The event is emitted when a new Page is created in the BrowserContext. The page may still be loading. The event will
+ also fire for popup pages. See also `page.on('popup')` to receive events about popups relevant to a specific page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ with context.expect_page() as page_info:
+ page.click(\"a[target=_blank]\"),
+ page = page_info.value
+ print(page.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["request"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To only
+ listen for requests from a particular page, use `page.on('request')`.
+
+ In order to intercept and mutate requests, see `browser_context.route()` or `page.route()`."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["requestfailed"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out. To only listen for failed requests from a particular page, use
+ `page.on('request_failed')`.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `browser_context.on('request_finished')` event and not with `browser_context.on('request_failed')`."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["requestfinished"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`. To listen for successful requests from a particular
+ page, use `page.on('request_finished')`."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["response"], f: typing.Callable[["Response"], "None"]
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`. To listen for response events from a particular page, use
+ `page.on('response')`."""
+
+ @typing.overload
+ def on(
+ self, event: Literal["serviceworker"], f: typing.Callable[["Worker"], "None"]
+ ) -> None:
+ """
+ > NOTE: Service workers are only supported on Chromium-based browsers.
+
+ Emitted when new service worker is created in the context."""
+
+ def on(self, event: str, f: typing.Callable[..., None]) -> None:
+ return super().on(event=event, f=f)
+
+ @typing.overload
+ def once(
+ self, event: Literal["backgroundpage"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ > NOTE: Only works with Chromium browser's persistent context.
+
+ Emitted when new background page is created in the context.
+
+ ```py
+ background_page = context.wait_for_event(\"backgroundpage\")
+ ```"""
+
+ @typing.overload
+ def once(
+ self, event: Literal["close"], f: typing.Callable[["BrowserContext"], "None"]
+ ) -> None:
+ """
+ Emitted when Browser context gets closed. This might happen because of one of the following:
+ - Browser context is closed.
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["page"], f: typing.Callable[["Page"], "None"]
+ ) -> None:
+ """
+ The event is emitted when a new Page is created in the BrowserContext. The page may still be loading. The event will
+ also fire for popup pages. See also `page.on('popup')` to receive events about popups relevant to a specific page.
+
+ The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ popup with `window.open('http://example.com')`, this event will fire when the network request to \"http://example.com\" is
+ done and its response has started loading in the popup.
+
+ ```py
+ with context.expect_page() as page_info:
+ page.click(\"a[target=_blank]\"),
+ page = page_info.value
+ print(page.evaluate(\"location.href\"))
+ ```
+
+ > NOTE: Use `page.wait_for_load_state()` to wait until the page gets to a particular state (you should not need it
+ in most cases)."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["request"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To only
+ listen for requests from a particular page, use `page.on('request')`.
+
+ In order to intercept and mutate requests, see `browser_context.route()` or `page.route()`."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["requestfailed"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request fails, for example by timing out. To only listen for failed requests from a particular page, use
+ `page.on('request_failed')`.
+
+ > NOTE: HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will
+ complete with `browser_context.on('request_finished')` event and not with `browser_context.on('request_failed')`."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["requestfinished"], f: typing.Callable[["Request"], "None"]
+ ) -> None:
+ """
+ Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ sequence of events is `request`, `response` and `requestfinished`. To listen for successful requests from a particular
+ page, use `page.on('request_finished')`."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["response"], f: typing.Callable[["Response"], "None"]
+ ) -> None:
+ """
+ Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events
+ is `request`, `response` and `requestfinished`. To listen for response events from a particular page, use
+ `page.on('response')`."""
+
+ @typing.overload
+ def once(
+ self, event: Literal["serviceworker"], f: typing.Callable[["Worker"], "None"]
+ ) -> None:
+ """
+ > NOTE: Service workers are only supported on Chromium-based browsers.
+
+ Emitted when new service worker is created in the context."""
+
+ def once(self, event: str, f: typing.Callable[..., None]) -> None:
+ return super().once(event=event, f=f)
+
@property
def pages(self) -> typing.List["Page"]:
"""BrowserContext.pages
@@ -9748,6 +10417,24 @@ def detach(self) -> NoneType:
class Browser(SyncContextManager):
+ def on(
+ self, event: Literal["disconnected"], f: typing.Callable[["Browser"], "None"]
+ ) -> None:
+ """
+ Emitted when Browser gets disconnected from the browser application. This might happen because of one of the following:
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+ return super().on(event=event, f=f)
+
+ def once(
+ self, event: Literal["disconnected"], f: typing.Callable[["Browser"], "None"]
+ ) -> None:
+ """
+ Emitted when Browser gets disconnected from the browser application. This might happen because of one of the following:
+ - Browser application is closed or crashed.
+ - The `browser.close()` method was called."""
+ return super().once(event=event, f=f)
+
@property
def contexts(self) -> typing.List["BrowserContext"]:
"""Browser.contexts
diff --git a/scripts/documentation_provider.py b/scripts/documentation_provider.py
index e52c2197f..626515ade 100644
--- a/scripts/documentation_provider.py
+++ b/scripts/documentation_provider.py
@@ -55,6 +55,7 @@ def _patch_case(self) -> None:
continue
members = {}
self.classes[clazz["name"]] = clazz
+ events = []
for member in clazz["members"]:
if not works_for_python(member):
continue
@@ -63,11 +64,11 @@ def _patch_case(self) -> None:
self._add_link(member["kind"], clazz["name"], member_name, new_name)
if member["kind"] == "event":
- continue
-
- new_name = to_snake_case(new_name)
- member["name"] = new_name
- members[new_name] = member
+ events.append(member)
+ else:
+ new_name = to_snake_case(new_name)
+ member["name"] = new_name
+ members[new_name] = member
apply_type_or_override(member)
if "args" in member:
@@ -93,6 +94,7 @@ def _patch_case(self) -> None:
member["args"] = args
clazz["members"] = members
+ clazz["events"] = events
def _add_link(self, kind: str, clazz: str, member: str, alias: str) -> None:
match = re.match(r"(JS|CDP|[A-Z])([^.]+)", clazz)
@@ -200,6 +202,39 @@ def print_entry(
f"Parameter not implemented: {class_name}.{method_name}({name}=)"
)
+ def print_events(self, class_name: str) -> None:
+ clazz = self.classes[class_name]
+ if events := clazz["events"]:
+ doc = []
+ for event_type in ["on", "once"]:
+ for event in events:
+ return_type = (
+ "typing.Union[typing.Awaitable[None], None]"
+ if self.is_async
+ else "None"
+ )
+ func_arg = self.serialize_doc_type(event["type"], "")
+ if func_arg.startswith("{"):
+ func_arg = "typing.Dict"
+ if len(events) > 1:
+ doc.append(" @typing.overload")
+ impl = ""
+ if len(events) == 1:
+ impl = f" return super().{event_type}(event=event,f=f)"
+ doc.append(
+ f" def {event_type}(self, event: Literal['{event['name'].lower()}'], f: typing.Callable[['{func_arg}'], '{return_type}']) -> None:"
+ )
+ doc.append(
+ f' """{self.beautify_method_comment(event["comment"]," " * 8)}"""'
+ )
+ doc.append(impl)
+ if len(events) > 1:
+ doc.append(
+ f" def {event_type}(self, event: str, f: typing.Callable[...,{return_type}]) -> None:"
+ )
+ doc.append(f" return super().{event_type}(event=event,f=f)")
+ print("\n".join(doc))
+
def indent_paragraph(self, p: str, indent: str) -> str:
lines = p.split("\n")
result = [lines[0]]
@@ -386,10 +421,9 @@ def inner_serialize_doc_type(self, type: Any, direction: str) -> str:
)
)
return f"{{{', '.join(items)}}}"
-
if type_name == "boolean":
return "bool"
- if type_name == "string":
+ if type_name.lower() == "string":
return "str"
if type_name == "any" or type_name == "Serializable":
return "Any"
diff --git a/scripts/generate_api.py b/scripts/generate_api.py
index 3d306b53e..3b1852d21 100644
--- a/scripts/generate_api.py
+++ b/scripts/generate_api.py
@@ -237,7 +237,7 @@ def return_value(value: Any) -> List[str]:
from playwright._impl._video import Video as VideoImpl
from playwright._impl._tracing import Tracing as TracingImpl
from playwright._impl._locator import Locator as LocatorImpl
-
+from playwright._impl._api_types import Error
"""
diff --git a/scripts/generate_async_api.py b/scripts/generate_async_api.py
index 066fce439..751ea711d 100755
--- a/scripts/generate_async_api.py
+++ b/scripts/generate_async_api.py
@@ -47,6 +47,7 @@ def generate(t: Any) -> None:
base_sync_class = base_class
print(f"class {class_name}({base_sync_class}):")
print("")
+ documentation_provider.print_events(class_name)
for [name, type] in get_type_hints(t, api_globals).items():
print("")
print(" @property")
diff --git a/scripts/generate_sync_api.py b/scripts/generate_sync_api.py
index 2efaeddb5..99f636fe3 100755
--- a/scripts/generate_sync_api.py
+++ b/scripts/generate_sync_api.py
@@ -48,6 +48,7 @@ def generate(t: Any) -> None:
base_sync_class = base_class
print(f"class {class_name}({base_sync_class}):")
print("")
+ documentation_provider.print_events(class_name)
for [name, type] in get_type_hints(t, api_globals).items():
print("")
print(" @property")
diff --git a/setup.cfg b/setup.cfg
index 669f82642..47e20a6fc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -14,7 +14,7 @@ warn_redundant_casts = True
warn_unused_configs = True
check_untyped_defs = True
disallow_untyped_defs = True
-[mypy-tests/async.*]
+[mypy-tests.*]
ignore_errors = True
[flake8]
ignore =