@@ -5862,6 +5862,32 @@ def last(self) -> "FrameLocator":
58625862 """
58635863 return mapping.from_impl(self._impl_obj.last)
58645864
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+
58655891 def locator(
58665892 self,
58675893 selector_or_locator: typing.Union["Locator", str],
@@ -11669,9 +11695,11 @@ async def add_locator_handler(
1166911695 ) -> None:
1167011696 """Page.add_locator_handler
1167111697
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.
1167511703
1167611704 This method lets you set up a special function, called a handler, that activates when it detects that overlay is
1167711705 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(
1168111709 a part of your normal test flow, instead of using `page.add_locator_handler()`.
1168211710 - Playwright checks for the overlay every time before executing or retrying an action that requires an
1168311711 [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.
1168511715 - The execution time of the handler counts towards the timeout of the action/assertion that executed the handler.
1168611716 If your handler takes too long, it might cause timeouts.
1168711717 - 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(
1169911729
1170011730 **Usage**
1170111731
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:
1170311733
1170411734 ```py
1170511735 # Setup the handler.
1170611736 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)
1170911739
1171011740 # Write the test as usual.
1171111741 page.goto(\"https://example.com\")
@@ -12319,13 +12349,40 @@ async def add_cookies(self, cookies: typing.Sequence[SetCookieParam]) -> None:
1231912349 await self._impl_obj.add_cookies(cookies=mapping.to_impl(cookies))
1232012350 )
1232112351
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:
1232312359 """BrowserContext.clear_cookies
1232412360
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.
1232612381 """
1232712382
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+ )
1232912386
1233012387 async def grant_permissions(
1233112388 self, permissions: typing.Sequence[str], *, origin: typing.Optional[str] = None
@@ -13798,6 +13855,7 @@ async def launch(
1379813855 devtools : Union[bool, None]
1379913856 **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
1380013857 `headless` option will be set `false`.
13858+ Deprecated: Use [debugging tools](../debug.md) instead.
1380113859 proxy : Union[{server: str, bypass: Union[str, None], username: Union[str, None], password: Union[str, None]}, None]
1380213860 Network proxy settings.
1380313861 downloads_path : Union[pathlib.Path, str, None]
@@ -13955,6 +14013,7 @@ async def launch_persistent_context(
1395514013 devtools : Union[bool, None]
1395614014 **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
1395714015 `headless` option will be set `false`.
14016+ Deprecated: Use [debugging tools](../debug.md) instead.
1395814017 proxy : Union[{server: str, bypass: Union[str, None], username: Union[str, None], password: Union[str, None]}, None]
1395914018 Network proxy settings.
1396014019 downloads_path : Union[pathlib.Path, str, None]
@@ -14538,6 +14597,32 @@ def last(self) -> "Locator":
1453814597 """
1453914598 return mapping.from_impl(self._impl_obj.last)
1454014599
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+
1454114626 async def bounding_box(
1454214627 self, *, timeout: typing.Optional[float] = None
1454314628 ) -> typing.Optional[FloatRect]:
0 commit comments