From 7bd803243952e2eb8b52db545d7db7ed97d35c1e Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 25 Sep 2023 10:59:39 -0700 Subject: [PATCH] docs: mention Locator.first in toBeVisible (#27292) Fixes #26842. --- docs/src/api/class-locatorassertions.md | 57 +++++++++++++++++++++++++ docs/src/locators.md | 12 +++--- packages/playwright/types/test.d.ts | 14 ++++++ 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index 4b79cd1213..e87f712b7e 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -833,26 +833,83 @@ element should intersect viewport at any positive ratio. Defaults to `0`. Ensures that [Locator] points to an [attached](../actionability.md#attached) and [visible](../actionability.md#visible) DOM node. +To check that at least one element from the list is visible, use [`method: Locator.first`]. + **Usage** ```js +// A specific element is visible. await expect(page.getByText('Welcome')).toBeVisible(); + +// At least one item in the list is visible. +await expect(page.getByTestId('todo-item').first()).toBeVisible(); + +// At least one of the two elements is visible, possibly both. +await expect( + page.getByRole('button', { name: 'Sign in' }) + .or(page.getByRole('button', { name: 'Sign up' })) + .first() +).toBeVisible(); ``` ```java +// A specific element is visible. assertThat(page.getByText("Welcome")).isVisible(); + +// At least one item in the list is visible. +asserThat(page.getByTestId("todo-item").first()).isVisible(); + +// At least one of the two elements is visible, possibly both. +asserThat( + page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign in")) + .or(page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Sign up"))) + .first() +).isVisible(); ``` ```python async +# A specific element is visible. await expect(page.get_by_text("Welcome")).to_be_visible() + +# At least one item in the list is visible. +await expect(page.get_by_test_id("todo-item").first).to_be_visible() + +# At least one of the two elements is visible, possibly both. +await expect( + page.get_by_role("button", name="Sign in") + .or_(page.get_by_role("button", name="Sign up")) + .first +).to_be_visible() ``` ```python sync +# A specific element is visible. expect(page.get_by_text("Welcome")).to_be_visible() + +# At least one item in the list is visible. +expect(page.get_by_test_id("todo-item").first).to_be_visible() + +# At least one of the two elements is visible, possibly both. +expect( + page.get_by_role("button", name="Sign in") + .or_(page.get_by_role("button", name="Sign up")) + .first +).to_be_visible() ``` ```csharp +// A specific element is visible. await Expect(Page.GetByText("Welcome")).ToBeVisibleAsync(); + +// At least one item in the list is visible. +await Expect(Page.GetByTestId("todo-item").First).ToBeVisibleAsync(); + +// At least one of the two elements is visible, possibly both. +await Expect( + Page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }) + .Or(Page.GetByRole(AriaRole.Button, new() { Name = "Sign up" })) + .First +).ToBeVisibleAsync(); ``` ### option: LocatorAssertions.toBeVisible.visible diff --git a/docs/src/locators.md b/docs/src/locators.md index 0395ee18ba..05b5301309 100644 --- a/docs/src/locators.md +++ b/docs/src/locators.md @@ -1171,13 +1171,13 @@ For example, consider a scenario where you'd like to click on a "New email" butt :::note If both "New email" button and security dialog appear on screen, the "or" locator will match both of them, -possibly throwing the ["strict mode violation" error](#strictness). +possibly throwing the ["strict mode violation" error](#strictness). In this case, you can use [`method: Locator.first`] to only match one of them. ::: ```js const newEmail = page.getByRole('button', { name: 'New' }); const dialog = page.getByText('Confirm security settings'); -await expect(newEmail.or(dialog)).toBeVisible(); +await expect(newEmail.or(dialog).first()).toBeVisible(); if (await dialog.isVisible()) await page.getByRole('button', { name: 'Dismiss' }).click(); await newEmail.click(); @@ -1186,7 +1186,7 @@ await newEmail.click(); ```java Locator newEmail = page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("New")); Locator dialog = page.getByText("Confirm security settings"); -assertThat(newEmail.or(dialog)).isVisible(); +assertThat(newEmail.or(dialog).first()).isVisible(); if (dialog.isVisible()) page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Dismiss")).click(); newEmail.click(); @@ -1195,7 +1195,7 @@ newEmail.click(); ```python async new_email = page.get_by_role("button", name="New") dialog = page.get_by_text("Confirm security settings") -await expect(new_email.or_(dialog)).to_be_visible() +await expect(new_email.or_(dialog).first).to_be_visible() if (await dialog.is_visible()): await page.get_by_role("button", name="Dismiss").click() await new_email.click() @@ -1204,7 +1204,7 @@ await new_email.click() ```python sync new_email = page.get_by_role("button", name="New") dialog = page.get_by_text("Confirm security settings") -expect(new_email.or_(dialog)).to_be_visible() +expect(new_email.or_(dialog).first).to_be_visible() if (dialog.is_visible()): page.get_by_role("button", name="Dismiss").click() new_email.click() @@ -1213,7 +1213,7 @@ new_email.click() ```csharp var newEmail = page.GetByRole(AriaRole.Button, new() { Name = "New" }); var dialog = page.GetByText("Confirm security settings"); -await Expect(newEmail.Or(dialog)).ToBeVisibleAsync(); +await Expect(newEmail.Or(dialog).First).ToBeVisibleAsync(); if (await dialog.IsVisibleAsync()) await page.GetByRole(AriaRole.Button, new() { Name = "Dismiss" }).ClickAsync(); await newEmail.ClickAsync(); diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index cb6be198c8..26b74528cd 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -5455,10 +5455,24 @@ interface LocatorAssertions { * Ensures that {@link Locator} points to an [attached](https://playwright.dev/docs/actionability#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). + * * **Usage** * * ```js + * // A specific element is visible. * await expect(page.getByText('Welcome')).toBeVisible(); + * + * // At least one item in the list is visible. + * await expect(page.getByTestId('todo-item').first()).toBeVisible(); + * + * // At least one of the two elements is visible, possibly both. + * await expect( + * page.getByRole('button', { name: 'Sign in' }) + * .or(page.getByRole('button', { name: 'Sign up' })) + * .first() + * ).toBeVisible(); * ``` * * @param options