@@ -6879,6 +6879,18 @@ async def pause_at(self, time: typing.Union[float, str, datetime.datetime]) -> N
68796879 await page.clock.pause_at(\"2020-02-02\")
68806880 ```
68816881
6882+ For best results, install the clock before navigating the page and set it to a time slightly before the intended
6883+ test time. This ensures that all timers run normally during page loading, preventing the page from getting stuck.
6884+ Once the page has fully loaded, you can safely use `clock.pause_at()` to pause the clock.
6885+
6886+ ```py
6887+ # Initialize clock with some time before the test time and let the page load
6888+ # naturally. `Date.now` will progress as the timers fire.
6889+ await page.clock.install(time=datetime.datetime(2024, 12, 10, 8, 0, 0))
6890+ await page.goto(\"http://localhost:3333\")
6891+ await page.clock.pause_at(datetime.datetime(2024, 12, 10, 10, 0, 0))
6892+ ```
6893+
68826894 Parameters
68836895 ----------
68846896 time : Union[datetime.datetime, float, str]
@@ -8036,7 +8048,7 @@ def set_default_timeout(self, timeout: float) -> None:
80368048 Parameters
80378049 ----------
80388050 timeout : float
8039- Maximum time in milliseconds
8051+ Maximum time in milliseconds. Pass `0` to disable timeout.
80408052 """
80418053
80428054 return mapping.from_maybe_impl(
@@ -11497,8 +11509,6 @@ async def pdf(
1149711509
1149811510 Returns the PDF buffer.
1149911511
11500- **NOTE** Generating a pdf is currently only supported in Chromium headless.
11501-
1150211512 `page.pdf()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call
1150311513 `page.emulate_media()` before calling `page.pdf()`:
1150411514
@@ -12750,7 +12760,7 @@ def set_default_timeout(self, timeout: float) -> None:
1275012760 Parameters
1275112761 ----------
1275212762 timeout : float
12753- Maximum time in milliseconds
12763+ Maximum time in milliseconds. Pass `0` to disable timeout.
1275412764 """
1275512765
1275612766 return mapping.from_maybe_impl(
@@ -12858,9 +12868,13 @@ async def grant_permissions(
1285812868 Parameters
1285912869 ----------
1286012870 permissions : Sequence[str]
12861- A permission or an array of permissions to grant. Permissions can be one of the following values:
12871+ A list of permissions to grant.
12872+
12873+ **NOTE** Supported permissions differ between browsers, and even between different versions of the same browser.
12874+ Any permission may stop working after an update.
12875+
12876+ Here are some permissions that may be supported by some browsers:
1286212877 - `'accelerometer'`
12863- - `'accessibility-events'`
1286412878 - `'ambient-light-sensor'`
1286512879 - `'background-sync'`
1286612880 - `'camera'`
@@ -14161,9 +14175,9 @@ async def close(self, *, reason: typing.Optional[str] = None) -> None:
1416114175 In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from
1416214176 the browser server.
1416314177
14164- **NOTE** This is similar to force quitting the browser. Therefore, you should call `browser_context. close()`
14165- on any `BrowserContext`'s you explicitly created earlier with `browser.new_context()` **before** calling
14166- `browser.close()`.
14178+ **NOTE** This is similar to force- quitting the browser. To close pages gracefully and ensure you receive page close
14179+ events, call `browser_context.close()` on any `BrowserContext` instances you explicitly created earlier
14180+ using `browser.new_context()` **before** calling `browser.close()`.
1416714181
1416814182 The `Browser` object itself is considered to be disposed and cannot be used anymore.
1416914183
@@ -14346,7 +14360,7 @@ async def launch(
1434614360 channel : Union[str, None]
1434714361 Browser distribution channel.
1434814362
14349- Use "chromium" to [opt in to new headless mode](../browsers.md#opt-in-to -new-headless-mode).
14363+ Use "chromium" to [opt in to new headless mode](../browsers.md#chromium -new-headless-mode).
1435014364
1435114365 Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or
1435214366 "msedge-canary" to use branded [Google Chrome and Microsoft Edge](../browsers.md#google-chrome--microsoft-edge).
@@ -14504,7 +14518,7 @@ async def launch_persistent_context(
1450414518 channel : Union[str, None]
1450514519 Browser distribution channel.
1450614520
14507- Use "chromium" to [opt in to new headless mode](../browsers.md#opt-in-to -new-headless-mode).
14521+ Use "chromium" to [opt in to new headless mode](../browsers.md#chromium -new-headless-mode).
1450814522
1450914523 Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or
1451014524 "msedge-canary" to use branded [Google Chrome and Microsoft Edge](../browsers.md#google-chrome--microsoft-edge).
@@ -15522,7 +15536,6 @@ async def dispatch_event(
1552215536 You can also specify `JSHandle` as the property value if you want live objects to be passed into the event:
1552315537
1552415538 ```py
15525- # note you can only create data_transfer in chromium and firefox
1552615539 data_transfer = await page.evaluate_handle(\"new DataTransfer()\")
1552715540 await locator.dispatch_event(\"#source\", \"dragstart\", {\"dataTransfer\": data_transfer})
1552815541 ```
@@ -16445,18 +16458,22 @@ def or_(self, locator: "Locator") -> "Locator":
1644516458
1644616459 Creates a locator matching all elements that match one or both of the two locators.
1644716460
16448- Note that when both locators match something, the resulting locator will have multiple matches and violate
16449- [locator strictness](https://playwright.dev/python/docs/locators#strictness) guidelines .
16461+ Note that when both locators match something, the resulting locator will have multiple matches, potentially causing
16462+ a [locator strictness](https://playwright.dev/python/docs/locators#strictness) violation .
1645016463
1645116464 **Usage**
1645216465
1645316466 Consider a scenario where you'd like to click on a \"New email\" button, but sometimes a security settings dialog
1645416467 shows up instead. In this case, you can wait for either a \"New email\" button, or a dialog and act accordingly.
1645516468
16469+ **NOTE** If both \"New email\" button and security dialog appear on screen, the \"or\" locator will match both of them,
16470+ possibly throwing the [\"strict mode violation\" error](https://playwright.dev/python/docs/locators#strictness). In this case, you can use
16471+ `locator.first()` to only match one of them.
16472+
1645616473 ```py
1645716474 new_email = page.get_by_role(\"button\", name=\"New\")
1645816475 dialog = page.get_by_text(\"Confirm security settings\")
16459- await expect(new_email.or_(dialog)).to_be_visible()
16476+ await expect(new_email.or_(dialog).first ).to_be_visible()
1646016477 if (await dialog.is_visible()):
1646116478 await page.get_by_role(\"button\", name=\"Dismiss\").click()
1646216479 await new_email.click()
@@ -16877,7 +16894,9 @@ async def is_disabled(self, *, timeout: typing.Optional[float] = None) -> bool:
1687716894 async def is_editable(self, *, timeout: typing.Optional[float] = None) -> bool:
1687816895 """Locator.is_editable
1687916896
16880- Returns whether the element is [editable](https://playwright.dev/python/docs/actionability#editable).
16897+ Returns whether the element is [editable](https://playwright.dev/python/docs/actionability#editable). If the target element is not an `<input>`,
16898+ `<textarea>`, `<select>`, `[contenteditable]` and does not have a role allowing `[aria-readonly]`, this method
16899+ throws an error.
1688116900
1688216901 **NOTE** If you need to assert that an element is editable, prefer `locator_assertions.to_be_editable()` to
1688316902 avoid flakiness. See [assertions guide](https://playwright.dev/python/docs/test-assertions) for more details.
@@ -19056,24 +19075,26 @@ async def to_have_class(
1905619075 ) -> None:
1905719076 """LocatorAssertions.to_have_class
1905819077
19059- Ensures the `Locator` points to an element with given CSS classes. This needs to be a full match or using a relaxed
19060- regular expression.
19078+ Ensures the `Locator` points to an element with given CSS classes. When a string is provided, it must fully match
19079+ the element's `class` attribute. To match individual classes or perform partial matches, use a regular expression:
1906119080
1906219081 **Usage**
1906319082
1906419083 ```html
19065- <div class='selected row' id='component'></div>
19084+ <div class='middle selected row' id='component'></div>
1906619085 ```
1906719086
1906819087 ```py
1906919088 from playwright.async_api import expect
1907019089
1907119090 locator = page.locator(\"#component\")
19072- await expect(locator).to_have_class(re.compile(r\"selected\"))
19073- await expect(locator).to_have_class(\"selected row\")
19091+ await expect(locator).to_have_class(re.compile(r\"(^|\\\\s) selected(\\\\s|$) \"))
19092+ await expect(locator).to_have_class(\"middle selected row\")
1907419093 ```
1907519094
19076- Note that if array is passed as an expected value, entire lists of elements can be asserted:
19095+ When an array is passed, the method asserts that the list of elements located matches the corresponding list of
19096+ expected class values. Each element's class attribute is matched against the corresponding string or regular
19097+ expression in the array:
1907719098
1907819099 ```py
1907919100 from playwright.async_api import expect
@@ -19656,6 +19677,7 @@ async def to_be_checked(
1965619677 *,
1965719678 timeout: typing.Optional[float] = None,
1965819679 checked: typing.Optional[bool] = None,
19680+ indeterminate: typing.Optional[bool] = None,
1965919681 ) -> None:
1966019682 """LocatorAssertions.to_be_checked
1966119683
@@ -19675,11 +19697,18 @@ async def to_be_checked(
1967519697 timeout : Union[float, None]
1967619698 Time to retry the assertion for in milliseconds. Defaults to `5000`.
1967719699 checked : Union[bool, None]
19700+ Provides state to assert for. Asserts for input to be checked by default. This option can't be used when
19701+ `indeterminate` is set to true.
19702+ indeterminate : Union[bool, None]
19703+ Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons.
19704+ This option can't be true when `checked` is provided.
1967819705 """
1967919706 __tracebackhide__ = True
1968019707
1968119708 return mapping.from_maybe_impl(
19682- await self._impl_obj.to_be_checked(timeout=timeout, checked=checked)
19709+ await self._impl_obj.to_be_checked(
19710+ timeout=timeout, checked=checked, indeterminate=indeterminate
19711+ )
1968319712 )
1968419713
1968519714 async def not_to_be_attached(
@@ -20373,6 +20402,72 @@ async def to_have_role(
2037320402 await self._impl_obj.to_have_role(role=role, timeout=timeout)
2037420403 )
2037520404
20405+ async def to_have_accessible_error_message(
20406+ self,
20407+ error_message: typing.Union[str, typing.Pattern[str]],
20408+ *,
20409+ ignore_case: typing.Optional[bool] = None,
20410+ timeout: typing.Optional[float] = None,
20411+ ) -> None:
20412+ """LocatorAssertions.to_have_accessible_error_message
20413+
20414+ Ensures the `Locator` points to an element with a given
20415+ [aria errormessage](https://w3c.github.io/aria/#aria-errormessage).
20416+
20417+ **Usage**
20418+
20419+ ```py
20420+ locator = page.get_by_test_id(\"username-input\")
20421+ await expect(locator).to_have_accessible_error_message(\"Username is required.\")
20422+ ```
20423+
20424+ Parameters
20425+ ----------
20426+ error_message : Union[Pattern[str], str]
20427+ Expected accessible error message.
20428+ ignore_case : Union[bool, None]
20429+ Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular
20430+ expression flag if specified.
20431+ timeout : Union[float, None]
20432+ Time to retry the assertion for in milliseconds. Defaults to `5000`.
20433+ """
20434+ __tracebackhide__ = True
20435+
20436+ return mapping.from_maybe_impl(
20437+ await self._impl_obj.to_have_accessible_error_message(
20438+ errorMessage=error_message, ignoreCase=ignore_case, timeout=timeout
20439+ )
20440+ )
20441+
20442+ async def not_to_have_accessible_error_message(
20443+ self,
20444+ error_message: typing.Union[str, typing.Pattern[str]],
20445+ *,
20446+ ignore_case: typing.Optional[bool] = None,
20447+ timeout: typing.Optional[float] = None,
20448+ ) -> None:
20449+ """LocatorAssertions.not_to_have_accessible_error_message
20450+
20451+ The opposite of `locator_assertions.to_have_accessible_error_message()`.
20452+
20453+ Parameters
20454+ ----------
20455+ error_message : Union[Pattern[str], str]
20456+ Expected accessible error message.
20457+ ignore_case : Union[bool, None]
20458+ Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular
20459+ expression flag if specified.
20460+ timeout : Union[float, None]
20461+ Time to retry the assertion for in milliseconds. Defaults to `5000`.
20462+ """
20463+ __tracebackhide__ = True
20464+
20465+ return mapping.from_maybe_impl(
20466+ await self._impl_obj.not_to_have_accessible_error_message(
20467+ errorMessage=error_message, ignoreCase=ignore_case, timeout=timeout
20468+ )
20469+ )
20470+
2037620471 async def not_to_have_role(
2037720472 self,
2037820473 role: Literal[
0 commit comments