docs: update auto-waiting doc (#28960)

- Replace action names with links to `Locator.click`.
- Remove "Attached" check in favor of "locator resolves to a single
element".
- Replace getter methods in assertion section with auto-retriying
assertions.
- Add missing actions.

---

<img width="837" alt="Screenshot 2024-01-11 at 1 02 34 PM"
src="https://github.com/microsoft/playwright/assets/9881434/1946678d-6a7e-45cf-a299-2f18cb3fb5a5">
This commit is contained in:
Dmitry Gozman 2024-01-12 09:33:42 -08:00 committed by GitHub
parent 808359ba6c
commit 90665ef056
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 67 deletions

View File

@ -8,8 +8,8 @@ title: "Auto-waiting"
Playwright performs a range of actionability checks on the elements before making actions to ensure these actions Playwright performs a range of actionability checks on the elements before making actions to ensure these actions
behave as expected. It auto-waits for all the relevant checks to pass and only then performs the requested action. If the required checks do not pass within the given `timeout`, action fails with the `TimeoutError`. behave as expected. It auto-waits for all the relevant checks to pass and only then performs the requested action. If the required checks do not pass within the given `timeout`, action fails with the `TimeoutError`.
For example, for [`method: Page.click`], Playwright will ensure that: For example, for [`method: Locator.click`], Playwright will ensure that:
- element is [Attached] to the DOM - locator resolves to an exactly one element
- element is [Visible] - element is [Visible]
- element is [Stable], as in not animating or completed animation - element is [Stable], as in not animating or completed animation
- element [Receives Events], as in not obscured by other elements - element [Receives Events], as in not obscured by other elements
@ -17,68 +17,66 @@ For example, for [`method: Page.click`], Playwright will ensure that:
Here is the complete list of actionability checks performed for each action: Here is the complete list of actionability checks performed for each action:
| Action | [Attached] | [Visible] | [Stable] | [Receives Events] | [Enabled] | [Editable] | | Action | [Visible] | [Stable] | [Receives Events] | [Enabled] | [Editable] |
| :- | :-: | :-: | :-: | :-: | :-: | :-: | | :- | :-: | :-: | :-: | :-: | :-: |
| check | Yes | Yes | Yes | Yes | Yes | - | | [`method: Locator.check`] | Yes | Yes | Yes | Yes | - |
| click | Yes | Yes | Yes | Yes | Yes | - | | [`method: Locator.click`] | Yes | Yes | Yes | Yes | - |
| dblclick | Yes | Yes | Yes | Yes | Yes | - | | [`method: Locator.dblclick`] | Yes | Yes | Yes | Yes | - |
| setChecked | Yes | Yes | Yes | Yes | Yes | - | | [`method: Locator.setChecked`] | Yes | Yes | Yes | Yes | - |
| tap | Yes | Yes | Yes | Yes | Yes | - | | [`method: Locator.tap`] | Yes | Yes | Yes | Yes | - |
| uncheck | Yes | Yes | Yes | Yes | Yes | - | | [`method: Locator.uncheck`] | Yes | Yes | Yes | Yes | - |
| hover | Yes | Yes | Yes | Yes | - | - | | [`method: Locator.hover`] | Yes | Yes | Yes | - | - |
| scrollIntoViewIfNeeded | Yes | - | Yes | - | - | - | | [`method: Locator.dragTo`] | Yes | Yes | Yes | - | - |
| screenshot | Yes | Yes | Yes | - | - | - | | [`method: Locator.screenshot`] | Yes | Yes | - | - | - |
| fill | Yes | Yes | - | - | Yes | Yes | | [`method: Locator.fill`] | Yes | - | - | Yes | Yes |
| selectText | Yes | Yes | - | - | - | - | | [`method: Locator.clear`] | Yes | - | - | Yes | Yes |
| dispatchEvent | Yes | - | - | - | - | - | | [`method: Locator.selectOption`] | Yes | - | - | Yes | - |
| focus | Yes | - | - | - | - | - | | [`method: Locator.selectText`] | Yes | - | - | - | - |
| getAttribute | Yes | - | - | - | - | - | | [`method: Locator.scrollIntoViewIfNeeded`] | - | Yes | - | - | - |
| innerText | Yes | - | - | - | - | - | | [`method: Locator.blur`] | - | - | - | - | - |
| innerHTML | Yes | - | - | - | - | - | | [`method: Locator.dispatchEvent`] | - | - | - | - | - |
| press | Yes | - | - | - | - | - | | [`method: Locator.focus`] | - | - | - | - | - |
| setInputFiles | Yes | - | - | - | - | - | | [`method: Locator.press`] | - | - | - | - | - |
| selectOption | Yes | Yes | - | - | Yes | - | | [`method: Locator.pressSequentially`] | - | - | - | - | - |
| textContent | Yes | - | - | - | - | - | | [`method: Locator.setInputFiles`] | - | - | - | - | - |
| type | Yes | - | - | - | - | - |
<br/>
## Forcing actions ## Forcing actions
Some actions like [`method: Page.click`] support `force` option that disables non-essential actionability checks, Some actions like [`method: Locator.click`] support `force` option that disables non-essential actionability checks,
for example passing truthy `force` to [`method: Page.click`] method will not check that the target element actually for example passing truthy `force` to [`method: Locator.click`] method will not check that the target element actually
receives click events. receives click events.
## Assertions ## Assertions
You can check the actionability state of the element using one of the following methods as well. This is typically Playwright includes auto-retrying assertions that remove flakiness by waiting until the condition is met, similarly to auto-waiting before actions.
not necessary, but it helps writing assertive tests that ensure that after certain actions, elements reach
actionable state:
- [`method: ElementHandle.isChecked`] | Assertion | Description |
- [`method: ElementHandle.isDisabled`] | :- | :- |
- [`method: ElementHandle.isEditable`] | [`method: LocatorAssertions.toBeAttached`] | Element is attached |
- [`method: ElementHandle.isEnabled`] | [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
- [`method: ElementHandle.isHidden`] | [`method: LocatorAssertions.toBeDisabled`] | Element is disabled |
- [`method: ElementHandle.isVisible`] | [`method: LocatorAssertions.toBeEditable`] | Element is editable |
- [`method: Page.isChecked`] | [`method: LocatorAssertions.toBeEmpty`] | Container is empty |
- [`method: Page.isDisabled`] | [`method: LocatorAssertions.toBeEnabled`] | Element is enabled |
- [`method: Page.isEditable`] | [`method: LocatorAssertions.toBeFocused`] | Element is focused |
- [`method: Page.isEnabled`] | [`method: LocatorAssertions.toBeHidden`] | Element is not visible |
- [`method: Page.isHidden`] | [`method: LocatorAssertions.toBeInViewport`] | Element intersects viewport |
- [`method: Page.isVisible`] | [`method: LocatorAssertions.toBeVisible`] | Element is visible |
- [`method: Locator.isChecked`] | [`method: LocatorAssertions.toContainText`] | Element contains text |
- [`method: Locator.isDisabled`] | [`method: LocatorAssertions.toHaveAttribute`] | Element has a DOM attribute |
- [`method: Locator.isEditable`] | [`method: LocatorAssertions.toHaveClass`] | Element has a class property |
- [`method: Locator.isEnabled`] | [`method: LocatorAssertions.toHaveCount`] | List has exact number of children |
- [`method: Locator.isHidden`] | [`method: LocatorAssertions.toHaveCSS`] | Element has CSS property |
- [`method: Locator.isVisible`] | [`method: LocatorAssertions.toHaveId`] | Element has an ID |
| [`method: LocatorAssertions.toHaveJSProperty`] | Element has a JavaScript property |
| [`method: LocatorAssertions.toHaveText`] | Element matches text |
| [`method: LocatorAssertions.toHaveValue`] | Input has a value |
| [`method: LocatorAssertions.toHaveValues`] | Select has options selected |
| [`method: PageAssertions.toHaveTitle`] | Page has a title |
| [`method: PageAssertions.toHaveURL`] | Page has a URL |
| [`method: APIResponseAssertions.toBeOK`] | Response has an OK status |
<br/> Learn more in the [assertions guide](./test-assertions.md).
## Attached
Element is considered attached when it is [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
## Visible ## Visible
@ -101,7 +99,7 @@ Element is considered editable when it is [enabled] and does not have `readonly`
Element is considered receiving pointer events when it is the hit target of the pointer event at the action point. For example, when clicking at the point `(10;10)`, Playwright checks whether some other element (usually an overlay) will instead capture the click at `(10;10)`. Element is considered receiving pointer events when it is the hit target of the pointer event at the action point. For example, when clicking at the point `(10;10)`, Playwright checks whether some other element (usually an overlay) will instead capture the click at `(10;10)`.
For example, consider a scenario where Playwright will click `Sign Up` button regardless of when the [`method: Page.click`] call was made: For example, consider a scenario where Playwright will click `Sign Up` button regardless of when the [`method: Locator.click`] call was made:
- page is checking that user name is unique and `Sign Up` button is disabled; - page is checking that user name is unique and `Sign Up` button is disabled;
- after checking with the server, the disabled `Sign Up` button is replaced with another one that is now enabled. - after checking with the server, the disabled `Sign Up` button is replaced with another one that is now enabled.
@ -110,4 +108,3 @@ For example, consider a scenario where Playwright will click `Sign Up` button re
[Enabled]: #enabled "Enabled" [Enabled]: #enabled "Enabled"
[Editable]: #editable "Editable" [Editable]: #editable "Editable"
[Receives Events]: #receives-events "Receives Events" [Receives Events]: #receives-events "Receives Events"
[Attached]: #attached "Attached"

View File

@ -1090,7 +1090,7 @@ Depending on the [`param: state`] parameter, this method waits for one of the [a
to pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"` state. to pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"` state.
* `"visible"` Wait until the element is [visible](../actionability.md#visible). * `"visible"` Wait until the element is [visible](../actionability.md#visible).
* `"hidden"` Wait until the element is [not visible](../actionability.md#visible) or * `"hidden"` Wait until the element is [not visible](../actionability.md#visible) or
[not attached](../actionability.md#attached). Note that waiting for hidden does not throw when the element detaches. not attached. Note that waiting for hidden does not throw when the element detaches.
* `"stable"` Wait until the element is both [visible](../actionability.md#visible) and * `"stable"` Wait until the element is both [visible](../actionability.md#visible) and
[stable](../actionability.md#stable). [stable](../actionability.md#stable).
* `"enabled"` Wait until the element is [enabled](../actionability.md#enabled). * `"enabled"` Wait until the element is [enabled](../actionability.md#enabled).

View File

@ -403,7 +403,7 @@ Expected options currently selected.
* langs: * langs:
- alias-java: isAttached - alias-java: isAttached
Ensures that [Locator] points to an [attached](../actionability.md#attached) DOM node. Ensures that [Locator] points to an element that is [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
**Usage** **Usage**
@ -837,7 +837,7 @@ element should intersect viewport at any positive ratio. Defaults to `0`.
* langs: * langs:
- alias-java: isVisible - alias-java: isVisible
Ensures that [Locator] points to an [attached](../actionability.md#attached) and [visible](../actionability.md#visible) DOM node. Ensures that [Locator] points to an attached and [visible](../actionability.md#visible) DOM node.
To check that at least one element from the list is visible, use [`method: Locator.first`]. To check that at least one element from the list is visible, use [`method: Locator.first`].

View File

@ -7,6 +7,7 @@ title: "Assertions"
| Assertion | Description | | Assertion | Description |
| :- | :- | | :- | :- |
| [`method: LocatorAssertions.toBeAttached`] | Element is attached |
| [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked | | [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
| [`method: LocatorAssertions.toBeDisabled`] | Element is disabled | | [`method: LocatorAssertions.toBeDisabled`] | Element is disabled |
| [`method: LocatorAssertions.toBeEditable`] | Element is editable | | [`method: LocatorAssertions.toBeEditable`] | Element is editable |
@ -14,6 +15,7 @@ title: "Assertions"
| [`method: LocatorAssertions.toBeEnabled`] | Element is enabled | | [`method: LocatorAssertions.toBeEnabled`] | Element is enabled |
| [`method: LocatorAssertions.toBeFocused`] | Element is focused | | [`method: LocatorAssertions.toBeFocused`] | Element is focused |
| [`method: LocatorAssertions.toBeHidden`] | Element is not visible | | [`method: LocatorAssertions.toBeHidden`] | Element is not visible |
| [`method: LocatorAssertions.toBeInViewport`] | Element intersects viewport |
| [`method: LocatorAssertions.toBeVisible`] | Element is visible | | [`method: LocatorAssertions.toBeVisible`] | Element is visible |
| [`method: LocatorAssertions.toContainText`] | Element contains text | | [`method: LocatorAssertions.toContainText`] | Element contains text |
| [`method: LocatorAssertions.toHaveAttribute`] | Element has a DOM attribute | | [`method: LocatorAssertions.toHaveAttribute`] | Element has a DOM attribute |
@ -44,7 +46,7 @@ The error would look like this:
def test_foobar(page: Page) -> None: def test_foobar(page: Page) -> None:
> expect(page.get_by_text("Name"), "should be logged in").to_be_visible() > expect(page.get_by_text("Name"), "should be logged in").to_be_visible()
E AssertionError: should be logged in E AssertionError: should be logged in
E Actual value: None E Actual value: None
E Call log: E Call log:
E LocatorAssertions.to_be_visible with timeout 5000ms E LocatorAssertions.to_be_visible with timeout 5000ms
E waiting for get_by_text("Name") E waiting for get_by_text("Name")

View File

@ -10589,9 +10589,8 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
* Depending on the `state` parameter, this method waits for one of the [actionability](https://playwright.dev/docs/actionability) checks to * Depending on the `state` parameter, this method waits for one of the [actionability](https://playwright.dev/docs/actionability) checks to
* pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"` state. * pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"` state.
* - `"visible"` Wait until the element is [visible](https://playwright.dev/docs/actionability#visible). * - `"visible"` Wait until the element is [visible](https://playwright.dev/docs/actionability#visible).
* - `"hidden"` Wait until the element is [not visible](https://playwright.dev/docs/actionability#visible) or * - `"hidden"` Wait until the element is [not visible](https://playwright.dev/docs/actionability#visible) or not attached. Note that
* [not attached](https://playwright.dev/docs/actionability#attached). Note that waiting for hidden does not throw when the element * waiting for hidden does not throw when the element detaches.
* detaches.
* - `"stable"` Wait until the element is both [visible](https://playwright.dev/docs/actionability#visible) and * - `"stable"` Wait until the element is both [visible](https://playwright.dev/docs/actionability#visible) and
* [stable](https://playwright.dev/docs/actionability#stable). * [stable](https://playwright.dev/docs/actionability#stable).
* - `"enabled"` Wait until the element is [enabled](https://playwright.dev/docs/actionability#enabled). * - `"enabled"` Wait until the element is [enabled](https://playwright.dev/docs/actionability#enabled).

View File

@ -5425,7 +5425,8 @@ interface APIResponseAssertions {
*/ */
interface LocatorAssertions { interface LocatorAssertions {
/** /**
* Ensures that {@link Locator} points to an [attached](https://playwright.dev/docs/actionability#attached) DOM node. * Ensures that {@link Locator} points to an element that is
* [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
* *
* **Usage** * **Usage**
* *
@ -5620,8 +5621,7 @@ interface LocatorAssertions {
}): Promise<void>; }): Promise<void>;
/** /**
* Ensures that {@link Locator} points to an [attached](https://playwright.dev/docs/actionability#attached) and * Ensures that {@link Locator} points to an attached and [visible](https://playwright.dev/docs/actionability#visible) DOM node.
* [visible](https://playwright.dev/docs/actionability#visible) DOM node.
* *
* To check that at least one element from the list is visible, use * To check that at least one element from the list is visible, use
* [locator.first()](https://playwright.dev/docs/api/class-locator#locator-first). * [locator.first()](https://playwright.dev/docs/api/class-locator#locator-first).