Skip to content

Commit

Permalink
docs: update auto-waiting doc (#28960)
Browse files Browse the repository at this point in the history
- 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">
  • Loading branch information
dgozman authored Jan 12, 2024
1 parent 808359b commit 90665ef
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 69 deletions.
115 changes: 56 additions & 59 deletions docs/src/actionability.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,77 +8,75 @@ title: "Auto-waiting"
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`.

For example, for [`method: Page.click`], Playwright will ensure that:
- element is [Attached] to the DOM
For example, for [`method: Locator.click`], Playwright will ensure that:
- locator resolves to an exactly one element
- element is [Visible]
- element is [Stable], as in not animating or completed animation
- element [Receives Events], as in not obscured by other elements
- element is [Enabled]

Here is the complete list of actionability checks performed for each action:

| Action | [Attached] | [Visible] | [Stable] | [Receives Events] | [Enabled] | [Editable] |
| :- | :-: | :-: | :-: | :-: | :-: | :-: |
| check | Yes | Yes | Yes | Yes | Yes | - |
| click | Yes | Yes | Yes | Yes | Yes | - |
| dblclick | Yes | Yes | Yes | Yes | Yes | - |
| setChecked | Yes | Yes | Yes | Yes | Yes | - |
| tap | Yes | Yes | Yes | Yes | Yes | - |
| uncheck | Yes | Yes | Yes | Yes | Yes | - |
| hover | Yes | Yes | Yes | Yes | - | - |
| scrollIntoViewIfNeeded | Yes | - | Yes | - | - | - |
| screenshot | Yes | Yes | Yes | - | - | - |
| fill | Yes | Yes | - | - | Yes | Yes |
| selectText | Yes | Yes | - | - | - | - |
| dispatchEvent | Yes | - | - | - | - | - |
| focus | Yes | - | - | - | - | - |
| getAttribute | Yes | - | - | - | - | - |
| innerText | Yes | - | - | - | - | - |
| innerHTML | Yes | - | - | - | - | - |
| press | Yes | - | - | - | - | - |
| setInputFiles | Yes | - | - | - | - | - |
| selectOption | Yes | Yes | - | - | Yes | - |
| textContent | Yes | - | - | - | - | - |
| type | Yes | - | - | - | - | - |

<br/>
| Action | [Visible] | [Stable] | [Receives Events] | [Enabled] | [Editable] |
| :- | :-: | :-: | :-: | :-: | :-: |
| [`method: Locator.check`] | Yes | Yes | Yes | Yes | - |
| [`method: Locator.click`] | Yes | Yes | Yes | Yes | - |
| [`method: Locator.dblclick`] | Yes | Yes | Yes | Yes | - |
| [`method: Locator.setChecked`] | Yes | Yes | Yes | Yes | - |
| [`method: Locator.tap`] | Yes | Yes | Yes | Yes | - |
| [`method: Locator.uncheck`] | Yes | Yes | Yes | Yes | - |
| [`method: Locator.hover`] | Yes | Yes | Yes | - | - |
| [`method: Locator.dragTo`] | Yes | Yes | Yes | - | - |
| [`method: Locator.screenshot`] | Yes | Yes | - | - | - |
| [`method: Locator.fill`] | Yes | - | - | Yes | Yes |
| [`method: Locator.clear`] | Yes | - | - | Yes | Yes |
| [`method: Locator.selectOption`] | Yes | - | - | Yes | - |
| [`method: Locator.selectText`] | Yes | - | - | - | - |
| [`method: Locator.scrollIntoViewIfNeeded`] | - | Yes | - | - | - |
| [`method: Locator.blur`] | - | - | - | - | - |
| [`method: Locator.dispatchEvent`] | - | - | - | - | - |
| [`method: Locator.focus`] | - | - | - | - | - |
| [`method: Locator.press`] | - | - | - | - | - |
| [`method: Locator.pressSequentially`] | - | - | - | - | - |
| [`method: Locator.setInputFiles`] | - | - | - | - | - |

## Forcing actions

Some actions like [`method: Page.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
Some actions like [`method: Locator.click`] support `force` option that disables non-essential actionability checks,
for example passing truthy `force` to [`method: Locator.click`] method will not check that the target element actually
receives click events.

## Assertions

You can check the actionability state of the element using one of the following methods as well. This is typically
not necessary, but it helps writing assertive tests that ensure that after certain actions, elements reach
actionable state:

- [`method: ElementHandle.isChecked`]
- [`method: ElementHandle.isDisabled`]
- [`method: ElementHandle.isEditable`]
- [`method: ElementHandle.isEnabled`]
- [`method: ElementHandle.isHidden`]
- [`method: ElementHandle.isVisible`]
- [`method: Page.isChecked`]
- [`method: Page.isDisabled`]
- [`method: Page.isEditable`]
- [`method: Page.isEnabled`]
- [`method: Page.isHidden`]
- [`method: Page.isVisible`]
- [`method: Locator.isChecked`]
- [`method: Locator.isDisabled`]
- [`method: Locator.isEditable`]
- [`method: Locator.isEnabled`]
- [`method: Locator.isHidden`]
- [`method: Locator.isVisible`]

<br/>

## 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.
Playwright includes auto-retrying assertions that remove flakiness by waiting until the condition is met, similarly to auto-waiting before actions.

| Assertion | Description |
| :- | :- |
| [`method: LocatorAssertions.toBeAttached`] | Element is attached |
| [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
| [`method: LocatorAssertions.toBeDisabled`] | Element is disabled |
| [`method: LocatorAssertions.toBeEditable`] | Element is editable |
| [`method: LocatorAssertions.toBeEmpty`] | Container is empty |
| [`method: LocatorAssertions.toBeEnabled`] | Element is enabled |
| [`method: LocatorAssertions.toBeFocused`] | Element is focused |
| [`method: LocatorAssertions.toBeHidden`] | Element is not visible |
| [`method: LocatorAssertions.toBeInViewport`] | Element intersects viewport |
| [`method: LocatorAssertions.toBeVisible`] | Element is visible |
| [`method: LocatorAssertions.toContainText`] | Element contains text |
| [`method: LocatorAssertions.toHaveAttribute`] | Element has a DOM attribute |
| [`method: LocatorAssertions.toHaveClass`] | Element has a class property |
| [`method: LocatorAssertions.toHaveCount`] | List has exact number of children |
| [`method: LocatorAssertions.toHaveCSS`] | Element has CSS property |
| [`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 |

Learn more in the [assertions guide](./test-assertions.md).

## Visible

Expand All @@ -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)`.


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;
- after checking with the server, the disabled `Sign Up` button is replaced with another one that is now enabled.

Expand All @@ -110,4 +108,3 @@ For example, consider a scenario where Playwright will click `Sign Up` button re
[Enabled]: #enabled "Enabled"
[Editable]: #editable "Editable"
[Receives Events]: #receives-events "Receives Events"
[Attached]: #attached "Attached"
2 changes: 1 addition & 1 deletion docs/src/api/class-elementhandle.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* `"visible"` Wait until the element is [visible](../actionability.md#visible).
* `"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](../actionability.md#stable).
* `"enabled"` Wait until the element is [enabled](../actionability.md#enabled).
Expand Down
4 changes: 2 additions & 2 deletions docs/src/api/class-locatorassertions.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ Expected options currently selected.
* langs:
- 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**

Expand Down Expand Up @@ -837,7 +837,7 @@ element should intersect viewport at any positive ratio. Defaults to `0`.
* langs:
- 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`].

Expand Down
4 changes: 3 additions & 1 deletion docs/src/test-assertions-csharp-java-python.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ title: "Assertions"

| Assertion | Description |
| :- | :- |
| [`method: LocatorAssertions.toBeAttached`] | Element is attached |
| [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
| [`method: LocatorAssertions.toBeDisabled`] | Element is disabled |
| [`method: LocatorAssertions.toBeEditable`] | Element is editable |
| [`method: LocatorAssertions.toBeEmpty`] | Container is empty |
| [`method: LocatorAssertions.toBeEnabled`] | Element is enabled |
| [`method: LocatorAssertions.toBeFocused`] | Element is focused |
| [`method: LocatorAssertions.toBeHidden`] | Element is not visible |
| [`method: LocatorAssertions.toBeInViewport`] | Element intersects viewport |
| [`method: LocatorAssertions.toBeVisible`] | Element is visible |
| [`method: LocatorAssertions.toContainText`] | Element contains text |
| [`method: LocatorAssertions.toHaveAttribute`] | Element has a DOM attribute |
Expand Down Expand Up @@ -44,7 +46,7 @@ The error would look like this:
def test_foobar(page: Page) -> None:
> expect(page.get_by_text("Name"), "should be logged in").to_be_visible()
E AssertionError: should be logged in
E Actual value: None
E Actual value: None
E Call log:
E LocatorAssertions.to_be_visible with timeout 5000ms
E waiting for get_by_text("Name")
Expand Down
5 changes: 2 additions & 3 deletions packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
* 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).
* - `"hidden"` Wait until the element is [not visible](https://playwright.dev/docs/actionability#visible) or
* [not attached](https://playwright.dev/docs/actionability#attached). Note that waiting for hidden does not throw when the element
* detaches.
* - `"hidden"` Wait until the element is [not visible](https://playwright.dev/docs/actionability#visible) or not attached. Note that
* waiting for hidden does not throw when the element detaches.
* - `"stable"` Wait until the element is both [visible](https://playwright.dev/docs/actionability#visible) and
* [stable](https://playwright.dev/docs/actionability#stable).
* - `"enabled"` Wait until the element is [enabled](https://playwright.dev/docs/actionability#enabled).
Expand Down
6 changes: 3 additions & 3 deletions packages/playwright/types/test.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5425,7 +5425,8 @@ interface APIResponseAssertions {
*/
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**
*
Expand Down Expand Up @@ -5620,8 +5621,7 @@ interface LocatorAssertions {
}): Promise<void>;

/**
* Ensures that {@link Locator} points to an [attached](https://playwright.dev/docs/actionability#attached) and
* [visible](https://playwright.dev/docs/actionability#visible) DOM node.
* Ensures that {@link Locator} points to an attached and [visible](https://playwright.dev/docs/actionability#visible) DOM node.
*
* To check that at least one element from the list is visible, use
* [locator.first()](https://playwright.dev/docs/api/class-locator#locator-first).
Expand Down

0 comments on commit 90665ef

Please sign in to comment.