Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(roll): roll Playwright 1.15.0-next-1630006646000 #871

Merged
merged 2 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions playwright/_impl/_browser_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -31,7 +32,7 @@
from playwright._impl._frame import Frame
from playwright._impl._helper import (
RouteHandler,
RouteHandlerEntry,
RouteHandlerCallback,
TimeoutSettings,
URLMatch,
URLMatcher,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -241,17 +242,20 @@ 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(
"setNetworkInterceptionEnabled", dict(enabled=True)
)

async def unroute(
self, url: URLMatch, handler: Optional[RouteHandler] = None
self, url: URLMatch, handler: Optional[RouteHandlerCallback] = None
) -> None:
self._routes = list(
filter(
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions playwright/_impl/_element_handle.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand Down
27 changes: 24 additions & 3 deletions playwright/_impl/_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
TYPE_CHECKING,
Any,
Callable,
Coroutine,
Dict,
List,
Optional,
Expand All @@ -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"]
Expand Down Expand Up @@ -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:
Expand Down
20 changes: 12 additions & 8 deletions playwright/_impl/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
MouseButton,
ReducedMotion,
RouteHandler,
RouteHandlerEntry,
RouteHandlerCallback,
TimeoutSettings,
URLMatch,
URLMatcher,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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(
Expand Down
57 changes: 40 additions & 17 deletions playwright/async_api/_generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
-------
Expand All @@ -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
),
)
)
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

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

DeprecationWarning should be emitted for this

returns immediately.

Returns
-------
Expand Down Expand Up @@ -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
-------
Expand Down Expand Up @@ -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
-------
Expand Down Expand Up @@ -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
-------
Expand Down Expand Up @@ -6865,6 +6869,8 @@ async def route(
typing.Callable[["Route"], typing.Any],
typing.Callable[["Route", "Request"], typing.Any],
],
*,
times: int = None
) -> NoneType:
"""Page.route

Expand All @@ -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);`
Copy link
Contributor

@kumaraditya303 kumaraditya303 Aug 27, 2021

Choose a reason for hiding this comment

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

The snippet should be of python not js/ts

Copy link
Member Author

Choose a reason for hiding this comment

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

feel free to follow up upstream.


An example of a naive handler that aborts all image requests:

Expand Down Expand Up @@ -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,
),
)
)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
),
)
)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
-------
Expand All @@ -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
-------
Expand Down
Loading