From adb95fb7491b67b70afc848ab05ce5f0fecfa4cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:56:57 +0200 Subject: [PATCH 01/15] build(deps): bump pytest from 8.2.2 to 8.3.2 (#2500) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index cbe5301c3..e93b1d48a 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -9,7 +9,7 @@ Pillow==10.4.0 pixelmatch==0.3.0 pre-commit==3.4.0 pyOpenSSL==24.1.0 -pytest==8.2.2 +pytest==8.3.2 pytest-asyncio==0.21.2 pytest-cov==5.0.0 pytest-repeat==0.9.3 From ead662a3f26ab84f27609f4fb0cf14e00eceb813 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:57:06 +0200 Subject: [PATCH 02/15] build(deps): bump types-pyopenssl from 24.1.0.20240425 to 24.1.0.20240722 (#2494) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index e93b1d48a..8ce0084f2 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -19,6 +19,6 @@ requests==2.32.3 service_identity==24.1.0 setuptools==70.3.0 twisted==24.3.0 -types-pyOpenSSL==24.1.0.20240425 +types-pyOpenSSL==24.1.0.20240722 types-requests==2.32.0.20240712 wheel==0.42.0 From 0c305706594ffb3fc5167e0bcedb8fc72d7a21c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:57:20 +0200 Subject: [PATCH 03/15] build(deps): bump mypy from 1.10.1 to 1.11.0 (#2490) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index 8ce0084f2..b96c3dd73 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -3,7 +3,7 @@ autobahn==23.1.2 black==24.4.2 flake8==7.1.0 flaky==3.8.1 -mypy==1.10.1 +mypy==1.11.0 objgraph==3.6.1 Pillow==10.4.0 pixelmatch==0.3.0 From 2ba0188455ddbcd8bda625361c1dbd737027997c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:57:36 +0200 Subject: [PATCH 04/15] build(deps): bump setuptools from 70.3.0 to 72.1.0 (#2501) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index b96c3dd73..239edaef8 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -17,7 +17,7 @@ pytest-timeout==2.3.1 pytest-xdist==3.6.1 requests==2.32.3 service_identity==24.1.0 -setuptools==70.3.0 +setuptools==72.1.0 twisted==24.3.0 types-pyOpenSSL==24.1.0.20240722 types-requests==2.32.0.20240712 From c13cd03cecb508937fb664e82d1282f6aa52848a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:35:56 +0200 Subject: [PATCH 05/15] build(deps): bump pyopenssl from 24.1.0 to 24.2.1 (#2493) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index 239edaef8..a47b06315 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -8,7 +8,7 @@ objgraph==3.6.1 Pillow==10.4.0 pixelmatch==0.3.0 pre-commit==3.4.0 -pyOpenSSL==24.1.0 +pyOpenSSL==24.2.1 pytest==8.3.2 pytest-asyncio==0.21.2 pytest-cov==5.0.0 From 65658108c693c267638d7cc87c4b95f9257a122b Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 31 Jul 2024 09:39:03 +0200 Subject: [PATCH 06/15] chore(roll): roll Playwright to v1.46 (#2499) --- README.md | 6 +- playwright/_impl/_api_structures.py | 9 + playwright/_impl/_browser.py | 10 +- playwright/_impl/_browser_type.py | 4 +- playwright/_impl/_fetch.py | 26 +- playwright/_impl/_js_handle.py | 23 +- playwright/_impl/_network.py | 33 +- playwright/async_api/_generated.py | 403 ++++++++++-------- playwright/sync_api/_generated.py | 403 ++++++++++-------- scripts/generate_api.py | 2 +- setup.py | 2 +- tests/assets/client-certificates/README.md | 60 +++ .../client/trusted/cert.pem | 29 ++ .../client/trusted/csr.pem | 26 ++ .../client/trusted/key.pem | 52 +++ .../server/server_cert.pem | 32 ++ .../client-certificates/server/server_key.pem | 52 +++ ...test_browsercontext_client_certificates.py | 135 ++++++ tests/async/test_fetch_browser_context.py | 23 +- tests/async/test_fetch_global.py | 25 +- ...test_evaluate.py => test_page_evaluate.py} | 48 ++- ...test_browsercontext_client_certificates.py | 135 ++++++ 22 files changed, 1174 insertions(+), 364 deletions(-) create mode 100644 tests/assets/client-certificates/README.md create mode 100644 tests/assets/client-certificates/client/trusted/cert.pem create mode 100644 tests/assets/client-certificates/client/trusted/csr.pem create mode 100644 tests/assets/client-certificates/client/trusted/key.pem create mode 100644 tests/assets/client-certificates/server/server_cert.pem create mode 100644 tests/assets/client-certificates/server/server_key.pem create mode 100644 tests/async/test_browsercontext_client_certificates.py rename tests/async/{test_evaluate.py => test_page_evaluate.py} (86%) create mode 100644 tests/sync/test_browsercontext_client_certificates.py diff --git a/README.md b/README.md index 92cd726ab..fdd043e95 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ Playwright is a Python library to automate [Chromium](https://www.chromium.org/H | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 127.0.6533.17 | ✅ | ✅ | ✅ | -| WebKit 17.4 | ✅ | ✅ | ✅ | -| Firefox 127.0 | ✅ | ✅ | ✅ | +| Chromium 128.0.6613.7 | ✅ | ✅ | ✅ | +| WebKit 18.0 | ✅ | ✅ | ✅ | +| Firefox 128.0 | ✅ | ✅ | ✅ | ## Documentation diff --git a/playwright/_impl/_api_structures.py b/playwright/_impl/_api_structures.py index ba46c2a71..34cfc8a48 100644 --- a/playwright/_impl/_api_structures.py +++ b/playwright/_impl/_api_structures.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +from pathlib import Path from typing import Any, Dict, List, Literal, Optional, Sequence, TypedDict, Union # These are the structures that we like keeping in a JSON form for their potential @@ -100,6 +101,14 @@ class StorageState(TypedDict, total=False): origins: List[OriginState] +class ClientCertificate(TypedDict, total=False): + origin: str + certPath: Optional[Union[str, Path]] + keyPath: Optional[Union[str, Path]] + pfxPath: Optional[Union[str, Path]] + passphrase: Optional[str] + + class ResourceTiming(TypedDict): startTime: float domainLookupStart: float diff --git a/playwright/_impl/_browser.py b/playwright/_impl/_browser.py index 8a248f703..c5a9022a3 100644 --- a/playwright/_impl/_browser.py +++ b/playwright/_impl/_browser.py @@ -18,6 +18,7 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Pattern, Sequence, Union, cast from playwright._impl._api_structures import ( + ClientCertificate, Geolocation, HttpCredentials, ProxySettings, @@ -41,7 +42,7 @@ make_dirs_for_file, prepare_record_har_options, ) -from playwright._impl._network import serialize_headers +from playwright._impl._network import serialize_headers, to_client_certificates_protocol from playwright._impl._page import Page if TYPE_CHECKING: # pragma: no cover @@ -120,6 +121,7 @@ async def new_context( recordHarUrlFilter: Union[Pattern[str], str] = None, recordHarMode: HarMode = None, recordHarContent: HarContentPolicy = None, + clientCertificates: List[ClientCertificate] = None, ) -> BrowserContext: params = locals_to_params(locals()) await prepare_browser_context_params(params) @@ -165,6 +167,7 @@ async def new_page( recordHarUrlFilter: Union[Pattern[str], str] = None, recordHarMode: HarMode = None, recordHarContent: HarContentPolicy = None, + clientCertificates: List[ClientCertificate] = None, ) -> Page: params = locals_to_params(locals()) @@ -253,3 +256,8 @@ async def prepare_browser_context_params(params: Dict) -> None: params["forcedColors"] = "no-override" if "acceptDownloads" in params: params["acceptDownloads"] = "accept" if params["acceptDownloads"] else "deny" + + if "clientCertificates" in params: + params["clientCertificates"] = await to_client_certificates_protocol( + params["clientCertificates"] + ) diff --git a/playwright/_impl/_browser_type.py b/playwright/_impl/_browser_type.py index 00e146061..70525949c 100644 --- a/playwright/_impl/_browser_type.py +++ b/playwright/_impl/_browser_type.py @@ -15,9 +15,10 @@ import asyncio import pathlib from pathlib import Path -from typing import TYPE_CHECKING, Dict, Optional, Pattern, Sequence, Union, cast +from typing import TYPE_CHECKING, Dict, List, Optional, Pattern, Sequence, Union, cast from playwright._impl._api_structures import ( + ClientCertificate, Geolocation, HttpCredentials, ProxySettings, @@ -147,6 +148,7 @@ async def launch_persistent_context( recordHarUrlFilter: Union[Pattern[str], str] = None, recordHarMode: HarMode = None, recordHarContent: HarContentPolicy = None, + clientCertificates: List[ClientCertificate] = None, ) -> BrowserContext: userDataDir = str(Path(userDataDir)) if userDataDir else "" params = locals_to_params(locals()) diff --git a/playwright/_impl/_fetch.py b/playwright/_impl/_fetch.py index da17c169c..8dde5a541 100644 --- a/playwright/_impl/_fetch.py +++ b/playwright/_impl/_fetch.py @@ -21,6 +21,7 @@ import playwright._impl._network as network from playwright._impl._api_structures import ( + ClientCertificate, FilePayload, FormField, Headers, @@ -42,7 +43,7 @@ object_to_array, to_impl, ) -from playwright._impl._network import serialize_headers +from playwright._impl._network import serialize_headers, to_client_certificates_protocol from playwright._impl._tracing import Tracing if typing.TYPE_CHECKING: @@ -71,6 +72,7 @@ async def new_context( userAgent: str = None, timeout: float = None, storageState: Union[StorageState, str, Path] = None, + clientCertificates: List[ClientCertificate] = None, ) -> "APIRequestContext": params = locals_to_params(locals()) if "storageState" in params: @@ -81,6 +83,9 @@ async def new_context( ) if "extraHTTPHeaders" in params: params["extraHTTPHeaders"] = serialize_headers(params["extraHTTPHeaders"]) + params["clientCertificates"] = await to_client_certificates_protocol( + params.get("clientCertificates") + ) context = cast( APIRequestContext, from_channel(await self.playwright._channel.send("newRequest", params)), @@ -118,6 +123,7 @@ async def delete( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": return await self.fetch( url, @@ -131,6 +137,7 @@ async def delete( failOnStatusCode=failOnStatusCode, ignoreHTTPSErrors=ignoreHTTPSErrors, maxRedirects=maxRedirects, + maxRetries=maxRetries, ) async def head( @@ -145,6 +152,7 @@ async def head( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": return await self.fetch( url, @@ -158,6 +166,7 @@ async def head( failOnStatusCode=failOnStatusCode, ignoreHTTPSErrors=ignoreHTTPSErrors, maxRedirects=maxRedirects, + maxRetries=maxRetries, ) async def get( @@ -172,6 +181,7 @@ async def get( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": return await self.fetch( url, @@ -185,6 +195,7 @@ async def get( failOnStatusCode=failOnStatusCode, ignoreHTTPSErrors=ignoreHTTPSErrors, maxRedirects=maxRedirects, + maxRetries=maxRetries, ) async def patch( @@ -199,6 +210,7 @@ async def patch( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": return await self.fetch( url, @@ -212,6 +224,7 @@ async def patch( failOnStatusCode=failOnStatusCode, ignoreHTTPSErrors=ignoreHTTPSErrors, maxRedirects=maxRedirects, + maxRetries=maxRetries, ) async def put( @@ -226,6 +239,7 @@ async def put( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": return await self.fetch( url, @@ -239,6 +253,7 @@ async def put( failOnStatusCode=failOnStatusCode, ignoreHTTPSErrors=ignoreHTTPSErrors, maxRedirects=maxRedirects, + maxRetries=maxRetries, ) async def post( @@ -253,6 +268,7 @@ async def post( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": return await self.fetch( url, @@ -266,6 +282,7 @@ async def post( failOnStatusCode=failOnStatusCode, ignoreHTTPSErrors=ignoreHTTPSErrors, maxRedirects=maxRedirects, + maxRetries=maxRetries, ) async def fetch( @@ -281,6 +298,7 @@ async def fetch( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": url = urlOrRequest if isinstance(urlOrRequest, str) else None request = ( @@ -304,6 +322,7 @@ async def fetch( failOnStatusCode, ignoreHTTPSErrors, maxRedirects, + maxRetries, ) async def _inner_fetch( @@ -320,6 +339,7 @@ async def _inner_fetch( failOnStatusCode: bool = None, ignoreHTTPSErrors: bool = None, maxRedirects: int = None, + maxRetries: int = None, ) -> "APIResponse": if self._close_reason: raise TargetClosedError(self._close_reason) @@ -329,6 +349,9 @@ async def _inner_fetch( assert ( maxRedirects is None or maxRedirects >= 0 ), "'max_redirects' must be greater than or equal to '0'" + assert ( + maxRetries is None or maxRetries >= 0 + ), "'max_retries' must be greater than or equal to '0'" url = url or (request.url if request else url) method = method or (request.method if request else "GET") # Cannot call allHeaders() here as the request may be paused inside route handler. @@ -392,6 +415,7 @@ async def _inner_fetch( "failOnStatusCode": failOnStatusCode, "ignoreHTTPSErrors": ignoreHTTPSErrors, "maxRedirects": maxRedirects, + "maxRetries": maxRetries, }, ) return APIResponse(self, response) diff --git a/playwright/_impl/_js_handle.py b/playwright/_impl/_js_handle.py index 415d79a76..a8be0ee18 100644 --- a/playwright/_impl/_js_handle.py +++ b/playwright/_impl/_js_handle.py @@ -15,12 +15,13 @@ import collections.abc import datetime import math +import traceback from pathlib import Path from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from urllib.parse import ParseResult, urlparse, urlunparse from playwright._impl._connection import Channel, ChannelOwner, from_channel -from playwright._impl._errors import is_target_closed_error +from playwright._impl._errors import Error, is_target_closed_error from playwright._impl._map import Map if TYPE_CHECKING: # pragma: no cover @@ -140,6 +141,20 @@ def serialize_value( value.astimezone(datetime.timezone.utc), "%Y-%m-%dT%H:%M:%S.%fZ" ) } + if isinstance(value, Exception): + return { + "e": { + "m": str(value), + "n": (value.name or "") + if isinstance(value, Error) + else value.__class__.__name__, + "s": (value.stack or "") + if isinstance(value, Error) + else "".join( + traceback.format_exception(type(value), value=value, tb=None) + ), + } + } if isinstance(value, bool): return {"b": value} if isinstance(value, (int, float)): @@ -207,6 +222,12 @@ def parse_value(value: Any, refs: Optional[Dict[int, Any]] = None) -> Any: if "bi" in value: return int(value["bi"]) + if "e" in value: + error = Error(value["e"]["m"]) + error._name = value["e"]["n"] + error._stack = value["e"]["s"] + return error + if "a" in value: a: List = [] refs[value["id"]] = a diff --git a/playwright/_impl/_network.py b/playwright/_impl/_network.py index 3656a01cc..d6df048bc 100644 --- a/playwright/_impl/_network.py +++ b/playwright/_impl/_network.py @@ -36,6 +36,7 @@ from urllib import parse from playwright._impl._api_structures import ( + ClientCertificate, Headers, HeadersArray, RemoteAddr, @@ -50,7 +51,7 @@ ) from playwright._impl._errors import Error from playwright._impl._event_context_manager import EventContextManagerImpl -from playwright._impl._helper import locals_to_params +from playwright._impl._helper import async_readfile, locals_to_params from playwright._impl._waiter import Waiter if TYPE_CHECKING: # pragma: no cover @@ -83,6 +84,34 @@ def serialize_headers(headers: Dict[str, str]) -> HeadersArray: ] +async def to_client_certificates_protocol( + clientCertificates: Optional[List[ClientCertificate]], +) -> Optional[List[Dict[str, str]]]: + if not clientCertificates: + return None + out = [] + for clientCertificate in clientCertificates: + out_record = { + "origin": clientCertificate["origin"], + } + if passphrase := clientCertificate.get("passphrase"): + out_record["passphrase"] = passphrase + if pfx_path := clientCertificate.get("pfxPath"): + out_record["pfx"] = base64.b64encode( + await async_readfile(pfx_path) + ).decode() + if cert_path := clientCertificate.get("certPath"): + out_record["cert"] = base64.b64encode( + await async_readfile(cert_path) + ).decode() + if key_path := clientCertificate.get("keyPath"): + out_record["key"] = base64.b64encode( + await async_readfile(key_path) + ).decode() + out.append(out_record) + return out + + class Request(ChannelOwner): def __init__( self, parent: ChannelOwner, type: str, guid: str, initializer: Dict @@ -410,6 +439,7 @@ async def fetch( headers: Dict[str, str] = None, postData: Union[Any, str, bytes] = None, maxRedirects: int = None, + maxRetries: int = None, timeout: float = None, ) -> "APIResponse": return await self._connection.wrap_api_call( @@ -420,6 +450,7 @@ async def fetch( headers, postData, maxRedirects=maxRedirects, + maxRetries=maxRetries, timeout=timeout, ) ) diff --git a/playwright/async_api/_generated.py b/playwright/async_api/_generated.py index 0a866ef75..dbd9a36b7 100644 --- a/playwright/async_api/_generated.py +++ b/playwright/async_api/_generated.py @@ -20,6 +20,7 @@ from playwright._impl._accessibility import Accessibility as AccessibilityImpl from playwright._impl._api_structures import ( + ClientCertificate, Cookie, FilePayload, FloatRect, @@ -365,7 +366,7 @@ async def headers_array(self) -> typing.List[NameValue]: async def header_value(self, name: str) -> typing.Optional[str]: """Request.header_value - Returns the value of the header matching the name. The name is case insensitive. + Returns the value of the header matching the name. The name is case-insensitive. Parameters ---------- @@ -512,7 +513,7 @@ async def headers_array(self) -> typing.List[NameValue]: async def header_value(self, name: str) -> typing.Optional[str]: """Response.header_value - Returns the value of the header matching the name. The name is case insensitive. If multiple headers have the same + Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have the same name (except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\\n` separator is used. If no headers are found, `null` is returned. @@ -531,7 +532,7 @@ async def header_value(self, name: str) -> typing.Optional[str]: async def header_values(self, name: str) -> typing.List[str]: """Response.header_values - Returns all values of the headers matching the name, for example `set-cookie`. The name is case insensitive. + Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive. Parameters ---------- @@ -733,6 +734,7 @@ async def fetch( headers: typing.Optional[typing.Dict[str, str]] = None, post_data: typing.Optional[typing.Union[typing.Any, str, bytes]] = None, max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None, timeout: typing.Optional[float] = None ) -> "APIResponse": """Route.fetch @@ -773,6 +775,9 @@ async def handle(route): max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. timeout : Union[float, None] Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. @@ -788,6 +793,7 @@ async def handle(route): headers=mapping.to_impl(headers), postData=mapping.to_impl(post_data), maxRedirects=max_redirects, + maxRetries=max_retries, timeout=timeout, ) ) @@ -1301,7 +1307,9 @@ async def move( Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. steps : Union[int, None] Defaults to 1. Sends intermediate `mousemove` events. """ @@ -1368,7 +1376,9 @@ async def click( Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. delay : Union[float, None] Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0. button : Union["left", "middle", "right", None] @@ -1399,7 +1409,9 @@ async def dblclick( Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. delay : Union[float, None] Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0. button : Union["left", "middle", "right", None] @@ -1446,7 +1458,9 @@ async def tap(self, x: float, y: float) -> None: Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. """ return mapping.from_maybe_impl(await self._impl_obj.tap(x=x, y=y)) @@ -1867,7 +1881,6 @@ async def hover( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -1887,9 +1900,8 @@ async def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. trial : Union[bool, None] @@ -1960,6 +1972,7 @@ async def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -1999,8 +2012,6 @@ async def dblclick( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if - the first click of the `dblclick()` triggers a navigation event, this method will throw. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2028,9 +2039,8 @@ async def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2108,6 +2118,7 @@ async def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. Returns ------- @@ -2144,7 +2155,6 @@ async def tap( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2168,9 +2178,8 @@ async def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2215,9 +2224,8 @@ async def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. """ @@ -2311,9 +2319,8 @@ async def set_input_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -2357,9 +2364,8 @@ async def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -2413,6 +2419,7 @@ async def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. """ return mapping.from_maybe_impl( @@ -2440,7 +2447,6 @@ async def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -2459,9 +2465,8 @@ async def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2495,7 +2500,6 @@ async def check( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2514,9 +2518,8 @@ async def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2549,7 +2552,6 @@ async def uncheck( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2568,9 +2570,8 @@ async def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -3066,9 +3067,8 @@ async def set_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -4083,7 +4083,7 @@ async def add_script_tag( content : Union[str, None] Raw JavaScript content to be injected into frame. type : Union[str, None] - Script type. Use 'module' in order to load a Javascript ES6 module. See + Script type. Use 'module' in order to load a JavaScript ES6 module. See [script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. Returns @@ -4187,6 +4187,7 @@ async def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -4234,8 +4235,7 @@ async def dblclick( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. - 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if + 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. if the first click of the `dblclick()` triggers a navigation event, this method will throw. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -4265,9 +4265,8 @@ async def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -4313,7 +4312,6 @@ async def tap( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -4338,9 +4336,8 @@ async def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -4396,9 +4393,8 @@ async def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5158,7 +5154,6 @@ async def hover( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -5179,9 +5174,8 @@ async def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. strict : Union[bool, None] @@ -5237,9 +5231,8 @@ async def drag_and_drop( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5326,6 +5319,7 @@ async def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5427,9 +5421,8 @@ async def set_input_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -5477,9 +5470,8 @@ async def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -5544,6 +5536,7 @@ async def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. """ return mapping.from_maybe_impl( @@ -5578,7 +5571,6 @@ async def check( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -5598,9 +5590,8 @@ async def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5642,7 +5633,6 @@ async def uncheck( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -5662,9 +5652,8 @@ async def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5808,7 +5797,6 @@ async def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -5830,9 +5818,8 @@ async def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -8508,7 +8495,7 @@ async def add_script_tag( content : Union[str, None] Raw JavaScript content to be injected into frame. type : Union[str, None] - Script type. Use 'module' in order to load a Javascript ES6 module. See + Script type. Use 'module' in order to load a JavaScript ES6 module. See [script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. Returns @@ -9008,7 +8995,7 @@ async def go_back( """Page.go_back Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of - the last redirect. If can not go back, returns `null`. + the last redirect. If cannot go back, returns `null`. Navigate to the previous page in history. @@ -9048,7 +9035,7 @@ async def go_forward( """Page.go_forward Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of - the last redirect. If can not go forward, returns `null`. + the last redirect. If cannot go forward, returns `null`. Navigate to the next page in history. @@ -9619,6 +9606,7 @@ async def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -9667,8 +9655,6 @@ async def dblclick( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if - the first click of the `dblclick()` triggers a navigation event, this method will throw. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -9697,9 +9683,8 @@ async def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -9745,7 +9730,6 @@ async def tap( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -9770,9 +9754,8 @@ async def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -9828,9 +9811,8 @@ async def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -10588,7 +10570,6 @@ async def hover( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -10609,9 +10590,8 @@ async def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. strict : Union[bool, None] @@ -10683,9 +10663,8 @@ async def drag_and_drop( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. timeout : Union[float, None] Maximum time in milliseconds. Defaults to `30000` (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. @@ -10773,6 +10752,7 @@ async def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. strict : Union[bool, None] @@ -10875,9 +10855,8 @@ async def set_input_files( When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -10922,9 +10901,8 @@ async def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11005,6 +10983,7 @@ async def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11042,7 +11021,6 @@ async def check( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -11062,9 +11040,8 @@ async def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11106,7 +11083,6 @@ async def uncheck( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -11126,9 +11102,8 @@ async def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11836,7 +11811,6 @@ async def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -11858,9 +11832,8 @@ async def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -12589,9 +12562,6 @@ async def add_cookies(self, cookies: typing.Sequence[SetCookieParam]) -> None: Parameters ---------- cookies : Sequence[{name: str, value: str, url: Union[str, None], domain: Union[str, None], path: Union[str, None], expires: Union[float, None], httpOnly: Union[bool, None], secure: Union[bool, None], sameSite: Union["Lax", "None", "Strict", None]}] - Adds cookies to the browser context. - - For the cookie to apply to all subdomains as well, prefix domain with a dot, like this: ".example.com". """ return mapping.from_maybe_impl( @@ -13469,7 +13439,8 @@ async def new_context( typing.Union[str, typing.Pattern[str]] ] = None, record_har_mode: typing.Optional[Literal["full", "minimal"]] = None, - record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None + record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "BrowserContext": """Browser.new_context @@ -13610,6 +13581,20 @@ async def new_context( Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persisted as separate files and all of these files are archived along with the HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -13652,6 +13637,7 @@ async def new_context( recordHarUrlFilter=record_har_url_filter, recordHarMode=record_har_mode, recordHarContent=record_har_content, + clientCertificates=client_certificates, ) ) @@ -13699,7 +13685,8 @@ async def new_page( typing.Union[str, typing.Pattern[str]] ] = None, record_har_mode: typing.Optional[Literal["full", "minimal"]] = None, - record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None + record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "Page": """Browser.new_page @@ -13824,6 +13811,20 @@ async def new_page( Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persisted as separate files and all of these files are archived along with the HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -13866,6 +13867,7 @@ async def new_page( recordHarUrlFilter=record_har_url_filter, recordHarMode=record_har_mode, recordHarContent=record_har_content, + clientCertificates=client_certificates, ) ) @@ -14196,7 +14198,8 @@ async def launch_persistent_context( typing.Union[str, typing.Pattern[str]] ] = None, record_har_mode: typing.Optional[Literal["full", "minimal"]] = None, - record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None + record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "BrowserContext": """BrowserType.launch_persistent_context @@ -14367,6 +14370,20 @@ async def launch_persistent_context( Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persisted as separate files and all of these files are archived along with the HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -14424,6 +14441,7 @@ async def launch_persistent_context( recordHarUrlFilter=record_har_url_filter, recordHarMode=record_har_mode, recordHarContent=record_har_content, + clientCertificates=client_certificates, ) ) @@ -14922,7 +14940,6 @@ async def check( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -14947,9 +14964,8 @@ async def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -15037,6 +15053,7 @@ async def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -15080,8 +15097,6 @@ async def dblclick( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if - the first click of the `dblclick()` triggers a navigation event, this method will throw. If the element is detached from the DOM at any moment during the action, this method throws. @@ -15109,9 +15124,8 @@ async def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -15370,9 +15384,8 @@ async def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. """ @@ -15416,9 +15429,8 @@ async def clear( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. """ @@ -16262,9 +16274,8 @@ async def drag_to( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. timeout : Union[float, None] Maximum time in milliseconds. Defaults to `30000` (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. @@ -16346,7 +16357,6 @@ async def hover( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -16366,9 +16376,8 @@ async def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. trial : Union[bool, None] @@ -16681,6 +16690,7 @@ async def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. """ return mapping.from_maybe_impl( @@ -16886,6 +16896,7 @@ async def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. @@ -16992,9 +17003,8 @@ async def set_input_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -17025,7 +17035,6 @@ async def tap( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -17049,9 +17058,8 @@ async def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -17120,9 +17128,8 @@ async def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -17174,9 +17181,8 @@ async def press_sequentially( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -17212,7 +17218,6 @@ async def uncheck( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -17231,9 +17236,8 @@ async def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -17361,7 +17365,6 @@ async def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -17380,9 +17383,8 @@ async def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -17568,7 +17570,8 @@ async def delete( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.delete @@ -17607,6 +17610,9 @@ async def delete( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17625,6 +17631,7 @@ async def delete( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) @@ -17644,7 +17651,8 @@ async def head( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.head @@ -17683,6 +17691,9 @@ async def head( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17701,6 +17712,7 @@ async def head( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) @@ -17720,7 +17732,8 @@ async def get( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.get @@ -17771,6 +17784,9 @@ async def get( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17789,6 +17805,7 @@ async def get( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) @@ -17808,7 +17825,8 @@ async def patch( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.patch @@ -17847,6 +17865,9 @@ async def patch( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17865,6 +17886,7 @@ async def patch( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) @@ -17884,7 +17906,8 @@ async def put( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.put @@ -17923,6 +17946,9 @@ async def put( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17941,6 +17967,7 @@ async def put( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) @@ -17960,7 +17987,8 @@ async def post( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.post @@ -18030,6 +18058,9 @@ async def post( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -18048,6 +18079,7 @@ async def post( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) @@ -18068,7 +18100,8 @@ async def fetch( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.fetch @@ -18124,6 +18157,9 @@ async def fetch( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -18143,6 +18179,7 @@ async def fetch( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) @@ -18184,7 +18221,8 @@ async def new_context( timeout: typing.Optional[float] = None, storage_state: typing.Optional[ typing.Union[StorageState, str, pathlib.Path] - ] = None + ] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "APIRequestContext": """APIRequest.new_context @@ -18220,6 +18258,20 @@ async def new_context( information obtained via `browser_context.storage_state()` or `a_pi_request_context.storage_state()`. Either a path to the file with saved storage, or the value returned by one of `browser_context.storage_state()` or `a_pi_request_context.storage_state()` methods. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -18236,6 +18288,7 @@ async def new_context( userAgent=user_agent, timeout=timeout, storageState=storage_state, + clientCertificates=client_certificates, ) ) diff --git a/playwright/sync_api/_generated.py b/playwright/sync_api/_generated.py index 2f28abbb9..aa4e60166 100644 --- a/playwright/sync_api/_generated.py +++ b/playwright/sync_api/_generated.py @@ -20,6 +20,7 @@ from playwright._impl._accessibility import Accessibility as AccessibilityImpl from playwright._impl._api_structures import ( + ClientCertificate, Cookie, FilePayload, FloatRect, @@ -365,7 +366,7 @@ def headers_array(self) -> typing.List[NameValue]: def header_value(self, name: str) -> typing.Optional[str]: """Request.header_value - Returns the value of the header matching the name. The name is case insensitive. + Returns the value of the header matching the name. The name is case-insensitive. Parameters ---------- @@ -514,7 +515,7 @@ def headers_array(self) -> typing.List[NameValue]: def header_value(self, name: str) -> typing.Optional[str]: """Response.header_value - Returns the value of the header matching the name. The name is case insensitive. If multiple headers have the same + Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have the same name (except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\\n` separator is used. If no headers are found, `null` is returned. @@ -535,7 +536,7 @@ def header_value(self, name: str) -> typing.Optional[str]: def header_values(self, name: str) -> typing.List[str]: """Response.header_values - Returns all values of the headers matching the name, for example `set-cookie`. The name is case insensitive. + Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive. Parameters ---------- @@ -743,6 +744,7 @@ def fetch( headers: typing.Optional[typing.Dict[str, str]] = None, post_data: typing.Optional[typing.Union[typing.Any, str, bytes]] = None, max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None, timeout: typing.Optional[float] = None ) -> "APIResponse": """Route.fetch @@ -783,6 +785,9 @@ def handle(route): max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. timeout : Union[float, None] Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. @@ -799,6 +804,7 @@ def handle(route): headers=mapping.to_impl(headers), postData=mapping.to_impl(post_data), maxRedirects=max_redirects, + maxRetries=max_retries, timeout=timeout, ) ) @@ -1299,7 +1305,9 @@ def move(self, x: float, y: float, *, steps: typing.Optional[int] = None) -> Non Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. steps : Union[int, None] Defaults to 1. Sends intermediate `mousemove` events. """ @@ -1368,7 +1376,9 @@ def click( Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. delay : Union[float, None] Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0. button : Union["left", "middle", "right", None] @@ -1401,7 +1411,9 @@ def dblclick( Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. delay : Union[float, None] Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0. button : Union["left", "middle", "right", None] @@ -1448,7 +1460,9 @@ def tap(self, x: float, y: float) -> None: Parameters ---------- x : float + X coordinate relative to the main frame's viewport in CSS pixels. y : float + Y coordinate relative to the main frame's viewport in CSS pixels. """ return mapping.from_maybe_impl(self._sync(self._impl_obj.tap(x=x, y=y))) @@ -1875,7 +1889,6 @@ def hover( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -1895,9 +1908,8 @@ def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. trial : Union[bool, None] @@ -1970,6 +1982,7 @@ def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2011,8 +2024,6 @@ def dblclick( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if - the first click of the `dblclick()` triggers a navigation event, this method will throw. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2040,9 +2051,8 @@ def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2122,6 +2132,7 @@ def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. Returns ------- @@ -2160,7 +2171,6 @@ def tap( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2184,9 +2194,8 @@ def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2233,9 +2242,8 @@ def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. """ @@ -2331,9 +2339,8 @@ def set_input_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -2381,9 +2388,8 @@ def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -2439,6 +2445,7 @@ def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. """ return mapping.from_maybe_impl( @@ -2468,7 +2475,6 @@ def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -2487,9 +2493,8 @@ def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2525,7 +2530,6 @@ def check( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2544,9 +2548,8 @@ def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -2581,7 +2584,6 @@ def uncheck( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -2600,9 +2602,8 @@ def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -3112,9 +3113,8 @@ def set_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -4158,7 +4158,7 @@ def add_script_tag( content : Union[str, None] Raw JavaScript content to be injected into frame. type : Union[str, None] - Script type. Use 'module' in order to load a Javascript ES6 module. See + Script type. Use 'module' in order to load a JavaScript ES6 module. See [script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. Returns @@ -4266,6 +4266,7 @@ def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -4315,8 +4316,7 @@ def dblclick( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. - 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if + 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. if the first click of the `dblclick()` triggers a navigation event, this method will throw. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -4346,9 +4346,8 @@ def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -4396,7 +4395,6 @@ def tap( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -4421,9 +4419,8 @@ def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -4481,9 +4478,8 @@ def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5253,7 +5249,6 @@ def hover( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -5274,9 +5269,8 @@ def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. strict : Union[bool, None] @@ -5334,9 +5328,8 @@ def drag_and_drop( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5425,6 +5418,7 @@ def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5530,9 +5524,8 @@ def set_input_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -5582,9 +5575,8 @@ def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -5651,6 +5643,7 @@ def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. """ return mapping.from_maybe_impl( @@ -5687,7 +5680,6 @@ def check( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -5707,9 +5699,8 @@ def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5753,7 +5744,6 @@ def uncheck( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -5773,9 +5763,8 @@ def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -5920,7 +5909,6 @@ def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -5942,9 +5930,8 @@ def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -8537,7 +8524,7 @@ def add_script_tag( content : Union[str, None] Raw JavaScript content to be injected into frame. type : Union[str, None] - Script type. Use 'module' in order to load a Javascript ES6 module. See + Script type. Use 'module' in order to load a JavaScript ES6 module. See [script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. Returns @@ -9049,7 +9036,7 @@ def go_back( """Page.go_back Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of - the last redirect. If can not go back, returns `null`. + the last redirect. If cannot go back, returns `null`. Navigate to the previous page in history. @@ -9089,7 +9076,7 @@ def go_forward( """Page.go_forward Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of - the last redirect. If can not go forward, returns `null`. + the last redirect. If cannot go forward, returns `null`. Navigate to the next page in history. @@ -9671,6 +9658,7 @@ def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -9721,8 +9709,6 @@ def dblclick( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if - the first click of the `dblclick()` triggers a navigation event, this method will throw. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -9751,9 +9737,8 @@ def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -9801,7 +9786,6 @@ def tap( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -9826,9 +9810,8 @@ def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -9886,9 +9869,8 @@ def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -10656,7 +10638,6 @@ def hover( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing zero timeout disables this. @@ -10677,9 +10658,8 @@ def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. strict : Union[bool, None] @@ -10753,9 +10733,8 @@ def drag_and_drop( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. timeout : Union[float, None] Maximum time in milliseconds. Defaults to `30000` (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. @@ -10845,6 +10824,7 @@ def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. strict : Union[bool, None] @@ -10951,9 +10931,8 @@ def set_input_files( When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -11000,9 +10979,8 @@ def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11085,6 +11063,7 @@ def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11124,7 +11103,6 @@ def check( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -11144,9 +11122,8 @@ def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11190,7 +11167,6 @@ def uncheck( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -11210,9 +11186,8 @@ def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -11923,7 +11898,6 @@ def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -11945,9 +11919,8 @@ def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. strict : Union[bool, None] When true, the call requires selector to resolve to a single element. If given selector resolves to more than one element, the call throws an exception. @@ -12614,9 +12587,6 @@ def add_cookies(self, cookies: typing.Sequence[SetCookieParam]) -> None: Parameters ---------- cookies : Sequence[{name: str, value: str, url: Union[str, None], domain: Union[str, None], path: Union[str, None], expires: Union[float, None], httpOnly: Union[bool, None], secure: Union[bool, None], sameSite: Union["Lax", "None", "Strict", None]}] - Adds cookies to the browser context. - - For the cookie to apply to all subdomains as well, prefix domain with a dot, like this: ".example.com". """ return mapping.from_maybe_impl( @@ -13501,7 +13471,8 @@ def new_context( typing.Union[str, typing.Pattern[str]] ] = None, record_har_mode: typing.Optional[Literal["full", "minimal"]] = None, - record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None + record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "BrowserContext": """Browser.new_context @@ -13642,6 +13613,20 @@ def new_context( Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persisted as separate files and all of these files are archived along with the HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -13685,6 +13670,7 @@ def new_context( recordHarUrlFilter=record_har_url_filter, recordHarMode=record_har_mode, recordHarContent=record_har_content, + clientCertificates=client_certificates, ) ) ) @@ -13733,7 +13719,8 @@ def new_page( typing.Union[str, typing.Pattern[str]] ] = None, record_har_mode: typing.Optional[Literal["full", "minimal"]] = None, - record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None + record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "Page": """Browser.new_page @@ -13858,6 +13845,20 @@ def new_page( Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persisted as separate files and all of these files are archived along with the HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -13901,6 +13902,7 @@ def new_page( recordHarUrlFilter=record_har_url_filter, recordHarMode=record_har_mode, recordHarContent=record_har_content, + clientCertificates=client_certificates, ) ) ) @@ -14236,7 +14238,8 @@ def launch_persistent_context( typing.Union[str, typing.Pattern[str]] ] = None, record_har_mode: typing.Optional[Literal["full", "minimal"]] = None, - record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None + record_har_content: typing.Optional[Literal["attach", "embed", "omit"]] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "BrowserContext": """BrowserType.launch_persistent_context @@ -14407,6 +14410,20 @@ def launch_persistent_context( Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persisted as separate files and all of these files are archived along with the HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -14465,6 +14482,7 @@ def launch_persistent_context( recordHarUrlFilter=record_har_url_filter, recordHarMode=record_har_mode, recordHarContent=record_har_content, + clientCertificates=client_certificates, ) ) ) @@ -14967,7 +14985,6 @@ def check( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -14992,9 +15009,8 @@ def check( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -15084,6 +15100,7 @@ def click( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -15129,8 +15146,6 @@ def dblclick( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to double click in the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if - the first click of the `dblclick()` triggers a navigation event, this method will throw. If the element is detached from the DOM at any moment during the action, this method throws. @@ -15158,9 +15173,8 @@ def dblclick( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -15429,9 +15443,8 @@ def fill( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. """ @@ -15477,9 +15490,8 @@ def clear( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. """ @@ -16328,9 +16340,8 @@ def drag_to( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. timeout : Union[float, None] Maximum time in milliseconds. Defaults to `30000` (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. @@ -16414,7 +16425,6 @@ def hover( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to hover over the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -16434,9 +16444,8 @@ def hover( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. trial : Union[bool, None] @@ -16763,6 +16772,7 @@ def press( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. """ return mapping.from_maybe_impl( @@ -16972,6 +16982,7 @@ def select_option( Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating to inaccessible pages. Defaults to `false`. + Deprecated: This option will default to `true` in the future. force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. @@ -17080,9 +17091,8 @@ def set_input_files( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -17117,7 +17127,6 @@ def tap( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.touchscreen` to tap the center of the element, or the specified `position`. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. If the element is detached from the DOM at any moment during the action, this method throws. @@ -17141,9 +17150,8 @@ def tap( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -17214,9 +17222,8 @@ def type( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -17270,9 +17277,8 @@ def press_sequentially( Maximum time in milliseconds. Defaults to `30000` (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. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. """ return mapping.from_maybe_impl( @@ -17310,7 +17316,6 @@ def uncheck( 1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the element, unless `force` option is set. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now unchecked. If not, this method throws. If the element is detached from the DOM at any moment during the action, this method throws. @@ -17329,9 +17334,8 @@ def uncheck( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -17461,7 +17465,6 @@ def set_checked( the element is detached during the checks, the whole action is retried. 1. Scroll the element into view if needed. 1. Use `page.mouse` to click in the center of the element. - 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. 1. Ensure that the element is now checked or unchecked. If not, this method throws. When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. @@ -17480,9 +17483,8 @@ def set_checked( force : Union[bool, None] Whether to bypass the [actionability](../actionability.md) checks. Defaults to `false`. no_wait_after : Union[bool, None] - Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You - can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as - navigating to inaccessible pages. Defaults to `false`. + This option has no effect. + Deprecated: This option has no effect. trial : Union[bool, None] When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. @@ -17672,7 +17674,8 @@ def delete( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.delete @@ -17711,6 +17714,9 @@ def delete( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17730,6 +17736,7 @@ def delete( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) ) @@ -17750,7 +17757,8 @@ def head( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.head @@ -17789,6 +17797,9 @@ def head( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17808,6 +17819,7 @@ def head( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) ) @@ -17828,7 +17840,8 @@ def get( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.get @@ -17879,6 +17892,9 @@ def get( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17898,6 +17914,7 @@ def get( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) ) @@ -17918,7 +17935,8 @@ def patch( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.patch @@ -17957,6 +17975,9 @@ def patch( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -17976,6 +17997,7 @@ def patch( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) ) @@ -17996,7 +18018,8 @@ def put( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.put @@ -18035,6 +18058,9 @@ def put( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -18054,6 +18080,7 @@ def put( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) ) @@ -18074,7 +18101,8 @@ def post( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.post @@ -18144,6 +18172,9 @@ def post( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -18163,6 +18194,7 @@ def post( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) ) @@ -18184,7 +18216,8 @@ def fetch( timeout: typing.Optional[float] = None, fail_on_status_code: typing.Optional[bool] = None, ignore_https_errors: typing.Optional[bool] = None, - max_redirects: typing.Optional[int] = None + max_redirects: typing.Optional[int] = None, + max_retries: typing.Optional[int] = None ) -> "APIResponse": """APIRequestContext.fetch @@ -18244,6 +18277,9 @@ def fetch( max_redirects : Union[int, None] Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded. Defaults to `20`. Pass `0` to not follow redirects. + max_retries : Union[int, None] + Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not + retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries. Returns ------- @@ -18264,6 +18300,7 @@ def fetch( failOnStatusCode=fail_on_status_code, ignoreHTTPSErrors=ignore_https_errors, maxRedirects=max_redirects, + maxRetries=max_retries, ) ) ) @@ -18306,7 +18343,8 @@ def new_context( timeout: typing.Optional[float] = None, storage_state: typing.Optional[ typing.Union[StorageState, str, pathlib.Path] - ] = None + ] = None, + client_certificates: typing.Optional[typing.List[ClientCertificate]] = None ) -> "APIRequestContext": """APIRequest.new_context @@ -18342,6 +18380,20 @@ def new_context( information obtained via `browser_context.storage_state()` or `a_pi_request_context.storage_state()`. Either a path to the file with saved storage, or the value returned by one of `browser_context.storage_state()` or `a_pi_request_context.storage_state()` methods. + client_certificates : Union[Sequence[{origin: str, certPath: Union[pathlib.Path, str, None], keyPath: Union[pathlib.Path, str, None], pfxPath: Union[pathlib.Path, str, None], passphrase: Union[str, None]}], None] + TLS Client Authentication allows the server to request a client certificate and verify it. + + **Details** + + An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a + single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the + certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + the certificate is valid for. + + **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. + + **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + work by replacing `localhost` with `local.playwright`. Returns ------- @@ -18359,6 +18411,7 @@ def new_context( userAgent=user_agent, timeout=timeout, storageState=storage_state, + clientCertificates=client_certificates, ) ) ) diff --git a/scripts/generate_api.py b/scripts/generate_api.py index 3c6f26fbf..7966dbc25 100644 --- a/scripts/generate_api.py +++ b/scripts/generate_api.py @@ -219,7 +219,7 @@ def return_value(value: Any) -> List[str]: from playwright._impl._accessibility import Accessibility as AccessibilityImpl -from playwright._impl._api_structures import Cookie, SetCookieParam, FloatRect, FilePayload, Geolocation, HttpCredentials, PdfMargins, Position, ProxySettings, ResourceTiming, SourceLocation, StorageState, ViewportSize, RemoteAddr, SecurityDetails, RequestSizes, NameValue +from playwright._impl._api_structures import Cookie, SetCookieParam, FloatRect, FilePayload, Geolocation, HttpCredentials, PdfMargins, Position, ProxySettings, ResourceTiming, SourceLocation, StorageState, ClientCertificate, ViewportSize, RemoteAddr, SecurityDetails, RequestSizes, NameValue 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 diff --git a/setup.py b/setup.py index 2a0454820..9380425c9 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ InWheel = None from wheel.bdist_wheel import bdist_wheel as BDistWheelCommand -driver_version = "1.45.1-beta-1719996498000" +driver_version = "1.46.0-beta-1722359450000" def extractall(zip: zipfile.ZipFile, path: str) -> None: diff --git a/tests/assets/client-certificates/README.md b/tests/assets/client-certificates/README.md new file mode 100644 index 000000000..b0ee78e70 --- /dev/null +++ b/tests/assets/client-certificates/README.md @@ -0,0 +1,60 @@ +# Client Certificate test-certificates + +## Server + +```bash +openssl req \ + -x509 \ + -newkey rsa:4096 \ + -keyout server/server_key.pem \ + -out server/server_cert.pem \ + -nodes \ + -days 365 \ + -subj "/CN=localhost/O=Client\ Certificate\ Demo" \ + -addext "subjectAltName=DNS:localhost,DNS:local.playwright" +``` + +## Trusted client-certificate (server signed/valid) + +``` +mkdir -p client/trusted +# generate server-signed (valid) certifcate +openssl req \ + -newkey rsa:4096 \ + -keyout client/trusted/key.pem \ + -out client/trusted/csr.pem \ + -nodes \ + -days 365 \ + -subj "/CN=Alice" + +# sign with server_cert.pem +openssl x509 \ + -req \ + -in client/trusted/csr.pem \ + -CA server/server_cert.pem \ + -CAkey server/server_key.pem \ + -out client/trusted/cert.pem \ + -set_serial 01 \ + -days 365 +``` + +## Self-signed certificate (invalid) + +``` +mkdir -p client/self-signed +openssl req \ + -newkey rsa:4096 \ + -keyout client/self-signed/key.pem \ + -out client/self-signed/csr.pem \ + -nodes \ + -days 365 \ + -subj "/CN=Bob" + +# sign with self-signed/key.pem +openssl x509 \ + -req \ + -in client/self-signed/csr.pem \ + -signkey client/self-signed/key.pem \ + -out client/self-signed/cert.pem \ + -days 365 +``` diff --git a/tests/assets/client-certificates/client/trusted/cert.pem b/tests/assets/client-certificates/client/trusted/cert.pem new file mode 100644 index 000000000..76d1e1a54 --- /dev/null +++ b/tests/assets/client-certificates/client/trusted/cert.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFAzCCAuugAwIBAgIBATANBgkqhkiG9w0BAQsFADA2MRIwEAYDVQQDDAlsb2Nh +bGhvc3QxIDAeBgNVBAoMF0NsaWVudCBDZXJ0aWZpY2F0ZSBEZW1vMB4XDTI0MDcx +OTEyNDczN1oXDTI1MDcxOTEyNDczN1owEDEOMAwGA1UEAwwFQWxpY2UwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCac3+4rNmH4/N1s4HqR2X168tgS/aA +6sHW5at8mWRnq54Nm11RvnK55jHQYVAdBgJy5M07w0wakp8inxzlY95wqxBimYG6 +3Un/1p7mX9FkB4LNISCc6j/s/Ufv85MXPbn0S5rm9UcQO9cINJb1RP1YgDDLN5cx +Mz6X4nyofN8H6Lhvh4JDdBw4DfDEFERkVfF+bkZ7YW4XHEChgzm3RxCF0eeGzIXG +rkkK9AsSdJAhOvTlHPFCQKXTYZhsL5+3Ma4RnWnDWvLTHx6KzoU+twTM2mYhhQuQ +gQpnmDHxGge8kGeHGtfdgAjtVJTE57xF/shP0JU+tuIV8NNhQ/vEmhL0Wa093/Ev +pTVp0EUEuDh9ORRH5K5M4bKJyU4XX5noiht6yOn00uaoJcWduUAWsU+cDSvDTMw8 +1opWWm0QIAV3G2yuRSkumHAKqvQLeyeyiKz+OEhyEiZ7EZNExPD0TSpApSTU6aCT +UAvPYGQ59VjsMHTuJ9r4wKIYaDvfL+t72vg2vTQma5cTOBJfIdxH9blFTjEnToH3 +LX8t0XndQ2RkiRnIze2p2jUShxo/lWCjCw+2Iaw0A0fNUK1BbOrFRPq1u7AnEuMJ +t7HF50MloItM97R9vofDwgDIzlX/PzlVRcn1WCo8Fr/0EXxPPreX0YDIp1ANQ8fS +v7bKb2vQIxWuCQIDAQABo0IwQDAdBgNVHQ4EFgQUVJVRJJ2k/Z4r0M1AXe6agyD4 +uCwwHwYDVR0jBBgwFoAUEHtrxWCk96Ehr60E0HBuwLk2i+IwDQYJKoZIhvcNAQEL +BQADggIBAGEvSkxhxRKmlvKG8wCXop2OaUUAOG16+T96vd+aFYaJNlfGoPvqv4Lw +qaHztVktnRrJ//fpNWOsdxkE1uPU4uyGjl2KbyH81JvkE6A3OX0P4B01n8lcimY2 +j3oje6KjORUouYVsypD1VcwfWJgsE3U2Txv5srD8BoemVWgWbWjfyim4kk8C5zlf +tWEazVAaI4MWecqtU4P5gIEomCI7MG9ebxYp5oQhRxeOndOYdUbSzAkZj50gXFA1 ++TNkvuhTFlJF0F7qIFVJSJTmJ+6E5B4ddbkyUYwbOdO+P8mz5N5mSljE+EiIQTxo +AwbG8cSivMy/jI3h048tCUONAJzcSWCF4k1r9Qr6xbyW2ud2GmKiFCEYJkYTsMWV +fM/RujTHlGvJ2+bQK5HiNyW0tO9znW9kaoxolu1YBvTh2492v3agK7nALyGGgdo1 +/nN/ikgkQiyaCpZwFeooJv1YFU5aDhR9RjIIJ9UbJ8FdAv8Xd00E3viunLTvqqXK +RVMokw+tFQTEzjKofKWYArPDjB9LUbN+vQbumKalis3+NlJ3WolYPrCg55tqt1o3 +zXi+xv7120cJFouilRFwrafNFV6F+pRMkMmiWopMnoVJPVXcoqyJRcsmO62uslhg +BLFgAH4H/14drYrgWIMz0no78RInEz0z507zwLkWk5d9W9pJ/4Rf +-----END CERTIFICATE----- diff --git a/tests/assets/client-certificates/client/trusted/csr.pem b/tests/assets/client-certificates/client/trusted/csr.pem new file mode 100644 index 000000000..8ead6da3d --- /dev/null +++ b/tests/assets/client-certificates/client/trusted/csr.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEVTCCAj0CAQAwEDEOMAwGA1UEAwwFQWxpY2UwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCac3+4rNmH4/N1s4HqR2X168tgS/aA6sHW5at8mWRnq54N +m11RvnK55jHQYVAdBgJy5M07w0wakp8inxzlY95wqxBimYG63Un/1p7mX9FkB4LN +ISCc6j/s/Ufv85MXPbn0S5rm9UcQO9cINJb1RP1YgDDLN5cxMz6X4nyofN8H6Lhv +h4JDdBw4DfDEFERkVfF+bkZ7YW4XHEChgzm3RxCF0eeGzIXGrkkK9AsSdJAhOvTl +HPFCQKXTYZhsL5+3Ma4RnWnDWvLTHx6KzoU+twTM2mYhhQuQgQpnmDHxGge8kGeH +GtfdgAjtVJTE57xF/shP0JU+tuIV8NNhQ/vEmhL0Wa093/EvpTVp0EUEuDh9ORRH +5K5M4bKJyU4XX5noiht6yOn00uaoJcWduUAWsU+cDSvDTMw81opWWm0QIAV3G2yu +RSkumHAKqvQLeyeyiKz+OEhyEiZ7EZNExPD0TSpApSTU6aCTUAvPYGQ59VjsMHTu +J9r4wKIYaDvfL+t72vg2vTQma5cTOBJfIdxH9blFTjEnToH3LX8t0XndQ2RkiRnI +ze2p2jUShxo/lWCjCw+2Iaw0A0fNUK1BbOrFRPq1u7AnEuMJt7HF50MloItM97R9 +vofDwgDIzlX/PzlVRcn1WCo8Fr/0EXxPPreX0YDIp1ANQ8fSv7bKb2vQIxWuCQID +AQABoAAwDQYJKoZIhvcNAQELBQADggIBAGgf3EC8WL3RGmuGA+d/4wd1jNfrfU6n +xjnDwdEEX0TQZGGPjh5xvoCK76yZPkO6+z0IYSepEmWBS27HJKl7nuoOvS7MjQyJ +C+3Bdk3ToCeQjmNBlRBKsUw5ftTU902oMl5BptHGj1KGjYBLAkPdXb44wXSVKJ8q +ihFhWlovsva6GDoUorksU3vOwijdlGzTANQHJGFncgrRud9ATavpGS3KVxR73R3A +aBbu3Qw+QIfu8Qx5eBJp8CbMrpAmjfuq17STvqr5bC10Fnn4NegrnHOQG9JcK02+ +5Bn3+9X/n1mue7aohIdErLEiDMSqMOwFfrJeaH6YM1G4QkWyqGugtmHsWOUf0nlU +nkH1krvfw9rb6b+03c4A6GSeHnbX5ufFDSf5gaR6Wy7c0jBnoxVbtBLH2zXlrd0k +iRQG7C6XZzGMS7hb7GL7+bkRy9kWjmDL7z7Fp+EgzKhNmzuWII3E9X9va33HoQ/Q +UdK3JVToxRQg6XRKOxL9+U/+8i6U8lxObLWkWh2cypZqbz5qJxa+2u5JYO/KEoHZ +G963UX7XWezR98vZuTc1XHGZtBDMrjjDd7Kmb4/i/xBPeWwseeGtzFy9z2pnEnkL +uKE4C8wUNpzUUlsn4LneZXObIoErE7FqAAlVFujVe7iaJBmXoUXZR36drbfiaODK +vwAGyrYHaOlR +-----END CERTIFICATE REQUEST----- diff --git a/tests/assets/client-certificates/client/trusted/key.pem b/tests/assets/client-certificates/client/trusted/key.pem new file mode 100644 index 000000000..d60201e5a --- /dev/null +++ b/tests/assets/client-certificates/client/trusted/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +Y+eu85cike5J4vnz8uG04yt7rXjIrUav +-----END PRIVATE KEY----- diff --git a/tests/assets/client-certificates/server/server_cert.pem b/tests/assets/client-certificates/server/server_cert.pem new file mode 100644 index 000000000..52d8f5314 --- /dev/null +++ b/tests/assets/client-certificates/server/server_cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFdTCCA12gAwIBAgIUNPWupe2xcu8YYG1ozoqk9viqDJswDQYJKoZIhvcNAQEL +BQAwNjESMBAGA1UEAwwJbG9jYWxob3N0MSAwHgYDVQQKDBdDbGllbnQgQ2VydGlm +aWNhdGUgRGVtbzAeFw0yNDA3MTkxMjQ3MzNaFw0yNTA3MTkxMjQ3MzNaMDYxEjAQ +BgNVBAMMCWxvY2FsaG9zdDEgMB4GA1UECgwXQ2xpZW50IENlcnRpZmljYXRlIERl +bW8wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC+K5JWhlfvI47ZL/Az +L0xnOl+cMelr2BqH+7XS8187SbvluhFfFkq/7V7rwgsHI64sn8pgRCOnqKWV6jtb +651dGzn7Nby6InmyOQzF4VwfSVWQ6BYXgXuryS9Gm0gi8sOL1Ji/jV49n1gzLyIx +LNhd7NG2DCCedTHJnxyz4xq8MWhI/qI85iWJqcHhxkDb8wtH1Vd6nd/ZRVDbjgTv +PH3EDK7JqmnYG9+x4Jz0yEhvV7jL3gNu2mIyttvm7oRna9oHgaKFUJt4BCfPbT5U +3ipvcq29hdD5/5QIDzTWcExTnklolg5xpFext1+3KPSppESxcfBBNoL3h1B8ZcZa +lEMC/IoFUIDJQj5gmSn4okwMWIxgf+AL0609MKEqQ2FavOsvBmhHcQsqLk4MO/v0 +NGFv1/xGe4tUkX4han6ykf1+sqzupJT5qnUONmvghb2SpIt83o4j4KHVzZwk8JK0 +N6hN7JEjXQwSKCh3b0FFg+kPAe12d6BBcsNzEYmt2C1KNPbXMX84zIkgPN01XMg6 +kdCdjP6DH7CK+brW9qQufOqYpd3eNhJyeBm+oP3PhnhEiMTIO8X2GdSN5Rxozgxl +VIj/QWhLV64r5AqPr/Vpd1vcsxrg3aS5CASmoWQmTPuhEZptRtrkPkGw7k9NPZ34 +lnRenvKJ9e3DXhXRMqeYUY6wjwIDAQABo3sweTAdBgNVHQ4EFgQUEHtrxWCk96Eh +r60E0HBuwLk2i+IwHwYDVR0jBBgwFoAUEHtrxWCk96Ehr60E0HBuwLk2i+IwDwYD +VR0TAQH/BAUwAwEB/zAmBgNVHREEHzAdgglsb2NhbGhvc3SCEGxvY2FsLnBsYXl3 +cmlnaHQwDQYJKoZIhvcNAQELBQADggIBALP4kOAP21ZusbEH89VkZT3MkGlZuDQP +LyTYdLzT3EzN//2+lBDmJfpIPLL/K3sNEVSzNppa6tcCXiVNes/xJM7tHRhTOJ31 +HinSsib2r6DZ6SitQJWmD5FoAdkp9qdG8mA/5vOiwiVKKFV2/Z3i+3iUI/ZnEhUq +uUA1I3TI5LAQzgWLwYu1jSEM1EbH6uQiZ8AmXLVO4GQnVQdbyarWHxIy+zsg+MJN +fxIG/phDpkt1mI3SkAdpWRWjCKESQhrIcRUtu5eVk0lho6ttHODXF8bM7iWLoRc7 +rpcllI4HXHoXQqQkZHRa7KwTf0YVwwQbXTecZONWXwE9Ej5R5IcZzja5FWCSstsb +ULNW0JVxGBE7j5aOjxasYAbRexDmlfEdLvnp6bctZuvMvuBxrB+x5HSEZl6bVnbC +nvtoslylQJM1bwlZdCqJm04JXe1787HDBef2gABv27BjvG/zn89L5ipogZCrGpl6 +P9qs0eSERHuSrm3eHUVgXSQ1nbvOpk7RPFbsbp/npc1NbEDBdAMoXhLP9A+ytxLq +TF+w08nfCF6yJJ3jTkvABo10UH6zcPnfH3Ys7JYsHRbcloMfn+mc88KrTaCO+VZx +qjhFcz+zDu/AbtJkDJtxX2X7jNL0pzWS+9H8jFTrd3ta8XrJiSFq2VMxEU6R0IHk +2Ct10prMWB/3 +-----END CERTIFICATE----- diff --git a/tests/assets/client-certificates/server/server_key.pem b/tests/assets/client-certificates/server/server_key.pem new file mode 100644 index 000000000..ff6a3fc11 --- /dev/null +++ b/tests/assets/client-certificates/server/server_key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +8ynLaTs3oV3BjQya9pAUyzIX5L67 +-----END PRIVATE KEY----- diff --git a/tests/async/test_browsercontext_client_certificates.py b/tests/async/test_browsercontext_client_certificates.py new file mode 100644 index 000000000..14892ecd8 --- /dev/null +++ b/tests/async/test_browsercontext_client_certificates.py @@ -0,0 +1,135 @@ +# 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 sys +import threading +from pathlib import Path +from typing import Dict, Generator, cast + +import pytest +from twisted.internet import reactor as _twisted_reactor +from twisted.internet import ssl +from twisted.internet.selectreactor import SelectReactor +from twisted.web import resource, server + +from playwright.async_api import Browser, BrowserType, Playwright, Request, expect + +reactor = cast(SelectReactor, _twisted_reactor) + + +@pytest.fixture(scope="function", autouse=True) +def _skip_webkit_darwin(browser_name: str) -> None: + if browser_name == "webkit" and sys.platform == "darwin": + pytest.skip("WebKit does not proxy localhost on macOS") + + +class Simple(resource.Resource): + isLeaf = True + + def render_GET(self, request: Request) -> bytes: + return b"Hello, world!" + + +@pytest.fixture(scope="session", autouse=True) +def _client_certificate_server(assetdir: Path) -> Generator[None, None, None]: + server.Site(Simple()) + + certAuthCert = ssl.Certificate.loadPEM( + (assetdir / "client-certificates/server/server_cert.pem").read_text() + ) + serverCert = ssl.PrivateCertificate.loadPEM( + (assetdir / "client-certificates/server/server_key.pem").read_text() + + (assetdir / "client-certificates/server/server_cert.pem").read_text() + ) + + contextFactory = serverCert.options(certAuthCert) + site = server.Site(Simple()) + + def _run() -> None: + reactor.listenSSL(8000, site, contextFactory) + + thread = threading.Thread(target=_run) + thread.start() + yield + thread.join() + + +async def test_should_work_with_new_context(browser: Browser, assetdir: Path) -> None: + context = await browser.new_context( + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": "https://127.0.0.1:8000", + "certPath": assetdir / "client-certificates/client/trusted/cert.pem", + "keyPath": assetdir / "client-certificates/client/trusted/key.pem", + } + ], + ) + page = await context.new_page() + await page.goto("https://localhost:8000") + await expect(page.get_by_text("alert certificate required")).to_be_visible() + await page.goto("https://127.0.0.1:8000") + await expect(page.get_by_text("Hello, world!")).to_be_visible() + + with pytest.raises(Exception, match="alert certificate required"): + await page.context.request.get("https://localhost:8000") + response = await page.context.request.get("https://127.0.0.1:8000") + assert "Hello, world!" in await response.text() + await context.close() + + +async def test_should_work_with_new_persistent_context( + browser_type: BrowserType, assetdir: Path, launch_arguments: Dict +) -> None: + context = await browser_type.launch_persistent_context( + "", + **launch_arguments, + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": "https://127.0.0.1:8000", + "certPath": assetdir / "client-certificates/client/trusted/cert.pem", + "keyPath": assetdir / "client-certificates/client/trusted/key.pem", + } + ], + ) + page = await context.new_page() + await page.goto("https://localhost:8000") + await expect(page.get_by_text("alert certificate required")).to_be_visible() + await page.goto("https://127.0.0.1:8000") + await expect(page.get_by_text("Hello, world!")).to_be_visible() + await context.close() + + +async def test_should_work_with_global_api_request_context( + playwright: Playwright, assetdir: Path +) -> None: + request = await playwright.request.new_context( + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": "https://127.0.0.1:8000", + "certPath": assetdir / "client-certificates/client/trusted/cert.pem", + "keyPath": assetdir / "client-certificates/client/trusted/key.pem", + } + ], + ) + with pytest.raises(Exception, match="alert certificate required"): + await request.get("https://localhost:8000") + response = await request.get("https://127.0.0.1:8000") + assert "Hello, world!" in await response.text() + await request.dispose() diff --git a/tests/async/test_fetch_browser_context.py b/tests/async/test_fetch_browser_context.py index 72f957cc1..ffab7b77c 100644 --- a/tests/async/test_fetch_browser_context.py +++ b/tests/async/test_fetch_browser_context.py @@ -21,7 +21,7 @@ import pytest from playwright.async_api import Browser, BrowserContext, Error, FilePayload, Page -from tests.server import Server +from tests.server import Server, TestServerRequest from tests.utils import must @@ -312,3 +312,24 @@ async def test_should_work_after_context_dispose( await context.close(reason="Test ended.") with pytest.raises(Error, match="Test ended."): await context.request.get(server.EMPTY_PAGE) + + +async def test_should_retry_ECONNRESET(context: BrowserContext, server: Server) -> None: + request_count = 0 + + def _handle_request(req: TestServerRequest) -> None: + nonlocal request_count + request_count += 1 + if request_count <= 3: + assert req.transport + req.transport.abortConnection() + return + req.setHeader("content-type", "text/plain") + req.write(b"Hello!") + req.finish() + + server.set_route("/test", _handle_request) + response = await context.request.fetch(server.PREFIX + "/test", max_retries=3) + assert response.status == 200 + assert await response.text() == "Hello!" + assert request_count == 4 diff --git a/tests/async/test_fetch_global.py b/tests/async/test_fetch_global.py index 82ecf38ec..838e56c7d 100644 --- a/tests/async/test_fetch_global.py +++ b/tests/async/test_fetch_global.py @@ -23,7 +23,7 @@ import pytest from playwright.async_api import APIResponse, Error, Playwright, StorageState -from tests.server import Server +from tests.server import Server, TestServerRequest @pytest.mark.parametrize( @@ -463,3 +463,26 @@ async def test_should_serialize_request_data( assert response.status == 200 assert await response.text() == expected await request.dispose() + + +async def test_should_retry_ECONNRESET(playwright: Playwright, server: Server) -> None: + request_count = 0 + + def _handle_request(req: TestServerRequest) -> None: + nonlocal request_count + request_count += 1 + if request_count <= 3: + assert req.transport + req.transport.abortConnection() + return + req.setHeader("content-type", "text/plain") + req.write(b"Hello!") + req.finish() + + server.set_route("/test", _handle_request) + request = await playwright.request.new_context() + response = await request.fetch(server.PREFIX + "/test", max_retries=3) + assert response.status == 200 + assert await response.text() == "Hello!" + assert request_count == 4 + await request.dispose() diff --git a/tests/async/test_evaluate.py b/tests/async/test_page_evaluate.py similarity index 86% rename from tests/async/test_evaluate.py rename to tests/async/test_page_evaluate.py index 0b2143769..9b7712906 100644 --- a/tests/async/test_evaluate.py +++ b/tests/async/test_page_evaluate.py @@ -208,8 +208,52 @@ async def test_evaluate_throw_if_underlying_element_was_disposed(page: Page) -> async def test_evaluate_evaluate_exception(page: Page) -> None: - error = await page.evaluate('new Error("error message")') - assert "Error: error message" in error + error = await page.evaluate( + """() => { + function innerFunction() { + const e = new Error('error message'); + e.name = 'foobar'; + return e; + } + return innerFunction(); + }""" + ) + assert isinstance(error, Error) + assert error.message == "error message" + assert error.name == "foobar" + assert error.stack + assert "innerFunction" in error.stack + + +async def test_should_pass_exception_argument(page: Page) -> None: + def _raise_and_get_exception(exception: Exception) -> Exception: + try: + raise exception + except Exception as e: + return e + + error_for_roundtrip = Error("error message") + error_for_roundtrip._name = "foobar" + error_for_roundtrip._stack = "test stack" + error = await page.evaluate( + """e => { + return { message: e.message, name: e.name, stack: e.stack }; + }""", + error_for_roundtrip, + ) + assert error["message"] == "error message" + assert error["name"] == "foobar" + assert "test stack" in error["stack"] + + error = await page.evaluate( + """e => { + return { message: e.message, name: e.name, stack: e.stack }; + }""", + _raise_and_get_exception(Exception("error message")), + ) + assert error["message"] == "error message" + assert error["name"] == "Exception" + assert "error message" in error["stack"] async def test_evaluate_evaluate_date(page: Page) -> None: diff --git a/tests/sync/test_browsercontext_client_certificates.py b/tests/sync/test_browsercontext_client_certificates.py new file mode 100644 index 000000000..442540ed1 --- /dev/null +++ b/tests/sync/test_browsercontext_client_certificates.py @@ -0,0 +1,135 @@ +# 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 sys +import threading +from pathlib import Path +from typing import Dict, Generator, cast + +import pytest +from twisted.internet import reactor as _twisted_reactor +from twisted.internet import ssl +from twisted.internet.selectreactor import SelectReactor +from twisted.web import resource, server + +from playwright.sync_api import Browser, BrowserType, Playwright, Request, expect + +reactor = cast(SelectReactor, _twisted_reactor) + + +@pytest.fixture(scope="function", autouse=True) +def _skip_webkit_darwin(browser_name: str) -> None: + if browser_name == "webkit" and sys.platform == "darwin": + pytest.skip("WebKit does not proxy localhost on macOS") + + +class Simple(resource.Resource): + isLeaf = True + + def render_GET(self, request: Request) -> bytes: + return b"Hello, world!" + + +@pytest.fixture(scope="session", autouse=True) +def _client_certificate_server(assetdir: Path) -> Generator[None, None, None]: + server.Site(Simple()) + + certAuthCert = ssl.Certificate.loadPEM( + (assetdir / "client-certificates/server/server_cert.pem").read_text() + ) + serverCert = ssl.PrivateCertificate.loadPEM( + (assetdir / "client-certificates/server/server_key.pem").read_text() + + (assetdir / "client-certificates/server/server_cert.pem").read_text() + ) + + contextFactory = serverCert.options(certAuthCert) + site = server.Site(Simple()) + + def _run() -> None: + reactor.listenSSL(8000, site, contextFactory) + + thread = threading.Thread(target=_run) + thread.start() + yield + thread.join() + + +def test_should_work_with_new_context(browser: Browser, assetdir: Path) -> None: + context = browser.new_context( + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": "https://127.0.0.1:8000", + "certPath": assetdir / "client-certificates/client/trusted/cert.pem", + "keyPath": assetdir / "client-certificates/client/trusted/key.pem", + } + ], + ) + page = context.new_page() + page.goto("https://localhost:8000") + expect(page.get_by_text("alert certificate required")).to_be_visible() + page.goto("https://127.0.0.1:8000") + expect(page.get_by_text("Hello, world!")).to_be_visible() + + with pytest.raises(Exception, match="alert certificate required"): + page.context.request.get("https://localhost:8000") + response = page.context.request.get("https://127.0.0.1:8000") + assert "Hello, world!" in response.text() + context.close() + + +def test_should_work_with_new_persistent_context( + browser_type: BrowserType, assetdir: Path, launch_arguments: Dict +) -> None: + context = browser_type.launch_persistent_context( + "", + **launch_arguments, + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": "https://127.0.0.1:8000", + "certPath": assetdir / "client-certificates/client/trusted/cert.pem", + "keyPath": assetdir / "client-certificates/client/trusted/key.pem", + } + ], + ) + page = context.new_page() + page.goto("https://localhost:8000") + expect(page.get_by_text("alert certificate required")).to_be_visible() + page.goto("https://127.0.0.1:8000") + expect(page.get_by_text("Hello, world!")).to_be_visible() + context.close() + + +def test_should_work_with_global_api_request_context( + playwright: Playwright, assetdir: Path +) -> None: + request = playwright.request.new_context( + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": "https://127.0.0.1:8000", + "certPath": assetdir / "client-certificates/client/trusted/cert.pem", + "keyPath": assetdir / "client-certificates/client/trusted/key.pem", + } + ], + ) + with pytest.raises(Exception, match="alert certificate required"): + request.get("https://localhost:8000") + response = request.get("https://127.0.0.1:8000") + assert "Hello, world!" in response.text() + request.dispose() From 86c0191b6705ac387be7e1b9a161ab325e4865e8 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 1 Aug 2024 19:45:51 +0200 Subject: [PATCH 07/15] test: client-certificate follow-ups (#2508) --- playwright/_impl/_element_handle.py | 3 - playwright/_impl/_frame.py | 3 - playwright/_impl/_locator.py | 6 +- playwright/_impl/_page.py | 2 - .../client/self-signed/cert.pem | 28 ++++ .../client/self-signed/csr.pem | 26 ++++ .../client/self-signed/key.pem | 52 ++++++++ ...test_browsercontext_client_certificates.py | 126 +++++++++++++++--- ...test_browsercontext_client_certificates.py | 119 ++++++++++++++--- 9 files changed, 319 insertions(+), 46 deletions(-) create mode 100644 tests/assets/client-certificates/client/self-signed/cert.pem create mode 100644 tests/assets/client-certificates/client/self-signed/csr.pem create mode 100644 tests/assets/client-certificates/client/self-signed/key.pem diff --git a/playwright/_impl/_element_handle.py b/playwright/_impl/_element_handle.py index 74e5bdff9..39e43a6fd 100644 --- a/playwright/_impl/_element_handle.py +++ b/playwright/_impl/_element_handle.py @@ -206,7 +206,6 @@ async def set_input_files( "setInputFiles", { "timeout": timeout, - "noWaitAfter": noWaitAfter, **converted, }, ) @@ -246,7 +245,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, trial=trial, ) else: @@ -254,7 +252,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, trial=trial, ) diff --git a/playwright/_impl/_frame.py b/playwright/_impl/_frame.py index bfeef1489..7dcfe0f4e 100644 --- a/playwright/_impl/_frame.py +++ b/playwright/_impl/_frame.py @@ -703,7 +703,6 @@ async def set_input_files( "selector": selector, "strict": strict, "timeout": timeout, - "noWaitAfter": noWaitAfter, **converted, }, ) @@ -792,7 +791,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, strict=strict, trial=trial, ) @@ -802,7 +800,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, strict=strict, trial=trial, ) diff --git a/playwright/_impl/_locator.py b/playwright/_impl/_locator.py index 0213ff9ea..521897978 100644 --- a/playwright/_impl/_locator.py +++ b/playwright/_impl/_locator.py @@ -213,7 +213,7 @@ async def clear( noWaitAfter: bool = None, force: bool = None, ) -> None: - await self.fill("", timeout=timeout, noWaitAfter=noWaitAfter, force=force) + await self.fill("", timeout=timeout, force=force) def locator( self, @@ -631,7 +631,7 @@ async def press_sequentially( timeout: float = None, noWaitAfter: bool = None, ) -> None: - await self.type(text, delay=delay, timeout=timeout, noWaitAfter=noWaitAfter) + await self.type(text, delay=delay, timeout=timeout) async def uncheck( self, @@ -685,7 +685,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, trial=trial, ) else: @@ -693,7 +692,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, trial=trial, ) diff --git a/playwright/_impl/_page.py b/playwright/_impl/_page.py index 97af978f3..88c6da720 100644 --- a/playwright/_impl/_page.py +++ b/playwright/_impl/_page.py @@ -1279,7 +1279,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, strict=strict, trial=trial, ) @@ -1289,7 +1288,6 @@ async def set_checked( position=position, timeout=timeout, force=force, - noWaitAfter=noWaitAfter, strict=strict, trial=trial, ) diff --git a/tests/assets/client-certificates/client/self-signed/cert.pem b/tests/assets/client-certificates/client/self-signed/cert.pem new file mode 100644 index 000000000..3c0771794 --- /dev/null +++ b/tests/assets/client-certificates/client/self-signed/cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEyzCCArOgAwIBAgIUYps4gh4MqFYg8zqQhHYL7zYfbLkwDQYJKoZIhvcNAQEL +BQAwDjEMMAoGA1UEAwwDQm9iMB4XDTI0MDcxOTEyNDc0MFoXDTI1MDcxOTEyNDc0 +MFowDjEMMAoGA1UEAwwDQm9iMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEA179eTsqcc1c3AOQHzCZEyYLPta2CCAscUFqcEZ9vWvjW0uzOv9TDlB33Unov +jch4CElZOBhzTadVsbmnYKpxwyVU89WCuQKvedz4k1vu7S1YryfNbmS8PWbnQ4ds +9NB7SgJNHZILvx9DXuWeFEyzRIo1984z4HheBzrkf791LqpYKaKziANUo8h8t0dm +TX/boOz8cEnQNwtTC0ZX3aD0obG/UAhr/22ZGPo/E659fh4ptyYX2LrIUHGy+Eux +nJ9Y4cTqa88Ee6K6AkDiT/AoNQNxE4X++jqLuie8j/ZYpI1Oll38GwKVOyy1msRL +toGmISNwkMIQDGABrJlxgpP4QQAQ+08v9srzXOlkdxdr7OCP81r+ccBXiSQEe7BA +kdJ8l98l5dprJ++GJ+SZcV4+/iGR0dKU2IdAG5HiKZIFn6ch9Ux+UMqeGaYCpkHr +TiietHwcXgtVBlE0jFmB/HspmI/O0abK+grMmueaH7XtTI8YHnw0mUpL8+yp7mfA +7zFusgFgyiBPXeD/NQgg8vja67k++d1VGoXm2xr+5WPQCSbgQoMkkOBMLHWJTefd +6F4Z5M+oI0VwYbf6eQW246wJgpCHSPR0Vdijd6MAGRWKUuLfDsA9+12iGbKvwJ2e +nJlStft2V2LZcjBfdIMbigW1aSVNN5w6m6YVrQPry3WPkWcCAwEAAaMhMB8wHQYD +VR0OBBYEFPxKWTFQJSg4HD2qjxL0dnXX/z4qMA0GCSqGSIb3DQEBCwUAA4ICAQBz +4H1d5eGRU9bekUvi7LbZ5CP/I6w6PL/9AlXqO3BZKxplK7fYGHd3uqyDorJEsvjV +hxwvFlEnS0JIU3nRzhJU/h4Yaivf1WLRFwGZ4TPBjX9KFU27exFWD3rppazkWybJ +i4WuEdP3TJMdKLcNTtXWUDroDOgPlS66u6oZ+mUyUROil+B+fgQgVDhjRc5fvRgZ +Lng8wuejCo3ExQyxkwn2G5guyIimgHmOQghPtLO5xlc67Z4GPUZ1m4tC+BCiFO4D +YIXl3QiIpmU7Pss39LLKMGXXAgLRqyMzqE52lsznu18v5vDLfTaRH4u/wjzULhXz +SrV1IUJmhgEXta4EeDmPH0itgKtkbwjgCOD7drrFrJq/EnvIaJ5cpxiI1pFmYD8g +VVD7/KT/CyT1Uz1dI8QaP/JX8XEgtMJaSkPfjPErIViN9rh9ECCNLgFyv7Y0Plar +A6YlvdyV1Rta/BHndf5Hqz9QWNhbFCMQRGVQNEcoKwpFyjAE9SXoKJvFIK/w5WXu +qKzIYA26QXE3p734Xu1n8QiFJIyltVHbyUlD0k06194t5a2WK+/eDeReIsk0QOI8 +FGqhyPZ7YjR5tSZTmgljtViqBO5AA23QOVFqtjOUrjXP5pTbPJel99Z/FTkqSwvB +Rt4OX7HfuokWQDTT0TMn5jVtJyi54cH7f9MmsNJ23g== +-----END CERTIFICATE----- diff --git a/tests/assets/client-certificates/client/self-signed/csr.pem b/tests/assets/client-certificates/client/self-signed/csr.pem new file mode 100644 index 000000000..4c99e1349 --- /dev/null +++ b/tests/assets/client-certificates/client/self-signed/csr.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEUzCCAjsCAQAwDjEMMAoGA1UEAwwDQm9iMIICIjANBgkqhkiG9w0BAQEFAAOC +Ag8AMIICCgKCAgEA179eTsqcc1c3AOQHzCZEyYLPta2CCAscUFqcEZ9vWvjW0uzO +v9TDlB33Unovjch4CElZOBhzTadVsbmnYKpxwyVU89WCuQKvedz4k1vu7S1YryfN +bmS8PWbnQ4ds9NB7SgJNHZILvx9DXuWeFEyzRIo1984z4HheBzrkf791LqpYKaKz +iANUo8h8t0dmTX/boOz8cEnQNwtTC0ZX3aD0obG/UAhr/22ZGPo/E659fh4ptyYX +2LrIUHGy+EuxnJ9Y4cTqa88Ee6K6AkDiT/AoNQNxE4X++jqLuie8j/ZYpI1Oll38 +GwKVOyy1msRLtoGmISNwkMIQDGABrJlxgpP4QQAQ+08v9srzXOlkdxdr7OCP81r+ +ccBXiSQEe7BAkdJ8l98l5dprJ++GJ+SZcV4+/iGR0dKU2IdAG5HiKZIFn6ch9Ux+ +UMqeGaYCpkHrTiietHwcXgtVBlE0jFmB/HspmI/O0abK+grMmueaH7XtTI8YHnw0 +mUpL8+yp7mfA7zFusgFgyiBPXeD/NQgg8vja67k++d1VGoXm2xr+5WPQCSbgQoMk +kOBMLHWJTefd6F4Z5M+oI0VwYbf6eQW246wJgpCHSPR0Vdijd6MAGRWKUuLfDsA9 ++12iGbKvwJ2enJlStft2V2LZcjBfdIMbigW1aSVNN5w6m6YVrQPry3WPkWcCAwEA +AaAAMA0GCSqGSIb3DQEBCwUAA4ICAQCb07d2IjUy1PeHCj/2k/z9FrZSo6K3c8y6 +b/u/MZ0AXPKLPDSo7UYpOJ8Z2cBiJ8jQapjTSEL8POUYqcvCmP55R6u68KmvINHo ++Ly7pP+xPrbA4Q0WmPnz37hQn+I1he0GuEQyjZZqUln9zwp67TsWNKxKtCH+1j8M +Ltzx6kuHCdPtDUtv291yhVRqvbjiDs+gzdQYNJtAkUbHwHFxu8oZhg8QZGyXYMN8 +TGoQ1LTezFZXJtX69K7WnrDGrjsgB6EMvwkqAFSYNH0LFvI0xo13OOgXr9mrwohA +76uZtjXL9B15EqrMce6mdUZi46QJuQ2avTi57Lz+fqvsBYdQO89VcFSmqu2nfspN +QZDrooyjHrlls8MpoBd8fde9oT4uA4/d9SJtuHUnjgGN7Qr7eTruWXL8wVMwFnvL +igWE4detO9y2gpRLq6uEqzWYMGtN9PXJCGU8C8m9E2EBUKMrT/bpNbboatLcgRrW +acj0BRVqoVzk1sRq7Sa6ejywqgARvIhTehg6DqdMdcENCPQ7rxDRu5PSDM8/mwIj +0KYl8d2PlECB4ofRyLcy17BZzjP6hSnkGzcFk0/bChZOSIRnwvKbvfXnB45hhPk8 +XwT/6UNSwC2STP3gtOmLqrWj+OE0gy0AkDMvP3UnQVGMUvgfYg+N4ROCVtlqzxe9 +W65c05Mm1g== +-----END CERTIFICATE REQUEST----- diff --git a/tests/assets/client-certificates/client/self-signed/key.pem b/tests/assets/client-certificates/client/self-signed/key.pem new file mode 100644 index 000000000..70d5e3dd0 --- /dev/null +++ b/tests/assets/client-certificates/client/self-signed/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +dg6m3MAyZ1IXjHlogOdmGvnq07/w +-----END PRIVATE KEY----- diff --git a/tests/async/test_browsercontext_client_certificates.py b/tests/async/test_browsercontext_client_certificates.py index 14892ecd8..6e223b9c5 100644 --- a/tests/async/test_browsercontext_client_certificates.py +++ b/tests/async/test_browsercontext_client_certificates.py @@ -15,16 +15,20 @@ import sys import threading from pathlib import Path -from typing import Dict, Generator, cast +from typing import Dict, Generator, Optional, cast +import OpenSSL.crypto +import OpenSSL.SSL import pytest from twisted.internet import reactor as _twisted_reactor from twisted.internet import ssl from twisted.internet.selectreactor import SelectReactor from twisted.web import resource, server +from twisted.web.http import Request -from playwright.async_api import Browser, BrowserType, Playwright, Request, expect +from playwright.async_api import Browser, BrowserType, Playwright, expect +ssl.optionsForClientTLS reactor = cast(SelectReactor, _twisted_reactor) @@ -34,17 +38,61 @@ def _skip_webkit_darwin(browser_name: str) -> None: pytest.skip("WebKit does not proxy localhost on macOS") -class Simple(resource.Resource): +class HttpsResource(resource.Resource): + serverCertificate: ssl.PrivateCertificate isLeaf = True + def _verify_cert_chain(self, cert: Optional[OpenSSL.crypto.X509]) -> bool: + if not cert: + return False + store = OpenSSL.crypto.X509Store() + store.add_cert(self.serverCertificate.original) + store_ctx = OpenSSL.crypto.X509StoreContext(store, cert) + try: + store_ctx.verify_certificate() + return True + except OpenSSL.crypto.X509StoreContextError: + return False + def render_GET(self, request: Request) -> bytes: - return b"Hello, world!" + tls_socket: OpenSSL.SSL.Connection = request.transport.getHandle() # type: ignore + cert = tls_socket.get_peer_certificate() + parts = [] + + if self._verify_cert_chain(cert): + request.setResponseCode(200) + parts.append( + { + "key": "message", + "value": f"Hello {cert.get_subject().CN}, your certificate was issued by {cert.get_issuer().CN}!", # type: ignore + } + ) + elif cert and cert.get_subject(): + request.setResponseCode(403) + parts.append( + { + "key": "message", + "value": f"Sorry {cert.get_subject().CN}, certificates from {cert.get_issuer().CN} are not welcome here.", + } + ) + else: + request.setResponseCode(401) + parts.append( + { + "key": "message", + "value": "Sorry, but you need to provide a client certificate to continue.", + } + ) + return b"".join( + [ + f'
{part["value"]}
'.encode() + for part in parts + ] + ) @pytest.fixture(scope="session", autouse=True) def _client_certificate_server(assetdir: Path) -> Generator[None, None, None]: - server.Site(Simple()) - certAuthCert = ssl.Certificate.loadPEM( (assetdir / "client-certificates/server/server_cert.pem").read_text() ) @@ -54,7 +102,10 @@ def _client_certificate_server(assetdir: Path) -> Generator[None, None, None]: ) contextFactory = serverCert.options(certAuthCert) - site = server.Site(Simple()) + contextFactory.requireCertificate = False + resource = HttpsResource() + resource.serverCertificate = serverCert + site = server.Site(resource) def _run() -> None: reactor.listenSSL(8000, site, contextFactory) @@ -65,6 +116,27 @@ def _run() -> None: thread.join() +async def test_should_throw_with_untrusted_client_certs( + playwright: Playwright, assetdir: Path +) -> None: + serverURL = "https://localhost:8000/" + request = await playwright.request.new_context( + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": serverURL, + "certPath": assetdir + / "client-certificates/client/self-signed/cert.pem", + "keyPath": assetdir / "client-certificates/client/self-signed/key.pem", + } + ], + ) + with pytest.raises(Exception, match="alert unknown ca"): + await request.get(serverURL) + await request.dispose() + + async def test_should_work_with_new_context(browser: Browser, assetdir: Path) -> None: context = await browser.new_context( # TODO: Remove this once we can pass a custom CA. @@ -79,14 +151,24 @@ async def test_should_work_with_new_context(browser: Browser, assetdir: Path) -> ) page = await context.new_page() await page.goto("https://localhost:8000") - await expect(page.get_by_text("alert certificate required")).to_be_visible() + await expect(page.get_by_test_id("message")).to_have_text( + "Sorry, but you need to provide a client certificate to continue." + ) await page.goto("https://127.0.0.1:8000") - await expect(page.get_by_text("Hello, world!")).to_be_visible() + await expect(page.get_by_test_id("message")).to_have_text( + "Hello Alice, your certificate was issued by localhost!" + ) - with pytest.raises(Exception, match="alert certificate required"): - await page.context.request.get("https://localhost:8000") + response = await page.context.request.get("https://localhost:8000") + assert ( + "Sorry, but you need to provide a client certificate to continue." + in await response.text() + ) response = await page.context.request.get("https://127.0.0.1:8000") - assert "Hello, world!" in await response.text() + assert ( + "Hello Alice, your certificate was issued by localhost!" + in await response.text() + ) await context.close() @@ -108,9 +190,13 @@ async def test_should_work_with_new_persistent_context( ) page = await context.new_page() await page.goto("https://localhost:8000") - await expect(page.get_by_text("alert certificate required")).to_be_visible() + await expect(page.get_by_test_id("message")).to_have_text( + "Sorry, but you need to provide a client certificate to continue." + ) await page.goto("https://127.0.0.1:8000") - await expect(page.get_by_text("Hello, world!")).to_be_visible() + await expect(page.get_by_test_id("message")).to_have_text( + "Hello Alice, your certificate was issued by localhost!" + ) await context.close() @@ -128,8 +214,14 @@ async def test_should_work_with_global_api_request_context( } ], ) - with pytest.raises(Exception, match="alert certificate required"): - await request.get("https://localhost:8000") + response = await request.get("https://localhost:8000") + assert ( + "Sorry, but you need to provide a client certificate to continue." + in await response.text() + ) response = await request.get("https://127.0.0.1:8000") - assert "Hello, world!" in await response.text() + assert ( + "Hello Alice, your certificate was issued by localhost!" + in await response.text() + ) await request.dispose() diff --git a/tests/sync/test_browsercontext_client_certificates.py b/tests/sync/test_browsercontext_client_certificates.py index 442540ed1..601d6eacc 100644 --- a/tests/sync/test_browsercontext_client_certificates.py +++ b/tests/sync/test_browsercontext_client_certificates.py @@ -15,15 +15,18 @@ import sys import threading from pathlib import Path -from typing import Dict, Generator, cast +from typing import Dict, Generator, Optional, cast +import OpenSSL.crypto +import OpenSSL.SSL import pytest from twisted.internet import reactor as _twisted_reactor from twisted.internet import ssl from twisted.internet.selectreactor import SelectReactor from twisted.web import resource, server +from twisted.web.http import Request -from playwright.sync_api import Browser, BrowserType, Playwright, Request, expect +from playwright.sync_api import Browser, BrowserType, Playwright, expect reactor = cast(SelectReactor, _twisted_reactor) @@ -34,17 +37,61 @@ def _skip_webkit_darwin(browser_name: str) -> None: pytest.skip("WebKit does not proxy localhost on macOS") -class Simple(resource.Resource): +class HttpsResource(resource.Resource): + serverCertificate: ssl.PrivateCertificate isLeaf = True + def _verify_cert_chain(self, cert: Optional[OpenSSL.crypto.X509]) -> bool: + if not cert: + return False + store = OpenSSL.crypto.X509Store() + store.add_cert(self.serverCertificate.original) + store_ctx = OpenSSL.crypto.X509StoreContext(store, cert) + try: + store_ctx.verify_certificate() + return True + except OpenSSL.crypto.X509StoreContextError: + return False + def render_GET(self, request: Request) -> bytes: - return b"Hello, world!" + tls_socket: OpenSSL.SSL.Connection = request.transport.getHandle() # type: ignore + cert = tls_socket.get_peer_certificate() + parts = [] + + if self._verify_cert_chain(cert): + request.setResponseCode(200) + parts.append( + { + "key": "message", + "value": f"Hello {cert.get_subject().CN}, your certificate was issued by {cert.get_issuer().CN}!", # type: ignore + } + ) + elif cert and cert.get_subject(): + request.setResponseCode(403) + parts.append( + { + "key": "message", + "value": f"Sorry {cert.get_subject().CN}, certificates from {cert.get_issuer().CN} are not welcome here.", + } + ) + else: + request.setResponseCode(401) + parts.append( + { + "key": "message", + "value": "Sorry, but you need to provide a client certificate to continue.", + } + ) + return b"".join( + [ + f'
{part["value"]}
'.encode() + for part in parts + ] + ) @pytest.fixture(scope="session", autouse=True) def _client_certificate_server(assetdir: Path) -> Generator[None, None, None]: - server.Site(Simple()) - certAuthCert = ssl.Certificate.loadPEM( (assetdir / "client-certificates/server/server_cert.pem").read_text() ) @@ -54,7 +101,10 @@ def _client_certificate_server(assetdir: Path) -> Generator[None, None, None]: ) contextFactory = serverCert.options(certAuthCert) - site = server.Site(Simple()) + contextFactory.requireCertificate = False + resource = HttpsResource() + resource.serverCertificate = serverCert + site = server.Site(resource) def _run() -> None: reactor.listenSSL(8000, site, contextFactory) @@ -65,6 +115,27 @@ def _run() -> None: thread.join() +def test_should_throw_with_untrusted_client_certs( + playwright: Playwright, assetdir: Path +) -> None: + serverURL = "https://localhost:8000/" + request = playwright.request.new_context( + # TODO: Remove this once we can pass a custom CA. + ignore_https_errors=True, + client_certificates=[ + { + "origin": serverURL, + "certPath": assetdir + / "client-certificates/client/self-signed/cert.pem", + "keyPath": assetdir / "client-certificates/client/self-signed/key.pem", + } + ], + ) + with pytest.raises(Exception, match="alert unknown ca"): + request.get(serverURL) + request.dispose() + + def test_should_work_with_new_context(browser: Browser, assetdir: Path) -> None: context = browser.new_context( # TODO: Remove this once we can pass a custom CA. @@ -79,14 +150,21 @@ def test_should_work_with_new_context(browser: Browser, assetdir: Path) -> None: ) page = context.new_page() page.goto("https://localhost:8000") - expect(page.get_by_text("alert certificate required")).to_be_visible() + expect(page.get_by_test_id("message")).to_have_text( + "Sorry, but you need to provide a client certificate to continue." + ) page.goto("https://127.0.0.1:8000") - expect(page.get_by_text("Hello, world!")).to_be_visible() + expect(page.get_by_test_id("message")).to_have_text( + "Hello Alice, your certificate was issued by localhost!" + ) - with pytest.raises(Exception, match="alert certificate required"): - page.context.request.get("https://localhost:8000") + response = page.context.request.get("https://localhost:8000") + assert ( + "Sorry, but you need to provide a client certificate to continue." + in response.text() + ) response = page.context.request.get("https://127.0.0.1:8000") - assert "Hello, world!" in response.text() + assert "Hello Alice, your certificate was issued by localhost!" in response.text() context.close() @@ -108,9 +186,13 @@ def test_should_work_with_new_persistent_context( ) page = context.new_page() page.goto("https://localhost:8000") - expect(page.get_by_text("alert certificate required")).to_be_visible() + expect(page.get_by_test_id("message")).to_have_text( + "Sorry, but you need to provide a client certificate to continue." + ) page.goto("https://127.0.0.1:8000") - expect(page.get_by_text("Hello, world!")).to_be_visible() + expect(page.get_by_test_id("message")).to_have_text( + "Hello Alice, your certificate was issued by localhost!" + ) context.close() @@ -128,8 +210,11 @@ def test_should_work_with_global_api_request_context( } ], ) - with pytest.raises(Exception, match="alert certificate required"): - request.get("https://localhost:8000") + response = request.get("https://localhost:8000") + assert ( + "Sorry, but you need to provide a client certificate to continue." + in response.text() + ) response = request.get("https://127.0.0.1:8000") - assert "Hello, world!" in response.text() + assert "Hello Alice, your certificate was issued by localhost!" in response.text() request.dispose() From 1b12403a6ffdf34d03c9b55720d6d8f13ddb3445 Mon Sep 17 00:00:00 2001 From: KRRT7 <106575910+KRRT7@users.noreply.github.com> Date: Thu, 8 Aug 2024 03:43:02 -0400 Subject: [PATCH 08/15] fix(Nuitka): Python single executable bundler support (#2518) --- playwright/_impl/_transport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/_impl/_transport.py b/playwright/_impl/_transport.py index f2f455c50..124f57823 100644 --- a/playwright/_impl/_transport.py +++ b/playwright/_impl/_transport.py @@ -107,7 +107,7 @@ async def connect(self) -> None: try: # For pyinstaller and Nuitka env = get_driver_env() - if getattr(sys, "frozen", False) or globals().get("_compiled__"): + if getattr(sys, "frozen", False) or globals().get("__compiled__"): env.setdefault("PLAYWRIGHT_BROWSERS_PATH", "0") startupinfo = None From 11cb324c97392a709525d90591d9586adffaa7c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:43:20 +0200 Subject: [PATCH 09/15] build(deps): bump black from 24.4.2 to 24.8.0 (#2512) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index a47b06315..6d410218a 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -1,6 +1,6 @@ auditwheel==6.0.0 autobahn==23.1.2 -black==24.4.2 +black==24.8.0 flake8==7.1.0 flaky==3.8.1 mypy==1.11.0 From e71bbeb043ddcd79f06970a475832c920d93d9c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:43:36 +0200 Subject: [PATCH 10/15] build(deps): bump mypy from 1.11.0 to 1.11.1 (#2516) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index 6d410218a..6e39a5145 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -3,7 +3,7 @@ autobahn==23.1.2 black==24.8.0 flake8==7.1.0 flaky==3.8.1 -mypy==1.11.0 +mypy==1.11.1 objgraph==3.6.1 Pillow==10.4.0 pixelmatch==0.3.0 From 8b9bcdc73b2828235c655c7c73ab709101d84670 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 12 Aug 2024 11:19:33 +0200 Subject: [PATCH 11/15] chore(roll): roll Playwright to v1.46.0 (#2519) --- README.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fdd043e95..9de46843e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Playwright is a Python library to automate [Chromium](https://www.chromium.org/H | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 128.0.6613.7 | ✅ | ✅ | ✅ | +| Chromium 128.0.6613.18 | ✅ | ✅ | ✅ | | WebKit 18.0 | ✅ | ✅ | ✅ | | Firefox 128.0 | ✅ | ✅ | ✅ | diff --git a/setup.py b/setup.py index 9380425c9..2a6195600 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ InWheel = None from wheel.bdist_wheel import bdist_wheel as BDistWheelCommand -driver_version = "1.46.0-beta-1722359450000" +driver_version = "1.46.0" def extractall(zip: zipfile.ZipFile, path: str) -> None: From 475935e67274012d13ebb7535b114af200df1b7b Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 12 Aug 2024 14:02:31 +0200 Subject: [PATCH 12/15] chore: add todo for waitFor* / browser.disconnected event ordering (#2520) --- playwright/_impl/_browser_type.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/playwright/_impl/_browser_type.py b/playwright/_impl/_browser_type.py index 70525949c..1c9303c7f 100644 --- a/playwright/_impl/_browser_type.py +++ b/playwright/_impl/_browser_type.py @@ -231,6 +231,13 @@ def handle_transport_close(reason: Optional[str]) -> None: context._on_close() browser._on_close() connection.cleanup(reason) + # TODO: Backport https://github.com/microsoft/playwright/commit/d8d5289e8692c9b1265d23ee66988d1ac5122f33 + # Give a chance to any API call promises to reject upon page/context closure. + # This happens naturally when we receive page.onClose and browser.onClose from the server + # in separate tasks. However, upon pipe closure we used to dispatch them all synchronously + # here and promises did not have a chance to reject. + # The order of rejects vs closure is a part of the API contract and our test runner + # relies on it to attribute rejections to the right test. transport.once("close", handle_transport_close) From 8a940e4814c27c3d75bd351129e61a175ad3ba81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:09:32 +0200 Subject: [PATCH 13/15] build(deps): bump twisted from 24.3.0 to 24.7.0 (#2523) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index 6e39a5145..e60db17de 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -18,7 +18,7 @@ pytest-xdist==3.6.1 requests==2.32.3 service_identity==24.1.0 setuptools==72.1.0 -twisted==24.3.0 +twisted==24.7.0 types-pyOpenSSL==24.1.0.20240722 types-requests==2.32.0.20240712 wheel==0.42.0 From f72a79ee10e89e1510c6ea068dadf6ef12569835 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:10:58 +0200 Subject: [PATCH 14/15] build(deps): bump auditwheel from 6.0.0 to 6.1.0 (#2522) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index e60db17de..6712ce150 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -1,4 +1,4 @@ -auditwheel==6.0.0 +auditwheel==6.1.0 autobahn==23.1.2 black==24.8.0 flake8==7.1.0 From 799c12428dc0999f75a81d57f2e6b9617b12e168 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:11:36 +0200 Subject: [PATCH 15/15] build(deps): bump flake8 from 7.1.0 to 7.1.1 (#2524) --- local-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-requirements.txt b/local-requirements.txt index 6712ce150..979dba8e6 100644 --- a/local-requirements.txt +++ b/local-requirements.txt @@ -1,7 +1,7 @@ auditwheel==6.1.0 autobahn==23.1.2 black==24.8.0 -flake8==7.1.0 +flake8==7.1.1 flaky==3.8.1 mypy==1.11.1 objgraph==3.6.1