diff --git a/docs/src/locators.md b/docs/src/locators.md
index bfb456413864c..04b5749c24f5f 100644
--- a/docs/src/locators.md
+++ b/docs/src/locators.md
@@ -77,6 +77,7 @@ For example, consider the following DOM structure.
```html
```
+
Locate the element by its role of `button` with name "Sign in".
```js
@@ -186,68 +187,74 @@ The [`method: Page.getByRole`] locator reflects how users and assistive technolo
For example, consider the following DOM structure.
```html
-
my form
-
```
-
-
You can locate each element by it's implicit role:
```js
-await expect(page.getByRole('heading', { name: 'my form' }))
+await expect(page.getByRole('heading', { name: 'Sign up' }))
.toBeVisible()
-await page.getByRole('checkbox', { checked: true, name: "newsletter" })
- .uncheck();
+await page.getByRole('checkbox', { name: 'Subscribe' })
+ .check();
await page.getByRole('button', { name: /submit/i })
.click();
```
```python async
-await expect(page.get_by_role("heading", name="my form")).to_be_visible()
+await expect(page.get_by_role("heading", name="Sign up")).to_be_visible()
-await page.get_by_role("checkbox", checked=True, name="newsletter").uncheck()
+await page.get_by_role("checkbox", name="Subscribe").check()
await page.get_by_role("button", name=re.compile("submit", re.IGNORECASE)).click()
```
```python sync
-expect(page.get_by_role("heading", name="my from")).to_be_visible()
+expect(page.get_by_role("heading", name="Sign up")).to_be_visible()
-page.get_by_role("checkbox", checked=True, name="newsletter").uncheck()
+page.get_by_role("checkbox", name="Subscribe").check()
page.get_by_role("button", name=re.compile("submit", re.IGNORECASE)).click()
```
```java
-assertThat(page.getByRole("heading", new Page.GetByRoleOptions().setName("my form")))
+assertThat(page.getByRole("heading", new Page.GetByRoleOptions().setName("Sign up")))
.isVisible();
-page.getByRole("checkbox", new Page.GetByRoleOptions().setChecked(true).setName("newsletter"))
- .uncheck();
+page.getByRole("checkbox", new Page.GetByRoleOptions().setName("Subscribe"))
+ .check();
page.getByRole("button", new Page.GetByRoleOptions().setName(Pattern.compile("submit", Pattern.CASE_INSENSITIVE)))
.click();
```
```csharp
-await Expect(page.GetByRole("heading", new() { NameString = "my form" }))
+await Expect(page.GetByRole("heading", new() { NameString = "Sign up" }))
.ToBeVisibleAsync();
-await page.GetByRole("checkbox", new() { Checked = true, NameString = "newsletter" })
- .UncheckAsync();
+await page.GetByRole("checkbox", new() { NameString = "Subscribe" })
+ .CheckAsync();
await page.GetByRole("button", new() { NameRegex = new Regex("submit", RegexOptions.IgnoreCase) })
.ClickAsync();
```
-
+```html
+
+```
Role locators include [buttons, checkboxes, headings, links, lists, tables, and many more](https://www.w3.org/TR/html-aria/#docconformance) and follow W3C specifications for [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles), [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/#aria-attributes) and [accessible name](https://w3c.github.io/accname/#dfn-accessible-name).
@@ -267,7 +274,6 @@ For example, consider the following DOM structure.
```
-
You can fill the input after locating it by the label text:
@@ -290,7 +296,11 @@ page.get_by_label("Password").fill("secret")
```csharp
await page.GetByLabel("Password").FillAsync("secret");
```
-
+
+```html
+
+
+```
:::tip When to use label locators
Use this locator when locating form fields.
@@ -302,11 +312,9 @@ Inputs may have a placeholder attribute to hint to the user what value should be
For example, consider the following DOM structure.
```html
-
+
```
-
-
You can fill the input after locating it by the placeholder text:
```js
@@ -332,7 +340,9 @@ await page.GetByPlaceholder("name@example.com")
.FillAsync("playwright@microsoft.com");
```
-
+```html
+
+```
:::tip When to use placeholder locators
Use this locator when locating form elements that do not have labels but do have placeholder texts.
@@ -347,7 +357,6 @@ For example, consider the following DOM structure.
```html
Welcome, John
```
-
You can locate the element by the text it contains:
@@ -380,7 +389,6 @@ await expect(page.getByText('Welcome, John', { exact: true }))
.toBeVisible();
```
-
```java
assertThat(page.getByText("Welcome, John", new Page.GetByTextOptions().setExact(true)))
.isVisible();
@@ -437,16 +445,12 @@ You can also [filter by text](#filter-by-text) which can be useful when trying t
All images should have an `alt` attribute that describes the image. You can locate an image based on the text alternative using [`method: Page.getByAltText`].
-
For example, consider the following DOM structure.
```html
```
-
-
-
You can click on the image after locating it by the text alternative:
```js
@@ -472,8 +476,9 @@ await page.GetByAltText("playwright logo")
.ClickAsync();
```
-
-
+```html
+
+```
:::tip When to use alt locators
Use this locator when your element supports alt text such as `img` and `area` elements.
@@ -488,7 +493,6 @@ For example, consider the following DOM structure.
```html
25 issues
```
-
You can check the issues count after locating it by the title text:
@@ -528,7 +532,6 @@ For example, consider the following DOM structure.
```html
```
-
You can locate the element by it's test id:
@@ -555,7 +558,9 @@ await page.GetByTestId("directions")
.ClickAsync();
```
-
+```html
+
+```
:::tip When to use testid locators
You can also use test ids when you choose to use the test id methodology or when you can't locate by [role](#locate-by-role) or [text](#locate-by-text).
@@ -735,9 +740,6 @@ Consider the following example with a custom web component:
```
-
-
-
You can locate in the same way as if the shadow root was not present at all.
To click `
+
+```
To ensure that `` contains the text "Details":
```js
@@ -808,17 +817,14 @@ Consider the following DOM structure where we want to click on the buy button of
```html
Product 1
-
+
-
Product 2
-
+
```
-
-
### Filter by text
Locators can be filtered by text with the [`method: Locator.filter`] method. It will search for a particular string somewhere inside the element, possibly in a descendant element, case-insensitively. You can also pass a regular expression.
@@ -826,28 +832,28 @@ Locators can be filtered by text with the [`method: Locator.filter`] method. It
```js
await page.getByTestId('product-card')
.filter({ hasText: 'Product 2' })
- .getByRole('button', { name: 'Buy' })
+ .getByRole('button', { name: 'Add to cart' })
.click();
```
```java
page.getByTestId("product-card")
.filter(new Locator.FilterOptions().setHasText("Product 2"))
- .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Buy"))
+ .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Add to cart"))
.click();
```
```python async
-await page.get_by_test_id("product-card").filter(has_text="Product 2").get_by_role("button", name="Buy").click()
+await page.get_by_test_id("product-card").filter(has_text="Product 2").get_by_role("button", name="Add to cart").click()
```
```python sync
-page.get_by_test_id("product-card").filter(has_text="Product 2").get_by_role("button", name="Buy").click()
+page.get_by_test_id("product-card").filter(has_text="Product 2").get_by_role("button", name="Add to cart").click()
```
```csharp
await page.GetByTestId("product-card")
.Filter(new() { HasTextString = "Product 2" })
- .GetByRole(AriaRole.Button, new () { NameString = "Buy" })
+ .GetByRole(AriaRole.Button, new () { NameString = "Add to cart" })
.ClickAsync();
```
@@ -856,36 +862,45 @@ Use a regular expression:
```js
await page.getByTestId('product-card')
.filter({ hasText: /Product 2/ })
- .getByRole('button', { name: 'Buy' })
+ .getByRole('button', { name: 'Add to cart' })
.click();
```
```java
page.getByTestId("product-card")
.filter(new Locator.FilterOptions().setHasText(Pattern.compile("Product 2")))
- .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Buy"))
+ .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Add to cart"))
.click();
```
```python async
-await page.get_by_test_id("product-card").filter(has_text=re.compile("Product 2")).get_by_role("button", name="Buy").click()
+await page.get_by_test_id("product-card").filter(has_text=re.compile("Product 2")).get_by_role("button", name="Add to cart").click()
```
```python sync
page.get_by_test_id("product-card")
.filter(has_text=re.compile("Product 2"))
- .get_by_role("button", name="Buy")
+ .get_by_role("button", name="Add to cart")
.click()
```
```csharp
await page.GetByTestId("product-card")
.Filter(new() { HasTextRegex = new Regex("Product 2") })
- .GetByRole(AriaRole.Button, new () { NameString = "Buy" })
+ .GetByRole(AriaRole.Button, new () { NameString = "Add to cart" })
.ClickAsync();
```
-
+```html
+
+
Product 1
+
+
+
+
Product 2
+
+
+```
### Filter by another locator
@@ -894,32 +909,41 @@ Locators support an option to only select elements that have a descendant matchi
```js
await page.getByTestId('product-card')
.filter({ has: page.getByRole('heading', { name: 'Product 2' })})
- .getByRole('button', { name: 'Buy' })
+ .getByRole('button', { name: 'Add to cart' })
.click()
```
```java
page.getByTestId("product-card")
.filter(new Locator.FilterOptions().setHas(page.GetByRole(AriaRole.HEADING, new Page.GetByRoleOptions().setName("Product 2"))))
- .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Buy")))
+ .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Add to cart")))
.click()
```
```python async
-await page.get_by_test_id("product-card").filter(has=page.get_by_role("heading", name="Product 2")).get_by_role("button", name="Buy").click()
+await page.get_by_test_id("product-card").filter(has=page.get_by_role("heading", name="Product 2")).get_by_role("button", name="Add to cart").click()
```
```python sync
page.get_by_test_id("product-card")
.filter(has=page.get_by_role("heading", name="Product 2"))
- .get_by_role("button", name="Buy")
+ .get_by_role("button", name="Add to cart")
.click()
```
```csharp
await page.GetByTestId("product-card")
.Filter(new() { Has = page.GetByRole(AriaRole.Heading, new () { NameString = "Product 2" })})
- .GetByRole(AriaRole.Button, new () { NameString = "Buy" })
+ .GetByRole(AriaRole.Button, new () { NameString = "Add to cart" })
.ClickAsync();
```
-
+```html
+
+
Product 1
+
+
+
+
Product 2
+
+
+```
We can also assert the product card to make sure there is only one
@@ -955,13 +979,13 @@ Note that the inner locator is matched starting from the outer one, not from the
You can chain methods that create a locator, like [`method: Page.getByText`] or [`method: Locator.getByRole`], to narrow down the search to a particular part of the page.
-In this example we first create a locator called product by locating the test id. We then filter by text. We can use the product locator again to get by role of button and click it and then use an assertion to make sure there is only one product with the text ' Product 2'.
+In this example we first create a locator called product by locating the test id. We then filter by text. We can use the product locator again to get by role of button and click it and then use an assertion to make sure there is only one product with the text "Product 2".
```js
const product = page.getByTestId('product-card')
.filter({ hasText: 'Product 2' });
-await product.getByRole('button', { name: 'Buy' })
+await product.getByRole('button', { name: 'Add to cart' })
.click();
await expect(product).toHaveCount(1);
@@ -970,20 +994,20 @@ await expect(product).toHaveCount(1);
```python async
product = page.get_by_test_id("product-card").filter(has_text="Product 2")
-await product.get_by_role("button", name="Buy").click()
+await product.get_by_role("button", name="Add to cart").click()
```
```python sync
product = page.get_by_test_id("product-card").filter(has_text="Product 2")
-product.get_by_role("button", name="Buy").click()
+product.get_by_role("button", name="Add to cart").click()
```
```java
Locator product = page.getByTestId("product-card")
.filter(new Locator.FilterOptions().setHasText("Product 2"));
-product.getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName("Buy"))
+product.getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName("Add to cart"))
.click();
```
@@ -991,11 +1015,20 @@ product.getByRole(AriaRole.BUTTON, new Locator.GetByRoleOptions().setName("Buy")
var product = page.GetByTestId("product-card")
.Filter(new() { HasTextString = "Product 2" });
-await product.GetByRole("button", new() { NameString = "Buy" })
+await product.GetByRole("button", new() { NameString = "Add to cart" })
.ClickAsync();
```
-
+```html
+
+
Product 1
+
+
+
+
Product 2
+
+
+```
## Lists
@@ -1013,8 +1046,6 @@ For example, consider the following DOM structure:
```
-
-
Use the count assertion to ensure that the list has 3 items.
```js
@@ -1050,7 +1081,6 @@ For example, consider the following DOM structure:
orange
```
-
Use [`method: LocatorAssertions.toHaveText`] to ensure that the list has the text "apple", "banana" and "orange".
@@ -1119,7 +1149,13 @@ await page.GetByText("orange")
.ClickAsync();
```
-
+```html
+
+
apple
+
banana
+
orange
+
+```
#### Filter by text
Use the [`method: Locator.filter`] to locate a specific item in a list.
@@ -1161,7 +1197,14 @@ await page.GetByRole("listitem")
.Filter(new() { HasTextString = "orange" })
.ClickAsync();
```
-
+
+```html
+
+
apple
+
banana
+
orange
+
+```
#### Get by test id
@@ -1202,7 +1245,13 @@ await page.GetByTestId("orange")
.ClickAsync();
```
-
+```html
+
+
apple
+
banana
+
orange
+
+```
#### Get by nth item
@@ -1256,7 +1305,6 @@ For example, consider the following DOM structure:
```
-
To take a screenshot of the row with "Mary" and "Say goodbye":
@@ -1299,8 +1347,10 @@ await rowLocator.Filter(new() { HasTextString = "Mary" })
You should now have a "screenshot.png" file in your project's root directory.
-
-
+```html
+
Mary
+
+```
### Rare use cases
#### Get All text contents