@@ -5862,6 +5862,32 @@ def last(self) -> "FrameLocator":
5862
5862
"""
5863
5863
return mapping.from_impl(self._impl_obj.last)
5864
5864
5865
+ @property
5866
+ def owner(self) -> "Locator":
5867
+ """FrameLocator.owner
5868
+
5869
+ Returns a `Locator` object pointing to the same `iframe` as this frame locator.
5870
+
5871
+ Useful when you have a `FrameLocator` object obtained somewhere, and later on would like to interact with the
5872
+ `iframe` element.
5873
+
5874
+ For a reverse operation, use `locator.content_frame()`.
5875
+
5876
+ **Usage**
5877
+
5878
+ ```py
5879
+ frame_locator = page.frame_locator(\"iframe[name=\\\"embedded\\\"]\")
5880
+ # ...
5881
+ locator = frame_locator.owner
5882
+ await expect(locator).to_be_visible()
5883
+ ```
5884
+
5885
+ Returns
5886
+ -------
5887
+ Locator
5888
+ """
5889
+ return mapping.from_impl(self._impl_obj.owner)
5890
+
5865
5891
def locator(
5866
5892
self,
5867
5893
selector_or_locator: typing.Union["Locator", str],
@@ -11669,9 +11695,11 @@ async def add_locator_handler(
11669
11695
) -> None:
11670
11696
"""Page.add_locator_handler
11671
11697
11672
- When testing a web page, sometimes unexpected overlays like a coookie consent dialog appear and block actions you
11673
- want to automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time,
11674
- making them tricky to handle in automated tests.
11698
+ **NOTE** This method is experimental and its behavior may change in the upcoming releases.
11699
+
11700
+ When testing a web page, sometimes unexpected overlays like a \"Sign up\" dialog appear and block actions you want to
11701
+ automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making
11702
+ them tricky to handle in automated tests.
11675
11703
11676
11704
This method lets you set up a special function, called a handler, that activates when it detects that overlay is
11677
11705
visible. The handler's job is to remove the overlay, allowing your test to continue as if the overlay wasn't there.
@@ -11681,7 +11709,9 @@ async def add_locator_handler(
11681
11709
a part of your normal test flow, instead of using `page.add_locator_handler()`.
11682
11710
- Playwright checks for the overlay every time before executing or retrying an action that requires an
11683
11711
[actionability check](https://playwright.dev/python/docs/actionability), or before performing an auto-waiting assertion check. When overlay
11684
- is visible, Playwright calls the handler first, and then proceeds with the action/assertion.
11712
+ is visible, Playwright calls the handler first, and then proceeds with the action/assertion. Note that the
11713
+ handler is only called when you perform an action/assertion - if the overlay becomes visible but you don't
11714
+ perform any actions, the handler will not be triggered.
11685
11715
- The execution time of the handler counts towards the timeout of the action/assertion that executed the handler.
11686
11716
If your handler takes too long, it might cause timeouts.
11687
11717
- You can register multiple handlers. However, only a single handler will be running at a time. Make sure the
@@ -11699,13 +11729,13 @@ async def add_locator_handler(
11699
11729
11700
11730
**Usage**
11701
11731
11702
- An example that closes a cookie consent dialog when it appears:
11732
+ An example that closes a \"Sign up to the newsletter\" dialog when it appears:
11703
11733
11704
11734
```py
11705
11735
# Setup the handler.
11706
11736
def handler():
11707
- page.get_by_role(\"button\", name=\"Reject all cookies \").click()
11708
- page.add_locator_handler(page.get_by_role (\"button\", name=\"Accept all cookies \"), handler)
11737
+ page.get_by_role(\"button\", name=\"No thanks \").click()
11738
+ page.add_locator_handler(page.get_by_text (\"Sign up to the newsletter \"), handler)
11709
11739
11710
11740
# Write the test as usual.
11711
11741
page.goto(\"https://example.com\")
@@ -12319,13 +12349,40 @@ async def add_cookies(self, cookies: typing.Sequence[SetCookieParam]) -> None:
12319
12349
await self._impl_obj.add_cookies(cookies=mapping.to_impl(cookies))
12320
12350
)
12321
12351
12322
- async def clear_cookies(self) -> None:
12352
+ async def clear_cookies(
12353
+ self,
12354
+ *,
12355
+ name: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,
12356
+ domain: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,
12357
+ path: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None
12358
+ ) -> None:
12323
12359
"""BrowserContext.clear_cookies
12324
12360
12325
- Clears context cookies.
12361
+ Removes cookies from context. Accepts optional filter.
12362
+
12363
+ **Usage**
12364
+
12365
+ ```py
12366
+ await context.clear_cookies()
12367
+ await context.clear_cookies(name=\"session-id\")
12368
+ await context.clear_cookies(domain=\"my-origin.com\")
12369
+ await context.clear_cookies(path=\"/api/v1\")
12370
+ await context.clear_cookies(name=\"session-id\", domain=\"my-origin.com\")
12371
+ ```
12372
+
12373
+ Parameters
12374
+ ----------
12375
+ name : Union[Pattern[str], str, None]
12376
+ Only removes cookies with the given name.
12377
+ domain : Union[Pattern[str], str, None]
12378
+ Only removes cookies with the given domain.
12379
+ path : Union[Pattern[str], str, None]
12380
+ Only removes cookies with the given path.
12326
12381
"""
12327
12382
12328
- return mapping.from_maybe_impl(await self._impl_obj.clear_cookies())
12383
+ return mapping.from_maybe_impl(
12384
+ await self._impl_obj.clear_cookies(name=name, domain=domain, path=path)
12385
+ )
12329
12386
12330
12387
async def grant_permissions(
12331
12388
self, permissions: typing.Sequence[str], *, origin: typing.Optional[str] = None
@@ -13798,6 +13855,7 @@ async def launch(
13798
13855
devtools : Union[bool, None]
13799
13856
**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
13800
13857
`headless` option will be set `false`.
13858
+ Deprecated: Use [debugging tools](../debug.md) instead.
13801
13859
proxy : Union[{server: str, bypass: Union[str, None], username: Union[str, None], password: Union[str, None]}, None]
13802
13860
Network proxy settings.
13803
13861
downloads_path : Union[pathlib.Path, str, None]
@@ -13955,6 +14013,7 @@ async def launch_persistent_context(
13955
14013
devtools : Union[bool, None]
13956
14014
**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
13957
14015
`headless` option will be set `false`.
14016
+ Deprecated: Use [debugging tools](../debug.md) instead.
13958
14017
proxy : Union[{server: str, bypass: Union[str, None], username: Union[str, None], password: Union[str, None]}, None]
13959
14018
Network proxy settings.
13960
14019
downloads_path : Union[pathlib.Path, str, None]
@@ -14538,6 +14597,32 @@ def last(self) -> "Locator":
14538
14597
"""
14539
14598
return mapping.from_impl(self._impl_obj.last)
14540
14599
14600
+ @property
14601
+ def content_frame(self) -> "FrameLocator":
14602
+ """Locator.content_frame
14603
+
14604
+ Returns a `FrameLocator` object pointing to the same `iframe` as this locator.
14605
+
14606
+ Useful when you have a `Locator` object obtained somewhere, and later on would like to interact with the content
14607
+ inside the frame.
14608
+
14609
+ For a reverse operation, use `frame_locator.owner()`.
14610
+
14611
+ **Usage**
14612
+
14613
+ ```py
14614
+ locator = page.locator(\"iframe[name=\\\"embedded\\\"]\")
14615
+ # ...
14616
+ frame_locator = locator.content_frame
14617
+ await frame_locator.get_by_role(\"button\").click()
14618
+ ```
14619
+
14620
+ Returns
14621
+ -------
14622
+ FrameLocator
14623
+ """
14624
+ return mapping.from_impl(self._impl_obj.content_frame)
14625
+
14541
14626
async def bounding_box(
14542
14627
self, *, timeout: typing.Optional[float] = None
14543
14628
) -> typing.Optional[FloatRect]:
0 commit comments