mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-13 17:14:02 +03:00
chore: update locator docs, make it not force-visible (#7888)
This commit is contained in:
parent
49e9f8c15e
commit
446d3f1018
@ -4,87 +4,28 @@
|
||||
ElementHandle represents an in-page DOM element. ElementHandles can be created with the [`method: Page.querySelector`] method.
|
||||
|
||||
```js
|
||||
const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto('https://example.com');
|
||||
const hrefElement = await page.$('a');
|
||||
await hrefElement.click();
|
||||
// ...
|
||||
})();
|
||||
const hrefElement = await page.$('a');
|
||||
await hrefElement.click();
|
||||
```
|
||||
|
||||
```java
|
||||
import com.microsoft.playwright.*;
|
||||
|
||||
public class Example {
|
||||
public static void main(String[] args) {
|
||||
try (Playwright playwright = Playwright.create()) {
|
||||
BrowserType chromium = playwright.chromium();
|
||||
Browser browser = chromium.launch();
|
||||
Page page = browser.newPage();
|
||||
page.navigate("https://example.com");
|
||||
ElementHandle hrefElement = page.querySelector("a");
|
||||
hrefElement.click();
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
ElementHandle hrefElement = page.querySelector("a");
|
||||
hrefElement.click();
|
||||
```
|
||||
|
||||
```python async
|
||||
import asyncio
|
||||
from playwright.async_api import async_playwright
|
||||
|
||||
async def run(playwright):
|
||||
chromium = playwright.chromium
|
||||
browser = await chromium.launch()
|
||||
page = await browser.new_page()
|
||||
await page.goto("https://example.com")
|
||||
href_element = await page.query_selector("a")
|
||||
await href_element.click()
|
||||
# ...
|
||||
|
||||
async def main():
|
||||
async with async_playwright() as playwright:
|
||||
await run(playwright)
|
||||
asyncio.run(main())
|
||||
href_element = await page.query_selector("a")
|
||||
await href_element.click()
|
||||
```
|
||||
|
||||
```python sync
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
def run(playwright):
|
||||
chromium = playwright.chromium
|
||||
browser = chromium.launch()
|
||||
page = browser.new_page()
|
||||
page.goto("https://example.com")
|
||||
href_element = page.query_selector("a")
|
||||
href_element.click()
|
||||
# ...
|
||||
|
||||
with sync_playwright() as playwright:
|
||||
run(playwright)
|
||||
href_element = page.query_selector("a")
|
||||
href_element.click()
|
||||
```
|
||||
|
||||
```csharp
|
||||
using Microsoft.Playwright;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class HandleExamples
|
||||
{
|
||||
public static async Task Run()
|
||||
{
|
||||
using var playwright = await Playwright.CreateAsync();
|
||||
var browser = await playwright.Chromium.LaunchAsync();
|
||||
var page = await browser.NewPageAsync();
|
||||
await page.GotoAsync("https://www.bing.com");
|
||||
var handle = await page.QuerySelectorAsync("a");
|
||||
await handle.ClickAsync();
|
||||
}
|
||||
}
|
||||
var handle = await page.QuerySelectorAsync("a");
|
||||
await handle.ClickAsync();
|
||||
```
|
||||
|
||||
ElementHandle prevents DOM element from garbage collection unless the handle is disposed with
|
||||
@ -92,6 +33,79 @@ ElementHandle prevents DOM element from garbage collection unless the handle is
|
||||
|
||||
ElementHandle instances can be used as an argument in [`method: Page.evalOnSelector`] and [`method: Page.evaluate`] methods.
|
||||
|
||||
:::note
|
||||
In most cases, you would want to use the [Locator] object instead. You should only use [ElementHandle] if you want to retain
|
||||
a handle to a particular DOM Node that you intend to pass into [`method: Page.evaluate`] as an argument.
|
||||
:::
|
||||
|
||||
The difference between the [Locator] and ElementHandle is that the ElementHandle points to a particular element, while [Locator] captures the logic of how to retrieve an 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();
|
||||
```
|
||||
|
||||
## async method: ElementHandle.boundingBox
|
||||
- returns: <[null]|[Object]>
|
||||
- `x` <[float]> the x coordinate of the element in pixels.
|
||||
|
@ -2,9 +2,34 @@
|
||||
|
||||
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.
|
||||
|
||||
The difference between the Locator and [ElementHandle] is that the latter points to a particular element, while Locator only captures the logic of how to retrieve an element at any given moment.
|
||||
```js
|
||||
const locator = page.locator('text=Submit');
|
||||
await locator.click();
|
||||
```
|
||||
|
||||
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.
|
||||
```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');
|
||||
@ -37,37 +62,37 @@ await handle.HoverAsync();
|
||||
await handle.ClickAsync();
|
||||
```
|
||||
|
||||
With the locator, every time the `element` is used, corresponding DOM element is located in the page using given selector. So in the snippet below, underlying DOM element is going to be located twice, using the given selector.
|
||||
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 element = page.locator('text=Submit');
|
||||
const locator = page.locator('text=Submit');
|
||||
// ...
|
||||
await element.hover();
|
||||
await element.click();
|
||||
await locator.hover();
|
||||
await locator.click();
|
||||
```
|
||||
|
||||
```java
|
||||
Locator element = page.locator("text=Submit");
|
||||
element.hover();
|
||||
element.click();
|
||||
Locator locator = page.locator("text=Submit");
|
||||
locator.hover();
|
||||
locator.click();
|
||||
```
|
||||
|
||||
```python async
|
||||
element = page.locator("text=Submit")
|
||||
await element.hover()
|
||||
await element.click()
|
||||
locator = page.locator("text=Submit")
|
||||
await locator.hover()
|
||||
await locator.click()
|
||||
```
|
||||
|
||||
```python sync
|
||||
element = page.locator("text=Submit")
|
||||
element.hover()
|
||||
element.click()
|
||||
locator = page.locator("text=Submit")
|
||||
locator.hover()
|
||||
locator.click()
|
||||
```
|
||||
|
||||
```csharp
|
||||
var element = page.Locator("text=Submit");
|
||||
await element.HoverAsync();
|
||||
await element.ClickAsync();
|
||||
var locator = page.Locator("text=Submit");
|
||||
await locator.HoverAsync();
|
||||
await locator.ClickAsync();
|
||||
```
|
||||
|
||||
## async method: Locator.boundingBox
|
||||
|
@ -26,12 +26,10 @@ 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 _withElement<R, O extends TimeoutOptions>(task: (handle: ElementHandle<SVGElement | HTMLElement>, options?: O) => Promise<R>, options?: O): Promise<R> {
|
||||
@ -54,19 +52,19 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async check(options: channels.ElementHandleCheckOptions = {}) {
|
||||
return this._frame.check(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.check(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async click(options: channels.ElementHandleClickOptions = {}): Promise<void> {
|
||||
return this._frame.click(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.click(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async dblclick(options: channels.ElementHandleDblclickOptions = {}): Promise<void> {
|
||||
return this._frame.dblclick(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.dblclick(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async dispatchEvent(type: string, eventInit: Object = {}, options?: TimeoutOptions) {
|
||||
return this._frame.dispatchEvent(this._visibleSelector, type, eventInit, { strict: true, ...options });
|
||||
return this._frame.dispatchEvent(this._selector, type, eventInit, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async evaluate<R, Arg>(pageFunction: structs.PageFunctionOn<SVGElement | HTMLElement, Arg, R>, arg?: Arg, options?: TimeoutOptions): Promise<R> {
|
||||
@ -74,7 +72,7 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async evaluateAll<R, Arg>(pageFunction: structs.PageFunctionOn<(SVGElement | HTMLElement)[], Arg, R>, arg?: Arg): Promise<R> {
|
||||
return this._frame.$$eval(this._visibleSelector, pageFunction as any, arg);
|
||||
return this._frame.$$eval(this._selector, pageFunction as any, arg);
|
||||
}
|
||||
|
||||
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg, options?: TimeoutOptions): Promise<structs.SmartHandle<R>> {
|
||||
@ -82,7 +80,7 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async fill(value: string, options: channels.ElementHandleFillOptions = {}): Promise<void> {
|
||||
return this._frame.fill(this._visibleSelector, value, { strict: true, ...options });
|
||||
return this._frame.fill(this._selector, value, { strict: true, ...options });
|
||||
}
|
||||
|
||||
locator(selector: string): Locator {
|
||||
@ -90,12 +88,12 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async elementHandle(options?: TimeoutOptions): Promise<ElementHandle<SVGElement | HTMLElement>> {
|
||||
const result = await this._frame.waitForSelector(this._visibleSelector, { strict: true, state: 'attached', ...options });
|
||||
const result = await this._frame.waitForSelector(this._selector, { strict: true, state: 'attached', ...options });
|
||||
return result!;
|
||||
}
|
||||
|
||||
async elementHandles(): Promise<api.ElementHandle<SVGElement | HTMLElement>[]> {
|
||||
return this._frame.$$(this._visibleSelector);
|
||||
return this._frame.$$(this._selector);
|
||||
}
|
||||
|
||||
first(): Locator {
|
||||
@ -111,7 +109,7 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async focus(options?: TimeoutOptions): Promise<void> {
|
||||
return this._frame.focus(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.focus(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async count(): Promise<number> {
|
||||
@ -119,39 +117,39 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async getAttribute(name: string, options?: TimeoutOptions): Promise<string | null> {
|
||||
return this._frame.getAttribute(this._visibleSelector, name, { strict: true, ...options });
|
||||
return this._frame.getAttribute(this._selector, name, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async hover(options: channels.ElementHandleHoverOptions = {}): Promise<void> {
|
||||
return this._frame.hover(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.hover(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async innerHTML(options?: TimeoutOptions): Promise<string> {
|
||||
return this._frame.innerHTML(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.innerHTML(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async innerText(options?: TimeoutOptions): Promise<string> {
|
||||
return this._frame.innerText(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.innerText(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async inputValue(options?: TimeoutOptions): Promise<string> {
|
||||
return this._frame.inputValue(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.inputValue(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isChecked(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isChecked(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.isChecked(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isDisabled(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isDisabled(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.isDisabled(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isEditable(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isEditable(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.isEditable(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isEnabled(options?: TimeoutOptions): Promise<boolean> {
|
||||
return this._frame.isEnabled(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.isEnabled(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async isHidden(options?: TimeoutOptions): Promise<boolean> {
|
||||
@ -163,7 +161,7 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async press(key: string, options: channels.ElementHandlePressOptions = {}): Promise<void> {
|
||||
return this._frame.press(this._visibleSelector, key, { strict: true, ...options });
|
||||
return this._frame.press(this._selector, key, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async screenshot(options: channels.ElementHandleScreenshotOptions & { path?: string } = {}): Promise<Buffer> {
|
||||
@ -175,7 +173,7 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async selectOption(values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
|
||||
return this._frame.selectOption(this._visibleSelector, values, { strict: true, ...options });
|
||||
return this._frame.selectOption(this._selector, values, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async selectText(options: channels.ElementHandleSelectTextOptions = {}): Promise<void> {
|
||||
@ -183,23 +181,23 @@ export class Locator implements api.Locator {
|
||||
}
|
||||
|
||||
async setInputFiles(files: string | FilePayload | string[] | FilePayload[], options: channels.ElementHandleSetInputFilesOptions = {}) {
|
||||
return this._frame.setInputFiles(this._visibleSelector, files, { strict: true, ...options });
|
||||
return this._frame.setInputFiles(this._selector, files, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async tap(options: channels.ElementHandleTapOptions = {}): Promise<void> {
|
||||
return this._frame.tap(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.tap(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async textContent(options?: TimeoutOptions): Promise<string | null> {
|
||||
return this._frame.textContent(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.textContent(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async type(text: string, options: channels.ElementHandleTypeOptions = {}): Promise<void> {
|
||||
return this._frame.type(this._visibleSelector, text, { strict: true, ...options });
|
||||
return this._frame.type(this._selector, text, { strict: true, ...options });
|
||||
}
|
||||
|
||||
async uncheck(options: channels.ElementHandleUncheckOptions = {}) {
|
||||
return this._frame.uncheck(this._visibleSelector, { strict: true, ...options });
|
||||
return this._frame.uncheck(this._selector, { strict: true, ...options });
|
||||
}
|
||||
|
||||
[(util.inspect as any).custom]() {
|
||||
|
61
types/types.d.ts
vendored
61
types/types.d.ts
vendored
@ -5929,16 +5929,8 @@ export interface JSHandle<T = any> {
|
||||
* [page.$(selector[, options])](https://playwright.dev/docs/api/class-page#page-query-selector) method.
|
||||
*
|
||||
* ```js
|
||||
* const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
|
||||
*
|
||||
* (async () => {
|
||||
* const browser = await chromium.launch();
|
||||
* const page = await browser.newPage();
|
||||
* await page.goto('https://example.com');
|
||||
* const hrefElement = await page.$('a');
|
||||
* await hrefElement.click();
|
||||
* // ...
|
||||
* })();
|
||||
* const hrefElement = await page.$('a');
|
||||
* await hrefElement.click();
|
||||
* ```
|
||||
*
|
||||
* ElementHandle prevents DOM element from garbage collection unless the handle is disposed with
|
||||
@ -5948,6 +5940,35 @@ export interface JSHandle<T = any> {
|
||||
* ElementHandle instances can be used as an argument in
|
||||
* [page.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-eval-on-selector)
|
||||
* and [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) methods.
|
||||
*
|
||||
* > NOTE: In most cases, you would want to use the [Locator] object instead. You should only use [ElementHandle] if you
|
||||
* want to retain a handle to a particular DOM Node that you intend to pass into
|
||||
* [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) as an argument.
|
||||
*
|
||||
* The difference between the [Locator] and ElementHandle is that the ElementHandle points to a particular element, while
|
||||
* [Locator] captures the logic of how to retrieve an 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();
|
||||
* ```
|
||||
*
|
||||
* 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();
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
export interface ElementHandle<T=Node> extends JSHandle<T> {
|
||||
/**
|
||||
@ -6943,11 +6964,17 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
|
||||
* given moment. Locator can be created with the
|
||||
* [page.locator(selector)](https://playwright.dev/docs/api/class-page#page-locator) method.
|
||||
*
|
||||
* ```js
|
||||
* const locator = page.locator('text=Submit');
|
||||
* await locator.click();
|
||||
* ```
|
||||
*
|
||||
* The difference between the Locator and [ElementHandle] is that the latter points to a particular element, while Locator
|
||||
* only captures the logic of how to retrieve an element at any given moment.
|
||||
* 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.
|
||||
* 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');
|
||||
@ -6956,14 +6983,14 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
|
||||
* await handle.click();
|
||||
* ```
|
||||
*
|
||||
* With the locator, every time the `element` is used, corresponding DOM element is located in the page using given
|
||||
* selector. So in the snippet below, underlying DOM element is going to be located twice, using the given selector.
|
||||
* 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 element = page.locator('text=Submit');
|
||||
* const locator = page.locator('text=Submit');
|
||||
* // ...
|
||||
* await element.hover();
|
||||
* await element.click();
|
||||
* await locator.hover();
|
||||
* await locator.click();
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user