diff --git a/playwright/_impl/_browser.py b/playwright/_impl/_browser.py
index fe84432f3..4f6ebe639 100644
--- a/playwright/_impl/_browser.py
+++ b/playwright/_impl/_browser.py
@@ -69,6 +69,7 @@ def is_connected(self) -> bool:
async def new_context(
self,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
noViewport: bool = None,
ignoreHTTPSErrors: bool = None,
javaScriptEnabled: bool = None,
@@ -107,6 +108,7 @@ async def new_context(
async def new_page(
self,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
noViewport: bool = None,
ignoreHTTPSErrors: bool = None,
javaScriptEnabled: bool = None,
diff --git a/playwright/_impl/_browser_type.py b/playwright/_impl/_browser_type.py
index 69ec77df5..1070b57ef 100644
--- a/playwright/_impl/_browser_type.py
+++ b/playwright/_impl/_browser_type.py
@@ -96,6 +96,7 @@ async def launch_persistent_context(
downloadsPath: Union[str, Path] = None,
slowMo: float = None,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
noViewport: bool = None,
ignoreHTTPSErrors: bool = None,
javaScriptEnabled: bool = None,
diff --git a/playwright/_impl/_frame.py b/playwright/_impl/_frame.py
index 04b4ac37a..5698a90f4 100644
--- a/playwright/_impl/_frame.py
+++ b/playwright/_impl/_frame.py
@@ -181,6 +181,21 @@ async def continuation() -> Optional[Response]:
return EventContextManagerImpl(asyncio.create_task(continuation()))
+ async def wait_for_url(
+ self,
+ url: URLMatch,
+ wait_until: DocumentLoadState = None,
+ timeout: float = None,
+ ) -> None:
+ matcher = URLMatcher(url)
+ if matcher.matches(self.url):
+ await self.wait_for_load_state(state=wait_until, timeout=timeout)
+ return
+ async with self.expect_navigation(
+ url=url, wait_until=wait_until, timeout=timeout
+ ):
+ pass
+
async def wait_for_load_state(
self, state: DocumentLoadState = None, timeout: float = None
) -> None:
diff --git a/playwright/_impl/_page.py b/playwright/_impl/_page.py
index 39f9568f4..1ba1573d6 100644
--- a/playwright/_impl/_page.py
+++ b/playwright/_impl/_page.py
@@ -477,6 +477,14 @@ async def wait_for_load_state(
) -> None:
return await self._main_frame.wait_for_load_state(**locals_to_params(locals()))
+ async def wait_for_url(
+ self,
+ url: URLMatch,
+ wait_until: DocumentLoadState = None,
+ timeout: float = None,
+ ) -> None:
+ return await self._main_frame.wait_for_url(**locals_to_params(locals()))
+
async def wait_for_event(
self, event: str, predicate: Callable = None, timeout: float = None
) -> Any:
diff --git a/playwright/async_api/_generated.py b/playwright/async_api/_generated.py
index dbed04d65..db311a7ae 100644
--- a/playwright/async_api/_generated.py
+++ b/playwright/async_api/_generated.py
@@ -819,7 +819,7 @@ async def press(self, key: str, *, delay: float = None) -> NoneType:
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
```py
@@ -1390,8 +1390,8 @@ async def dispatch_event(
) -> NoneType:
"""ElementHandle.dispatch_event
- The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
- is dispatched. This is equivalend to calling
+ The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ `click` is dispatched. This is equivalent to calling
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
```py
@@ -1948,7 +1948,7 @@ async def press(
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
Parameters
@@ -2709,6 +2709,47 @@ def expect_navigation(
).future
)
+ async def wait_for_url(
+ self,
+ url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
+ *,
+ wait_until: Literal["domcontentloaded", "load", "networkidle"] = None,
+ timeout: float = None
+ ) -> NoneType:
+ """Frame.wait_for_url
+
+ Waits for the frame to navigate to the given URL.
+
+ ```py
+ await frame.click(\"a.delayed-navigation\") # clicking the link will indirectly cause a navigation
+ await frame.wait_for_url(\"**/target.html\")
+ ```
+
+ Parameters
+ ----------
+ url : Union[Callable[[str], bool], Pattern, str]
+ A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ wait_until : Union["domcontentloaded", "load", "networkidle", NoneType]
+ When to consider operation succeeded, defaults to `load`. Events can be either:
+ - `'domcontentloaded'` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ - `'load'` - consider operation to be finished when the `load` event is fired.
+ - `'networkidle'` - consider operation to be finished when there are no network connections for at least `500` ms.
+ timeout : Union[float, NoneType]
+ Maximum operation 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_navigation_timeout()`,
+ `browser_context.set_default_timeout()`, `page.set_default_navigation_timeout()` or
+ `page.set_default_timeout()` methods.
+ """
+
+ return mapping.from_maybe_impl(
+ await self._async(
+ "frame.wait_for_url",
+ self._impl_obj.wait_for_url(
+ url=self._wrap_handler(url), wait_until=wait_until, timeout=timeout
+ ),
+ )
+ )
+
async def wait_for_load_state(
self,
state: Literal["domcontentloaded", "load", "networkidle"] = None,
@@ -3169,8 +3210,8 @@ async def dispatch_event(
) -> NoneType:
"""Frame.dispatch_event
- The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
- is dispatched. This is equivalend to calling
+ The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ `click` is dispatched. This is equivalent to calling
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
```py
@@ -4089,7 +4130,7 @@ async def press(
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
Parameters
@@ -4894,6 +4935,7 @@ def set_default_navigation_timeout(self, timeout: float) -> NoneType:
- `page.reload()`
- `page.set_content()`
- `page.expect_navigation()`
+ - `page.wait_for_url()`
> NOTE: `page.set_default_navigation_timeout()` takes priority over `page.set_default_timeout()`,
`browser_context.set_default_timeout()` and `browser_context.set_default_navigation_timeout()`.
@@ -5210,8 +5252,8 @@ async def dispatch_event(
) -> NoneType:
"""Page.dispatch_event
- The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
- is dispatched. This is equivalend to calling
+ The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ `click` is dispatched. This is equivalent to calling
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
```py
@@ -5904,6 +5946,49 @@ async def wait_for_load_state(
)
)
+ async def wait_for_url(
+ self,
+ url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
+ *,
+ wait_until: Literal["domcontentloaded", "load", "networkidle"] = None,
+ timeout: float = None
+ ) -> NoneType:
+ """Page.wait_for_url
+
+ Waits for the main frame to navigate to the given URL.
+
+ ```py
+ await page.click(\"a.delayed-navigation\") # clicking the link will indirectly cause a navigation
+ await page.wait_for_url(\"**/target.html\")
+ ```
+
+ Shortcut for main frame's `frame.wait_for_url()`.
+
+ Parameters
+ ----------
+ url : Union[Callable[[str], bool], Pattern, str]
+ A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ wait_until : Union["domcontentloaded", "load", "networkidle", NoneType]
+ When to consider operation succeeded, defaults to `load`. Events can be either:
+ - `'domcontentloaded'` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ - `'load'` - consider operation to be finished when the `load` event is fired.
+ - `'networkidle'` - consider operation to be finished when there are no network connections for at least `500` ms.
+ timeout : Union[float, NoneType]
+ Maximum operation 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_navigation_timeout()`,
+ `browser_context.set_default_timeout()`, `page.set_default_navigation_timeout()` or
+ `page.set_default_timeout()` methods.
+ """
+
+ return mapping.from_maybe_impl(
+ await self._async(
+ "page.wait_for_url",
+ self._impl_obj.wait_for_url(
+ url=self._wrap_handler(url), wait_until=wait_until, timeout=timeout
+ ),
+ )
+ )
+
async def wait_for_event(
self, event: str, predicate: typing.Callable = None, *, timeout: float = None
) -> typing.Any:
@@ -6163,7 +6248,7 @@ async def route(
> NOTE: The handler will only be called for the first url if the response is a redirect.
- An example of a naïve handler that aborts all image requests:
+ An example of a naive handler that aborts all image requests:
```py
page = await browser.new_page()
@@ -6184,6 +6269,8 @@ async def route(
Page routes take precedence over browser context routes (set up with `browser_context.route()`) when request
matches both handlers.
+ To remove a route with its handler you can use `page.unroute()`.
+
> NOTE: Enabling routing disables http cache.
Parameters
@@ -6247,9 +6334,6 @@ async def screenshot(
Returns the buffer with the captured screenshot.
- > NOTE: Screenshots take at least 1/6 second on Chromium OS X and Chromium Windows. See https://crbug.com/741689 for
- discussion.
-
Parameters
----------
timeout : Union[float, NoneType]
@@ -7001,7 +7085,7 @@ async def press(
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
```py
@@ -8190,7 +8274,7 @@ async def 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.
- An example of a naïve handler that aborts all image requests:
+ An example of a naive handler that aborts all image requests:
```py
context = await browser.new_context()
@@ -8214,6 +8298,8 @@ async def route(
Page routes (set up with `page.route()`) take precedence over browser context routes when request matches both
handlers.
+ To remove a route with its handler you can use `browser_context.unroute()`.
+
> NOTE: Enabling routing disables http cache.
Parameters
@@ -8553,6 +8639,7 @@ async def new_context(
self,
*,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
no_viewport: bool = None,
ignore_https_errors: bool = None,
java_script_enabled: bool = None,
@@ -8595,6 +8682,9 @@ async def new_context(
----------
viewport : Union[{width: int, height: int}, NoneType]
Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed viewport.
+ screen : Union[{width: int, height: int}, NoneType]
+ Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
+ is set.
no_viewport : Union[bool, NoneType]
Does not enforce fixed viewport, allows resizing window in the headed mode.
ignore_https_errors : Union[bool, NoneType]
@@ -8666,6 +8756,7 @@ async def new_context(
"browser.new_context",
self._impl_obj.new_context(
viewport=viewport,
+ screen=screen,
noViewport=no_viewport,
ignoreHTTPSErrors=ignore_https_errors,
javaScriptEnabled=java_script_enabled,
@@ -8698,6 +8789,7 @@ async def new_page(
self,
*,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
no_viewport: bool = None,
ignore_https_errors: bool = None,
java_script_enabled: bool = None,
@@ -8735,6 +8827,9 @@ async def new_page(
----------
viewport : Union[{width: int, height: int}, NoneType]
Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed viewport.
+ screen : Union[{width: int, height: int}, NoneType]
+ Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
+ is set.
no_viewport : Union[bool, NoneType]
Does not enforce fixed viewport, allows resizing window in the headed mode.
ignore_https_errors : Union[bool, NoneType]
@@ -8806,6 +8901,7 @@ async def new_page(
"browser.new_page",
self._impl_obj.new_page(
viewport=viewport,
+ screen=screen,
noViewport=no_viewport,
ignoreHTTPSErrors=ignore_https_errors,
javaScriptEnabled=java_script_enabled,
@@ -8947,7 +9043,8 @@ async def launch(
resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium, Firefox
or WebKit, use at your own risk.
channel : Union["chrome", "chrome-beta", "chrome-canary", "chrome-dev", "msedge", "msedge-beta", "msedge-canary", "msedge-dev", NoneType]
- Browser distribution channel.
+ Browser distribution channel. Read more about using
+ [Google Chrome and Microsoft Edge](./browsers#google-chrome--microsoft-edge).
args : Union[List[str], NoneType]
Additional arguments to pass to the browser instance. The list of Chromium flags can be found
[here](http://peter.sh/experiments/chromium-command-line-switches/).
@@ -9043,6 +9140,7 @@ async def launch_persistent_context(
downloads_path: typing.Union[str, pathlib.Path] = None,
slow_mo: float = None,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
no_viewport: bool = None,
ignore_https_errors: bool = None,
java_script_enabled: bool = None,
@@ -9121,6 +9219,9 @@ async def launch_persistent_context(
Defaults to 0.
viewport : Union[{width: int, height: int}, NoneType]
Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed viewport.
+ screen : Union[{width: int, height: int}, NoneType]
+ Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
+ is set.
no_viewport : Union[bool, NoneType]
Does not enforce fixed viewport, allows resizing window in the headed mode.
ignore_https_errors : Union[bool, NoneType]
@@ -9201,6 +9302,7 @@ async def launch_persistent_context(
downloadsPath=downloads_path,
slowMo=slow_mo,
viewport=viewport,
+ screen=screen,
noViewport=no_viewport,
ignoreHTTPSErrors=ignore_https_errors,
javaScriptEnabled=java_script_enabled,
diff --git a/playwright/sync_api/_generated.py b/playwright/sync_api/_generated.py
index da05b60c5..dcf6e0375 100644
--- a/playwright/sync_api/_generated.py
+++ b/playwright/sync_api/_generated.py
@@ -815,7 +815,7 @@ def press(self, key: str, *, delay: float = None) -> NoneType:
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
```py
@@ -1368,8 +1368,8 @@ def is_visible(self) -> bool:
def dispatch_event(self, type: str, event_init: typing.Dict = None) -> NoneType:
"""ElementHandle.dispatch_event
- The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
- is dispatched. This is equivalend to calling
+ The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ `click` is dispatched. This is equivalent to calling
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
```py
@@ -1937,7 +1937,7 @@ def press(
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
Parameters
@@ -2696,6 +2696,47 @@ def expect_navigation(
).future,
)
+ def wait_for_url(
+ self,
+ url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
+ *,
+ wait_until: Literal["domcontentloaded", "load", "networkidle"] = None,
+ timeout: float = None
+ ) -> NoneType:
+ """Frame.wait_for_url
+
+ Waits for the frame to navigate to the given URL.
+
+ ```py
+ frame.click(\"a.delayed-navigation\") # clicking the link will indirectly cause a navigation
+ frame.wait_for_url(\"**/target.html\")
+ ```
+
+ Parameters
+ ----------
+ url : Union[Callable[[str], bool], Pattern, str]
+ A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ wait_until : Union["domcontentloaded", "load", "networkidle", NoneType]
+ When to consider operation succeeded, defaults to `load`. Events can be either:
+ - `'domcontentloaded'` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ - `'load'` - consider operation to be finished when the `load` event is fired.
+ - `'networkidle'` - consider operation to be finished when there are no network connections for at least `500` ms.
+ timeout : Union[float, NoneType]
+ Maximum operation 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_navigation_timeout()`,
+ `browser_context.set_default_timeout()`, `page.set_default_navigation_timeout()` or
+ `page.set_default_timeout()` methods.
+ """
+
+ return mapping.from_maybe_impl(
+ self._sync(
+ "frame.wait_for_url",
+ self._impl_obj.wait_for_url(
+ url=self._wrap_handler(url), wait_until=wait_until, timeout=timeout
+ ),
+ )
+ )
+
def wait_for_load_state(
self,
state: Literal["domcontentloaded", "load", "networkidle"] = None,
@@ -3151,8 +3192,8 @@ def dispatch_event(
) -> NoneType:
"""Frame.dispatch_event
- The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
- is dispatched. This is equivalend to calling
+ The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ `click` is dispatched. This is equivalent to calling
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
```py
@@ -4071,7 +4112,7 @@ def press(
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
Parameters
@@ -4867,6 +4908,7 @@ def set_default_navigation_timeout(self, timeout: float) -> NoneType:
- `page.reload()`
- `page.set_content()`
- `page.expect_navigation()`
+ - `page.wait_for_url()`
> NOTE: `page.set_default_navigation_timeout()` takes priority over `page.set_default_timeout()`,
`browser_context.set_default_timeout()` and `browser_context.set_default_navigation_timeout()`.
@@ -5180,8 +5222,8 @@ def dispatch_event(
) -> NoneType:
"""Page.dispatch_event
- The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
- is dispatched. This is equivalend to calling
+ The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ `click` is dispatched. This is equivalent to calling
[element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
```py
@@ -5866,6 +5908,49 @@ def wait_for_load_state(
)
)
+ def wait_for_url(
+ self,
+ url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
+ *,
+ wait_until: Literal["domcontentloaded", "load", "networkidle"] = None,
+ timeout: float = None
+ ) -> NoneType:
+ """Page.wait_for_url
+
+ Waits for the main frame to navigate to the given URL.
+
+ ```py
+ page.click(\"a.delayed-navigation\") # clicking the link will indirectly cause a navigation
+ page.wait_for_url(\"**/target.html\")
+ ```
+
+ Shortcut for main frame's `frame.wait_for_url()`.
+
+ Parameters
+ ----------
+ url : Union[Callable[[str], bool], Pattern, str]
+ A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation.
+ wait_until : Union["domcontentloaded", "load", "networkidle", NoneType]
+ When to consider operation succeeded, defaults to `load`. Events can be either:
+ - `'domcontentloaded'` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ - `'load'` - consider operation to be finished when the `load` event is fired.
+ - `'networkidle'` - consider operation to be finished when there are no network connections for at least `500` ms.
+ timeout : Union[float, NoneType]
+ Maximum operation 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_navigation_timeout()`,
+ `browser_context.set_default_timeout()`, `page.set_default_navigation_timeout()` or
+ `page.set_default_timeout()` methods.
+ """
+
+ return mapping.from_maybe_impl(
+ self._sync(
+ "page.wait_for_url",
+ self._impl_obj.wait_for_url(
+ url=self._wrap_handler(url), wait_until=wait_until, timeout=timeout
+ ),
+ )
+ )
+
def wait_for_event(
self, event: str, predicate: typing.Callable = None, *, timeout: float = None
) -> typing.Any:
@@ -6124,7 +6209,7 @@ def route(
> NOTE: The handler will only be called for the first url if the response is a redirect.
- An example of a naïve handler that aborts all image requests:
+ An example of a naive handler that aborts all image requests:
```py
page = browser.new_page()
@@ -6145,6 +6230,8 @@ def route(
Page routes take precedence over browser context routes (set up with `browser_context.route()`) when request
matches both handlers.
+ To remove a route with its handler you can use `page.unroute()`.
+
> NOTE: Enabling routing disables http cache.
Parameters
@@ -6208,9 +6295,6 @@ def screenshot(
Returns the buffer with the captured screenshot.
- > NOTE: Screenshots take at least 1/6 second on Chromium OS X and Chromium Windows. See https://crbug.com/741689 for
- discussion.
-
Parameters
----------
timeout : Union[float, NoneType]
@@ -6960,7 +7044,7 @@ def press(
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
texts.
- Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When speficied with the
+ Shortcuts such as `key: \"Control+o\"` or `key: \"Control+Shift+T\"` are supported as well. When specified with the
modifier, modifier is pressed and being held while the subsequent key is being pressed.
```py
@@ -8135,7 +8219,7 @@ def 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.
- An example of a naïve handler that aborts all image requests:
+ An example of a naive handler that aborts all image requests:
```py
context = browser.new_context()
@@ -8160,6 +8244,8 @@ def route(
Page routes (set up with `page.route()`) take precedence over browser context routes when request matches both
handlers.
+ To remove a route with its handler you can use `browser_context.unroute()`.
+
> NOTE: Enabling routing disables http cache.
Parameters
@@ -8499,6 +8585,7 @@ def new_context(
self,
*,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
no_viewport: bool = None,
ignore_https_errors: bool = None,
java_script_enabled: bool = None,
@@ -8541,6 +8628,9 @@ def new_context(
----------
viewport : Union[{width: int, height: int}, NoneType]
Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed viewport.
+ screen : Union[{width: int, height: int}, NoneType]
+ Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
+ is set.
no_viewport : Union[bool, NoneType]
Does not enforce fixed viewport, allows resizing window in the headed mode.
ignore_https_errors : Union[bool, NoneType]
@@ -8612,6 +8702,7 @@ def new_context(
"browser.new_context",
self._impl_obj.new_context(
viewport=viewport,
+ screen=screen,
noViewport=no_viewport,
ignoreHTTPSErrors=ignore_https_errors,
javaScriptEnabled=java_script_enabled,
@@ -8644,6 +8735,7 @@ def new_page(
self,
*,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
no_viewport: bool = None,
ignore_https_errors: bool = None,
java_script_enabled: bool = None,
@@ -8681,6 +8773,9 @@ def new_page(
----------
viewport : Union[{width: int, height: int}, NoneType]
Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed viewport.
+ screen : Union[{width: int, height: int}, NoneType]
+ Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
+ is set.
no_viewport : Union[bool, NoneType]
Does not enforce fixed viewport, allows resizing window in the headed mode.
ignore_https_errors : Union[bool, NoneType]
@@ -8752,6 +8847,7 @@ def new_page(
"browser.new_page",
self._impl_obj.new_page(
viewport=viewport,
+ screen=screen,
noViewport=no_viewport,
ignoreHTTPSErrors=ignore_https_errors,
javaScriptEnabled=java_script_enabled,
@@ -8893,7 +8989,8 @@ def launch(
resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium, Firefox
or WebKit, use at your own risk.
channel : Union["chrome", "chrome-beta", "chrome-canary", "chrome-dev", "msedge", "msedge-beta", "msedge-canary", "msedge-dev", NoneType]
- Browser distribution channel.
+ Browser distribution channel. Read more about using
+ [Google Chrome and Microsoft Edge](./browsers#google-chrome--microsoft-edge).
args : Union[List[str], NoneType]
Additional arguments to pass to the browser instance. The list of Chromium flags can be found
[here](http://peter.sh/experiments/chromium-command-line-switches/).
@@ -8989,6 +9086,7 @@ def launch_persistent_context(
downloads_path: typing.Union[str, pathlib.Path] = None,
slow_mo: float = None,
viewport: ViewportSize = None,
+ screen: ViewportSize = None,
no_viewport: bool = None,
ignore_https_errors: bool = None,
java_script_enabled: bool = None,
@@ -9067,6 +9165,9 @@ def launch_persistent_context(
Defaults to 0.
viewport : Union[{width: int, height: int}, NoneType]
Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed viewport.
+ screen : Union[{width: int, height: int}, NoneType]
+ Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the `viewport`
+ is set.
no_viewport : Union[bool, NoneType]
Does not enforce fixed viewport, allows resizing window in the headed mode.
ignore_https_errors : Union[bool, NoneType]
@@ -9147,6 +9248,7 @@ def launch_persistent_context(
downloadsPath=downloads_path,
slowMo=slow_mo,
viewport=viewport,
+ screen=screen,
noViewport=no_viewport,
ignoreHTTPSErrors=ignore_https_errors,
javaScriptEnabled=java_script_enabled,
diff --git a/setup.py b/setup.py
index b644a46be..a29749ac8 100644
--- a/setup.py
+++ b/setup.py
@@ -24,7 +24,7 @@
from auditwheel.wheeltools import InWheel
from wheel.bdist_wheel import bdist_wheel as BDistWheelCommand
-driver_version = "1.10.0-next-1616530863000"
+driver_version = "1.11.0-next-1617207797000"
def extractall(zip: zipfile.ZipFile, path: str) -> None:
diff --git a/tests/async/test_navigation.py b/tests/async/test_navigation.py
index e77bf77ff..d685e602f 100644
--- a/tests/async/test_navigation.py
+++ b/tests/async/test_navigation.py
@@ -440,9 +440,9 @@ async def test_wait_for_nav_should_work(page, server):
async def test_wait_for_nav_should_respect_timeout(page, server):
with pytest.raises(Error) as exc_info:
- async with page.expect_navigation(url="**/frame.html", timeout=5000):
+ async with page.expect_navigation(url="**/frame.html", timeout=2500):
await page.goto(server.EMPTY_PAGE)
- assert "Timeout 5000ms exceeded" in exc_info.value.message
+ assert "Timeout 2500ms exceeded" in exc_info.value.message
async def test_wait_for_nav_should_work_with_both_domcontentloaded_and_load(
@@ -866,9 +866,9 @@ async def test_frame_goto_should_continue_after_client_redirect(page, server):
url = server.PREFIX + "/frames/child-redirect.html"
with pytest.raises(Error) as exc_info:
- await page.goto(url, timeout=5000, wait_until="networkidle")
+ await page.goto(url, timeout=2500, wait_until="networkidle")
- assert "Timeout 5000ms exceeded." in exc_info.value.message
+ assert "Timeout 2500ms exceeded." in exc_info.value.message
assert (
f'navigating to "{url}", waiting until "networkidle"' in exc_info.value.message
)
diff --git a/tests/async/test_video.py b/tests/async/test_video.py
index bb6210da7..40e8ff0d7 100644
--- a/tests/async/test_video.py
+++ b/tests/async/test_video.py
@@ -14,6 +14,8 @@
import os
+import pytest
+
async def test_should_expose_video_path(browser, tmpdir, server):
page = await browser.new_page(record_video_dir=tmpdir)
@@ -23,6 +25,7 @@ async def test_should_expose_video_path(browser, tmpdir, server):
await page.context.close()
+@pytest.mark.skip("Upstream is changing, will fix with next roll")
async def test_short_video_should_exist(browser, tmpdir, server):
page = await browser.new_page(record_video_dir=tmpdir)
await page.goto(server.PREFIX + "/grid.html")
@@ -32,6 +35,7 @@ async def test_short_video_should_exist(browser, tmpdir, server):
assert os.path.exists(path)
+@pytest.mark.skip("Upstream is changing, will fix with next roll")
async def test_short_video_should_exist_persistent_context(
browser_type, tmpdir, launch_arguments
):
diff --git a/tests/async/test_wait_for_url.py b/tests/async/test_wait_for_url.py
new file mode 100644
index 000000000..4c4882170
--- /dev/null
+++ b/tests/async/test_wait_for_url.py
@@ -0,0 +1,122 @@
+# Copyright (c) Microsoft Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import re
+
+import pytest
+
+from playwright.async_api import Error, Page
+
+
+async def test_wait_for_url_should_work(page: Page, server):
+ await page.goto(server.EMPTY_PAGE)
+ await page.evaluate(
+ "url => window.location.href = url", server.PREFIX + "/grid.html"
+ )
+ await page.wait_for_url("**/grid.html")
+ assert "grid.html" in page.url
+
+
+async def test_wait_for_url_should_respect_timeout(page: Page, server):
+ await page.goto(server.EMPTY_PAGE)
+ with pytest.raises(Error) as exc_info:
+ await page.wait_for_url("**/frame.html", timeout=2500)
+ assert "Timeout 2500ms exceeded" in exc_info.value.message
+
+
+async def test_wait_for_url_should_work_with_both_domcontentloaded_and_load(
+ page: Page, server
+):
+ await page.goto(server.EMPTY_PAGE)
+ await page.wait_for_url("**/*", wait_until="domcontentloaded")
+ await page.wait_for_url("**/*", wait_until="load")
+
+
+async def test_wait_for_url_should_work_with_clicking_on_anchor_links(
+ page: Page, server
+):
+ await page.goto(server.EMPTY_PAGE)
+ await page.set_content('foobar')
+ await page.click("a")
+ await page.wait_for_url("**/*#foobar")
+ assert page.url == server.EMPTY_PAGE + "#foobar"
+
+
+async def test_wait_for_url_should_work_with_history_push_state(page: Page, server):
+ await page.goto(server.EMPTY_PAGE)
+ await page.set_content(
+ """
+ SPA
+
+ """
+ )
+ await page.click("a")
+ await page.wait_for_url("**/wow.html")
+ assert page.url == server.PREFIX + "/wow.html"
+
+
+async def test_wait_for_url_should_work_with_history_replace_state(page: Page, server):
+ await page.goto(server.EMPTY_PAGE)
+ await page.set_content(
+ """
+ SPA
+
+ """
+ )
+ await page.click("a")
+ await page.wait_for_url("**/replaced.html")
+ assert page.url == server.PREFIX + "/replaced.html"
+
+
+async def test_wait_for_url_should_work_with_dom_history_back_forward(
+ page: Page, server
+):
+ await page.goto(server.EMPTY_PAGE)
+ await page.set_content(
+ """
+ back
+ forward
+
+ """
+ )
+
+ assert page.url == server.PREFIX + "/second.html"
+
+ await page.click("a#back"),
+ await page.wait_for_url("**/first.html")
+ assert page.url == server.PREFIX + "/first.html"
+
+ await page.click("a#forward"),
+ await page.wait_for_url("**/second.html")
+ assert page.url == server.PREFIX + "/second.html"
+
+
+async def test_wait_for_url_should_work_with_url_match_for_same_document_navigations(
+ page: Page, server
+):
+ await page.goto(server.EMPTY_PAGE)
+ await page.evaluate("history.pushState({}, '', '/first.html')")
+ await page.evaluate("history.pushState({}, '', '/second.html')")
+ await page.evaluate("history.pushState({}, '', '/third.html')")
+ await page.wait_for_url(re.compile(r"third\.html"))
+ assert "/third.html" in page.url