From 8384034b54f6fb4ecf4f4a2a14fda2635eeb7445 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 27 Aug 2021 00:43:56 +0200 Subject: [PATCH 1/2] feat(roll): roll Playwright 1.15.0-next-1630006646000 --- playwright/_impl/_browser_context.py | 28 ++++++++++---- playwright/_impl/_element_handle.py | 1 + playwright/_impl/_helper.py | 27 +++++++++++-- playwright/_impl/_page.py | 20 ++++++---- playwright/async_api/_generated.py | 57 +++++++++++++++++++--------- playwright/sync_api/_generated.py | 57 +++++++++++++++++++--------- scripts/expected_api_mismatch.txt | 1 + setup.py | 2 +- tests/async/test_interception.py | 35 ++++++++++++++++- 9 files changed, 174 insertions(+), 54 deletions(-) diff --git a/playwright/_impl/_browser_context.py b/playwright/_impl/_browser_context.py index 405394fba..f5f4bb6a2 100644 --- a/playwright/_impl/_browser_context.py +++ b/playwright/_impl/_browser_context.py @@ -21,6 +21,7 @@ from playwright._impl._api_structures import Cookie, Geolocation, StorageState from playwright._impl._api_types import Error +from playwright._impl._artifact import Artifact from playwright._impl._cdp_session import CDPSession from playwright._impl._connection import ( ChannelOwner, @@ -31,7 +32,7 @@ from playwright._impl._frame import Frame from playwright._impl._helper import ( RouteHandler, - RouteHandlerEntry, + RouteHandlerCallback, TimeoutSettings, URLMatch, URLMatcher, @@ -68,7 +69,7 @@ def __init__( ) -> None: super().__init__(parent, type, guid, initializer) self._pages: List[Page] = [] - self._routes: List[RouteHandlerEntry] = [] + self._routes: List[RouteHandler] = [] self._bindings: Dict[str, Any] = {} self._timeout_settings = TimeoutSettings(None) self._browser: Optional["Browser"] = None @@ -146,8 +147,8 @@ def _on_page(self, page: Page) -> None: def _on_route(self, route: Route, request: Request) -> None: for handler_entry in self._routes: - if handler_entry.matcher.matches(request.url): - result = cast(Any, handler_entry.handler)(route, request) + if handler_entry.matches(request.url): + result = handler_entry.handle(route, request) if inspect.iscoroutine(result): asyncio.create_task(result) return @@ -241,9 +242,12 @@ async def expose_binding( async def expose_function(self, name: str, callback: Callable) -> None: await self.expose_binding(name, lambda source, *args: callback(*args)) - async def route(self, url: URLMatch, handler: RouteHandler) -> None: + async def route( + self, url: URLMatch, handler: RouteHandlerCallback, times: int = None + ) -> None: self._routes.insert( - 0, RouteHandlerEntry(URLMatcher(self._options.get("baseURL"), url), handler) + 0, + RouteHandler(URLMatcher(self._options.get("baseURL"), url), handler, times), ) if len(self._routes) == 1: await self._channel.send( @@ -251,7 +255,7 @@ async def route(self, url: URLMatch, handler: RouteHandler) -> None: ) async def unroute( - self, url: URLMatch, handler: Optional[RouteHandler] = None + self, url: URLMatch, handler: Optional[RouteHandlerCallback] = None ) -> None: self._routes = list( filter( @@ -291,6 +295,16 @@ def _on_close(self) -> None: async def close(self) -> None: try: + if self._options.get("recordHar"): + har = cast( + Artifact, from_channel(await self._channel.send("harExport")) + ) + if self.browser and self.browser._is_remote: + har._is_remote = True + await har.save_as( + cast(Dict[str, str], self._options["recordHar"])["path"] + ) + await har.delete() await self._channel.send("close") await self._closed_future except Exception as e: diff --git a/playwright/_impl/_element_handle.py b/playwright/_impl/_element_handle.py index 5a8aaef7f..345d5adf2 100644 --- a/playwright/_impl/_element_handle.py +++ b/playwright/_impl/_element_handle.py @@ -315,6 +315,7 @@ async def wait_for_selector( selector: str, state: Literal["attached", "detached", "hidden", "visible"] = None, timeout: float = None, + strict: bool = None, ) -> Optional["ElementHandle"]: return from_nullable_channel( await self._channel.send("waitForSelector", locals_to_params(locals())) diff --git a/playwright/_impl/_helper.py b/playwright/_impl/_helper.py index a038e47e9..2758bd5c0 100644 --- a/playwright/_impl/_helper.py +++ b/playwright/_impl/_helper.py @@ -25,6 +25,7 @@ TYPE_CHECKING, Any, Callable, + Coroutine, Dict, List, Optional, @@ -49,7 +50,9 @@ URLMatch = Union[str, Pattern, Callable[[str], bool]] URLMatchRequest = Union[str, Pattern, Callable[["Request"], bool]] URLMatchResponse = Union[str, Pattern, Callable[["Response"], bool]] -RouteHandler = Union[Callable[["Route"], Any], Callable[["Route", "Request"], Any]] +RouteHandlerCallback = Union[ + Callable[["Route"], Any], Callable[["Route", "Request"], Any] +] ColorScheme = Literal["dark", "light", "no-preference"] ReducedMotion = Literal["no-preference", "reduce"] @@ -199,10 +202,28 @@ def monotonic_time() -> int: return math.floor(time.monotonic() * 1000) -class RouteHandlerEntry: - def __init__(self, matcher: URLMatcher, handler: RouteHandler): +class RouteHandler: + def __init__( + self, + matcher: URLMatcher, + handler: RouteHandlerCallback, + times: Optional[int], + ): self.matcher = matcher self.handler = handler + self._times = times + self._handled_count = 0 + + def matches(self, request_url: str) -> bool: + if self._times and self._handled_count >= self._times: + return False + return self.matcher.matches(request_url) + + def handle(self, route: "Route", request: "Request") -> Union[Coroutine, Any]: + self._handled_count += 1 + return cast( + Callable[["Route", "Request"], Union[Coroutine, Any]], self.handler + )(route, request) def is_safe_close_error(error: Exception) -> bool: diff --git a/playwright/_impl/_page.py b/playwright/_impl/_page.py index 5e0bce5cd..cd09de8a2 100644 --- a/playwright/_impl/_page.py +++ b/playwright/_impl/_page.py @@ -49,7 +49,7 @@ MouseButton, ReducedMotion, RouteHandler, - RouteHandlerEntry, + RouteHandlerCallback, TimeoutSettings, URLMatch, URLMatcher, @@ -130,7 +130,7 @@ def __init__( self._is_closed = False self._workers: List["Worker"] = [] self._bindings: Dict[str, Any] = {} - self._routes: List[RouteHandlerEntry] = [] + self._routes: List[RouteHandler] = [] self._owned_context: Optional["BrowserContext"] = None self._timeout_settings: TimeoutSettings = TimeoutSettings( self._browser_context._timeout_settings @@ -211,8 +211,8 @@ def _on_frame_detached(self, frame: Frame) -> None: def _on_route(self, route: Route, request: Request) -> None: for handler_entry in self._routes: - if handler_entry.matcher.matches(request.url): - result = cast(Any, handler_entry.handler)(route, request) + if handler_entry.matches(request.url): + result = handler_entry.handle(route, request) if inspect.iscoroutine(result): asyncio.create_task(result) return @@ -536,11 +536,15 @@ async def add_init_script( raise Error("Either path or script parameter must be specified") await self._channel.send("addInitScript", dict(source=script)) - async def route(self, url: URLMatch, handler: RouteHandler) -> None: + async def route( + self, url: URLMatch, handler: RouteHandlerCallback, times: int = None + ) -> None: self._routes.insert( 0, - RouteHandlerEntry( - URLMatcher(self._browser_context._options.get("baseURL"), url), handler + RouteHandler( + URLMatcher(self._browser_context._options.get("baseURL"), url), + handler, + times, ), ) if len(self._routes) == 1: @@ -549,7 +553,7 @@ async def route(self, url: URLMatch, handler: RouteHandler) -> None: ) async def unroute( - self, url: URLMatch, handler: Optional[RouteHandler] = None + self, url: URLMatch, handler: Optional[RouteHandlerCallback] = None ) -> None: self._routes = list( filter( diff --git a/playwright/async_api/_generated.py b/playwright/async_api/_generated.py index 53e1d40f4..e47f4ebd1 100644 --- a/playwright/async_api/_generated.py +++ b/playwright/async_api/_generated.py @@ -2467,7 +2467,8 @@ async def wait_for_selector( selector: str, *, state: Literal["attached", "detached", "hidden", "visible"] = None, - timeout: float = None + timeout: float = None, + strict: bool = None ) -> typing.Optional["ElementHandle"]: """ElementHandle.wait_for_selector @@ -2503,6 +2504,9 @@ async def wait_for_selector( timeout : Union[float, NoneType] Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + strict : Union[bool, NoneType] + When true, the call requires selector to resolve to a single element. If given selector resolves to more then one + element, the call throws an exception. Returns ------- @@ -2513,7 +2517,7 @@ async def wait_for_selector( await self._async( "element_handle.wait_for_selector", self._impl_obj.wait_for_selector( - selector=selector, state=state, timeout=timeout + selector=selector, state=state, timeout=timeout, strict=strict ), ) ) @@ -3339,8 +3343,8 @@ async def is_hidden( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `frame.is_hidden()` does not wait for the element to become hidden and + returns immediately. Returns ------- @@ -3373,8 +3377,8 @@ async def is_visible( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `frame.is_visible()` does not wait for the element to become visible and + returns immediately. Returns ------- @@ -5790,8 +5794,8 @@ async def is_hidden( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `page.is_hidden()` does not wait for the element to become hidden and + returns immediately. Returns ------- @@ -5824,8 +5828,8 @@ async def is_visible( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `page.is_visible()` does not wait for the element to become visible and + returns immediately. Returns ------- @@ -6865,6 +6869,8 @@ async def route( typing.Callable[["Route"], typing.Any], typing.Callable[["Route", "Request"], typing.Any], ], + *, + times: int = None ) -> NoneType: """Page.route @@ -6873,6 +6879,9 @@ async def route( Once routing is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted. > NOTE: The handler will only be called for the first url if the response is a redirect. + > NOTE: `page.route()` will not intercept requests intercepted by Service Worker. See + [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using + request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);` An example of a naive handler that aborts all image requests: @@ -6919,13 +6928,17 @@ def handle_route(route): [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. handler : Union[Callable[[Route, Request], Any], Callable[[Route], Any]] handler function to route the request. + times : Union[int, NoneType] + How often a route should be used. By default it will be used every time. """ return mapping.from_maybe_impl( await self._async( "page.route", self._impl_obj.route( - url=self._wrap_handler(url), handler=self._wrap_handler(handler) + url=self._wrap_handler(url), + handler=self._wrap_handler(handler), + times=times, ), ) ) @@ -9265,12 +9278,18 @@ async def route( typing.Callable[["Route"], typing.Any], typing.Callable[["Route", "Request"], typing.Any], ], + *, + times: int = None ) -> NoneType: """BrowserContext.route Routing provides the capability to modify network requests that are made by any page in the browser context. Once route is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted. + > NOTE: `page.route()` will not intercept requests intercepted by Service Worker. See + [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using + request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);` + An example of a naive handler that aborts all image requests: ```py @@ -9319,13 +9338,17 @@ def handle_route(route): [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. handler : Union[Callable[[Route, Request], Any], Callable[[Route], Any]] handler function to route the request. + times : Union[int, NoneType] + How often a route should be used. By default it will be used every time. """ return mapping.from_maybe_impl( await self._async( "browser_context.route", self._impl_obj.route( - url=self._wrap_handler(url), handler=self._wrap_handler(handler) + url=self._wrap_handler(url), + handler=self._wrap_handler(handler), + times=times, ), ) ) @@ -9512,7 +9535,7 @@ async def new_cdp_session( Parameters ---------- page : Union[Frame, Page] - Target to create new session for. For backwards-compatability, this parameter is named `page`, but it can be a `Page` or + Target to create new session for. For backwards-compatibility, this parameter is named `page`, but it can be a `Page` or `Frame` type. Returns @@ -11559,8 +11582,8 @@ async def is_hidden(self, *, timeout: float = None) -> bool: Parameters ---------- timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `locator.is_hidden()` does not wait for the element to become hidden and + returns immediately. Returns ------- @@ -11581,8 +11604,8 @@ async def is_visible(self, *, timeout: float = None) -> bool: Parameters ---------- timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `locator.is_visible()` does not wait for the element to become visible and + returns immediately. Returns ------- diff --git a/playwright/sync_api/_generated.py b/playwright/sync_api/_generated.py index 5c26ddf40..60e426d94 100644 --- a/playwright/sync_api/_generated.py +++ b/playwright/sync_api/_generated.py @@ -2450,7 +2450,8 @@ def wait_for_selector( selector: str, *, state: Literal["attached", "detached", "hidden", "visible"] = None, - timeout: float = None + timeout: float = None, + strict: bool = None ) -> typing.Optional["ElementHandle"]: """ElementHandle.wait_for_selector @@ -2486,6 +2487,9 @@ def wait_for_selector( timeout : Union[float, NoneType] Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + strict : Union[bool, NoneType] + When true, the call requires selector to resolve to a single element. If given selector resolves to more then one + element, the call throws an exception. Returns ------- @@ -2496,7 +2500,7 @@ def wait_for_selector( self._sync( "element_handle.wait_for_selector", self._impl_obj.wait_for_selector( - selector=selector, state=state, timeout=timeout + selector=selector, state=state, timeout=timeout, strict=strict ), ) ) @@ -3317,8 +3321,8 @@ def is_hidden( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `frame.is_hidden()` does not wait for the element to become hidden and + returns immediately. Returns ------- @@ -3351,8 +3355,8 @@ def is_visible( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `frame.is_visible()` does not wait for the element to become visible and + returns immediately. Returns ------- @@ -5752,8 +5756,8 @@ def is_hidden( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `page.is_hidden()` does not wait for the element to become hidden and + returns immediately. Returns ------- @@ -5786,8 +5790,8 @@ def is_visible( When true, the call requires selector to resolve to a single element. If given selector resolves to more then one element, the call throws an exception. timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `page.is_visible()` does not wait for the element to become visible and + returns immediately. Returns ------- @@ -6818,6 +6822,8 @@ def route( typing.Callable[["Route"], typing.Any], typing.Callable[["Route", "Request"], typing.Any], ], + *, + times: int = None ) -> NoneType: """Page.route @@ -6826,6 +6832,9 @@ def route( Once routing is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted. > NOTE: The handler will only be called for the first url if the response is a redirect. + > NOTE: `page.route()` will not intercept requests intercepted by Service Worker. See + [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using + request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);` An example of a naive handler that aborts all image requests: @@ -6872,13 +6881,17 @@ def handle_route(route): [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. handler : Union[Callable[[Route, Request], Any], Callable[[Route], Any]] handler function to route the request. + times : Union[int, NoneType] + How often a route should be used. By default it will be used every time. """ return mapping.from_maybe_impl( self._sync( "page.route", self._impl_obj.route( - url=self._wrap_handler(url), handler=self._wrap_handler(handler) + url=self._wrap_handler(url), + handler=self._wrap_handler(handler), + times=times, ), ) ) @@ -9201,12 +9214,18 @@ def route( typing.Callable[["Route"], typing.Any], typing.Callable[["Route", "Request"], typing.Any], ], + *, + times: int = None ) -> NoneType: """BrowserContext.route Routing provides the capability to modify network requests that are made by any page in the browser context. Once route is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted. + > NOTE: `page.route()` will not intercept requests intercepted by Service Worker. See + [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using + request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);` + An example of a naive handler that aborts all image requests: ```py @@ -9256,13 +9275,17 @@ def handle_route(route): [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. handler : Union[Callable[[Route, Request], Any], Callable[[Route], Any]] handler function to route the request. + times : Union[int, NoneType] + How often a route should be used. By default it will be used every time. """ return mapping.from_maybe_impl( self._sync( "browser_context.route", self._impl_obj.route( - url=self._wrap_handler(url), handler=self._wrap_handler(handler) + url=self._wrap_handler(url), + handler=self._wrap_handler(handler), + times=times, ), ) ) @@ -9447,7 +9470,7 @@ def new_cdp_session(self, page: typing.Union["Page", "Frame"]) -> "CDPSession": Parameters ---------- page : Union[Frame, Page] - Target to create new session for. For backwards-compatability, this parameter is named `page`, but it can be a `Page` or + Target to create new session for. For backwards-compatibility, this parameter is named `page`, but it can be a `Page` or `Frame` type. Returns @@ -11479,8 +11502,8 @@ def is_hidden(self, *, timeout: float = None) -> bool: Parameters ---------- timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `locator.is_hidden()` does not wait for the element to become hidden and + returns immediately. Returns ------- @@ -11499,8 +11522,8 @@ def is_visible(self, *, timeout: float = None) -> bool: Parameters ---------- timeout : Union[float, NoneType] - Maximum time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be changed by - using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods. + **DEPRECATED** This option is ignored. `locator.is_visible()` does not wait for the element to become visible and + returns immediately. Returns ------- diff --git a/scripts/expected_api_mismatch.txt b/scripts/expected_api_mismatch.txt index 5fa814272..798876034 100644 --- a/scripts/expected_api_mismatch.txt +++ b/scripts/expected_api_mismatch.txt @@ -20,3 +20,4 @@ Parameter type mismatch in BrowserContext.cookies(return=): documented as List[{ Method not implemented: Error.name Method not implemented: Error.stack Method not implemented: Error.message +Parameter not implemented: Route.fulfill(_response=) diff --git a/setup.py b/setup.py index faf0b1add..73849f724 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ InWheel = None from wheel.bdist_wheel import bdist_wheel as BDistWheelCommand -driver_version = "1.15.0-next-1629487941000" +driver_version = "1.15.0-next-1630006646000" def extractall(zip: zipfile.ZipFile, path: str) -> None: diff --git a/tests/async/test_interception.py b/tests/async/test_interception.py index 722811441..42e53203f 100644 --- a/tests/async/test_interception.py +++ b/tests/async/test_interception.py @@ -17,7 +17,8 @@ import pytest -from playwright.async_api import Browser, Error, Page, Route +from playwright.async_api import Browser, BrowserContext, Error, Page, Route +from tests.server import Server async def test_page_route_should_intercept(page, server): @@ -907,3 +908,35 @@ def _handle_route(route): # Page route is not applied to service worker initiated fetch. non_intercepted_response = await page.evaluate('() => fetchDummy("passthrough")') assert non_intercepted_response == "FAILURE: Not Found" + + +async def test_page_route_should_support_times_parameter(page: Page, server: Server): + intercepted = [] + + async def handle_request(route): + await route.continue_() + intercepted.append(True) + + await page.route("**/empty.html", handle_request, times=1) + + await page.goto(server.EMPTY_PAGE) + await page.goto(server.EMPTY_PAGE) + await page.goto(server.EMPTY_PAGE) + assert len(intercepted) == 1 + + +async def test_context_route_should_support_times_parameter( + context: BrowserContext, page: Page, server: Server +): + intercepted = [] + + async def handle_request(route): + await route.continue_() + intercepted.append(True) + + await context.route("**/empty.html", handle_request, times=1) + + await page.goto(server.EMPTY_PAGE) + await page.goto(server.EMPTY_PAGE) + await page.goto(server.EMPTY_PAGE) + assert len(intercepted) == 1 From 78c22ebb6556615807c77687aad7f8cc93736d60 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 27 Aug 2021 15:30:10 +0200 Subject: [PATCH 2/2] new driver --- scripts/expected_api_mismatch.txt | 1 - setup.py | 2 +- tests/async/test_console.py | 4 ++++ tests/async/test_interception.py | 9 +++++++-- tests/async/test_launcher.py | 2 +- tests/async/test_page.py | 2 +- tests/async/test_worker.py | 2 +- tests/sync/test_console.py | 4 ++++ tests/sync/test_sync.py | 2 +- 9 files changed, 20 insertions(+), 8 deletions(-) diff --git a/scripts/expected_api_mismatch.txt b/scripts/expected_api_mismatch.txt index 798876034..5fa814272 100644 --- a/scripts/expected_api_mismatch.txt +++ b/scripts/expected_api_mismatch.txt @@ -20,4 +20,3 @@ Parameter type mismatch in BrowserContext.cookies(return=): documented as List[{ Method not implemented: Error.name Method not implemented: Error.stack Method not implemented: Error.message -Parameter not implemented: Route.fulfill(_response=) diff --git a/setup.py b/setup.py index 73849f724..81765a424 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ InWheel = None from wheel.bdist_wheel import bdist_wheel as BDistWheelCommand -driver_version = "1.15.0-next-1630006646000" +driver_version = "1.15.0-next-1630059769000" def extractall(zip: zipfile.ZipFile, path: str) -> None: diff --git a/tests/async/test_console.py b/tests/async/test_console.py index e6f75681a..4345e8e41 100644 --- a/tests/async/test_console.py +++ b/tests/async/test_console.py @@ -14,6 +14,8 @@ from typing import List +import pytest + from playwright.async_api import ConsoleMessage, Page @@ -95,6 +97,8 @@ async def test_console_should_not_fail_for_window_object(page, browser_name): assert message.text == "JSHandle@object" +# Upstream issue https://bugs.webkit.org/show_bug.cgi?id=229515 +@pytest.mark.skip_browser("webkit") async def test_console_should_trigger_correct_log(page, server): await page.goto("about:blank") async with page.expect_console_message() as message_info: diff --git a/tests/async/test_interception.py b/tests/async/test_interception.py index 42e53203f..ea6643b43 100644 --- a/tests/async/test_interception.py +++ b/tests/async/test_interception.py @@ -541,7 +541,7 @@ async def handle_route(route, request): assert text == "" -async def test_page_route_should_support_cors_with_GET(page, server): +async def test_page_route_should_support_cors_with_GET(page, server, browser_name): await page.goto(server.EMPTY_PAGE) async def handle_route(route, request): @@ -579,7 +579,12 @@ async def handle_route(route, request): return response.json(); }""" ) - assert "failed" in exc.value.message + if browser_name == "chromium": + assert "Failed" in exc.value.message + elif browser_name == "webkit": + assert "TypeError" in exc.value.message + elif browser_name == "firefox": + assert "NetworkError" in exc.value.message async def test_page_route_should_support_cors_with_POST(page, server): diff --git a/tests/async/test_launcher.py b/tests/async/test_launcher.py index 72f42add5..3ed7b6603 100644 --- a/tests/async/test_launcher.py +++ b/tests/async/test_launcher.py @@ -29,7 +29,7 @@ async def test_browser_type_launch_should_reject_all_promises_when_browser_is_cl await page.close() with pytest.raises(Error) as exc: await never_resolves - assert "Protocol error" in exc.value.message + assert "Target closed" in exc.value.message @pytest.mark.skip_browser("firefox") diff --git a/tests/async/test_page.py b/tests/async/test_page.py index 89d83ba3d..680635e68 100644 --- a/tests/async/test_page.py +++ b/tests/async/test_page.py @@ -28,7 +28,7 @@ async def test_close_should_reject_all_promises(context): await asyncio.gather( new_page.evaluate("() => new Promise(r => {})"), new_page.close() ) - assert "Protocol error" in exc_info.value.message + assert "Target closed" in exc_info.value.message async def test_closed_should_not_visible_in_context_pages(context): diff --git a/tests/async/test_worker.py b/tests/async/test_worker.py index 8d9baa2b8..3ec764efa 100644 --- a/tests/async/test_worker.py +++ b/tests/async/test_worker.py @@ -51,7 +51,7 @@ async def test_workers_should_emit_created_and_destroyed_events(page: Page): assert await worker_destroyed_promise == worker with pytest.raises(Error) as exc: await worker_this_obj.get_property("self") - assert "Most likely the worker has been closed." in exc.value.message + assert "Target closed" in exc.value.message async def test_workers_should_report_console_logs(page): diff --git a/tests/sync/test_console.py b/tests/sync/test_console.py index d55ee2ada..291febc62 100644 --- a/tests/sync/test_console.py +++ b/tests/sync/test_console.py @@ -14,6 +14,8 @@ from typing import List +import pytest + from playwright.sync_api import ConsoleMessage, Page @@ -98,6 +100,8 @@ def test_console_should_not_fail_for_window_object(page: Page, browser_name): assert messages[0].text == "JSHandle@object" +# Upstream issue https://bugs.webkit.org/show_bug.cgi?id=229515 +@pytest.mark.skip_browser("webkit") def test_console_should_trigger_correct_Log(page, server): page.goto("about:blank") with page.expect_console_message() as message: diff --git a/tests/sync/test_sync.py b/tests/sync/test_sync.py index bfd6b7d42..175a34b65 100644 --- a/tests/sync/test_sync.py +++ b/tests/sync/test_sync.py @@ -261,7 +261,7 @@ def test_close_should_reject_all_promises(context): lambda: new_page.evaluate("() => new Promise(r => {})"), lambda: new_page.close(), ) - assert "Protocol error" in exc_info.value.message + assert "Target closed" in exc_info.value.message def test_expect_response_should_work(page: Page, server):