mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: move locators to strict selectors (#7866)
This commit is contained in:
parent
982f61d575
commit
b9aad5eb86
@ -70,11 +70,6 @@ await element.HoverAsync();
|
||||
await element.ClickAsync();
|
||||
```
|
||||
|
||||
## async method: Locator.all
|
||||
- returns: <[Array]<[ElementHandle]>>
|
||||
|
||||
Resolves given locator to all matching DOM elements.
|
||||
|
||||
## async method: Locator.boundingBox
|
||||
- returns: <[null]|[Object]>
|
||||
- `x` <[float]> the x coordinate of the element in pixels.
|
||||
@ -167,6 +162,13 @@ When all steps combined have not finished during the specified [`option: timeout
|
||||
### option: Locator.click.timeout = %%-input-timeout-%%
|
||||
### option: Locator.click.trial = %%-input-trial-%%
|
||||
|
||||
## async method: Locator.count
|
||||
- returns: <[int]>
|
||||
|
||||
Returns the number of elements matching given selector.
|
||||
|
||||
### option: Locator.elementHandle.elementHandle = %%-input-timeout-%%
|
||||
|
||||
## async method: Locator.dblclick
|
||||
* langs:
|
||||
- alias-csharp: DblClickAsync
|
||||
@ -284,6 +286,19 @@ Optional event-specific initialization properties.
|
||||
|
||||
### option: Locator.dispatchEvent.timeout = %%-input-timeout-%%
|
||||
|
||||
## async method: Locator.elementHandle
|
||||
- returns: <[ElementHandle]>
|
||||
|
||||
Resolves given locator to the first matching DOM element. If no elements matching the query are visible, waits for them up to a given timeout. If multiple elements match the selector, throws.
|
||||
|
||||
### option: Locator.elementHandle.elementHandle = %%-input-timeout-%%
|
||||
|
||||
|
||||
## async method: Locator.elementHandles
|
||||
- returns: <[Array]<[ElementHandle]>>
|
||||
|
||||
Resolves given locator to all matching DOM elements.
|
||||
|
||||
## async method: Locator.evaluate
|
||||
- returns: <[Serializable]>
|
||||
|
||||
@ -414,13 +429,10 @@ Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
|
||||
### option: Locator.fill.noWaitAfter = %%-input-no-wait-after-%%
|
||||
### option: Locator.fill.timeout = %%-input-timeout-%%
|
||||
|
||||
## async method: Locator.first
|
||||
- returns: <[ElementHandle]>
|
||||
## method: Locator.first
|
||||
- returns: <[Locator]>
|
||||
|
||||
Resolves given locator to the first VISIBLE matching DOM element. If no elements matching
|
||||
the query are visible, waits for them up to a given timeout.
|
||||
|
||||
### option: Locator.first.timeout = %%-input-timeout-%%
|
||||
Returns locator to the first matching element.
|
||||
|
||||
## async method: Locator.focus
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ import { Page } from './page';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Waiter } from './waiter';
|
||||
import { Events } from './events';
|
||||
import { LifecycleEvent, URLMatch, SelectOption, SelectOptionOptions, FilePayload, WaitForFunctionOptions, kLifecycleEvents } from './types';
|
||||
import { LifecycleEvent, URLMatch, SelectOption, SelectOptionOptions, FilePayload, WaitForFunctionOptions, kLifecycleEvents, StrictOptions } from './types';
|
||||
import { urlMatches } from './clientHelper';
|
||||
import * as api from '../../types/types';
|
||||
import * as structs from '../../types/structs';
|
||||
@ -401,7 +401,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel, channels.FrameIni
|
||||
});
|
||||
}
|
||||
|
||||
async selectOption(selector: string, values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
|
||||
async selectOption(selector: string, values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions & StrictOptions = {}): Promise<string[]> {
|
||||
return this._wrapApiCall(async (channel: channels.FrameChannel) => {
|
||||
return (await channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options })).values;
|
||||
});
|
||||
|
||||
@ -26,166 +26,178 @@ import { FilePayload, Rect, SelectOption, SelectOptionOptions, TimeoutOptions }
|
||||
export class Locator implements api.Locator {
|
||||
private _frame: Frame;
|
||||
private _selector: string;
|
||||
private _visibleSelector: string;
|
||||
|
||||
constructor(frame: Frame, selector: string) {
|
||||
this._frame = frame;
|
||||
this._selector = selector;
|
||||
this._visibleSelector = selector + ' >> _visible=true';
|
||||
}
|
||||
|
||||
private async _withFirst<R, O extends TimeoutOptions>(task: (handle: ElementHandle<SVGElement | HTMLElement>, options?: O) => Promise<R>, options?: O): Promise<R> {
|
||||
private async _withElement<R, O extends TimeoutOptions>(task: (handle: ElementHandle<SVGElement | HTMLElement>, options?: O) => Promise<R>, options?: O): Promise<R> {
|
||||
if (!options)
|
||||
options = {} as any;
|
||||
const timeout = this._frame.page()._timeoutSettings.timeout(options!);
|
||||
const deadline = timeout ? monotonicTime() + timeout : 0;
|
||||
const first = await this.first(options);
|
||||
const handle = await this.elementHandle(options);
|
||||
if (!handle)
|
||||
throw new Error(`Could not resolve ${this._selector} to DOM Element`);
|
||||
try {
|
||||
return await task(first, { ...options!, timeout: deadline ? deadline - monotonicTime() : 0 });
|
||||
return await task(handle, { ...options!, timeout: deadline ? deadline - monotonicTime() : 0 });
|
||||
} finally {
|
||||
first.dispose();
|
||||
handle.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
async all(): Promise<api.ElementHandle<SVGElement | HTMLElement>[]> {
|
||||
return this._frame.$$(this._selector);
|
||||
}
|
||||
|
||||
async boundingBox(options?: TimeoutOptions): Promise<Rect | null> {
|
||||
return this._withFirst(h => h.boundingBox(), options);
|
||||
return this._withElement(h => h.boundingBox(), { strict: true, ...options });
|
||||
}
|
||||
|
||||
async check(options: channels.ElementHandleCheckOptions = {}) {
|
||||
return this._frame.check(this._selector, options);
|
||||
return this._frame.check(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async click(options: channels.ElementHandleClickOptions = {}): Promise<void> {
|
||||
return this._frame.click(this._selector, options);
|
||||
return this._frame.click(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async dblclick(options: channels.ElementHandleDblclickOptions = {}): Promise<void> {
|
||||
return this._frame.dblclick(this._selector, options);
|
||||
return this._frame.dblclick(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async dispatchEvent(type: string, eventInit: Object = {}, options?: TimeoutOptions) {
|
||||
return this._frame.dispatchEvent(this._selector, type, eventInit, options);
|
||||
return this._frame.dispatchEvent(this._visibleSelector, type, eventInit, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunctionOn<SVGElement | HTMLElement, Arg, R>, arg?: Arg, options?: TimeoutOptions): Promise<R> {
|
||||
return this._withFirst(h => h.evaluate(pageFunction as any, arg), options);
|
||||
return this._withElement(h => h.evaluate(pageFunction as any, arg), { strict: true, ...options });
|
||||
}
|
||||
|
||||
async evaluateAll<R, Arg>(pageFunction: structs.PageFunctionOn<(SVGElement | HTMLElement)[], Arg, R>, arg?: Arg): Promise<R> {
|
||||
return this._frame.$$eval(this._selector, pageFunction as any, arg);
|
||||
return this._frame.$$eval(this._visibleSelector, pageFunction as any, arg);
|
||||
}
|
||||
|
||||
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg, options?: TimeoutOptions): Promise<structs.SmartHandle<R>> {
|
||||
return this._withFirst(h => h.evaluateHandle(pageFunction as any, arg), options);
|
||||
return this._withElement(h => h.evaluateHandle(pageFunction as any, arg), { strict: true, ...options });
|
||||
}
|
||||
|
||||
async fill(value: string, options: channels.ElementHandleFillOptions = {}): Promise<void> {
|
||||
return this._frame.fill(this._selector, value, options);
|
||||
return this._frame.fill(this._visibleSelector, value, { strict: true, ...options });
|
||||
}
|
||||
|
||||
locator(selector: string): Locator {
|
||||
return new Locator(this._frame, this._selector + ' >> ' + selector);
|
||||
}
|
||||
|
||||
async first(options?: TimeoutOptions): Promise<ElementHandle<SVGElement | HTMLElement>> {
|
||||
const result = await this._frame.waitForSelector(this._selector, options);
|
||||
async elementHandle(options?: TimeoutOptions): Promise<ElementHandle<SVGElement | HTMLElement>> {
|
||||
const result = await this._frame.waitForSelector(this._visibleSelector, { strict: true, state: 'attached', ...options });
|
||||
return result!;
|
||||
}
|
||||
|
||||
async elementHandles(): Promise<api.ElementHandle<SVGElement | HTMLElement>[]> {
|
||||
return this._frame.$$(this._visibleSelector);
|
||||
}
|
||||
|
||||
first(): Locator {
|
||||
return new Locator(this._frame, this._selector + ' >> _first=true');
|
||||
}
|
||||
|
||||
async focus(options?: TimeoutOptions): Promise<void> {
|
||||
return this._frame.focus(this._selector, options);
|
||||
return this._frame.focus(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async count(): Promise<number> {
|
||||
return this.evaluateAll(ee => ee.length);
|
||||
}
|
||||
|
||||
async getAttribute(name: string, options?: TimeoutOptions): Promise<string | null> {
|
||||
return this._frame.getAttribute(this._selector, name, options);
|
||||
return this._frame.getAttribute(this._visibleSelector, name, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async hover(options: channels.ElementHandleHoverOptions = {}): Promise<void> {
|
||||
return this._frame.hover(this._selector, options);
|
||||
return this._frame.hover(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async innerHTML(options?: TimeoutOptions): Promise<string> {
|
||||
return this._frame.innerHTML(this._selector, options);
|
||||
return this._frame.innerHTML(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async innerText(options?: TimeoutOptions): Promise<string> {
|
||||
return this._frame.innerText(this._selector, options);
|
||||
return this._frame.innerText(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async inputValue(options?: TimeoutOptions): Promise<string> {
|
||||
return this._frame.inputValue(this._selector, options);
|
||||
return this._frame.inputValue(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isChecked(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isChecked(this._selector, options);
|
||||
return this._frame.isChecked(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isDisabled(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isDisabled(this._selector, options);
|
||||
return this._frame.isDisabled(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isEditable(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isEditable(this._selector, options);
|
||||
return this._frame.isEditable(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isEnabled(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isEnabled(this._selector, options);
|
||||
return this._frame.isEnabled(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isHidden(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isHidden(this._selector);
|
||||
return this._frame.isHidden(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isVisible(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isVisible(this._selector);
|
||||
return this._frame.isVisible(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async press(key: string, options: channels.ElementHandlePressOptions = {}): Promise<void> {
|
||||
return this._frame.press(this._selector, key, options);
|
||||
return this._frame.press(this._visibleSelector, key, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async screenshot(options: channels.ElementHandleScreenshotOptions & { path?: string } = {}): Promise<Buffer> {
|
||||
return this._withFirst((h, o) => h.screenshot(o), options);
|
||||
return this._withElement((h, o) => h.screenshot(o), { strict: true, ...options });
|
||||
}
|
||||
|
||||
async scrollIntoViewIfNeeded(options: channels.ElementHandleScrollIntoViewIfNeededOptions = {}) {
|
||||
return this._withFirst((h, o) => h.scrollIntoViewIfNeeded(o), options);
|
||||
return this._withElement((h, o) => h.scrollIntoViewIfNeeded(o), { strict: true, ...options });
|
||||
}
|
||||
|
||||
async selectOption(values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
|
||||
return this._frame.selectOption(this._selector, values, options);
|
||||
return this._frame.selectOption(this._visibleSelector, values, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async selectText(options: channels.ElementHandleSelectTextOptions = {}): Promise<void> {
|
||||
return this._withFirst((h, o) => h.selectText(o), options);
|
||||
return this._withElement((h, o) => h.selectText(o), { strict: true, ...options });
|
||||
}
|
||||
|
||||
async setInputFiles(files: string | FilePayload | string[] | FilePayload[], options: channels.ElementHandleSetInputFilesOptions = {}) {
|
||||
return this._frame.setInputFiles(this._selector, files, options);
|
||||
return this._frame.setInputFiles(this._visibleSelector, files, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async tap(options: channels.ElementHandleTapOptions = {}): Promise<void> {
|
||||
return this._frame.tap(this._selector, options);
|
||||
return this._frame.tap(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async textContent(options?: TimeoutOptions): Promise<string | null> {
|
||||
return this._frame.textContent(this._selector, options);
|
||||
return this._frame.textContent(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async type(text: string, options: channels.ElementHandleTypeOptions = {}): Promise<void> {
|
||||
return this._frame.type(this._selector, text, options);
|
||||
return this._frame.type(this._visibleSelector, text, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async uncheck(options: channels.ElementHandleUncheckOptions = {}) {
|
||||
return this._frame.uncheck(this._selector, options);
|
||||
return this._frame.uncheck(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
waitFor(options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>;
|
||||
waitFor(options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
|
||||
async waitFor(options?: channels.FrameWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
|
||||
return this._frame.waitForSelector(this._selector, options);
|
||||
return this._frame.waitForSelector(this._visibleSelector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
[(util.inspect as any).custom]() {
|
||||
|
||||
@ -25,7 +25,7 @@ export interface Logger {
|
||||
|
||||
import { Size } from '../common/types';
|
||||
export { Size, Point, Rect, Quad, URLMatch, TimeoutOptions } from '../common/types';
|
||||
|
||||
export type StrictOptions = { strict?: boolean };
|
||||
export type Headers = { [key: string]: string };
|
||||
export type Env = { [key: string]: string | number | boolean | undefined };
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@ export class Selectors {
|
||||
'data-testid', 'data-testid:light',
|
||||
'data-test-id', 'data-test-id:light',
|
||||
'data-test', 'data-test:light',
|
||||
'_visible', '_first'
|
||||
]);
|
||||
this._engines = new Map();
|
||||
}
|
||||
|
||||
@ -39,21 +39,6 @@ it('should work for TextNodes', async ({ page, server }) => {
|
||||
expect(await page.evaluate(() => window['result'])).toBe('Clicked');
|
||||
});
|
||||
|
||||
it('should throw for recursively hidden nodes with force', async ({ page, server }) => {
|
||||
await page.goto(server.PREFIX + '/input/button.html');
|
||||
const button = page.locator('button');
|
||||
await page.evaluate(button => button.parentElement.style.display = 'none', await button.first());
|
||||
const error = await button.click({ force: true }).catch(err => err);
|
||||
expect(error.message).toContain('Element is not visible');
|
||||
});
|
||||
|
||||
it('should throw for <br> elements with force', async ({ page, server }) => {
|
||||
await page.setContent('hello<br>goodbye');
|
||||
const br = page.locator('br');
|
||||
const error = await br.click({ force: true }).catch(err => err);
|
||||
expect(error.message).toContain('Element is outside of the viewport');
|
||||
});
|
||||
|
||||
it('should double click the button', async ({ page, server }) => {
|
||||
await page.goto(server.PREFIX + '/input/button.html');
|
||||
await page.evaluate(() => {
|
||||
|
||||
@ -23,14 +23,14 @@ it('should query existing element', async ({page, server}) => {
|
||||
const html = page.locator('html');
|
||||
const second = html.locator('.second');
|
||||
const inner = second.locator('.inner');
|
||||
const content = await page.evaluate(e => e.textContent, await inner.first());
|
||||
const content = await page.evaluate(e => e.textContent, await inner.elementHandle());
|
||||
expect(content).toBe('A');
|
||||
});
|
||||
|
||||
it('should query existing elements', async ({page, server}) => {
|
||||
await page.setContent('<html><body><div>A</div><br/><div>B</div></body></html>');
|
||||
const html = page.locator('html');
|
||||
const elements = await html.locator('div').all();
|
||||
const elements = await html.locator('div').elementHandles();
|
||||
expect(elements.length).toBe(2);
|
||||
const promises = elements.map(element => page.evaluate(e => e.textContent, element));
|
||||
expect(await Promise.all(promises)).toEqual(['A', 'B']);
|
||||
@ -39,7 +39,7 @@ it('should query existing elements', async ({page, server}) => {
|
||||
it('should return empty array for non-existing elements', async ({page, server}) => {
|
||||
await page.setContent('<html><body><span>A</span><br/><span>B</span></body></html>');
|
||||
const html = page.locator('html');
|
||||
const elements = await html.locator('div').all();
|
||||
const elements = await html.locator('div').elementHandles();
|
||||
expect(elements.length).toBe(0);
|
||||
});
|
||||
|
||||
@ -50,13 +50,13 @@ it('xpath should query existing element', async ({page, server}) => {
|
||||
const html = page.locator('html');
|
||||
const second = html.locator(`xpath=./body/div[contains(@class, 'second')]`);
|
||||
const inner = second.locator(`xpath=./div[contains(@class, 'inner')]`);
|
||||
const content = await page.evaluate(e => e.textContent, await inner.first());
|
||||
const content = await page.evaluate(e => e.textContent, await inner.elementHandle());
|
||||
expect(content).toBe('A');
|
||||
});
|
||||
|
||||
it('xpath should return null for non-existing element', async ({page, server}) => {
|
||||
await page.setContent('<html><body><div class="second"><div class="inner">B</div></div></body></html>');
|
||||
const html = page.locator('html');
|
||||
const second = await html.locator(`xpath=/div[contains(@class, 'third')]`).all();
|
||||
const second = await html.locator(`xpath=/div[contains(@class, 'third')]`).elementHandles();
|
||||
expect(second).toEqual([]);
|
||||
});
|
||||
@ -88,9 +88,9 @@ it('should dispatch click event via ElementHandles', async ({page, server}) => {
|
||||
it('should upload the file', async ({page, server, asset}) => {
|
||||
await page.goto(server.PREFIX + '/input/fileupload.html');
|
||||
const filePath = path.relative(process.cwd(), asset('file-to-upload.txt'));
|
||||
const input = page.locator('input');
|
||||
const input = page.locator('input[type=file]');
|
||||
await input.setInputFiles(filePath);
|
||||
expect(await page.evaluate(e => (e as HTMLInputElement).files[0].name, await input.first())).toBe('file-to-upload.txt');
|
||||
expect(await page.evaluate(e => (e as HTMLInputElement).files[0].name, await input.elementHandle())).toBe('file-to-upload.txt');
|
||||
});
|
||||
|
||||
it.describe('tap group', () => {
|
||||
|
||||
30
tests/page/locator-query.spec.ts
Normal file
30
tests/page/locator-query.spec.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test as it, expect } from './pageTest';
|
||||
|
||||
it('should respect first()', async ({page}) => {
|
||||
await page.setContent(`
|
||||
<section>
|
||||
<div><p>A</p></div>
|
||||
<div><p>A</p><p>A</p></div>
|
||||
<div><p>A</p><p>A</p><p>A</p></div>
|
||||
</section>`);
|
||||
expect(await page.locator('div >> p').count()).toBe(6);
|
||||
expect(await page.locator('div').locator('p').count()).toBe(6);
|
||||
expect(await page.locator('div').first().locator('p').count()).toBe(1);
|
||||
});
|
||||
18
types/types.d.ts
vendored
18
types/types.d.ts
vendored
@ -6963,17 +6963,17 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
|
||||
*/
|
||||
export interface Locator {
|
||||
/**
|
||||
* Resolves given locator to the first VISIBLE matching DOM element. If no elements matching the query are visible, waits
|
||||
* for them up to a given timeout.
|
||||
* Resolves given locator to the first matching DOM element. If no elements matching the query are visible, waits for them
|
||||
* up to a given timeout. If multiple elements match the selector, throws.
|
||||
* @param options
|
||||
*/
|
||||
first(options?: {
|
||||
elementHandle(options?: {
|
||||
timeout?: number;
|
||||
}): Promise<null|ElementHandle<SVGElement | HTMLElement>>;
|
||||
/**
|
||||
* Resolves given locator to all matching DOM elements.
|
||||
*/
|
||||
all(): Promise<null|ElementHandle<SVGElement | HTMLElement>[]>;
|
||||
elementHandles(): Promise<null|ElementHandle<SVGElement | HTMLElement>[]>;
|
||||
/**
|
||||
* Returns the return value of `pageFunction`.
|
||||
*
|
||||
@ -7192,6 +7192,11 @@ export interface Locator {
|
||||
trial?: boolean;
|
||||
}): Promise<void>;
|
||||
|
||||
/**
|
||||
* Returns the number of elements matching given selector.
|
||||
*/
|
||||
count(): Promise<number>;
|
||||
|
||||
/**
|
||||
* This method double clicks the element by performing the following steps:
|
||||
* 1. Wait for [actionability](https://playwright.dev/docs/actionability) checks on the element, unless `force` option is set.
|
||||
@ -7376,6 +7381,11 @@ export interface Locator {
|
||||
timeout?: number;
|
||||
}): Promise<void>;
|
||||
|
||||
/**
|
||||
* Returns locator to the first matching element.
|
||||
*/
|
||||
first(): Locator;
|
||||
|
||||
/**
|
||||
* Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element.
|
||||
* @param options
|
||||
|
||||
4
utils/generate_types/overrides.d.ts
vendored
4
utils/generate_types/overrides.d.ts
vendored
@ -141,10 +141,10 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
|
||||
}
|
||||
|
||||
export interface Locator {
|
||||
first(options?: {
|
||||
elementHandle(options?: {
|
||||
timeout?: number;
|
||||
}): Promise<null|ElementHandle<SVGElement | HTMLElement>>;
|
||||
all(): Promise<null|ElementHandle<SVGElement | HTMLElement>[]>;
|
||||
elementHandles(): Promise<null|ElementHandle<SVGElement | HTMLElement>[]>;
|
||||
evaluate<R, Arg>(pageFunction: PageFunctionOn<SVGElement | HTMLElement, Arg, R>, arg: Arg): Promise<R>;
|
||||
evaluate<R>(pageFunction: PageFunctionOn<SVGElement | HTMLElement, void, R>): Promise<R>;
|
||||
evaluateAll<R, Arg>(pageFunction: PageFunctionOn<(SVGElement | HTMLElement)[], Arg, R>, arg: Arg): Promise<R>;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user