feat(locators): rename locator.that to locator.filter (#14025)

This commit is contained in:
Dmitry Gozman 2022-05-08 21:59:40 +01:00 committed by GitHub
parent 64cd55089a
commit 6931d89eaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 172 additions and 158 deletions

View File

@ -990,6 +990,8 @@ Returns whether the element is [visible](../actionability.md#visible). [`option:
The method returns an element locator that can be used to perform actions in the frame. The method returns an element locator that can be used to perform actions in the frame.
Locator is resolved to the element immediately before performing an action, so a series of actions on the same locator can in fact be performed on different DOM elements. That would happen if the DOM structure between those actions has changed. Locator is resolved to the element immediately before performing an action, so a series of actions on the same locator can in fact be performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
[Learn more about locators](../locators.md).
### param: Frame.locator.selector = %%-find-selector-%% ### param: Frame.locator.selector = %%-find-selector-%%
### option: Frame.locator.-inline- = %%-locator-options-list-%% ### option: Frame.locator.-inline- = %%-locator-options-list-%%

View File

@ -384,6 +384,13 @@ Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
### option: Locator.fill.noWaitAfter = %%-input-no-wait-after-%% ### option: Locator.fill.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.fill.timeout = %%-input-timeout-%% ### option: Locator.fill.timeout = %%-input-timeout-%%
## method: Locator.filter
- returns: <[Locator]>
This method narrows existing locator according to the options, for example filters by text.
### option: Locator.filter.-inline- = %%-locator-options-list-%%
## method: Locator.first ## method: Locator.first
- returns: <[Locator]> - returns: <[Locator]>
@ -544,7 +551,7 @@ Returns locator to the last matching element.
## method: Locator.locator ## method: Locator.locator
- returns: <[Locator]> - returns: <[Locator]>
The method finds an element matching the specified selector in the `Locator`'s subtree. The method finds an element matching the specified selector in the `Locator`'s subtree. It also accepts filter options, similar to [`method: Locator.filter`] method.
### param: Locator.locator.selector = %%-find-selector-%% ### param: Locator.locator.selector = %%-find-selector-%%
### option: Locator.locator.-inline- = %%-locator-options-list-%% ### option: Locator.locator.-inline- = %%-locator-options-list-%%
@ -772,13 +779,6 @@ Returns the `node.textContent`.
### option: Locator.textContent.timeout = %%-input-timeout-%% ### option: Locator.textContent.timeout = %%-input-timeout-%%
## method: Locator.that
- returns: <[Locator]>
This method narrows existing locator according to the options, for example filters by text.
### option: Locator.that.-inline- = %%-locator-options-list-%%
## async method: Locator.type ## async method: Locator.type
Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.

View File

@ -2199,6 +2199,8 @@ Returns whether the element is [visible](../actionability.md#visible). [`option:
The method returns an element locator that can be used to perform actions on the page. The method returns an element locator that can be used to perform actions on the page.
Locator is resolved to the element immediately before performing an action, so a series of actions on the same locator can in fact be performed on different DOM elements. That would happen if the DOM structure between those actions has changed. Locator is resolved to the element immediately before performing an action, so a series of actions on the same locator can in fact be performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
[Learn more about locators](../locators.md).
Shortcut for main frame's [`method: Frame.locator`]. Shortcut for main frame's [`method: Frame.locator`].
### param: Page.locator.selector = %%-find-selector-%% ### param: Page.locator.selector = %%-find-selector-%%

View File

@ -316,32 +316,32 @@ page.locator("article", has=page.locator("button.subscribe"))
page.Locator("article", new PageLocatorOptions { Has = page.Locator("button.subscribe") }) page.Locator("article", new PageLocatorOptions { Has = page.Locator("button.subscribe") })
``` ```
You can also filter an existing locator with [`method: Locator.that`] method. You can also filter an existing locator with [`method: Locator.filter`] method.
```js ```js
const buttonLocator = page.locator('button'); const buttonLocator = page.locator('button');
// ... // ...
await buttonLocator.that({ hasText: 'Sign up' }).click(); await buttonLocator.filter({ hasText: 'Sign up' }).click();
``` ```
```java ```java
Locator buttonLocator = page.locator("button"); Locator buttonLocator = page.locator("button");
// ... // ...
buttonLocator.that(new Locator.ThatOptions().setHasText("Sign up")).click(); buttonLocator.filter(new Locator.FilterOptions().setHasText("Sign up")).click();
``` ```
```python async ```python async
button_locator = page.locator("button") button_locator = page.locator("button")
# ... # ...
await button_locator.that(has_text="Sign up").click() await button_locator.filter(has_text="Sign up").click()
``` ```
```python sync ```python sync
button_locator = page.locator("button") button_locator = page.locator("button")
# ... # ...
button_locator.that(has_text="Sign up").click() button_locator.filter(has_text="Sign up").click()
``` ```
```csharp ```csharp
var buttonLocator = page.Locator("button"); var buttonLocator = page.Locator("button");
// ... // ...
await buttonLocator.That(new LocatorThatOptions { HasText = "Sign up" }).ClickAsync(); await buttonLocator.Filter(new LocatorFilterOptions { HasText = "Sign up" }).ClickAsync();
``` ```
## Locator vs ElementHandle ## Locator vs ElementHandle

View File

@ -144,7 +144,7 @@ export class Locator implements api.Locator {
return new FrameLocator(this._frame, this._selector + ' >> ' + selector); return new FrameLocator(this._frame, this._selector + ' >> ' + selector);
} }
that(options?: LocatorOptions): Locator { filter(options?: LocatorOptions): Locator {
return new Locator(this._frame, this._selector, options); return new Locator(this._frame, this._selector, options);
} }

View File

@ -2613,6 +2613,8 @@ export interface Page {
* element immediately before performing an action, so a series of actions on the same locator can in fact be performed on * element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
* different DOM elements. That would happen if the DOM structure between those actions has changed. * different DOM elements. That would happen if the DOM structure between those actions has changed.
* *
* [Learn more about locators](https://playwright.dev/docs/locators).
*
* Shortcut for main frame's * Shortcut for main frame's
* [frame.locator(selector[, options])](https://playwright.dev/docs/api/class-frame#frame-locator). * [frame.locator(selector[, options])](https://playwright.dev/docs/api/class-frame#frame-locator).
* @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
@ -5484,6 +5486,8 @@ export interface Frame {
* The method returns an element locator that can be used to perform actions in the frame. Locator is resolved to the * The method returns an element locator that can be used to perform actions in the frame. Locator is resolved to the
* element immediately before performing an action, so a series of actions on the same locator can in fact be performed on * element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
* different DOM elements. That would happen if the DOM structure between those actions has changed. * different DOM elements. That would happen if the DOM structure between those actions has changed.
*
* [Learn more about locators](https://playwright.dev/docs/locators).
* @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param options * @param options
*/ */
@ -9263,6 +9267,72 @@ export interface Locator {
timeout?: number; timeout?: number;
}): Promise<void>; }): Promise<void>;
/**
* This method narrows existing locator according to the options, for example filters by text.
* @param options
*/
filter(options?: {
/**
* Matches elements that are above any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
above?: Locator;
/**
* Matches elements that are below any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
below?: Locator;
/**
* Matches elements containing an element that matches an inner locator. Inner locator is queried against the outer one.
* For example, `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
has?: Locator;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
* `<article><div>Playwright</div></article>`.
*/
hasText?: string|RegExp;
/**
* Matches elements that are to the left of any element matching the inner locator, at any vertical position. Inner locator
* is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
leftOf?: Locator;
/**
* Matches elements that are near (<= 50 css pixels) any of the elements matching the inner locator. Inner locator is
* queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
near?: Locator;
/**
* Matches elements that are to the right of any element matching the inner locator, at any vertical position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
rightOf?: Locator;
}): Locator;
/** /**
* Returns locator to the first matching element. * Returns locator to the first matching element.
*/ */
@ -9502,7 +9572,8 @@ export interface Locator {
last(): Locator; last(): Locator;
/** /**
* The method finds an element matching the specified selector in the `Locator`'s subtree. * The method finds an element matching the specified selector in the `Locator`'s subtree. It also accepts filter options,
* similar to [locator.filter([options])](https://playwright.dev/docs/api/class-locator#locator-filter) method.
* @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param options * @param options
*/ */
@ -9942,72 +10013,6 @@ export interface Locator {
timeout?: number; timeout?: number;
}): Promise<null|string>; }): Promise<null|string>;
/**
* This method narrows existing locator according to the options, for example filters by text.
* @param options
*/
that(options?: {
/**
* Matches elements that are above any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
above?: Locator;
/**
* Matches elements that are below any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
below?: Locator;
/**
* Matches elements containing an element that matches an inner locator. Inner locator is queried against the outer one.
* For example, `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
has?: Locator;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
* `<article><div>Playwright</div></article>`.
*/
hasText?: string|RegExp;
/**
* Matches elements that are to the left of any element matching the inner locator, at any vertical position. Inner locator
* is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
leftOf?: Locator;
/**
* Matches elements that are near (<= 50 css pixels) any of the elements matching the inner locator. Inner locator is
* queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
near?: Locator;
/**
* Matches elements that are to the right of any element matching the inner locator, at any vertical position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
rightOf?: Locator;
}): Locator;
/** /**
* Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. * Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
* *

View File

@ -2615,6 +2615,8 @@ export interface Page {
* element immediately before performing an action, so a series of actions on the same locator can in fact be performed on * element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
* different DOM elements. That would happen if the DOM structure between those actions has changed. * different DOM elements. That would happen if the DOM structure between those actions has changed.
* *
* [Learn more about locators](https://playwright.dev/docs/locators).
*
* Shortcut for main frame's * Shortcut for main frame's
* [frame.locator(selector[, options])](https://playwright.dev/docs/api/class-frame#frame-locator). * [frame.locator(selector[, options])](https://playwright.dev/docs/api/class-frame#frame-locator).
* @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
@ -5486,6 +5488,8 @@ export interface Frame {
* The method returns an element locator that can be used to perform actions in the frame. Locator is resolved to the * The method returns an element locator that can be used to perform actions in the frame. Locator is resolved to the
* element immediately before performing an action, so a series of actions on the same locator can in fact be performed on * element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
* different DOM elements. That would happen if the DOM structure between those actions has changed. * different DOM elements. That would happen if the DOM structure between those actions has changed.
*
* [Learn more about locators](https://playwright.dev/docs/locators).
* @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param options * @param options
*/ */
@ -9265,6 +9269,72 @@ export interface Locator {
timeout?: number; timeout?: number;
}): Promise<void>; }): Promise<void>;
/**
* This method narrows existing locator according to the options, for example filters by text.
* @param options
*/
filter(options?: {
/**
* Matches elements that are above any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
above?: Locator;
/**
* Matches elements that are below any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
below?: Locator;
/**
* Matches elements containing an element that matches an inner locator. Inner locator is queried against the outer one.
* For example, `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
has?: Locator;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
* `<article><div>Playwright</div></article>`.
*/
hasText?: string|RegExp;
/**
* Matches elements that are to the left of any element matching the inner locator, at any vertical position. Inner locator
* is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
leftOf?: Locator;
/**
* Matches elements that are near (<= 50 css pixels) any of the elements matching the inner locator. Inner locator is
* queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
near?: Locator;
/**
* Matches elements that are to the right of any element matching the inner locator, at any vertical position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
rightOf?: Locator;
}): Locator;
/** /**
* Returns locator to the first matching element. * Returns locator to the first matching element.
*/ */
@ -9504,7 +9574,8 @@ export interface Locator {
last(): Locator; last(): Locator;
/** /**
* The method finds an element matching the specified selector in the `Locator`'s subtree. * The method finds an element matching the specified selector in the `Locator`'s subtree. It also accepts filter options,
* similar to [locator.filter([options])](https://playwright.dev/docs/api/class-locator#locator-filter) method.
* @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param selector A selector to use when resolving DOM element. See [working with selectors](https://playwright.dev/docs/selectors) for more details.
* @param options * @param options
*/ */
@ -9944,72 +10015,6 @@ export interface Locator {
timeout?: number; timeout?: number;
}): Promise<null|string>; }): Promise<null|string>;
/**
* This method narrows existing locator according to the options, for example filters by text.
* @param options
*/
that(options?: {
/**
* Matches elements that are above any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
above?: Locator;
/**
* Matches elements that are below any of the elements matching the inner locator, at any horizontal position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
below?: Locator;
/**
* Matches elements containing an element that matches an inner locator. Inner locator is queried against the outer one.
* For example, `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
has?: Locator;
/**
* Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When passed a
* [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
* `<article><div>Playwright</div></article>`.
*/
hasText?: string|RegExp;
/**
* Matches elements that are to the left of any element matching the inner locator, at any vertical position. Inner locator
* is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
leftOf?: Locator;
/**
* Matches elements that are near (<= 50 css pixels) any of the elements matching the inner locator. Inner locator is
* queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
near?: Locator;
/**
* Matches elements that are to the right of any element matching the inner locator, at any vertical position. Inner
* locator is queried against the same root as the outer one. More details in
* [layout selectors](https://playwright.dev/docs/selectors#selecting-elements-based-on-layout) guide.
*
* Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
*/
rightOf?: Locator;
}): Locator;
/** /**
* Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. * Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
* *

View File

@ -124,18 +124,18 @@ it('should support has:locator', async ({ page, trace }) => {
})).toHaveCount(1); })).toHaveCount(1);
}); });
it('should support locator.that', async ({ page, trace }) => { it('should support locator.filter', async ({ page, trace }) => {
it.skip(trace === 'on'); it.skip(trace === 'on');
await page.setContent(`<section><div><span>hello</span></div><div><span>world</span></div></section>`); await page.setContent(`<section><div><span>hello</span></div><div><span>world</span></div></section>`);
await expect(page.locator(`div`).that({ hasText: 'hello' })).toHaveCount(1); await expect(page.locator(`div`).filter({ hasText: 'hello' })).toHaveCount(1);
await expect(page.locator(`div`, { hasText: 'hello' }).that({ hasText: 'hello' })).toHaveCount(1); await expect(page.locator(`div`, { hasText: 'hello' }).filter({ hasText: 'hello' })).toHaveCount(1);
await expect(page.locator(`div`, { hasText: 'hello' }).that({ hasText: 'world' })).toHaveCount(0); await expect(page.locator(`div`, { hasText: 'hello' }).filter({ hasText: 'world' })).toHaveCount(0);
await expect(page.locator(`section`, { hasText: 'hello' }).that({ hasText: 'world' })).toHaveCount(1); await expect(page.locator(`section`, { hasText: 'hello' }).filter({ hasText: 'world' })).toHaveCount(1);
await expect(page.locator(`div`).that({ hasText: 'hello' }).locator('span')).toHaveCount(1); await expect(page.locator(`div`).filter({ hasText: 'hello' }).locator('span')).toHaveCount(1);
await expect(page.locator(`div`).that({ has: page.locator('span', { hasText: 'world' }) })).toHaveCount(1); await expect(page.locator(`div`).filter({ has: page.locator('span', { hasText: 'world' }) })).toHaveCount(1);
await expect(page.locator(`div`).that({ has: page.locator('span') })).toHaveCount(2); await expect(page.locator(`div`).filter({ has: page.locator('span') })).toHaveCount(2);
await expect(page.locator(`div`).that({ await expect(page.locator(`div`).filter({
has: page.locator('span'), has: page.locator('span'),
hasText: 'world', hasText: 'world',
})).toHaveCount(1); })).toHaveCount(1);