Skip to content

Commit

Permalink
docs: extract locators doc (microsoft#10795)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman authored Dec 8, 2021
1 parent 3272af9 commit 917924d
Show file tree
Hide file tree
Showing 4 changed files with 547 additions and 561 deletions.
246 changes: 3 additions & 243 deletions docs/src/api/class-locator.md
Original file line number Diff line number Diff line change
@@ -1,249 +1,9 @@
# class: Locator

Locator represents a view to the element(s) on the page. It captures the logic sufficient to retrieve the element at any given moment. Locator can be created with the [`method: Page.locator`] method.
Locators are the central piece of Playwright's auto-waiting and retry-ability. In a nutshell, locators represent
a way to find element(s) on the page at any moment. Locator can be created with the [`method: Page.locator`] method.

```js
const locator = page.locator('text=Submit');
await locator.click();
```

```java
Locator locator = page.locator("text=Submit");
locator.click();
```

```python async
locator = page.locator("text=Submit")
await locator.click()
```

```python sync
locator = page.locator("text=Submit")
locator.click()
```

```csharp
var locator = page.Locator("text=Submit");
await locator.ClickAsync();
```

The difference between the Locator and [ElementHandle] is that the latter points to a particular element, while Locator captures the logic of how to retrieve that element.

In the example below, handle points to a particular DOM element on page. If that element changes text or is used by React to render an entirely different component, handle is still pointing to that very DOM element. This can lead to unexpected behaviors.

```js
const handle = await page.$('text=Submit');
// ...
await handle.hover();
await handle.click();
```

```java
ElementHandle handle = page.querySelector("text=Submit");
handle.hover();
handle.click();
```

```python async
handle = await page.query_selector("text=Submit")
await handle.hover()
await handle.click()
```

```python sync
handle = page.query_selector("text=Submit")
handle.hover()
handle.click()
```

```csharp
var handle = await page.QuerySelectorAsync("text=Submit");
await handle.HoverAsync();
await handle.ClickAsync();
```

With the locator, every time the `element` is used, up-to-date DOM element is located in the page using the selector. So in the snippet below, underlying DOM element is going to be located twice.

```js
const locator = page.locator('text=Submit');
// ...
await locator.hover();
await locator.click();
```

```java
Locator locator = page.locator("text=Submit");
locator.hover();
locator.click();
```

```python async
locator = page.locator("text=Submit")
await locator.hover()
await locator.click()
```

```python sync
locator = page.locator("text=Submit")
locator.hover()
locator.click()
```

```csharp
var locator = page.Locator("text=Submit");
await locator.HoverAsync();
await locator.ClickAsync();
```

**Strictness**

Locators are strict. This means that all operations on locators that imply
some target DOM element will throw if more than one element matches given
selector.

```js
// Throws if there are several buttons in DOM:
await page.locator('button').click();

// Works because we explicitly tell locator to pick the first element:
await page.locator('button').first().click();

// Works because count knows what to do with multiple matches:
await page.locator('button').count();
```

```python async
# Throws if there are several buttons in DOM:
await page.locator('button').click()

# Works because we explicitly tell locator to pick the first element:
await page.locator('button').first.click()

# Works because count knows what to do with multiple matches:
await page.locator('button').count()
```

```python sync
# Throws if there are several buttons in DOM:
page.locator('button').click()

# Works because we explicitly tell locator to pick the first element:
page.locator('button').first.click()

# Works because count knows what to do with multiple matches:
page.locator('button').count()
```

```java
// Throws if there are several buttons in DOM:
page.locator("button").click();

// Works because we explicitly tell locator to pick the first element:
page.locator("button").first().click();

// Works because count knows what to do with multiple matches:
page.locator("button").count();
```

```csharp
// Throws if there are several buttons in DOM:
await page.Locator("button").ClickAsync();

// Works because we explicitly tell locator to pick the first element:
await page.Locator("button").First.ClickAsync();

// Works because Count knows what to do with multiple matches:
await page.Locator("button").CountAsync();
```

**Lists**

You can also use locators to work with the element lists.

```js
// Locate elements, this locator points to a list.
const rows = page.locator('table tr');

// Pattern 1: use locator methods to calculate text on the whole list.
const texts = await rows.allTextContents();

// Pattern 2: do something with each element in the list.
const count = await rows.count()
for (let i = 0; i < count; ++i)
console.log(await rows.nth(i).textContent());

// Pattern 3: resolve locator to elements on page and map them to their text content.
// Note: the code inside evaluateAll runs in page, you can call any DOM apis there.
const texts = await rows.evaluateAll(list => list.map(element => element.textContent));
```

```python async
# Locate elements, this locator points to a list.
rows = page.locator("table tr")

# Pattern 1: use locator methods to calculate text on the whole list.
texts = await rows.all_text_contents()

# Pattern 2: do something with each element in the list.
count = await rows.count()
for i in range(count):
print(await rows.nth(i).text_content())

# Pattern 3: resolve locator to elements on page and map them to their text content.
# Note: the code inside evaluateAll runs in page, you can call any DOM apis there.
texts = await rows.evaluate_all("list => list.map(element => element.textContent)")
```

```python sync
# Locate elements, this locator points to a list.
rows = page.locator("table tr")

# Pattern 1: use locator methods to calculate text on the whole list.
texts = rows.all_text_contents()

# Pattern 2: do something with each element in the list.
count = rows.count()
for i in range(count):
print(rows.nth(i).text_content())

# Pattern 3: resolve locator to elements on page and map them to their text content.
# Note: the code inside evaluateAll runs in page, you can call any DOM apis there.
texts = rows.evaluate_all("list => list.map(element => element.textContent)")
```

```java
// Locate elements, this locator points to a list.
Locator rows = page.locator("table tr");

// Pattern 1: use locator methods to calculate text on the whole list.
List<String> texts = rows.allTextContents();

// Pattern 2: do something with each element in the list.
int count = rows.count()
for (int i = 0; i < count; ++i)
System.out.println(rows.nth(i).textContent());

// Pattern 3: resolve locator to elements on page and map them to their text content.
// Note: the code inside evaluateAll runs in page, you can call any DOM apis there.
Object texts = rows.evaluateAll("list => list.map(element => element.textContent)");
```

```csharp
// Locate elements, this locator points to a list.
var rows = page.Locator("table tr");

// Pattern 1: use locator methods to calculate text on the whole list.
var texts = await rows.AllTextContentsAsync();

// Pattern 2: do something with each element in the list:
var count = await rows.CountAsync()
for (let i = 0; i < count; ++i)
Console.WriteLine(await rows.Nth(i).TextContentAsync());

// Pattern 3: resolve locator to elements on page and map them to their text content
// Note: the code inside evaluateAll runs in page, you can call any DOM apis there
var texts = await rows.EvaluateAllAsync("list => list.map(element => element.textContent)");
```
[Learn more about locators](./locators.md).

## async method: Locator.allInnerTexts
- returns: <[Array]<[string]>>
Expand Down
Loading

0 comments on commit 917924d

Please sign in to comment.