Skip to content

Commit ab18c77

Browse files
authored
chore: roll Playwright to 1.63.0 (#3198)
1 parent 0e66a09 commit ab18c77

31 files changed

Lines changed: 1021 additions & 134 deletions

‎DRIVER_VERSION‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.62.1
1+
1.63.0

‎NODE_VERSION‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
24.19.0
1+
24.21.0

‎README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Playwright is a Python library to automate [Chromium](https://www.chromium.org/H
44

55
| | Linux | macOS | Windows |
66
| :--- | :---: | :---: | :---: |
7-
| Chromium <!-- GEN:chromium-version -->151.0.7922.34<!-- GEN:stop --> | ✅ | ✅ | ✅ |
8-
| WebKit <!-- GEN:webkit-version -->26.5<!-- GEN:stop --> | ✅ | ✅ | ✅ |
9-
| Firefox <!-- GEN:firefox-version -->153.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
7+
| Chromium <!-- GEN:chromium-version -->153.0.8010.12<!-- GEN:stop --> | ✅ | ✅ | ✅ |
8+
| WebKit <!-- GEN:webkit-version -->26.6<!-- GEN:stop --> | ✅ | ✅ | ✅ |
9+
| Firefox <!-- GEN:firefox-version -->155.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
1010

1111
## Documentation
1212

‎playwright/_impl/_browser.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def _did_create_context(self, context: BrowserContext) -> None:
109109

110110
def _setup_browser_context(self, context: BrowserContext) -> None:
111111
context._tracing._traces_dir = self._traces_dir
112+
context._request._tracing._traces_dir = self._traces_dir
112113
assert self._browser_type is not None
113114
self._browser_type._playwright.selectors._contexts_for_selectors.add(context)
114115

@@ -143,7 +144,7 @@ async def new_context(
143144
permissions: Sequence[str] = None,
144145
extraHTTPHeaders: Dict[str, str] = None,
145146
offline: bool = None,
146-
httpCredentials: HttpCredentials = None,
147+
httpCredentials: Union[HttpCredentials, Sequence[HttpCredentials]] = None,
147148
deviceScaleFactor: float = None,
148149
isMobile: bool = None,
149150
hasTouch: bool = None,
@@ -197,7 +198,7 @@ async def new_page(
197198
permissions: Sequence[str] = None,
198199
extraHTTPHeaders: Dict[str, str] = None,
199200
offline: bool = None,
200-
httpCredentials: HttpCredentials = None,
201+
httpCredentials: Union[HttpCredentials, Sequence[HttpCredentials]] = None,
201202
deviceScaleFactor: float = None,
202203
isMobile: bool = None,
203204
hasTouch: bool = None,

‎playwright/_impl/_browser_context.py‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class BrowserContext(ChannelOwner):
9696
Close="close",
9797
Console="console",
9898
Dialog="dialog",
99+
DialogClosed="dialogclosed",
99100
Download="download",
100101
FrameAttached="frameattached",
101102
FrameDetached="framedetached",
@@ -173,6 +174,10 @@ def __init__(
173174
self._channel.on(
174175
"dialog", lambda params: self._on_dialog(from_channel(params["dialog"]))
175176
)
177+
self._channel.on(
178+
"dialogClosed",
179+
lambda params: self._on_dialog_closed(from_channel(params["dialog"])),
180+
)
176181
self._channel.on(
177182
"pageError",
178183
lambda params: self._on_page_error(
@@ -226,6 +231,7 @@ def __init__(
226231
{
227232
BrowserContext.Events.Console: "console",
228233
BrowserContext.Events.Dialog: "dialog",
234+
BrowserContext.Events.DialogClosed: "dialogClosed",
229235
BrowserContext.Events.Request: "request",
230236
BrowserContext.Events.Response: "response",
231237
BrowserContext.Events.RequestFinished: "requestFinished",
@@ -567,6 +573,7 @@ def _on_close(self) -> None:
567573

568574
self._dispose_har_routers()
569575
self._tracing._reset_stack_counter()
576+
self._request._tracing._reset_stack_counter()
570577
self.emit(BrowserContext.Events.Close, self)
571578

572579
def is_closed(self) -> bool:
@@ -591,10 +598,13 @@ async def storage_state(
591598
self,
592599
path: Union[str, Path] = None,
593600
indexedDB: bool = None,
601+
opfs: bool = None,
594602
credentials: bool = None,
595603
) -> StorageState:
596604
result = await self._channel.send_return_as_dict(
597-
"storageState", None, {"indexedDB": indexedDB, "credentials": credentials}
605+
"storageState",
606+
None,
607+
{"indexedDB": indexedDB, "opfs": opfs, "credentials": credentials},
598608
)
599609
if path:
600610
await async_writefile(path, json.dumps(result))
@@ -694,6 +704,12 @@ def _on_dialog(self, dialog: Dialog) -> None:
694704
else:
695705
create_task_and_ignore_exception(self._loop, dialog.dismiss())
696706

707+
def _on_dialog_closed(self, dialog: Dialog) -> None:
708+
self.emit(BrowserContext.Events.DialogClosed, dialog)
709+
page = dialog.page
710+
if page:
711+
page.emit(Page.Events.DialogClosed, dialog)
712+
697713
def _on_page_error(
698714
self, error: Error, page: Optional[Page], location: WebErrorLocation
699715
) -> None:

‎playwright/_impl/_browser_type.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@
4444
locals_to_params,
4545
)
4646
from playwright._impl._json_pipe import JsonPipeTransport
47-
from playwright._impl._network import serialize_headers, to_client_certificates_protocol
47+
from playwright._impl._network import (
48+
serialize_headers,
49+
to_client_certificates_protocol,
50+
to_http_credentials_protocol,
51+
)
4852
from playwright._impl._waiter import throw_on_timeout
4953

5054
if TYPE_CHECKING:
@@ -133,7 +137,7 @@ async def launch_persistent_context(
133137
permissions: Sequence[str] = None,
134138
extraHTTPHeaders: Dict[str, str] = None,
135139
offline: bool = None,
136-
httpCredentials: HttpCredentials = None,
140+
httpCredentials: Union[HttpCredentials, Sequence[HttpCredentials]] = None,
137141
deviceScaleFactor: float = None,
138142
isMobile: bool = None,
139143
hasTouch: bool = None,
@@ -333,6 +337,10 @@ async def _prepare_browser_context_params(self, params: Dict) -> None:
333337
params["clientCertificates"] = await to_client_certificates_protocol(
334338
params["clientCertificates"]
335339
)
340+
if "httpCredentials" in params:
341+
params["httpCredentials"] = to_http_credentials_protocol(
342+
params["httpCredentials"]
343+
)
336344
params["selectorEngines"] = self._playwright.selectors._selector_engines
337345
params["testIdAttributeName"] = (
338346
self._playwright.selectors._test_id_attribute_name

‎playwright/_impl/_fetch.py‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import pathlib
1919
import typing
2020
from pathlib import Path
21-
from typing import Any, Dict, List, Optional, Union, cast
21+
from typing import Any, Dict, List, Optional, Sequence, Union, cast
2222

2323
import playwright._impl._network as network
2424
from playwright._impl._api_structures import (
@@ -49,7 +49,11 @@
4949
object_to_array,
5050
to_impl,
5151
)
52-
from playwright._impl._network import serialize_headers, to_client_certificates_protocol
52+
from playwright._impl._network import (
53+
serialize_headers,
54+
to_client_certificates_protocol,
55+
to_http_credentials_protocol,
56+
)
5357
from playwright._impl._tracing import Tracing
5458

5559
if typing.TYPE_CHECKING:
@@ -72,7 +76,7 @@ async def new_context(
7276
self,
7377
baseURL: str = None,
7478
extraHTTPHeaders: Dict[str, str] = None,
75-
httpCredentials: HttpCredentials = None,
79+
httpCredentials: Union[HttpCredentials, Sequence[HttpCredentials]] = None,
7680
ignoreHTTPSErrors: bool = None,
7781
proxy: ProxySettings = None,
7882
userAgent: str = None,
@@ -94,6 +98,10 @@ async def new_context(
9498
params["clientCertificates"] = await to_client_certificates_protocol(
9599
params.get("clientCertificates")
96100
)
101+
if "httpCredentials" in params:
102+
params["httpCredentials"] = to_http_credentials_protocol(
103+
params["httpCredentials"]
104+
)
97105
context = cast(
98106
APIRequestContext,
99107
from_channel(
@@ -458,9 +466,10 @@ async def storage_state(
458466
self,
459467
path: Union[pathlib.Path, str] = None,
460468
indexedDB: bool = None,
469+
opfs: bool = None,
461470
) -> StorageState:
462471
result = await self._channel.send_return_as_dict(
463-
"storageState", None, {"indexedDB": indexedDB}
472+
"storageState", None, {"indexedDB": indexedDB, "opfs": opfs}
464473
)
465474
if path:
466475
await async_writefile(path, json.dumps(result))

‎playwright/_impl/_frame.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
serialize_argument,
6868
)
6969
from playwright._impl._locator import (
70+
ANY_FRAME_SELECTOR,
7071
FrameLocator,
7172
Locator,
7273
get_by_alt_text_selector,
@@ -722,8 +723,8 @@ def get_by_title(
722723
) -> "Locator":
723724
return self.locator(get_by_title_selector(text, exact=exact))
724725

725-
def frame_locator(self, selector: str) -> FrameLocator:
726-
return FrameLocator(self, selector)
726+
def frame_locator(self, selector: str = None) -> FrameLocator:
727+
return FrameLocator(self, ANY_FRAME_SELECTOR if selector is None else selector)
727728

728729
async def focus(
729730
self, selector: str, strict: bool = None, timeout: float = None

‎playwright/_impl/_locator.py‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ def filter(
384384
visible=visible,
385385
)
386386

387+
@property
388+
def visible(self) -> "Locator":
389+
return Locator(self._frame, self._selector, visible=True)
390+
387391
def or_(self, locator: "Locator") -> "Locator":
388392
if locator._frame != self._frame:
389393
raise Error("Locators must belong to the same frame.")
@@ -809,13 +813,26 @@ async def hide_highlight(self) -> None:
809813
await self._frame._hide_highlight(self._selector)
810814

811815

816+
ANY_FRAME_SELECTOR = "internal:control=any-frame"
817+
818+
812819
class FrameLocator:
813820
def __init__(self, frame: "Frame", frame_selector: str) -> None:
814821
self._frame = frame
815822
self._loop = frame._loop
816823
self._dispatcher_fiber = frame._connection._dispatcher_fiber
817824
self._frame_selector = frame_selector
818825

826+
def _child_selector(self, selector: str) -> str:
827+
if self._frame_selector == ANY_FRAME_SELECTOR:
828+
return f"{self._frame_selector} >> {selector}"
829+
return f"{self._frame_selector} >> internal:control=enter-frame >> {selector}"
830+
831+
def _nth_selector(self, nth: str) -> str:
832+
if self._frame_selector == ANY_FRAME_SELECTOR:
833+
raise Error("Selecting the nth frame is not allowed on frame_locator().")
834+
return f"{self._frame_selector} >> nth={nth}"
835+
819836
def locator(
820837
self,
821838
selectorOrLocator: Union["Locator", str],
@@ -827,7 +844,7 @@ def locator(
827844
if isinstance(selectorOrLocator, str):
828845
return Locator(
829846
self._frame,
830-
f"{self._frame_selector} >> internal:control=enter-frame >> {selectorOrLocator}",
847+
self._child_selector(selectorOrLocator),
831848
has_text=hasText,
832849
has_not_text=hasNotText,
833850
has=has,
@@ -838,7 +855,7 @@ def locator(
838855
raise ValueError("Locators must belong to the same frame.")
839856
return Locator(
840857
self._frame,
841-
f"{self._frame_selector} >> internal:control=enter-frame >> {selectorOrLocator._selector}",
858+
self._child_selector(selectorOrLocator._selector),
842859
has_text=hasText,
843860
has_not_text=hasNotText,
844861
has=has,
@@ -904,25 +921,22 @@ def get_by_title(
904921
return self.locator(get_by_title_selector(text, exact=exact))
905922

906923
def frame_locator(self, selector: str) -> "FrameLocator":
907-
return FrameLocator(
908-
self._frame,
909-
f"{self._frame_selector} >> internal:control=enter-frame >> {selector}",
910-
)
924+
return FrameLocator(self._frame, self._child_selector(selector))
911925

912926
@property
913927
def first(self) -> "FrameLocator":
914-
return FrameLocator(self._frame, f"{self._frame_selector} >> nth=0")
928+
return FrameLocator(self._frame, self._nth_selector("0"))
915929

916930
@property
917931
def last(self) -> "FrameLocator":
918-
return FrameLocator(self._frame, f"{self._frame_selector} >> nth=-1")
932+
return FrameLocator(self._frame, self._nth_selector("-1"))
919933

920934
@property
921935
def owner(self) -> "Locator":
922936
return Locator(self._frame, self._frame_selector)
923937

924938
def nth(self, index: int) -> "FrameLocator":
925-
return FrameLocator(self._frame, f"{self._frame_selector} >> nth={index}")
939+
return FrameLocator(self._frame, self._nth_selector(str(index)))
926940

927941
def __repr__(self) -> str:
928942
return f"<FrameLocator frame={self._frame!r} selector={self._frame_selector!r}>"

‎playwright/_impl/_network.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
Dict,
3030
List,
3131
Optional,
32+
Sequence,
3233
TypedDict,
3334
Union,
3435
cast,
@@ -39,6 +40,7 @@
3940
ClientCertificate,
4041
Headers,
4142
HeadersArray,
43+
HttpCredentials,
4244
RemoteAddr,
4345
RequestSizes,
4446
ResourceTiming,
@@ -126,6 +128,20 @@ async def to_client_certificates_protocol(
126128
return out
127129

128130

131+
def to_http_credentials_protocol(
132+
httpCredentials: Optional[Union[HttpCredentials, Sequence[HttpCredentials]]],
133+
) -> Optional[List[HttpCredentials]]:
134+
if not httpCredentials:
135+
return None
136+
credentials_list = (
137+
[httpCredentials] if isinstance(httpCredentials, dict) else httpCredentials
138+
)
139+
return [
140+
cast(HttpCredentials, {k: v for k, v in c.items() if v is not None})
141+
for c in credentials_list
142+
] or None
143+
144+
129145
class Request(ChannelOwner):
130146
def __init__(
131147
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict

0 commit comments

Comments
 (0)