Repository: microsoft/playwright-python
Pull request #2721 (2025-01-22 13:19:21)

fix(webError): fix WebError when using sync API
Fixes https://github.com/microsoft/playwright-python/issues/2706


Patch:
diff --git a/playwright/_impl/_browser_context.py b/playwright/_impl/_browser_context.py
index f415d59..e5a9b14 100644
--- a/playwright/_impl/_browser_context.py
+++ b/playwright/_impl/_browser_context.py
@@ -692,7 +692,10 @@ class BrowserContext(ChannelOwner):
                 asyncio.create_task(dialog.dismiss())
 
     def _on_page_error(self, error: Error, page: Optional[Page]) -> None:
-        self.emit(BrowserContext.Events.WebError, WebError(self._loop, page, error))
+        self.emit(
+            BrowserContext.Events.WebError,
+            WebError(self._loop, self._dispatcher_fiber, page, error),
+        )
         if page:
             page.emit(Page.Events.PageError, error)
 
diff --git a/playwright/_impl/_web_error.py b/playwright/_impl/_web_error.py
index eb1b519..345f95b 100644
--- a/playwright/_impl/_web_error.py
+++ b/playwright/_impl/_web_error.py
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 from asyncio import AbstractEventLoop
-from typing import Optional
+from typing import Any, Optional
 
 from playwright._impl._helper import Error
 from playwright._impl._page import Page
@@ -21,9 +21,14 @@ from playwright._impl._page import Page
 
 class WebError:
     def __init__(
-        self, loop: AbstractEventLoop, page: Optional[Page], error: Error
+        self,
+        loop: AbstractEventLoop,
+        dispatcher_fiber: Any,
+        page: Optional[Page],
+        error: Error,
     ) -> None:
         self._loop = loop
+        self._dispatcher_fiber = dispatcher_fiber
         self._page = page
         self._error = error
 
diff --git a/playwright/async_api/__init__.py b/playwright/async_api/__init__.py
index a64a066..be918f5 100644
--- a/playwright/async_api/__init__.py
+++ b/playwright/async_api/__init__.py
@@ -60,6 +60,7 @@ from playwright.async_api._generated import (
     Selectors,
     Touchscreen,
     Video,
+    WebError,
     WebSocket,
     WebSocketRoute,
     Worker,
@@ -190,6 +191,7 @@ __all__ = [
     "Touchscreen",
     "Video",
     "ViewportSize",
+    "WebError",
     "WebSocket",
     "WebSocketRoute",
     "Worker",
diff --git a/playwright/sync_api/__init__.py b/playwright/sync_api/__init__.py
index 80eaf71..1364339 100644
--- a/playwright/sync_api/__init__.py
+++ b/playwright/sync_api/__init__.py
@@ -60,6 +60,7 @@ from playwright.sync_api._generated import (
     Selectors,
     Touchscreen,
     Video,
+    WebError,
     WebSocket,
     WebSocketRoute,
     Worker,
@@ -190,6 +191,7 @@ __all__ = [
     "Touchscreen",
     "Video",
     "ViewportSize",
+    "WebError",
     "WebSocket",
     "WebSocketRoute",
     "Worker",


Test patch:
diff --git a/tests/async/test_browsercontext_events.py b/tests/async/test_browsercontext_events.py
index a0a3b90..8ae14de 100644
--- a/tests/async/test_browsercontext_events.py
+++ b/tests/async/test_browsercontext_events.py
@@ -17,7 +17,7 @@ from typing import Optional
 
 import pytest
 
-from playwright.async_api import Page
+from playwright.async_api import BrowserContext, Page
 from tests.utils import must
 
 from ..server import Server, TestServerRequest
@@ -198,3 +198,11 @@ async def test_page_error_event_should_work(page: Page) -> None:
     page_error = await page_error_info.value
     assert page_error.page == page
     assert "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"
diff --git a/tests/sync/test_browsercontext_events.py b/tests/sync/test_browsercontext_events.py
index 315fff0..6e44b76 100644
--- a/tests/sync/test_browsercontext_events.py
+++ b/tests/sync/test_browsercontext_events.py
@@ -16,7 +16,7 @@ from typing import Optional
 
 import pytest
 
-from playwright.sync_api import Dialog, Page
+from playwright.sync_api import BrowserContext, Dialog, Page
 
 from ..server import Server, TestServerRequest
 
@@ -198,3 +198,11 @@ def test_console_event_should_work_with_context_manager(page: Page) -> None:
     message = cm_info.value
     assert message.text == "hello"
     assert message.page == page
+
+
+def test_weberror_event_should_work(context: BrowserContext, page: Page) -> None:
+    with context.expect_event("weberror") as error_info:
+        page.goto('data:text/html,<script>throw new Error("Test")</script>')
+    error = error_info.value
+    assert error.page == page
+    assert error.error.message == "Test"