fix: extends ElementHandle to Nodes (#8552)

* fix: extends `ElementHandle` to `Node`s (#8552)
This commit is contained in:
jrandolf 2022-07-06 09:05:37 +02:00 committed by GitHub
parent b49d530d73
commit 5ff205dc8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
93 changed files with 597 additions and 1095 deletions

View File

@ -1,6 +1,39 @@
assets/ ## [START] Keep in sync with .gitignore
# Dependencies
node_modules
# Production
build/ build/
coverage/ lib/
lib
# Generated files
tsconfig.tsbuildinfo tsconfig.tsbuildinfo
puppeteer.api.json
puppeteer*.tgz
yarn.lock
.docusaurus/
.cache-loader
.local-chromium/
.local-firefox/
test/output-*/
.dev_profile*
coverage/
# IDE Artifacts
.vscode
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
## [END] Keep in sync with .gitignore
# ESLint ignores.
assets/
vendor/ vendor/

View File

@ -140,6 +140,8 @@ module.exports = {
'arrow-body-style': ['error', 'always'], 'arrow-body-style': ['error', 'always'],
// Error if comments do not adhere to `tsdoc`. // Error if comments do not adhere to `tsdoc`.
'tsdoc/syntax': 2, 'tsdoc/syntax': 2,
// Keeps array types simple only when they are simple for readability.
'@typescript-eslint/array-type': ['error', {default: 'array-simple'}],
'no-unused-vars': 0, 'no-unused-vars': 0,
'@typescript-eslint/no-unused-vars': [ '@typescript-eslint/no-unused-vars': [
'error', 'error',

1
.gitignore vendored
View File

@ -16,6 +16,7 @@ yarn.lock
.local-firefox/ .local-firefox/
test/output-*/ test/output-*/
.dev_profile* .dev_profile*
coverage/
# IDE Artifacts # IDE Artifacts
.vscode .vscode

View File

@ -1,5 +1,4 @@
# Keep in sync with .gitignore ## [START] Keep in sync with .gitignore
# Dependencies # Dependencies
node_modules node_modules
@ -18,6 +17,7 @@ yarn.lock
.local-firefox/ .local-firefox/
test/output-*/ test/output-*/
.dev_profile* .dev_profile*
coverage/
# IDE Artifacts # IDE Artifacts
.vscode .vscode
@ -32,6 +32,7 @@ test/output-*/
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
## [END] Keep in sync with .gitignore
# Prettier-only ignores. # Prettier-only ignores.
assets/ assets/

View File

@ -155,6 +155,7 @@ sidebar_label: API
| [KeyInput](./puppeteer.keyinput.md) | All the valid keys that can be passed to functions that take user input, such as [keyboard.press](./puppeteer.keyboard.press.md) | | [KeyInput](./puppeteer.keyinput.md) | All the valid keys that can be passed to functions that take user input, such as [keyboard.press](./puppeteer.keyboard.press.md) |
| [LowerCasePaperFormat](./puppeteer.lowercasepaperformat.md) | | | [LowerCasePaperFormat](./puppeteer.lowercasepaperformat.md) | |
| [MouseButton](./puppeteer.mousebutton.md) | | | [MouseButton](./puppeteer.mousebutton.md) | |
| [NodeFor](./puppeteer.nodefor.md) | |
| [PaperFormat](./puppeteer.paperformat.md) | All the valid paper format types when printing a PDF. | | [PaperFormat](./puppeteer.paperformat.md) | All the valid paper format types when printing a PDF. |
| [Permission](./puppeteer.permission.md) | | | [Permission](./puppeteer.permission.md) | |
| [Platform](./puppeteer.platform.md) | Supported platforms. | | [Platform](./puppeteer.platform.md) | Supported platforms. |

View File

@ -14,7 +14,7 @@ export interface CustomQueryHandler
## Properties ## Properties
| Property | Modifiers | Type | Description | | Property | Modifiers | Type | Description |
| ------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------- | ----------------- | | ------------------------------------------------------- | --------- | ---------------------------------------------------- | ----------------- |
| [queryAll?](./puppeteer.customqueryhandler.queryall.md) | | (element: Element \| Document, selector: string) =&gt; Element\[\] \| NodeListOf&lt;Element&gt; | <i>(Optional)</i> | | [queryAll?](./puppeteer.customqueryhandler.queryall.md) | | (element: Node, selector: string) =&gt; Node\[\] | <i>(Optional)</i> |
| [queryOne?](./puppeteer.customqueryhandler.queryone.md) | | (element: Element \| Document, selector: string) =&gt; Element \| null | <i>(Optional)</i> | | [queryOne?](./puppeteer.customqueryhandler.queryone.md) | | (element: Node, selector: string) =&gt; Node \| null | <i>(Optional)</i> |

View File

@ -8,9 +8,6 @@ sidebar_label: CustomQueryHandler.queryAll
```typescript ```typescript
interface CustomQueryHandler { interface CustomQueryHandler {
queryAll?: ( queryAll?: (element: Node, selector: string) => Node[];
element: Element | Document,
selector: string
) => Element[] | NodeListOf<Element>;
} }
``` ```

View File

@ -8,6 +8,6 @@ sidebar_label: CustomQueryHandler.queryOne
```typescript ```typescript
interface CustomQueryHandler { interface CustomQueryHandler {
queryOne?: (element: Element | Document, selector: string) => Element | null; queryOne?: (element: Node, selector: string) => Node | null;
} }
``` ```

View File

@ -10,9 +10,9 @@ Runs `element.querySelector` within the page.
```typescript ```typescript
class ElementHandle { class ElementHandle {
$<Selector extends keyof HTMLElementTagNameMap>( $<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null>;
} }
``` ```
@ -24,7 +24,7 @@ class ElementHandle {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt; \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt; \| null&gt;
`null` if no element matches the selector. `null` if no element matches the selector.

View File

@ -10,9 +10,9 @@ Runs `element.querySelectorAll` within the page.
```typescript ```typescript
class ElementHandle { class ElementHandle {
$$<Selector extends keyof HTMLElementTagNameMap>( $$<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]>[]>; ): Promise<Array<ElementHandle<NodeFor<Selector>>>>;
} }
``` ```
@ -24,7 +24,7 @@ class ElementHandle {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt;\[\]&gt; Promise&lt;Array&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt;&gt;&gt;
`[]` if no element matches the selector. `[]` if no element matches the selector.

View File

@ -1,23 +0,0 @@
---
sidebar_label: ElementHandle.$_1
---
# ElementHandle.$() method
**Signature:**
```typescript
class ElementHandle {
$(selector: string): Promise<ElementHandle | null>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| selector | string | |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt;

View File

@ -1,23 +0,0 @@
---
sidebar_label: ElementHandle.$$_1
---
# ElementHandle.$$() method
**Signature:**
```typescript
class ElementHandle {
$$(selector: string): Promise<ElementHandle[]>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| selector | string | |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)\[\]&gt;

View File

@ -13,11 +13,11 @@ If `pageFunction` returns a Promise, then `frame.$$eval` would wait for the prom
```typescript ```typescript
class ElementHandle { class ElementHandle {
$$eval< $$eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector][], ...Params] [Array<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector][], ...Params]> > = EvaluateFunc<[Array<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,

View File

@ -1,34 +0,0 @@
---
sidebar_label: ElementHandle.$$eval_1
---
# ElementHandle.$$eval() method
**Signature:**
```typescript
class ElementHandle {
$$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
}
```
## Parameters
| Parameter | Type | Description |
| ------------ | -------------- | ----------- |
| selector | string | |
| pageFunction | Func \| string | |
| args | Params | |
**Returns:**
Promise&lt;Awaited&lt;ReturnType&lt;Func&gt;&gt;&gt;

View File

@ -13,11 +13,11 @@ If `pageFunction` returns a Promise, then `frame.$eval` would wait for the promi
```typescript ```typescript
class ElementHandle { class ElementHandle {
$eval< $eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector], ...Params] [ElementHandle<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector], ...Params]> > = EvaluateFunc<[ElementHandle<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,

View File

@ -1,34 +0,0 @@
---
sidebar_label: ElementHandle.$eval_1
---
# ElementHandle.$eval() method
**Signature:**
```typescript
class ElementHandle {
$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
}
```
## Parameters
| Parameter | Type | Description |
| ------------ | -------------- | ----------- |
| selector | string | |
| pageFunction | Func \| string | |
| args | Params | |
**Returns:**
Promise&lt;Awaited&lt;ReturnType&lt;Func&gt;&gt;&gt;

View File

@ -10,7 +10,7 @@ The method evaluates the XPath expression relative to the elementHandle. If ther
```typescript ```typescript
class ElementHandle { class ElementHandle {
$x(expression: string): Promise<ElementHandle[]>; $x(expression: string): Promise<Array<ElementHandle<Node>>>;
} }
``` ```
@ -22,4 +22,4 @@ class ElementHandle {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)\[\]&gt; Promise&lt;Array&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt;&gt;&gt;

View File

@ -10,15 +10,16 @@ This method scrolls element into view if needed, and then uses [Page.mouse](./pu
```typescript ```typescript
class ElementHandle { class ElementHandle {
click(options?: ClickOptions): Promise<void>; click(this: ElementHandle<Element>, options?: ClickOptions): Promise<void>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ------------------------------------------- | ----------------- | | --------- | ------------------------------------------------------------ | ----------------- |
| options | [ClickOptions](./puppeteer.clickoptions.md) | <i>(Optional)</i> | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| options | [ClickOptions](./puppeteer.clickoptions.md) | <i>(Optional)</i> |
**Returns:** **Returns:**

View File

@ -10,15 +10,19 @@ This method creates and captures a dragevent from the element.
```typescript ```typescript
class ElementHandle { class ElementHandle {
drag(target: Point): Promise<Protocol.Input.DragData>; drag(
this: ElementHandle<Element>,
target: Point
): Promise<Protocol.Input.DragData>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ----------------------------- | ----------- | | --------- | ------------------------------------------------------------ | ----------- |
| target | [Point](./puppeteer.point.md) | | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| target | [Point](./puppeteer.point.md) | |
**Returns:** **Returns:**

View File

@ -11,7 +11,8 @@ This method triggers a dragenter, dragover, and drop on the element.
```typescript ```typescript
class ElementHandle { class ElementHandle {
dragAndDrop( dragAndDrop(
target: ElementHandle, this: ElementHandle<Element>,
target: ElementHandle<Node>,
options?: { options?: {
delay: number; delay: number;
} }
@ -21,10 +22,11 @@ class ElementHandle {
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | --------------------------------------------- | ----------------- | | --------- | ------------------------------------------------------------ | ----------------- |
| target | [ElementHandle](./puppeteer.elementhandle.md) | | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| options | { delay: number; } | <i>(Optional)</i> | | target | [ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt; | |
| options | { delay: number; } | <i>(Optional)</i> |
**Returns:** **Returns:**

View File

@ -10,15 +10,19 @@ This method creates a `dragenter` event on the element.
```typescript ```typescript
class ElementHandle { class ElementHandle {
dragEnter(data?: Protocol.Input.DragData): Promise<void>; dragEnter(
this: ElementHandle<Element>,
data?: Protocol.Input.DragData
): Promise<void>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ----------------------- | ----------------- | | --------- | ------------------------------------------------------------ | ----------------- |
| data | Protocol.Input.DragData | <i>(Optional)</i> | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| data | Protocol.Input.DragData | <i>(Optional)</i> |
**Returns:** **Returns:**

View File

@ -10,15 +10,19 @@ This method creates a `dragover` event on the element.
```typescript ```typescript
class ElementHandle { class ElementHandle {
dragOver(data?: Protocol.Input.DragData): Promise<void>; dragOver(
this: ElementHandle<Element>,
data?: Protocol.Input.DragData
): Promise<void>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ----------------------- | ----------------- | | --------- | ------------------------------------------------------------ | ----------------- |
| data | Protocol.Input.DragData | <i>(Optional)</i> | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| data | Protocol.Input.DragData | <i>(Optional)</i> |
**Returns:** **Returns:**

View File

@ -10,15 +10,19 @@ This method triggers a drop on the element.
```typescript ```typescript
class ElementHandle { class ElementHandle {
drop(data?: Protocol.Input.DragData): Promise<void>; drop(
this: ElementHandle<Element>,
data?: Protocol.Input.DragData
): Promise<void>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ----------------------- | ----------------- | | --------- | ------------------------------------------------------------ | ----------------- |
| data | Protocol.Input.DragData | <i>(Optional)</i> | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| data | Protocol.Input.DragData | <i>(Optional)</i> |
**Returns:** **Returns:**

View File

@ -10,10 +10,16 @@ This method scrolls element into view if needed, and then uses [Page.mouse](./pu
```typescript ```typescript
class ElementHandle { class ElementHandle {
hover(): Promise<void>; hover(this: ElementHandle<Element>): Promise<void>;
} }
``` ```
## Parameters
| Parameter | Type | Description |
| --------- | ------------------------------------------------------------ | ----------- |
| this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
**Returns:** **Returns:**
Promise&lt;void&gt; Promise&lt;void&gt;

View File

@ -10,15 +10,21 @@ Resolves to true if the element is visible in the current viewport.
```typescript ```typescript
class ElementHandle { class ElementHandle {
isIntersectingViewport(options?: {threshold?: number}): Promise<boolean>; isIntersectingViewport(
this: ElementHandle<Element>,
options?: {
threshold?: number;
}
): Promise<boolean>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ----------------------- | ----------------- | | --------- | ------------------------------------------------------------ | ----------------- |
| options | { threshold?: number; } | <i>(Optional)</i> | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| options | { threshold?: number; } | <i>(Optional)</i> |
**Returns:** **Returns:**

View File

@ -9,14 +9,14 @@ ElementHandle represents an in-page DOM element.
**Signature:** **Signature:**
```typescript ```typescript
export declare class ElementHandle<ElementType extends Element = Element> extends JSHandle<ElementType> export declare class ElementHandle<ElementType extends Node = Element> extends JSHandle<ElementType>
``` ```
**Extends:** [JSHandle](./puppeteer.jshandle.md) **Extends:** [JSHandle](./puppeteer.jshandle.md)
## Remarks ## Remarks
ElementHandles can be created with the method. ElementHandles can be created with the [Page.$()](./puppeteer.page._.md) method.
```ts ```ts
const puppeteer = require('puppeteer'); const puppeteer = require('puppeteer');
@ -33,7 +33,7 @@ const puppeteer = require('puppeteer');
ElementHandle prevents the DOM element from being garbage-collected unless the handle is [disposed](./puppeteer.jshandle.dispose.md). ElementHandles are auto-disposed when their origin frame gets navigated. ElementHandle prevents the DOM element from being garbage-collected unless the handle is [disposed](./puppeteer.jshandle.dispose.md). ElementHandles are auto-disposed when their origin frame gets navigated.
ElementHandle instances can be used as arguments in and [Page.evaluate()](./puppeteer.page.evaluate.md) methods. ElementHandle instances can be used as arguments in [Page.$eval()](./puppeteer.page._eval.md) and [Page.evaluate()](./puppeteer.page.evaluate.md) methods.
If you're using TypeScript, ElementHandle takes a generic argument that denotes the type of element the handle is holding within. For example, if you have a handle to a `<select>` element, you can type it as `ElementHandle<HTMLSelectElement>` and you get some nicer type checks. If you're using TypeScript, ElementHandle takes a generic argument that denotes the type of element the handle is holding within. For example, if you have a handle to a `<select>` element, you can type it as `ElementHandle<HTMLSelectElement>` and you get some nicer type checks.
@ -41,40 +41,35 @@ The constructor for this class is marked as internal. Third-party code should no
## Methods ## Methods
| Method | Modifiers | Description | | Method | Modifiers | Description |
| -------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | -------------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$(selector)](./puppeteer.elementhandle._.md) | | Runs <code>element.querySelector</code> within the page. | | [$(selector)](./puppeteer.elementhandle._.md) | | Runs <code>element.querySelector</code> within the page. |
| [$(selector)](./puppeteer.elementhandle.__1.md) | | | | [$$(selector)](./puppeteer.elementhandle.__.md) | | Runs <code>element.querySelectorAll</code> within the page. |
| [$$(selector)](./puppeteer.elementhandle.__.md) | | Runs <code>element.querySelectorAll</code> within the page. | | [$$eval(selector, pageFunction, args)](./puppeteer.elementhandle.__eval.md) | | <p>This method runs <code>document.querySelectorAll</code> within the element and passes it as the first argument to <code>pageFunction</code>. If there's no element matching <code>selector</code>, the method throws an error.</p><p>If <code>pageFunction</code> returns a Promise, then <code>frame.$$eval</code> would wait for the promise to resolve and return its value.</p> |
| [$$(selector)](./puppeteer.elementhandle.___1.md) | | | | [$eval(selector, pageFunction, args)](./puppeteer.elementhandle._eval.md) | | <p>This method runs <code>document.querySelector</code> within the element and passes it as the first argument to <code>pageFunction</code>. If there's no element matching <code>selector</code>, the method throws an error.</p><p>If <code>pageFunction</code> returns a Promise, then <code>frame.$eval</code> would wait for the promise to resolve and return its value.</p> |
| [$$eval(selector, pageFunction, args)](./puppeteer.elementhandle.__eval.md) | | <p>This method runs <code>document.querySelectorAll</code> within the element and passes it as the first argument to <code>pageFunction</code>. If there's no element matching <code>selector</code>, the method throws an error.</p><p>If <code>pageFunction</code> returns a Promise, then <code>frame.$$eval</code> would wait for the promise to resolve and return its value.</p> | | [$x(expression)](./puppeteer.elementhandle._x.md) | | The method evaluates the XPath expression relative to the elementHandle. If there are no such elements, the method will resolve to an empty array. |
| [$$eval(selector, pageFunction, args)](./puppeteer.elementhandle.__eval_1.md) | | | | [asElement()](./puppeteer.elementhandle.aselement.md) | | |
| [$eval(selector, pageFunction, args)](./puppeteer.elementhandle._eval.md) | | <p>This method runs <code>document.querySelector</code> within the element and passes it as the first argument to <code>pageFunction</code>. If there's no element matching <code>selector</code>, the method throws an error.</p><p>If <code>pageFunction</code> returns a Promise, then <code>frame.$eval</code> would wait for the promise to resolve and return its value.</p> | | [boundingBox()](./puppeteer.elementhandle.boundingbox.md) | | This method returns the bounding box of the element (relative to the main frame), or <code>null</code> if the element is not visible. |
| [$eval(selector, pageFunction, args)](./puppeteer.elementhandle._eval_1.md) | | | | [boxModel()](./puppeteer.elementhandle.boxmodel.md) | | This method returns boxes of the element, or <code>null</code> if the element is not visible. |
| [$x(expression)](./puppeteer.elementhandle._x.md) | | The method evaluates the XPath expression relative to the elementHandle. If there are no such elements, the method will resolve to an empty array. | | [click(this, options)](./puppeteer.elementhandle.click.md) | | This method scrolls element into view if needed, and then uses [Page.mouse](./puppeteer.page.mouse.md) to click in the center of the element. If the element is detached from DOM, the method throws an error. |
| [asElement()](./puppeteer.elementhandle.aselement.md) | | | | [clickablePoint(offset)](./puppeteer.elementhandle.clickablepoint.md) | | Returns the middle point within an element unless a specific offset is provided. |
| [boundingBox()](./puppeteer.elementhandle.boundingbox.md) | | This method returns the bounding box of the element (relative to the main frame), or <code>null</code> if the element is not visible. | | [contentFrame()](./puppeteer.elementhandle.contentframe.md) | | Resolves to the content frame for element handles referencing iframe nodes, or null otherwise |
| [boxModel()](./puppeteer.elementhandle.boxmodel.md) | | This method returns boxes of the element, or <code>null</code> if the element is not visible. | | [drag(this, target)](./puppeteer.elementhandle.drag.md) | | This method creates and captures a dragevent from the element. |
| [click(options)](./puppeteer.elementhandle.click.md) | | This method scrolls element into view if needed, and then uses [Page.mouse](./puppeteer.page.mouse.md) to click in the center of the element. If the element is detached from DOM, the method throws an error. | | [dragAndDrop(this, target, options)](./puppeteer.elementhandle.draganddrop.md) | | This method triggers a dragenter, dragover, and drop on the element. |
| [clickablePoint(offset)](./puppeteer.elementhandle.clickablepoint.md) | | Returns the middle point within an element unless a specific offset is provided. | | [dragEnter(this, data)](./puppeteer.elementhandle.dragenter.md) | | This method creates a <code>dragenter</code> event on the element. |
| [contentFrame()](./puppeteer.elementhandle.contentframe.md) | | Resolves to the content frame for element handles referencing iframe nodes, or null otherwise | | [dragOver(this, data)](./puppeteer.elementhandle.dragover.md) | | This method creates a <code>dragover</code> event on the element. |
| [drag(target)](./puppeteer.elementhandle.drag.md) | | This method creates and captures a dragevent from the element. | | [drop(this, data)](./puppeteer.elementhandle.drop.md) | | This method triggers a drop on the element. |
| [dragAndDrop(target, options)](./puppeteer.elementhandle.draganddrop.md) | | This method triggers a dragenter, dragover, and drop on the element. | | [focus()](./puppeteer.elementhandle.focus.md) | | Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element. |
| [dragEnter(data)](./puppeteer.elementhandle.dragenter.md) | | This method creates a <code>dragenter</code> event on the element. | | [hover(this)](./puppeteer.elementhandle.hover.md) | | This method scrolls element into view if needed, and then uses [Page.mouse](./puppeteer.page.mouse.md) to hover over the center of the element. If the element is detached from DOM, the method throws an error. |
| [dragOver(data)](./puppeteer.elementhandle.dragover.md) | | This method creates a <code>dragover</code> event on the element. | | [isIntersectingViewport(this, options)](./puppeteer.elementhandle.isintersectingviewport.md) | | Resolves to true if the element is visible in the current viewport. |
| [drop(data)](./puppeteer.elementhandle.drop.md) | | This method triggers a drop on the element. | | [press(key, options)](./puppeteer.elementhandle.press.md) | | Focuses the element, and then uses [Keyboard.down()](./puppeteer.keyboard.down.md) and [Keyboard.up()](./puppeteer.keyboard.up.md). |
| [focus()](./puppeteer.elementhandle.focus.md) | | Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element. | | [screenshot(this, options)](./puppeteer.elementhandle.screenshot.md) | | This method scrolls element into view if needed, and then uses [Page.screenshot()](./puppeteer.page.screenshot.md) to take a screenshot of the element. If the element is detached from DOM, the method throws an error. |
| [hover()](./puppeteer.elementhandle.hover.md) | | This method scrolls element into view if needed, and then uses [Page.mouse](./puppeteer.page.mouse.md) to hover over the center of the element. If the element is detached from DOM, the method throws an error. | | [select(values)](./puppeteer.elementhandle.select.md) | | Triggers a <code>change</code> and <code>input</code> event once all the provided options have been selected. If there's no <code>&lt;select&gt;</code> element matching <code>selector</code>, the method throws an error. |
| [isIntersectingViewport(options)](./puppeteer.elementhandle.isintersectingviewport.md) | | Resolves to true if the element is visible in the current viewport. | | [tap(this)](./puppeteer.elementhandle.tap.md) | | This method scrolls element into view if needed, and then uses [Touchscreen.tap()](./puppeteer.touchscreen.tap.md) to tap in the center of the element. If the element is detached from DOM, the method throws an error. |
| [press(key, options)](./puppeteer.elementhandle.press.md) | | Focuses the element, and then uses [Keyboard.down()](./puppeteer.keyboard.down.md) and [Keyboard.up()](./puppeteer.keyboard.up.md). | | [type(text, options)](./puppeteer.elementhandle.type.md) | | <p>Focuses the element, and then sends a <code>keydown</code>, <code>keypress</code>/<code>input</code>, and <code>keyup</code> event for each character in the text.</p><p>To press a special key, like <code>Control</code> or <code>ArrowDown</code>, use [ElementHandle.press()](./puppeteer.elementhandle.press.md).</p> |
| [screenshot(options)](./puppeteer.elementhandle.screenshot.md) | | This method scrolls element into view if needed, and then uses [Page.screenshot()](./puppeteer.page.screenshot.md) to take a screenshot of the element. If the element is detached from DOM, the method throws an error. | | [uploadFile(this, filePaths)](./puppeteer.elementhandle.uploadfile.md) | | This method expects <code>elementHandle</code> to point to an [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). |
| [select(values)](./puppeteer.elementhandle.select.md) | | Triggers a <code>change</code> and <code>input</code> event once all the provided options have been selected. If there's no <code>&lt;select&gt;</code> element matching <code>selector</code>, the method throws an error. | | [waitForSelector(selector, options)](./puppeteer.elementhandle.waitforselector.md) | | <p>Wait for the <code>selector</code> to appear within the element. If at the moment of calling the method the <code>selector</code> already exists, the method will return immediately. If the <code>selector</code> doesn't appear after the <code>timeout</code> milliseconds of waiting, the function will throw.</p><p>This method does not work across navigations or if the element is detached from DOM.</p> |
| [tap()](./puppeteer.elementhandle.tap.md) | | This method scrolls element into view if needed, and then uses [Touchscreen.tap()](./puppeteer.touchscreen.tap.md) to tap in the center of the element. If the element is detached from DOM, the method throws an error. | | [waitForXPath(xpath, options)](./puppeteer.elementhandle.waitforxpath.md) | | <p>Wait for the <code>xpath</code> within the element. If at the moment of calling the method the <code>xpath</code> already exists, the method will return immediately. If the <code>xpath</code> doesn't appear after the <code>timeout</code> milliseconds of waiting, the function will throw.</p><p>If <code>xpath</code> starts with <code>//</code> instead of <code>.//</code>, the dot will be appended automatically.</p><p>This method works across navigation</p> |
| [type(text, options)](./puppeteer.elementhandle.type.md) | | <p>Focuses the element, and then sends a <code>keydown</code>, <code>keypress</code>/<code>input</code>, and <code>keyup</code> event for each character in the text.</p><p>To press a special key, like <code>Control</code> or <code>ArrowDown</code>, use [ElementHandle.press()](./puppeteer.elementhandle.press.md).</p> |
| [uploadFile(this, filePaths)](./puppeteer.elementhandle.uploadfile.md) | | This method expects <code>elementHandle</code> to point to an [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). |
| [waitForSelector(selector, options)](./puppeteer.elementhandle.waitforselector.md) | | <p>Wait for the <code>selector</code> to appear within the element. If at the moment of calling the method the <code>selector</code> already exists, the method will return immediately. If the <code>selector</code> doesn't appear after the <code>timeout</code> milliseconds of waiting, the function will throw.</p><p>This method does not work across navigations or if the element is detached from DOM.</p> |
| [waitForSelector(selector, options)](./puppeteer.elementhandle.waitforselector_1.md) | | |
| [waitForXPath(xpath, options)](./puppeteer.elementhandle.waitforxpath.md) | | <p>Wait for the <code>xpath</code> within the element. If at the moment of calling the method the <code>xpath</code> already exists, the method will return immediately. If the <code>xpath</code> doesn't appear after the <code>timeout</code> milliseconds of waiting, the function will throw.</p><p>If <code>xpath</code> starts with <code>//</code> instead of <code>.//</code>, the dot will be appended automatically.</p><p>This method works across navigation</p> |
```ts ```ts
const puppeteer = require('puppeteer'); const puppeteer = require('puppeteer');

View File

@ -10,15 +10,19 @@ This method scrolls element into view if needed, and then uses [Page.screenshot(
```typescript ```typescript
class ElementHandle { class ElementHandle {
screenshot(options?: ScreenshotOptions): Promise<string | Buffer>; screenshot(
this: ElementHandle<Element>,
options?: ScreenshotOptions
): Promise<string | Buffer>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| --------- | ----------------------------------------------------- | ----------------- | | --------- | ------------------------------------------------------------ | ----------------- |
| options | [ScreenshotOptions](./puppeteer.screenshotoptions.md) | <i>(Optional)</i> | | this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
| options | [ScreenshotOptions](./puppeteer.screenshotoptions.md) | <i>(Optional)</i> |
**Returns:** **Returns:**

View File

@ -10,10 +10,16 @@ This method scrolls element into view if needed, and then uses [Touchscreen.tap(
```typescript ```typescript
class ElementHandle { class ElementHandle {
tap(): Promise<void>; tap(this: ElementHandle<Element>): Promise<void>;
} }
``` ```
## Parameters
| Parameter | Type | Description |
| --------- | ------------------------------------------------------------ | ----------- |
| this | [ElementHandle](./puppeteer.elementhandle.md)&lt;Element&gt; | |
**Returns:** **Returns:**
Promise&lt;void&gt; Promise&lt;void&gt;

View File

@ -12,10 +12,10 @@ This method does not work across navigations or if the element is detached from
```typescript ```typescript
class ElementHandle { class ElementHandle {
waitForSelector<Selector extends keyof HTMLElementTagNameMap>( waitForSelector<Selector extends string>(
selector: Selector, selector: Selector,
options?: Exclude<WaitForSelectorOptions, 'root'> options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null>;
} }
``` ```
@ -28,7 +28,7 @@ class ElementHandle {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt; \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt; \| null&gt;
Promise which resolves when element specified by selector string is added to DOM. Resolves to `null` if waiting for hidden: `true` and selector is not found in DOM. Promise which resolves when element specified by selector string is added to DOM. Resolves to `null` if waiting for hidden: `true` and selector is not found in DOM.

View File

@ -1,27 +0,0 @@
---
sidebar_label: ElementHandle.waitForSelector_1
---
# ElementHandle.waitForSelector() method
**Signature:**
```typescript
class ElementHandle {
waitForSelector(
selector: string,
options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle | null>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | -------------------------------------------------------------------------------------- | ----------------- |
| selector | string | |
| options | Exclude&lt;[WaitForSelectorOptions](./puppeteer.waitforselectoroptions.md), 'root'&gt; | <i>(Optional)</i> |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt;

View File

@ -41,7 +41,7 @@ class ElementHandle {
hidden?: boolean; hidden?: boolean;
timeout?: number; timeout?: number;
} }
): Promise<ElementHandle | null>; ): Promise<ElementHandle<Node> | null>;
} }
``` ```
@ -54,7 +54,7 @@ class ElementHandle {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt; \| null&gt;
Promise which resolves when element specified by xpath string is added to DOM. Resolves to `null` if waiting for `hidden: true` and xpath is not found in DOM. Promise which resolves when element specified by xpath string is added to DOM. Resolves to `null` if waiting for `hidden: true` and xpath is not found in DOM.

View File

@ -10,9 +10,9 @@ This method queries the frame for the given selector.
```typescript ```typescript
class Frame { class Frame {
$<Selector extends keyof HTMLElementTagNameMap>( $<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null>;
} }
``` ```
@ -24,6 +24,6 @@ class Frame {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt; \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt; \| null&gt;
A promise which resolves to an `ElementHandle` pointing at the element, or `null` if it was not found. A promise which resolves to an `ElementHandle` pointing at the element, or `null` if it was not found.

View File

@ -10,9 +10,9 @@ This runs `document.querySelectorAll` in the frame and returns the result.
```typescript ```typescript
class Frame { class Frame {
$$<Selector extends keyof HTMLElementTagNameMap>( $$<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]>[]>; ): Promise<Array<ElementHandle<NodeFor<Selector>>>>;
} }
``` ```
@ -24,6 +24,6 @@ class Frame {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt;\[\]&gt; Promise&lt;Array&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt;&gt;&gt;
An array of element handles pointing to the found frame elements. An array of element handles pointing to the found frame elements.

View File

@ -1,23 +0,0 @@
---
sidebar_label: Frame.$_1
---
# Frame.$() method
**Signature:**
```typescript
class Frame {
$(selector: string): Promise<ElementHandle | null>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| selector | string | |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt;

View File

@ -1,23 +0,0 @@
---
sidebar_label: Frame.$$_1
---
# Frame.$$() method
**Signature:**
```typescript
class Frame {
$$(selector: string): Promise<ElementHandle[]>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| selector | string | |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)\[\]&gt;

View File

@ -9,11 +9,11 @@ sidebar_label: Frame.$$eval
```typescript ```typescript
class Frame { class Frame {
$$eval< $$eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector][], ...Params] [Array<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector][], ...Params]> > = EvaluateFunc<[Array<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,

View File

@ -1,34 +0,0 @@
---
sidebar_label: Frame.$$eval_1
---
# Frame.$$eval() method
**Signature:**
```typescript
class Frame {
$$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
}
```
## Parameters
| Parameter | Type | Description |
| ------------ | -------------- | ----------- |
| selector | string | |
| pageFunction | Func \| string | |
| args | Params | |
**Returns:**
Promise&lt;Awaited&lt;ReturnType&lt;Func&gt;&gt;&gt;

View File

@ -9,11 +9,11 @@ sidebar_label: Frame.$eval
```typescript ```typescript
class Frame { class Frame {
$eval< $eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector], ...Params] [ElementHandle<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector], ...Params]> > = EvaluateFunc<[ElementHandle<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,

View File

@ -1,34 +0,0 @@
---
sidebar_label: Frame.$eval_1
---
# Frame.$eval() method
**Signature:**
```typescript
class Frame {
$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
}
```
## Parameters
| Parameter | Type | Description |
| ------------ | -------------- | ----------- |
| selector | string | |
| pageFunction | Func \| string | |
| args | Params | |
**Returns:**
Promise&lt;Awaited&lt;ReturnType&lt;Func&gt;&gt;&gt;

View File

@ -10,7 +10,7 @@ This method evaluates the given XPath expression and returns the results.
```typescript ```typescript
class Frame { class Frame {
$x(expression: string): Promise<ElementHandle[]>; $x(expression: string): Promise<Array<ElementHandle<Node>>>;
} }
``` ```
@ -22,4 +22,4 @@ class Frame {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)\[\]&gt; Promise&lt;Array&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt;&gt;&gt;

View File

@ -10,7 +10,9 @@ Adds a `<script>` tag into the page with the desired url or content.
```typescript ```typescript
class Frame { class Frame {
addScriptTag(options: FrameAddScriptTagOptions): Promise<ElementHandle>; addScriptTag(
options: FrameAddScriptTagOptions
): Promise<ElementHandle<HTMLScriptElement>>;
} }
``` ```
@ -22,6 +24,6 @@ class Frame {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLScriptElement&gt;&gt;
a promise that resolves to the added tag when the script's `onload` event fires or when the script content was injected into the frame. a promise that resolves to the added tag when the script's `onload` event fires or when the script content was injected into the frame.

View File

@ -10,7 +10,7 @@ Adds a `<link rel="stylesheet">` tag into the page with the desired url or a `<s
```typescript ```typescript
class Frame { class Frame {
addStyleTag(options: FrameAddStyleTagOptions): Promise<ElementHandle>; addStyleTag(options: FrameAddStyleTagOptions): Promise<ElementHandle<Node>>;
} }
``` ```
@ -22,6 +22,6 @@ class Frame {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt;&gt;
a promise that resolves to the added tag when the stylesheets's `onload` event fires or when the CSS content was injected into the frame. a promise that resolves to the added tag when the stylesheets's `onload` event fires or when the CSS content was injected into the frame.

View File

@ -62,13 +62,9 @@ console.log(text);
| Method | Modifiers | Description | | Method | Modifiers | Description |
| ------------------------------------------------------------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$(selector)](./puppeteer.frame._.md) | | This method queries the frame for the given selector. | | [$(selector)](./puppeteer.frame._.md) | | This method queries the frame for the given selector. |
| [$(selector)](./puppeteer.frame.__1.md) | | |
| [$$(selector)](./puppeteer.frame.__.md) | | This runs <code>document.querySelectorAll</code> in the frame and returns the result. | | [$$(selector)](./puppeteer.frame.__.md) | | This runs <code>document.querySelectorAll</code> in the frame and returns the result. |
| [$$(selector)](./puppeteer.frame.___1.md) | | |
| [$$eval(selector, pageFunction, args)](./puppeteer.frame.__eval.md) | | | | [$$eval(selector, pageFunction, args)](./puppeteer.frame.__eval.md) | | |
| [$$eval(selector, pageFunction, args)](./puppeteer.frame.__eval_1.md) | | |
| [$eval(selector, pageFunction, args)](./puppeteer.frame._eval.md) | | | | [$eval(selector, pageFunction, args)](./puppeteer.frame._eval.md) | | |
| [$eval(selector, pageFunction, args)](./puppeteer.frame._eval_1.md) | | |
| [$x(expression)](./puppeteer.frame._x.md) | | This method evaluates the given XPath expression and returns the results. | | [$x(expression)](./puppeteer.frame._x.md) | | This method evaluates the given XPath expression and returns the results. |
| [addScriptTag(options)](./puppeteer.frame.addscripttag.md) | | Adds a <code>&lt;script&gt;</code> tag into the page with the desired url or content. | | [addScriptTag(options)](./puppeteer.frame.addscripttag.md) | | Adds a <code>&lt;script&gt;</code> tag into the page with the desired url or content. |
| [addStyleTag(options)](./puppeteer.frame.addstyletag.md) | | Adds a <code>&lt;link rel=&quot;stylesheet&quot;&gt;</code> tag into the page with the desired url or a <code>&lt;style type=&quot;text/css&quot;&gt;</code> tag with the content. | | [addStyleTag(options)](./puppeteer.frame.addstyletag.md) | | Adds a <code>&lt;link rel=&quot;stylesheet&quot;&gt;</code> tag into the page with the desired url or a <code>&lt;style type=&quot;text/css&quot;&gt;</code> tag with the content. |
@ -94,6 +90,5 @@ console.log(text);
| [waitForFunction(pageFunction, options, args)](./puppeteer.frame.waitforfunction.md) | | | | [waitForFunction(pageFunction, options, args)](./puppeteer.frame.waitforfunction.md) | | |
| [waitForNavigation(options)](./puppeteer.frame.waitfornavigation.md) | | | | [waitForNavigation(options)](./puppeteer.frame.waitfornavigation.md) | | |
| [waitForSelector(selector, options)](./puppeteer.frame.waitforselector.md) | | | | [waitForSelector(selector, options)](./puppeteer.frame.waitforselector.md) | | |
| [waitForSelector(selector, options)](./puppeteer.frame.waitforselector_1.md) | | |
| [waitForTimeout(milliseconds)](./puppeteer.frame.waitfortimeout.md) | | Causes your script to wait for the given number of milliseconds. | | [waitForTimeout(milliseconds)](./puppeteer.frame.waitfortimeout.md) | | Causes your script to wait for the given number of milliseconds. |
| [waitForXPath(xpath, options)](./puppeteer.frame.waitforxpath.md) | | | | [waitForXPath(xpath, options)](./puppeteer.frame.waitforxpath.md) | | |

View File

@ -8,10 +8,10 @@ sidebar_label: Frame.waitForSelector
```typescript ```typescript
class Frame { class Frame {
waitForSelector<Selector extends keyof HTMLElementTagNameMap>( waitForSelector<Selector extends string>(
selector: Selector, selector: Selector,
options?: WaitForSelectorOptions options?: WaitForSelectorOptions
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null>;
} }
``` ```
@ -24,7 +24,7 @@ class Frame {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt; \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt; \| null&gt;
a promise which resolves when an element matching the selector string is added to the DOM. a promise which resolves when an element matching the selector string is added to the DOM.

View File

@ -1,27 +0,0 @@
---
sidebar_label: Frame.waitForSelector_1
---
# Frame.waitForSelector() method
**Signature:**
```typescript
class Frame {
waitForSelector(
selector: string,
options?: WaitForSelectorOptions
): Promise<ElementHandle | null>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | --------------------------------------------------------------- | ----------------- |
| selector | string | |
| options | [WaitForSelectorOptions](./puppeteer.waitforselectoroptions.md) | <i>(Optional)</i> |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt;

View File

@ -26,7 +26,7 @@ Promise&lt;void&gt;
## Remarks ## Remarks
It's generally recommended to not wait for a number of seconds, but instead use , [Frame.waitForXPath()](./puppeteer.frame.waitforxpath.md) or [Frame.waitForFunction()](./puppeteer.frame.waitforfunction.md) to wait for exactly the conditions you want. It's generally recommended to not wait for a number of seconds, but instead use [Frame.waitForSelector()](./puppeteer.frame.waitforselector.md), [Frame.waitForXPath()](./puppeteer.frame.waitforxpath.md) or [Frame.waitForFunction()](./puppeteer.frame.waitforfunction.md) to wait for exactly the conditions you want.
## Example ## Example

View File

@ -11,7 +11,7 @@ class Frame {
waitForXPath( waitForXPath(
xpath: string, xpath: string,
options?: WaitForSelectorOptions options?: WaitForSelectorOptions
): Promise<ElementHandle | null>; ): Promise<ElementHandle<Node> | null>;
} }
``` ```
@ -24,10 +24,10 @@ class Frame {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt; \| null&gt;
## Remarks ## Remarks
Wait for the `xpath` to appear in page. If at the moment of calling the method the `xpath` already exists, the method will return immediately. If the xpath doesn't appear after the `timeout` milliseconds of waiting, the function will throw. Wait for the `xpath` to appear in page. If at the moment of calling the method the `xpath` already exists, the method will return immediately. If the xpath doesn't appear after the `timeout` milliseconds of waiting, the function will throw.
For a code example, see the example for . That function behaves identically other than taking a CSS selector rather than an XPath. For a code example, see the example for [Frame.waitForSelector()](./puppeteer.frame.waitforselector.md). That function behaves identically other than taking a CSS selector rather than an XPath.

View File

@ -7,7 +7,7 @@ sidebar_label: HandleFor
**Signature:** **Signature:**
```typescript ```typescript
export declare type HandleFor<T> = T extends Element export declare type HandleFor<T> = T extends Node
? ElementHandle<T> ? ElementHandle<T>
: JSHandle<T>; : JSHandle<T>;
``` ```

View File

@ -0,0 +1,15 @@
---
sidebar_label: JSHandle.[__JSHandleSymbol]
---
# JSHandle.\[\_\_JSHandleSymbol\] property
Used for nominally typing [JSHandle](./puppeteer.jshandle.md).
**Signature:**
```typescript
class JSHandle {
[__JSHandleSymbol]?: T;
}
```

View File

@ -8,12 +8,12 @@ sidebar_label: JSHandle.asElement
```typescript ```typescript
class JSHandle { class JSHandle {
asElement(): ElementHandle | null; asElement(): ElementHandle<Node> | null;
} }
``` ```
**Returns:** **Returns:**
[ElementHandle](./puppeteer.elementhandle.md) \| null [ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt; \| null
Either `null` or the object handle itself, if the object handle is an instance of [ElementHandle](./puppeteer.elementhandle.md). Either `null` or the object handle itself, if the object handle is an instance of [ElementHandle](./puppeteer.elementhandle.md).

View File

@ -24,7 +24,13 @@ const windowHandle = await page.evaluateHandle(() => window);
JSHandle prevents the referenced JavaScript object from being garbage-collected unless the handle is [disposed](./puppeteer.jshandle.dispose.md). JSHandles are auto- disposed when their origin frame gets navigated or the parent context gets destroyed. JSHandle prevents the referenced JavaScript object from being garbage-collected unless the handle is [disposed](./puppeteer.jshandle.dispose.md). JSHandles are auto- disposed when their origin frame gets navigated or the parent context gets destroyed.
JSHandle instances can be used as arguments for , [Page.evaluate()](./puppeteer.page.evaluate.md), and [Page.evaluateHandle()](./puppeteer.page.evaluatehandle.md). JSHandle instances can be used as arguments for [Page.$eval()](./puppeteer.page._eval.md), [Page.evaluate()](./puppeteer.page.evaluate.md), and [Page.evaluateHandle()](./puppeteer.page.evaluatehandle.md).
## Properties
| Property | Modifiers | Type | Description |
| --------------------------------------------------------------------- | --------- | ---- | -------------------------------------------------------------------------------- |
| [\[\_\_JSHandleSymbol\]?](./puppeteer.jshandle.___jshandlesymbol_.md) | | T | <i>(Optional)</i> Used for nominally typing [JSHandle](./puppeteer.jshandle.md). |
## Methods ## Methods

View File

@ -0,0 +1,16 @@
---
sidebar_label: NodeFor
---
# NodeFor type
**Signature:**
```typescript
export declare type NodeFor<Selector extends string> =
Selector extends keyof HTMLElementTagNameMap
? HTMLElementTagNameMap[Selector]
: Selector extends keyof SVGElementTagNameMap
? SVGElementTagNameMap[Selector]
: Element;
```

View File

@ -10,9 +10,9 @@ Runs `document.querySelector` within the page. If no element matches the selecto
```typescript ```typescript
class Page { class Page {
$<Selector extends keyof HTMLElementTagNameMap>( $<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null>;
} }
``` ```
@ -24,4 +24,4 @@ class Page {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt; \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt; \| null&gt;

View File

@ -10,9 +10,9 @@ The method runs `document.querySelectorAll` within the page. If no elements matc
```typescript ```typescript
class Page { class Page {
$$<Selector extends keyof HTMLElementTagNameMap>( $$<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]>[]>; ): Promise<Array<ElementHandle<NodeFor<Selector>>>>;
} }
``` ```
@ -24,8 +24,8 @@ class Page {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt;\[\]&gt; Promise&lt;Array&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt;&gt;&gt;
## Remarks ## Remarks
Shortcut for . Shortcut for [Page.mainFrame().$$(selector)](./puppeteer.frame.__.md).

View File

@ -1,23 +0,0 @@
---
sidebar_label: Page.$_1
---
# Page.$() method
**Signature:**
```typescript
class Page {
$(selector: string): Promise<ElementHandle | null>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| selector | string | |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt;

View File

@ -1,23 +0,0 @@
---
sidebar_label: Page.$$_1
---
# Page.$$() method
**Signature:**
```typescript
class Page {
$$(selector: string): Promise<ElementHandle[]>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| selector | string | |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)\[\]&gt;

View File

@ -11,11 +11,11 @@ This method runs `Array.from(document.querySelectorAll(selector))` within the pa
```typescript ```typescript
class Page { class Page {
$$eval< $$eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector][], ...Params] [Array<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector][], ...Params]> > = EvaluateFunc<[Array<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,

View File

@ -1,34 +0,0 @@
---
sidebar_label: Page.$$eval_1
---
# Page.$$eval() method
**Signature:**
```typescript
class Page {
$$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
}
```
## Parameters
| Parameter | Type | Description |
| ------------ | -------------- | ----------- |
| selector | string | |
| pageFunction | Func \| string | |
| args | Params | |
**Returns:**
Promise&lt;Awaited&lt;ReturnType&lt;Func&gt;&gt;&gt;

View File

@ -11,11 +11,11 @@ This method runs `document.querySelector` within the page and passes the result
```typescript ```typescript
class Page { class Page {
$eval< $eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector], ...Params] [ElementHandle<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector], ...Params]> > = EvaluateFunc<[ElementHandle<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,

View File

@ -1,34 +0,0 @@
---
sidebar_label: Page.$eval_1
---
# Page.$eval() method
**Signature:**
```typescript
class Page {
$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
}
```
## Parameters
| Parameter | Type | Description |
| ------------ | -------------- | ----------- |
| selector | string | |
| pageFunction | Func \| string | |
| args | Params | |
**Returns:**
Promise&lt;Awaited&lt;ReturnType&lt;Func&gt;&gt;&gt;

View File

@ -10,7 +10,7 @@ The method evaluates the XPath expression relative to the page document as its c
```typescript ```typescript
class Page { class Page {
$x(expression: string): Promise<ElementHandle[]>; $x(expression: string): Promise<Array<ElementHandle<Node>>>;
} }
``` ```
@ -22,7 +22,7 @@ class Page {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)\[\]&gt; Promise&lt;Array&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt;&gt;&gt;
## Remarks ## Remarks

View File

@ -16,7 +16,7 @@ class Page {
content?: string; content?: string;
type?: string; type?: string;
id?: string; id?: string;
}): Promise<ElementHandle>; }): Promise<ElementHandle<HTMLScriptElement>>;
} }
``` ```
@ -28,7 +28,7 @@ class Page {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLScriptElement&gt;&gt;
Promise which resolves to the added tag when the script's onload fires or when the script content was injected into frame. Promise which resolves to the added tag when the script's onload fires or when the script content was injected into frame.

View File

@ -14,7 +14,7 @@ class Page {
url?: string; url?: string;
path?: string; path?: string;
content?: string; content?: string;
}): Promise<ElementHandle>; }): Promise<ElementHandle<Node>>;
} }
``` ```
@ -26,6 +26,6 @@ class Page {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt;&gt;
Promise which resolves to the added tag when the stylesheet's onload fires or when the CSS content was injected into frame. Promise which resolves to the added tag when the stylesheet's onload fires or when the CSS content was injected into frame.

View File

@ -77,13 +77,9 @@ page.off('request', logRequest);
| Method | Modifiers | Description | | Method | Modifiers | Description |
| ------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [$(selector)](./puppeteer.page._.md) | | Runs <code>document.querySelector</code> within the page. If no element matches the selector, the return value resolves to <code>null</code>. | | [$(selector)](./puppeteer.page._.md) | | Runs <code>document.querySelector</code> within the page. If no element matches the selector, the return value resolves to <code>null</code>. |
| [$(selector)](./puppeteer.page.__1.md) | | |
| [$$(selector)](./puppeteer.page.__.md) | | The method runs <code>document.querySelectorAll</code> within the page. If no elements match the selector, the return value resolves to <code>[]</code>. | | [$$(selector)](./puppeteer.page.__.md) | | The method runs <code>document.querySelectorAll</code> within the page. If no elements match the selector, the return value resolves to <code>[]</code>. |
| [$$(selector)](./puppeteer.page.___1.md) | | |
| [$$eval(selector, pageFunction, args)](./puppeteer.page.__eval.md) | | This method runs <code>Array.from(document.querySelectorAll(selector))</code> within the page and passes the result as the first argument to the <code>pageFunction</code>. | | [$$eval(selector, pageFunction, args)](./puppeteer.page.__eval.md) | | This method runs <code>Array.from(document.querySelectorAll(selector))</code> within the page and passes the result as the first argument to the <code>pageFunction</code>. |
| [$$eval(selector, pageFunction, args)](./puppeteer.page.__eval_1.md) | | |
| [$eval(selector, pageFunction, args)](./puppeteer.page._eval.md) | | This method runs <code>document.querySelector</code> within the page and passes the result as the first argument to the <code>pageFunction</code>. | | [$eval(selector, pageFunction, args)](./puppeteer.page._eval.md) | | This method runs <code>document.querySelector</code> within the page and passes the result as the first argument to the <code>pageFunction</code>. |
| [$eval(selector, pageFunction, args)](./puppeteer.page._eval_1.md) | | |
| [$x(expression)](./puppeteer.page._x.md) | | The method evaluates the XPath expression relative to the page document as its context node. If there are no such elements, the method resolves to an empty array. | | [$x(expression)](./puppeteer.page._x.md) | | The method evaluates the XPath expression relative to the page document as its context node. If there are no such elements, the method resolves to an empty array. |
| [addScriptTag(options)](./puppeteer.page.addscripttag.md) | | Adds a <code>&lt;script&gt;</code> tag into the page with the desired URL or content. | | [addScriptTag(options)](./puppeteer.page.addscripttag.md) | | Adds a <code>&lt;script&gt;</code> tag into the page with the desired URL or content. |
| [addStyleTag(options)](./puppeteer.page.addstyletag.md) | | Adds a <code>&lt;link rel=&quot;stylesheet&quot;&gt;</code> tag into the page with the desired URL or a <code>&lt;style type=&quot;text/css&quot;&gt;</code> tag with the content. | | [addStyleTag(options)](./puppeteer.page.addstyletag.md) | | Adds a <code>&lt;link rel=&quot;stylesheet&quot;&gt;</code> tag into the page with the desired URL or a <code>&lt;style type=&quot;text/css&quot;&gt;</code> tag with the content. |
@ -178,7 +174,6 @@ const puppeteer = require('puppeteer');
``` ```
| |
| [waitForSelector(selector, options)](./puppeteer.page.waitforselector_1.md) | | |
| [waitForTimeout(milliseconds)](./puppeteer.page.waitfortimeout.md) | | Causes your script to wait for the given number of milliseconds. | | [waitForTimeout(milliseconds)](./puppeteer.page.waitfortimeout.md) | | Causes your script to wait for the given number of milliseconds. |
| [waitForXPath(xpath, options)](./puppeteer.page.waitforxpath.md) | | <p>Wait for the <code>xpath</code> to appear in page. If at the moment of calling the method the <code>xpath</code> already exists, the method will return immediately. If the <code>xpath</code> doesn't appear after the <code>timeout</code> milliseconds of waiting, the function will throw.</p><p>This method works across navigation</p> | [waitForXPath(xpath, options)](./puppeteer.page.waitforxpath.md) | | <p>Wait for the <code>xpath</code> to appear in page. If at the moment of calling the method the <code>xpath</code> already exists, the method will return immediately. If the <code>xpath</code> doesn't appear after the <code>timeout</code> milliseconds of waiting, the function will throw.</p><p>This method works across navigation</p>

View File

@ -32,10 +32,10 @@ const puppeteer = require('puppeteer');
```typescript ```typescript
class Page { class Page {
waitForSelector<Selector extends keyof HTMLElementTagNameMap>( waitForSelector<Selector extends string>(
selector: Selector, selector: Selector,
options?: Exclude<WaitForSelectorOptions, 'root'> options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null>;
} }
``` ```
@ -48,7 +48,7 @@ class Page {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLElementTagNameMap\[Selector\]&gt; \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;[NodeFor](./puppeteer.nodefor.md)&lt;Selector&gt;&gt; \| null&gt;
Promise which resolves when element specified by selector string is added to DOM. Resolves to `null` if waiting for hidden: `true` and selector is not found in DOM. Promise which resolves when element specified by selector string is added to DOM. Resolves to `null` if waiting for hidden: `true` and selector is not found in DOM.

View File

@ -1,27 +0,0 @@
---
sidebar_label: Page.waitForSelector_1
---
# Page.waitForSelector() method
**Signature:**
```typescript
class Page {
waitForSelector(
selector: string,
options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle | null>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | -------------------------------------------------------------------------------------- | ----------------- |
| selector | string | |
| options | Exclude&lt;[WaitForSelectorOptions](./puppeteer.waitforselectoroptions.md), 'root'&gt; | <i>(Optional)</i> |
**Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt;

View File

@ -26,7 +26,7 @@ Promise&lt;void&gt;
## Remarks ## Remarks
It's generally recommended to not wait for a number of seconds, but instead use , [Page.waitForXPath()](./puppeteer.page.waitforxpath.md) or [Page.waitForFunction()](./puppeteer.page.waitforfunction.md) to wait for exactly the conditions you want. It's generally recommended to not wait for a number of seconds, but instead use [Page.waitForSelector()](./puppeteer.page.waitforselector.md), [Page.waitForXPath()](./puppeteer.page.waitforxpath.md) or [Page.waitForFunction()](./puppeteer.page.waitforfunction.md) to wait for exactly the conditions you want.
## Example ## Example

View File

@ -39,7 +39,7 @@ class Page {
hidden?: boolean; hidden?: boolean;
timeout?: number; timeout?: number;
} }
): Promise<ElementHandle | null>; ): Promise<ElementHandle<Node> | null>;
} }
``` ```
@ -52,7 +52,7 @@ class Page {
**Returns:** **Returns:**
Promise&lt;[ElementHandle](./puppeteer.elementhandle.md) \| null&gt; Promise&lt;[ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt; \| null&gt;
Promise which resolves when element specified by xpath string is added to DOM. Resolves to `null` if waiting for `hidden: true` and xpath is not found in DOM. Promise which resolves when element specified by xpath string is added to DOM. Resolves to `null` if waiting for `hidden: true` and xpath is not found in DOM.

View File

@ -12,7 +12,7 @@ export interface SnapshotOptions
## Properties ## Properties
| Property | Modifiers | Type | Description | | Property | Modifiers | Type | Description |
| ------------------------------------------------------------------ | --------- | --------------------------------------------- | ------------------------------------------------------------- | | ------------------------------------------------------------------ | --------- | --------------------------------------------------------- | ------------------------------------------------------------- |
| [interestingOnly?](./puppeteer.snapshotoptions.interestingonly.md) | | boolean | <i>(Optional)</i> Prune uninteresting nodes from the tree. | | [interestingOnly?](./puppeteer.snapshotoptions.interestingonly.md) | | boolean | <i>(Optional)</i> Prune uninteresting nodes from the tree. |
| [root?](./puppeteer.snapshotoptions.root.md) | | [ElementHandle](./puppeteer.elementhandle.md) | <i>(Optional)</i> Root node to get the accessibility tree for | | [root?](./puppeteer.snapshotoptions.root.md) | | [ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt; | <i>(Optional)</i> Root node to get the accessibility tree for |

View File

@ -10,6 +10,6 @@ Root node to get the accessibility tree for
```typescript ```typescript
interface SnapshotOptions { interface SnapshotOptions {
root?: ElementHandle; root?: ElementHandle<Node>;
} }
``` ```

View File

@ -16,4 +16,4 @@ export declare class TimeoutError extends CustomError
## Remarks ## Remarks
Example operations are or [puppeteer.launch](./puppeteer.puppeteernode.launch.md). Example operations are [page.waitForSelector](./puppeteer.page.waitforselector.md) or [puppeteer.launch](./puppeteer.puppeteernode.launch.md).

View File

@ -12,9 +12,9 @@ export interface WaitForSelectorOptions
## Properties ## Properties
| Property | Modifiers | Type | Description | | Property | Modifiers | Type | Description |
| --------------------------------------------------------- | --------- | --------------------------------------------- | ----------------- | | --------------------------------------------------------- | --------- | --------------------------------------------------------- | ----------------- |
| [hidden?](./puppeteer.waitforselectoroptions.hidden.md) | | boolean | <i>(Optional)</i> | | [hidden?](./puppeteer.waitforselectoroptions.hidden.md) | | boolean | <i>(Optional)</i> |
| [root?](./puppeteer.waitforselectoroptions.root.md) | | [ElementHandle](./puppeteer.elementhandle.md) | <i>(Optional)</i> | | [root?](./puppeteer.waitforselectoroptions.root.md) | | [ElementHandle](./puppeteer.elementhandle.md)&lt;Node&gt; | <i>(Optional)</i> |
| [timeout?](./puppeteer.waitforselectoroptions.timeout.md) | | number | <i>(Optional)</i> | | [timeout?](./puppeteer.waitforselectoroptions.timeout.md) | | number | <i>(Optional)</i> |
| [visible?](./puppeteer.waitforselectoroptions.visible.md) | | boolean | <i>(Optional)</i> | | [visible?](./puppeteer.waitforselectoroptions.visible.md) | | boolean | <i>(Optional)</i> |

View File

@ -8,6 +8,6 @@ sidebar_label: WaitForSelectorOptions.root
```typescript ```typescript
interface WaitForSelectorOptions { interface WaitForSelectorOptions {
root?: ElementHandle; root?: ElementHandle<Node>;
} }
``` ```

View File

@ -28,7 +28,7 @@
}, },
"scripts": { "scripts": {
"test": "c8 --check-coverage --lines 94 run-s test:chrome test:chrome:* test:firefox", "test": "c8 --check-coverage --lines 94 run-s test:chrome test:chrome:* test:firefox",
"test:types": "tsc -b test-d", "test:types": "tsd",
"test:install": "scripts/test-install.sh", "test:install": "scripts/test-install.sh",
"test:firefox": "cross-env PUPPETEER_PRODUCT=firefox MOZ_WEBRENDER=0 mocha", "test:firefox": "cross-env PUPPETEER_PRODUCT=firefox MOZ_WEBRENDER=0 mocha",
"test:chrome": "mocha", "test:chrome": "mocha",

View File

@ -104,7 +104,7 @@ export interface SnapshotOptions {
* Root node to get the accessibility tree for * Root node to get the accessibility tree for
* @defaultValue The root node of the entire page. * @defaultValue The root node of the entire page.
*/ */
root?: ElementHandle; root?: ElementHandle<Node>;
} }
/** /**

View File

@ -24,7 +24,7 @@ import {InternalQueryHandler} from './QueryHandler.js';
async function queryAXTree( async function queryAXTree(
client: CDPSession, client: CDPSession,
element: ElementHandle, element: ElementHandle<Node>,
accessibleName?: string, accessibleName?: string,
role?: string role?: string
): Promise<Protocol.Accessibility.AXNode[]> { ): Promise<Protocol.Accessibility.AXNode[]> {
@ -86,9 +86,9 @@ function parseAriaSelector(selector: string): ARIAQueryOption {
} }
const queryOne = async ( const queryOne = async (
element: ElementHandle, element: ElementHandle<Node>,
selector: string selector: string
): Promise<ElementHandle | null> => { ): Promise<ElementHandle<Node> | null> => {
const exeCtx = element.executionContext(); const exeCtx = element.executionContext();
const {name, role} = parseAriaSelector(selector); const {name, role} = parseAriaSelector(selector);
const res = await queryAXTree(exeCtx._client, element, name, role); const res = await queryAXTree(exeCtx._client, element, name, role);
@ -111,7 +111,7 @@ const waitFor = async (
return element; return element;
}, },
}; };
return domWorld._waitForSelectorInPage( return (await domWorld._waitForSelectorInPage(
(_: Element, selector: string) => { (_: Element, selector: string) => {
return ( return (
globalThis as any as unknown as { globalThis as any as unknown as {
@ -122,13 +122,13 @@ const waitFor = async (
selector, selector,
options, options,
binding binding
); )) as ElementHandle<Element> | null;
}; };
const queryAll = async ( const queryAll = async (
element: ElementHandle, element: ElementHandle<Node>,
selector: string selector: string
): Promise<ElementHandle[]> => { ): Promise<Array<ElementHandle<Node>>> => {
const exeCtx = element.executionContext(); const exeCtx = element.executionContext();
const {name, role} = parseAriaSelector(selector); const {name, role} = parseAriaSelector(selector);
const res = await queryAXTree(exeCtx._client, element, name, role); const res = await queryAXTree(exeCtx._client, element, name, role);
@ -140,9 +140,9 @@ const queryAll = async (
}; };
const queryAllArray = async ( const queryAllArray = async (
element: ElementHandle, element: ElementHandle<Node>,
selector: string selector: string
): Promise<JSHandle<Element[]>> => { ): Promise<JSHandle<Node[]>> => {
const elementHandles = await queryAll(element, selector); const elementHandles = await queryAll(element, selector);
const exeCtx = element.executionContext(); const exeCtx = element.executionContext();
const jsHandle = exeCtx.evaluateHandle((...elements) => { const jsHandle = exeCtx.evaluateHandle((...elements) => {

View File

@ -26,7 +26,7 @@ import {JSHandle} from './JSHandle.js';
import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js'; import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
import {getQueryHandlerAndSelector} from './QueryHandler.js'; import {getQueryHandlerAndSelector} from './QueryHandler.js';
import {TimeoutSettings} from './TimeoutSettings.js'; import {TimeoutSettings} from './TimeoutSettings.js';
import {EvaluateFunc, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor, NodeFor} from './types.js';
import { import {
debugError, debugError,
isNumber, isNumber,
@ -54,7 +54,7 @@ export interface WaitForSelectorOptions {
visible?: boolean; visible?: boolean;
hidden?: boolean; hidden?: boolean;
timeout?: number; timeout?: number;
root?: ElementHandle; root?: ElementHandle<Node>;
} }
/** /**
@ -73,7 +73,7 @@ export class DOMWorld {
#client: CDPSession; #client: CDPSession;
#frame: Frame; #frame: Frame;
#timeoutSettings: TimeoutSettings; #timeoutSettings: TimeoutSettings;
#documentPromise: Promise<ElementHandle> | null = null; #documentPromise: Promise<ElementHandle<Document>> | null = null;
#contextPromise: Promise<ExecutionContext> | null = null; #contextPromise: Promise<ExecutionContext> | null = null;
#contextResolveCallback: ((x: ExecutionContext) => void) | null = null; #contextResolveCallback: ((x: ExecutionContext) => void) | null = null;
#detached = false; #detached = false;
@ -85,16 +85,10 @@ export class DOMWorld {
#boundFunctions = new Map<string, Function>(); #boundFunctions = new Map<string, Function>();
#waitTasks = new Set<WaitTask>(); #waitTasks = new Set<WaitTask>();
/**
* @internal
*/
get _waitTasks(): Set<WaitTask> { get _waitTasks(): Set<WaitTask> {
return this.#waitTasks; return this.#waitTasks;
} }
/**
* @internal
*/
get _boundFunctions(): Map<string, Function> { get _boundFunctions(): Map<string, Function> {
return this.#boundFunctions; return this.#boundFunctions;
} }
@ -123,9 +117,6 @@ export class DOMWorld {
return this.#frame; return this.#frame;
} }
/**
* @internal
*/
async _setContext(context: ExecutionContext | null): Promise<void> { async _setContext(context: ExecutionContext | null): Promise<void> {
if (context) { if (context) {
assert( assert(
@ -146,16 +137,10 @@ export class DOMWorld {
} }
} }
/**
* @internal
*/
_hasContext(): boolean { _hasContext(): boolean {
return !this.#contextResolveCallback; return !this.#contextResolveCallback;
} }
/**
* @internal
*/
_detach(): void { _detach(): void {
this.#detached = true; this.#detached = true;
this.#client.off('Runtime.bindingCalled', this.#onBindingCalled); this.#client.off('Runtime.bindingCalled', this.#onBindingCalled);
@ -200,115 +185,64 @@ export class DOMWorld {
return context.evaluate(pageFunction, ...args); return context.evaluate(pageFunction, ...args);
} }
async $<Selector extends keyof HTMLElementTagNameMap>( async $<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null> {
async $(selector: string): Promise<ElementHandle | null>;
async $(selector: string): Promise<ElementHandle | null> {
const document = await this._document(); const document = await this._document();
const value = await document.$(selector); const value = await document.$(selector);
return value; return value;
} }
async $$<Selector extends keyof HTMLElementTagNameMap>( async $$<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]>[]>; ): Promise<Array<ElementHandle<NodeFor<Selector>>>> {
async $$(selector: string): Promise<ElementHandle[]>;
async $$(selector: string): Promise<ElementHandle[]> {
const document = await this._document(); const document = await this._document();
const value = await document.$$(selector); return document.$$(selector);
return value;
} }
/** async _document(): Promise<ElementHandle<Document>> {
* @internal
*/
async _document(): Promise<ElementHandle> {
if (this.#documentPromise) { if (this.#documentPromise) {
return this.#documentPromise; return this.#documentPromise;
} }
this.#documentPromise = this.executionContext().then(async context => { this.#documentPromise = this.executionContext().then(async context => {
const document = await context.evaluateHandle('document'); return await context.evaluateHandle(() => {
const element = document.asElement(); return document;
if (element === null) { });
throw new Error('Document is null');
}
return element;
}); });
return this.#documentPromise; return this.#documentPromise;
} }
async $x(expression: string): Promise<ElementHandle[]> { async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
const document = await this._document(); const document = await this._document();
const value = await document.$x(expression); const value = await document.$x(expression);
return value; return value;
} }
async $eval< async $eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector], ...Params] [ElementHandle<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector], ...Params]> > = EvaluateFunc<[ElementHandle<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const document = await this._document(); const document = await this._document();
return document.$eval(selector, pageFunction, ...args); return document.$eval(selector, pageFunction, ...args);
} }
async $$eval< async $$eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector][], ...Params] [Array<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector][], ...Params]> > = EvaluateFunc<[Array<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const document = await this._document(); const document = await this._document();
const value = await document.$$eval(selector, pageFunction, ...args); const value = await document.$$eval(selector, pageFunction, ...args);
@ -377,7 +311,7 @@ export class DOMWorld {
content?: string; content?: string;
id?: string; id?: string;
type?: string; type?: string;
}): Promise<ElementHandle> { }): Promise<ElementHandle<HTMLScriptElement>> {
const { const {
url = null, url = null,
path = null, path = null,
@ -388,17 +322,7 @@ export class DOMWorld {
if (url !== null) { if (url !== null) {
try { try {
const context = await this.executionContext(); const context = await this.executionContext();
const handle = await context.evaluateHandle( return await context.evaluateHandle(addScriptUrl, url, id, type);
addScriptUrl,
url,
id,
type
);
const elementHandle = handle.asElement();
if (elementHandle === null) {
throw new Error('Script element is not found');
}
return elementHandle;
} catch (error) { } catch (error) {
throw new Error(`Loading script from ${url} failed`); throw new Error(`Loading script from ${url} failed`);
} }
@ -419,43 +343,19 @@ export class DOMWorld {
let contents = await fs.readFile(path, 'utf8'); let contents = await fs.readFile(path, 'utf8');
contents += '//# sourceURL=' + path.replace(/\n/g, ''); contents += '//# sourceURL=' + path.replace(/\n/g, '');
const context = await this.executionContext(); const context = await this.executionContext();
const handle = await context.evaluateHandle( return await context.evaluateHandle(addScriptContent, contents, id, type);
addScriptContent,
contents,
id,
type
);
const elementHandle = handle.asElement();
if (elementHandle === null) {
throw new Error('Script element is not found');
}
return elementHandle;
} }
if (content !== null) { if (content !== null) {
const context = await this.executionContext(); const context = await this.executionContext();
const handle = await context.evaluateHandle( return await context.evaluateHandle(addScriptContent, content, id, type);
addScriptContent,
content,
id,
type
);
const elementHandle = handle.asElement();
if (elementHandle === null) {
throw new Error('Script element is not found');
}
return elementHandle;
} }
throw new Error( throw new Error(
'Provide an object with a `url`, `path` or `content` property' 'Provide an object with a `url`, `path` or `content` property'
); );
async function addScriptUrl( async function addScriptUrl(url: string, id: string, type: string) {
url: string,
id: string,
type: string
): Promise<HTMLElement> {
const script = document.createElement('script'); const script = document.createElement('script');
script.src = url; script.src = url;
if (id) { if (id) {
@ -477,7 +377,7 @@ export class DOMWorld {
content: string, content: string,
id: string, id: string,
type = 'text/javascript' type = 'text/javascript'
): HTMLElement { ) {
const script = document.createElement('script'); const script = document.createElement('script');
script.type = type; script.type = type;
script.text = content; script.text = content;
@ -510,7 +410,7 @@ export class DOMWorld {
url?: string; url?: string;
path?: string; path?: string;
content?: string; content?: string;
}): Promise<ElementHandle> { }): Promise<ElementHandle<Node>> {
const {url = null, path = null, content = null} = options; const {url = null, path = null, content = null} = options;
if (url !== null) { if (url !== null) {
try { try {
@ -640,31 +540,24 @@ export class DOMWorld {
await handle.dispose(); await handle.dispose();
} }
async waitForSelector<Selector extends keyof HTMLElementTagNameMap>( async waitForSelector<Selector extends string>(
selector: Selector, selector: Selector,
options: WaitForSelectorOptions options: WaitForSelectorOptions
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null> {
async waitForSelector(
selector: string,
options: WaitForSelectorOptions
): Promise<ElementHandle | null>;
async waitForSelector(
selector: string,
options: WaitForSelectorOptions
): Promise<ElementHandle | null> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert(queryHandler.waitFor, 'Query handler does not support waiting'); assert(queryHandler.waitFor, 'Query handler does not support waiting');
return queryHandler.waitFor(this, updatedSelector, options); return (await queryHandler.waitFor(
this,
updatedSelector,
options
)) as ElementHandle<NodeFor<Selector>> | null;
} }
// If multiple waitFor are set up asynchronously, we need to wait for the // If multiple waitFor are set up asynchronously, we need to wait for the
// first one to set up the binding in the page before running the others. // first one to set up the binding in the page before running the others.
#settingUpBinding: Promise<void> | null = null; #settingUpBinding: Promise<void> | null = null;
/**
* @internal
*/
async _addBindingToContext( async _addBindingToContext(
context: ExecutionContext, context: ExecutionContext,
name: string name: string
@ -776,15 +669,12 @@ export class DOMWorld {
} }
}; };
/**
* @internal
*/
async _waitForSelectorInPage( async _waitForSelectorInPage(
queryOne: Function, queryOne: Function,
selector: string, selector: string,
options: WaitForSelectorOptions, options: WaitForSelectorOptions,
binding?: PageBinding binding?: PageBinding
): Promise<ElementHandle | null> { ): Promise<ElementHandle<Node> | null> {
const { const {
visible: waitForVisible = false, visible: waitForVisible = false,
hidden: waitForHidden = false, hidden: waitForHidden = false,
@ -829,7 +719,7 @@ export class DOMWorld {
async waitForXPath( async waitForXPath(
xpath: string, xpath: string,
options: WaitForSelectorOptions options: WaitForSelectorOptions
): Promise<ElementHandle | null> { ): Promise<ElementHandle<Node> | null> {
const { const {
visible: waitForVisible = false, visible: waitForVisible = false,
hidden: waitForHidden = false, hidden: waitForHidden = false,
@ -911,7 +801,7 @@ export interface WaitTaskOptions {
timeout: number; timeout: number;
binding?: PageBinding; binding?: PageBinding;
args: unknown[]; args: unknown[];
root?: ElementHandle; root?: ElementHandle<Node>;
} }
const noop = (): void => {}; const noop = (): void => {};
@ -932,7 +822,7 @@ export class WaitTask {
#reject: (x: Error) => void = noop; #reject: (x: Error) => void = noop;
#timeoutTimer?: NodeJS.Timeout; #timeoutTimer?: NodeJS.Timeout;
#terminated = false; #terminated = false;
#root: ElementHandle | null = null; #root: ElementHandle<Node> | null = null;
promise: Promise<JSHandle>; promise: Promise<JSHandle>;
@ -1099,7 +989,7 @@ export class WaitTask {
} }
async function waitForPredicatePageFunction( async function waitForPredicatePageFunction(
root: Element | Document | null, root: Node | null,
predicateBody: string, predicateBody: string,
predicateAcceptsContextElement: boolean, predicateAcceptsContextElement: boolean,
polling: 'raf' | 'mutation' | number, polling: 'raf' | 'mutation' | number,

View File

@ -15,7 +15,7 @@ import {
} from './JSHandle.js'; } from './JSHandle.js';
import {Page, ScreenshotOptions} from './Page.js'; import {Page, ScreenshotOptions} from './Page.js';
import {getQueryHandlerAndSelector} from './QueryHandler.js'; import {getQueryHandlerAndSelector} from './QueryHandler.js';
import {EvaluateFunc} from './types.js'; import {EvaluateFunc, NodeFor} from './types.js';
import {KeyInput} from './USKeyboardLayout.js'; import {KeyInput} from './USKeyboardLayout.js';
import {debugError, isString} from './util.js'; import {debugError, isString} from './util.js';
@ -64,7 +64,7 @@ const applyOffsetsToQuad = (
*/ */
export class ElementHandle< export class ElementHandle<
ElementType extends Element = Element ElementType extends Node = Element
> extends JSHandle<ElementType> { > extends JSHandle<ElementType> {
#frame: Frame; #frame: Frame;
#page: Page; #page: Page;
@ -117,18 +117,10 @@ export class ElementHandle<
* (30 seconds). Pass `0` to disable timeout. The default value can be changed * (30 seconds). Pass `0` to disable timeout. The default value can be changed
* by using the {@link Page.setDefaultTimeout} method. * by using the {@link Page.setDefaultTimeout} method.
*/ */
async waitForSelector<Selector extends keyof HTMLElementTagNameMap>( async waitForSelector<Selector extends string>(
selector: Selector, selector: Selector,
options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>;
async waitForSelector(
selector: string,
options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle | null>;
async waitForSelector(
selector: string,
options: Exclude<WaitForSelectorOptions, 'root'> = {} options: Exclude<WaitForSelectorOptions, 'root'> = {}
): Promise<ElementHandle | null> { ): Promise<ElementHandle<NodeFor<Selector>> | null> {
const frame = this._context.frame(); const frame = this._context.frame();
assert(frame); assert(frame);
const secondaryContext = await frame._secondaryWorld.executionContext(); const secondaryContext = await frame._secondaryWorld.executionContext();
@ -204,7 +196,7 @@ export class ElementHandle<
hidden?: boolean; hidden?: boolean;
timeout?: number; timeout?: number;
} = {} } = {}
): Promise<ElementHandle | null> { ): Promise<ElementHandle<Node> | null> {
const frame = this._context.frame(); const frame = this._context.frame();
assert(frame); assert(frame);
const secondaryContext = await frame._secondaryWorld.executionContext(); const secondaryContext = await frame._secondaryWorld.executionContext();
@ -246,7 +238,7 @@ export class ElementHandle<
return this.#frameManager.frame(nodeInfo.node.frameId); return this.#frameManager.frame(nodeInfo.node.frameId);
} }
async #scrollIntoViewIfNeeded(): Promise<void> { async #scrollIntoViewIfNeeded(this: ElementHandle<Element>): Promise<void> {
const error = await this.evaluate( const error = await this.evaluate(
async (element, pageJavascriptEnabled): Promise<string | false> => { async (element, pageJavascriptEnabled): Promise<string | false> => {
if (!element.isConnected) { if (!element.isConnected) {
@ -432,7 +424,7 @@ export class ElementHandle<
* uses {@link Page.mouse} to hover over the center of the element. * uses {@link Page.mouse} to hover over the center of the element.
* If the element is detached from DOM, the method throws an error. * If the element is detached from DOM, the method throws an error.
*/ */
async hover(): Promise<void> { async hover(this: ElementHandle<Element>): Promise<void> {
await this.#scrollIntoViewIfNeeded(); await this.#scrollIntoViewIfNeeded();
const {x, y} = await this.clickablePoint(); const {x, y} = await this.clickablePoint();
await this.#page.mouse.move(x, y); await this.#page.mouse.move(x, y);
@ -443,7 +435,10 @@ export class ElementHandle<
* uses {@link Page.mouse} to click in the center of the element. * uses {@link Page.mouse} to click in the center of the element.
* If the element is detached from DOM, the method throws an error. * If the element is detached from DOM, the method throws an error.
*/ */
async click(options: ClickOptions = {}): Promise<void> { async click(
this: ElementHandle<Element>,
options: ClickOptions = {}
): Promise<void> {
await this.#scrollIntoViewIfNeeded(); await this.#scrollIntoViewIfNeeded();
const {x, y} = await this.clickablePoint(options.offset); const {x, y} = await this.clickablePoint(options.offset);
await this.#page.mouse.click(x, y, options); await this.#page.mouse.click(x, y, options);
@ -452,7 +447,10 @@ export class ElementHandle<
/** /**
* This method creates and captures a dragevent from the element. * This method creates and captures a dragevent from the element.
*/ */
async drag(target: Point): Promise<Protocol.Input.DragData> { async drag(
this: ElementHandle<Element>,
target: Point
): Promise<Protocol.Input.DragData> {
assert( assert(
this.#page.isDragInterceptionEnabled(), this.#page.isDragInterceptionEnabled(),
'Drag Interception is not enabled!' 'Drag Interception is not enabled!'
@ -466,6 +464,7 @@ export class ElementHandle<
* This method creates a `dragenter` event on the element. * This method creates a `dragenter` event on the element.
*/ */
async dragEnter( async dragEnter(
this: ElementHandle<Element>,
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1} data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
): Promise<void> { ): Promise<void> {
await this.#scrollIntoViewIfNeeded(); await this.#scrollIntoViewIfNeeded();
@ -477,6 +476,7 @@ export class ElementHandle<
* This method creates a `dragover` event on the element. * This method creates a `dragover` event on the element.
*/ */
async dragOver( async dragOver(
this: ElementHandle<Element>,
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1} data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
): Promise<void> { ): Promise<void> {
await this.#scrollIntoViewIfNeeded(); await this.#scrollIntoViewIfNeeded();
@ -488,6 +488,7 @@ export class ElementHandle<
* This method triggers a drop on the element. * This method triggers a drop on the element.
*/ */
async drop( async drop(
this: ElementHandle<Element>,
data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1} data: Protocol.Input.DragData = {items: [], dragOperationsMask: 1}
): Promise<void> { ): Promise<void> {
await this.#scrollIntoViewIfNeeded(); await this.#scrollIntoViewIfNeeded();
@ -499,7 +500,8 @@ export class ElementHandle<
* This method triggers a dragenter, dragover, and drop on the element. * This method triggers a dragenter, dragover, and drop on the element.
*/ */
async dragAndDrop( async dragAndDrop(
target: ElementHandle, this: ElementHandle<Element>,
target: ElementHandle<Node>,
options?: {delay: number} options?: {delay: number}
): Promise<void> { ): Promise<void> {
await this.#scrollIntoViewIfNeeded(); await this.#scrollIntoViewIfNeeded();
@ -637,7 +639,7 @@ export class ElementHandle<
* {@link Touchscreen.tap} to tap in the center of the element. * {@link Touchscreen.tap} to tap in the center of the element.
* If the element is detached from DOM, the method throws an error. * If the element is detached from DOM, the method throws an error.
*/ */
async tap(): Promise<void> { async tap(this: ElementHandle<Element>): Promise<void> {
await this.#scrollIntoViewIfNeeded(); await this.#scrollIntoViewIfNeeded();
const {x, y} = await this.clickablePoint(); const {x, y} = await this.clickablePoint();
await this.#page.touchscreen.tap(x, y); await this.#page.touchscreen.tap(x, y);
@ -771,7 +773,10 @@ export class ElementHandle<
* {@link Page.screenshot} to take a screenshot of the element. * {@link Page.screenshot} to take a screenshot of the element.
* If the element is detached from DOM, the method throws an error. * If the element is detached from DOM, the method throws an error.
*/ */
async screenshot(options: ScreenshotOptions = {}): Promise<string | Buffer> { async screenshot(
this: ElementHandle<Element>,
options: ScreenshotOptions = {}
): Promise<string | Buffer> {
let needsViewportReset = false; let needsViewportReset = false;
let boundingBox = await this.boundingBox(); let boundingBox = await this.boundingBox();
@ -833,18 +838,19 @@ export class ElementHandle<
* @returns `null` if no element matches the selector. * @returns `null` if no element matches the selector.
* @throws `Error` if the selector has no associated query handler. * @throws `Error` if the selector has no associated query handler.
*/ */
async $<Selector extends keyof HTMLElementTagNameMap>( async $<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null> {
async $(selector: string): Promise<ElementHandle | null>;
async $(selector: string): Promise<ElementHandle | null> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert( assert(
queryHandler.queryOne, queryHandler.queryOne,
'Cannot handle queries for a single element with the given selector' 'Cannot handle queries for a single element with the given selector'
); );
return queryHandler.queryOne(this, updatedSelector); return (await queryHandler.queryOne(
this,
updatedSelector
)) as ElementHandle<NodeFor<Selector>> | null;
} }
/** /**
@ -858,18 +864,18 @@ export class ElementHandle<
* @returns `[]` if no element matches the selector. * @returns `[]` if no element matches the selector.
* @throws `Error` if the selector has no associated query handler. * @throws `Error` if the selector has no associated query handler.
*/ */
async $$<Selector extends keyof HTMLElementTagNameMap>( async $$<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]>[]>; ): Promise<Array<ElementHandle<NodeFor<Selector>>>> {
async $$(selector: string): Promise<ElementHandle[]>;
async $$(selector: string): Promise<ElementHandle[]> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert( assert(
queryHandler.queryAll, queryHandler.queryAll,
'Cannot handle queries for a multiple element with the given selector' 'Cannot handle queries for a multiple element with the given selector'
); );
return queryHandler.queryAll(this, updatedSelector); return (await queryHandler.queryAll(this, updatedSelector)) as Array<
ElementHandle<NodeFor<Selector>>
>;
} }
/** /**
@ -888,35 +894,15 @@ export class ElementHandle<
* ``` * ```
*/ */
async $eval< async $eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector], ...Params] [ElementHandle<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector], ...Params]> > = EvaluateFunc<[ElementHandle<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const elementHandle = await this.$(selector); const elementHandle = await this.$(selector);
if (!elementHandle) { if (!elementHandle) {
@ -953,40 +939,23 @@ export class ElementHandle<
* ``` * ```
*/ */
async $$eval< async $$eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector][], ...Params] [Array<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector][], ...Params]> > = EvaluateFunc<[Array<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert(queryHandler.queryAllArray); assert(queryHandler.queryAllArray);
const arrayHandle = await queryHandler.queryAllArray(this, updatedSelector); const arrayHandle = (await queryHandler.queryAllArray(
this,
updatedSelector
)) as JSHandle<Array<NodeFor<Selector>>>;
const result = await arrayHandle.evaluate(pageFunction, ...args); const result = await arrayHandle.evaluate(pageFunction, ...args);
await arrayHandle.dispose(); await arrayHandle.dispose();
return result; return result;
@ -997,10 +966,10 @@ export class ElementHandle<
* If there are no such elements, the method will resolve to an empty array. * If there are no such elements, the method will resolve to an empty array.
* @param expression - Expression to {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate | evaluate} * @param expression - Expression to {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate | evaluate}
*/ */
async $x(expression: string): Promise<ElementHandle[]> { async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
const arrayHandle = await this.evaluateHandle((element, expression) => { const arrayHandle = await this.evaluateHandle((element, expression) => {
const document = element.ownerDocument || element; const doc = element.ownerDocument || document;
const iterator = document.evaluate( const iterator = doc.evaluate(
expression, expression,
element, element,
null, null,
@ -1028,9 +997,12 @@ export class ElementHandle<
/** /**
* Resolves to true if the element is visible in the current viewport. * Resolves to true if the element is visible in the current viewport.
*/ */
async isIntersectingViewport(options?: { async isIntersectingViewport(
threshold?: number; this: ElementHandle<Element>,
}): Promise<boolean> { options?: {
threshold?: number;
}
): Promise<boolean> {
const {threshold = 0} = options ?? {}; const {threshold = 0} = options ?? {};
return await this.evaluate(async (element, threshold) => { return await this.evaluate(async (element, threshold) => {
const visibleRatio = await new Promise<number>(resolve => { const visibleRatio = await new Promise<number>(resolve => {

View File

@ -415,20 +415,20 @@ export class ExecutionContext {
*/ */
async _adoptBackendNodeId( async _adoptBackendNodeId(
backendNodeId?: Protocol.DOM.BackendNodeId backendNodeId?: Protocol.DOM.BackendNodeId
): Promise<ElementHandle> { ): Promise<ElementHandle<Node>> {
const {object} = await this._client.send('DOM.resolveNode', { const {object} = await this._client.send('DOM.resolveNode', {
backendNodeId: backendNodeId, backendNodeId: backendNodeId,
executionContextId: this._contextId, executionContextId: this._contextId,
}); });
return createJSHandle(this, object) as ElementHandle; return createJSHandle(this, object) as ElementHandle<Node>;
} }
/** /**
* @internal * @internal
*/ */
async _adoptElementHandle( async _adoptElementHandle<T extends ElementHandle<Node>>(
elementHandle: ElementHandle elementHandle: T
): Promise<ElementHandle> { ): Promise<T> {
assert( assert(
elementHandle.executionContext() !== this, elementHandle.executionContext() !== this,
'Cannot adopt handle that already belongs to this execution context' 'Cannot adopt handle that already belongs to this execution context'
@ -437,6 +437,6 @@ export class ExecutionContext {
const nodeInfo = await this._client.send('DOM.describeNode', { const nodeInfo = await this._client.send('DOM.describeNode', {
objectId: elementHandle._remoteObject.objectId, objectId: elementHandle._remoteObject.objectId,
}); });
return this._adoptBackendNodeId(nodeInfo.node.backendNodeId); return (await this._adoptBackendNodeId(nodeInfo.node.backendNodeId)) as T;
} }
} }

View File

@ -18,16 +18,16 @@ import {Protocol} from 'devtools-protocol';
import {assert} from './assert.js'; import {assert} from './assert.js';
import {CDPSession, Connection} from './Connection.js'; import {CDPSession, Connection} from './Connection.js';
import {DOMWorld, WaitForSelectorOptions} from './DOMWorld.js'; import {DOMWorld, WaitForSelectorOptions} from './DOMWorld.js';
import {ElementHandle} from './ElementHandle.js';
import {EventEmitter} from './EventEmitter.js'; import {EventEmitter} from './EventEmitter.js';
import {EVALUATION_SCRIPT_URL, ExecutionContext} from './ExecutionContext.js'; import {EVALUATION_SCRIPT_URL, ExecutionContext} from './ExecutionContext.js';
import {HTTPResponse} from './HTTPResponse.js'; import {HTTPResponse} from './HTTPResponse.js';
import {MouseButton} from './Input.js'; import {MouseButton} from './Input.js';
import {ElementHandle} from './ElementHandle.js';
import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js'; import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
import {NetworkManager} from './NetworkManager.js'; import {NetworkManager} from './NetworkManager.js';
import {Page} from './Page.js'; import {Page} from './Page.js';
import {TimeoutSettings} from './TimeoutSettings.js'; import {TimeoutSettings} from './TimeoutSettings.js';
import {EvaluateFunc, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor, NodeFor} from './types.js';
import {debugError, isErrorLike} from './util.js'; import {debugError, isErrorLike} from './util.js';
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__'; const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
@ -920,11 +920,9 @@ export class Frame {
* @returns A promise which resolves to an `ElementHandle` pointing at the * @returns A promise which resolves to an `ElementHandle` pointing at the
* element, or `null` if it was not found. * element, or `null` if it was not found.
*/ */
async $<Selector extends keyof HTMLElementTagNameMap>( async $<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null> {
async $(selector: string): Promise<ElementHandle | null>;
async $(selector: string): Promise<ElementHandle | null> {
return this._mainWorld.$(selector); return this._mainWorld.$(selector);
} }
@ -934,11 +932,9 @@ export class Frame {
* @param selector - a selector to search for * @param selector - a selector to search for
* @returns An array of element handles pointing to the found frame elements. * @returns An array of element handles pointing to the found frame elements.
*/ */
async $$<Selector extends keyof HTMLElementTagNameMap>( async $$<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]>[]>; ): Promise<Array<ElementHandle<NodeFor<Selector>>>> {
async $$(selector: string): Promise<ElementHandle[]>;
async $$(selector: string): Promise<ElementHandle[]> {
return this._mainWorld.$$(selector); return this._mainWorld.$$(selector);
} }
@ -947,7 +943,7 @@ export class Frame {
* *
* @param expression - the XPath expression to evaluate. * @param expression - the XPath expression to evaluate.
*/ */
async $x(expression: string): Promise<ElementHandle[]> { async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
return this._mainWorld.$x(expression); return this._mainWorld.$x(expression);
} }
@ -971,35 +967,15 @@ export class Frame {
* @param args - additional arguments to pass to `pageFunction` * @param args - additional arguments to pass to `pageFunction`
*/ */
async $eval< async $eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector], ...Params] [ElementHandle<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector], ...Params]> > = EvaluateFunc<[ElementHandle<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this._mainWorld.$eval(selector, pageFunction, ...args); return this._mainWorld.$eval(selector, pageFunction, ...args);
} }
@ -1024,35 +1000,15 @@ export class Frame {
* @param args - additional arguments to pass to `pageFunction` * @param args - additional arguments to pass to `pageFunction`
*/ */
async $$eval< async $$eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector][], ...Params] [Array<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector][], ...Params]> > = EvaluateFunc<[Array<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this._mainWorld.$$eval(selector, pageFunction, ...args); return this._mainWorld.$$eval(selector, pageFunction, ...args);
} }
@ -1134,7 +1090,7 @@ export class Frame {
*/ */
async addScriptTag( async addScriptTag(
options: FrameAddScriptTagOptions options: FrameAddScriptTagOptions
): Promise<ElementHandle> { ): Promise<ElementHandle<HTMLScriptElement>> {
return this._mainWorld.addScriptTag(options); return this._mainWorld.addScriptTag(options);
} }
@ -1148,7 +1104,9 @@ export class Frame {
* `onload` event fires or when the CSS content was injected into the * `onload` event fires or when the CSS content was injected into the
* frame. * frame.
*/ */
async addStyleTag(options: FrameAddStyleTagOptions): Promise<ElementHandle> { async addStyleTag(
options: FrameAddStyleTagOptions
): Promise<ElementHandle<Node>> {
return this._mainWorld.addStyleTag(options); return this._mainWorld.addStyleTag(options);
} }
@ -1345,18 +1303,10 @@ export class Frame {
* @returns a promise which resolves when an element matching the selector * @returns a promise which resolves when an element matching the selector
* string is added to the DOM. * string is added to the DOM.
*/ */
async waitForSelector<Selector extends keyof HTMLElementTagNameMap>( async waitForSelector<Selector extends string>(
selector: Selector, selector: Selector,
options?: WaitForSelectorOptions
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>;
async waitForSelector(
selector: string,
options?: WaitForSelectorOptions
): Promise<ElementHandle | null>;
async waitForSelector(
selector: string,
options: WaitForSelectorOptions = {} options: WaitForSelectorOptions = {}
): Promise<ElementHandle | null> { ): Promise<ElementHandle<NodeFor<Selector>> | null> {
const handle = await this._secondaryWorld.waitForSelector( const handle = await this._secondaryWorld.waitForSelector(
selector, selector,
options options
@ -1388,7 +1338,7 @@ export class Frame {
async waitForXPath( async waitForXPath(
xpath: string, xpath: string,
options: WaitForSelectorOptions = {} options: WaitForSelectorOptions = {}
): Promise<ElementHandle | null> { ): Promise<ElementHandle<Node> | null> {
const handle = await this._secondaryWorld.waitForXPath(xpath, options); const handle = await this._secondaryWorld.waitForXPath(xpath, options);
if (!handle) { if (!handle) {
return null; return null;

View File

@ -23,6 +23,8 @@ import {MouseButton} from './Input.js';
import {releaseObject, valueFromRemoteObject, createJSHandle} from './util.js'; import {releaseObject, valueFromRemoteObject, createJSHandle} from './util.js';
import type {ElementHandle} from './ElementHandle.js'; import type {ElementHandle} from './ElementHandle.js';
declare const __JSHandleSymbol: unique symbol;
/** /**
* @public * @public
*/ */
@ -68,6 +70,11 @@ export interface BoundingBox extends Point {
* @public * @public
*/ */
export class JSHandle<T = unknown> { export class JSHandle<T = unknown> {
/**
* Used for nominally typing {@link JSHandle}.
*/
[__JSHandleSymbol]?: T;
#client: CDPSession; #client: CDPSession;
#disposed = false; #disposed = false;
#context: ExecutionContext; #context: ExecutionContext;
@ -253,7 +260,7 @@ export class JSHandle<T = unknown> {
* @returns Either `null` or the object handle itself, if the object * @returns Either `null` or the object handle itself, if the object
* handle is an instance of {@link ElementHandle}. * handle is an instance of {@link ElementHandle}.
*/ */
asElement(): ElementHandle | null { asElement(): ElementHandle<Node> | null {
/* This always returns null, but subclasses can override this and return an /* This always returns null, but subclasses can override this and return an
ElementHandle. ElementHandle.
*/ */

View File

@ -49,7 +49,7 @@ import {Target} from './Target.js';
import {TaskQueue} from './TaskQueue.js'; import {TaskQueue} from './TaskQueue.js';
import {TimeoutSettings} from './TimeoutSettings.js'; import {TimeoutSettings} from './TimeoutSettings.js';
import {Tracing} from './Tracing.js'; import {Tracing} from './Tracing.js';
import {EvaluateFunc, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor, NodeFor} from './types.js';
import { import {
createJSHandle, createJSHandle,
debugError, debugError,
@ -1025,11 +1025,9 @@ export class Page extends EventEmitter {
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector} * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | selector}
* to query page for. * to query page for.
*/ */
async $<Selector extends keyof HTMLElementTagNameMap>( async $<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>; ): Promise<ElementHandle<NodeFor<Selector>> | null> {
async $(selector: string): Promise<ElementHandle | null>;
async $(selector: string): Promise<ElementHandle | null> {
return this.mainFrame().$(selector); return this.mainFrame().$(selector);
} }
@ -1040,11 +1038,9 @@ export class Page extends EventEmitter {
* Shortcut for {@link Frame.$$ | Page.mainFrame().$$(selector) }. * Shortcut for {@link Frame.$$ | Page.mainFrame().$$(selector) }.
* @param selector - A `selector` to query page for * @param selector - A `selector` to query page for
*/ */
async $$<Selector extends keyof HTMLElementTagNameMap>( async $$<Selector extends string>(
selector: Selector selector: Selector
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]>[]>; ): Promise<Array<ElementHandle<NodeFor<Selector>>>> {
async $$(selector: string): Promise<ElementHandle[]>;
async $$(selector: string): Promise<ElementHandle[]> {
return this.mainFrame().$$(selector); return this.mainFrame().$$(selector);
} }
@ -1201,35 +1197,15 @@ export class Page extends EventEmitter {
* returned. * returned.
*/ */
async $eval< async $eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector], ...Params] [ElementHandle<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector], ...Params]> > = EvaluateFunc<[ElementHandle<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element, ...Params]> = EvaluateFunc<
[Element, ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this.mainFrame().$eval(selector, pageFunction, ...args); return this.mainFrame().$eval(selector, pageFunction, ...args);
} }
@ -1297,35 +1273,15 @@ export class Page extends EventEmitter {
* returned. * returned.
*/ */
async $$eval< async $$eval<
Selector extends keyof HTMLElementTagNameMap, Selector extends string,
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc< Func extends EvaluateFunc<
[HTMLElementTagNameMap[Selector][], ...Params] [Array<NodeFor<Selector>>, ...Params]
> = EvaluateFunc<[HTMLElementTagNameMap[Selector][], ...Params]> > = EvaluateFunc<[Array<NodeFor<Selector>>, ...Params]>
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async $$eval<
Params extends unknown[],
Func extends EvaluateFunc<[Element[], ...Params]> = EvaluateFunc<
[Element[], ...Params]
>
>(
selector: string,
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this.mainFrame().$$eval(selector, pageFunction, ...args); return this.mainFrame().$$eval(selector, pageFunction, ...args);
} }
@ -1338,7 +1294,7 @@ export class Page extends EventEmitter {
* Shortcut for {@link Frame.$x | Page.mainFrame().$x(expression) }. * Shortcut for {@link Frame.$x | Page.mainFrame().$x(expression) }.
* @param expression - Expression to evaluate * @param expression - Expression to evaluate
*/ */
async $x(expression: string): Promise<ElementHandle[]> { async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
return this.mainFrame().$x(expression); return this.mainFrame().$x(expression);
} }
@ -1421,7 +1377,7 @@ export class Page extends EventEmitter {
content?: string; content?: string;
type?: string; type?: string;
id?: string; id?: string;
}): Promise<ElementHandle> { }): Promise<ElementHandle<HTMLScriptElement>> {
return this.mainFrame().addScriptTag(options); return this.mainFrame().addScriptTag(options);
} }
@ -1435,7 +1391,7 @@ export class Page extends EventEmitter {
url?: string; url?: string;
path?: string; path?: string;
content?: string; content?: string;
}): Promise<ElementHandle> { }): Promise<ElementHandle<Node>> {
return this.mainFrame().addStyleTag(options); return this.mainFrame().addStyleTag(options);
} }
@ -3339,18 +3295,10 @@ export class Page extends EventEmitter {
* (30 seconds). Pass `0` to disable timeout. The default value can be changed * (30 seconds). Pass `0` to disable timeout. The default value can be changed
* by using the {@link Page.setDefaultTimeout} method. * by using the {@link Page.setDefaultTimeout} method.
*/ */
async waitForSelector<Selector extends keyof HTMLElementTagNameMap>( async waitForSelector<Selector extends string>(
selector: Selector, selector: Selector,
options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle<HTMLElementTagNameMap[Selector]> | null>;
async waitForSelector(
selector: string,
options?: Exclude<WaitForSelectorOptions, 'root'>
): Promise<ElementHandle | null>;
async waitForSelector(
selector: string,
options: Exclude<WaitForSelectorOptions, 'root'> = {} options: Exclude<WaitForSelectorOptions, 'root'> = {}
): Promise<ElementHandle | null> { ): Promise<ElementHandle<NodeFor<Selector>> | null> {
return await this.mainFrame().waitForSelector(selector, options); return await this.mainFrame().waitForSelector(selector, options);
} }
@ -3409,7 +3357,7 @@ export class Page extends EventEmitter {
hidden?: boolean; hidden?: boolean;
timeout?: number; timeout?: number;
} = {} } = {}
): Promise<ElementHandle | null> { ): Promise<ElementHandle<Node> | null> {
return this.mainFrame().waitForXPath(xpath, options); return this.mainFrame().waitForXPath(xpath, options);
} }

View File

@ -14,32 +14,33 @@
* limitations under the License. * limitations under the License.
*/ */
import {WaitForSelectorOptions, DOMWorld} from './DOMWorld.js';
import {JSHandle} from './JSHandle.js';
import {ariaHandler} from './AriaQueryHandler.js'; import {ariaHandler} from './AriaQueryHandler.js';
import {DOMWorld, WaitForSelectorOptions} from './DOMWorld.js';
import {ElementHandle} from './ElementHandle.js'; import {ElementHandle} from './ElementHandle.js';
import {JSHandle} from './JSHandle.js';
/** /**
* @internal * @internal
*/ */
export interface InternalQueryHandler { export interface InternalQueryHandler {
queryOne?: ( queryOne?: (
element: ElementHandle, element: ElementHandle<Node>,
selector: string selector: string
) => Promise<ElementHandle | null>; ) => Promise<ElementHandle<Node> | null>;
queryAll?: (
element: ElementHandle<Node>,
selector: string
) => Promise<Array<ElementHandle<Node>>>;
waitFor?: ( waitFor?: (
domWorld: DOMWorld, domWorld: DOMWorld,
selector: string, selector: string,
options: WaitForSelectorOptions options: WaitForSelectorOptions
) => Promise<ElementHandle | null>; ) => Promise<ElementHandle<Node> | null>;
queryAll?: (
element: ElementHandle,
selector: string
) => Promise<ElementHandle[]>;
queryAllArray?: ( queryAllArray?: (
element: ElementHandle, element: ElementHandle<Node>,
selector: string selector: string
) => Promise<JSHandle<Element[]>>; ) => Promise<JSHandle<Node[]>>;
} }
/** /**
@ -54,14 +55,13 @@ export interface InternalQueryHandler {
* @public * @public
*/ */
export interface CustomQueryHandler { export interface CustomQueryHandler {
queryOne?: (element: Element | Document, selector: string) => Element | null; queryOne?: (element: Node, selector: string) => Node | null;
queryAll?: ( queryAll?: (element: Node, selector: string) => Node[];
element: Element | Document,
selector: string
) => Element[] | NodeListOf<Element>;
} }
function makeQueryHandler(handler: CustomQueryHandler): InternalQueryHandler { function createInternalQueryHandler(
handler: CustomQueryHandler
): InternalQueryHandler {
const internalHandler: InternalQueryHandler = {}; const internalHandler: InternalQueryHandler = {};
if (handler.queryOne) { if (handler.queryOne) {
@ -114,19 +114,37 @@ function makeQueryHandler(handler: CustomQueryHandler): InternalQueryHandler {
return internalHandler; return internalHandler;
} }
const defaultHandler = makeQueryHandler({ const defaultHandler = createInternalQueryHandler({
queryOne: (element: Element | Document, selector: string) => { queryOne: (element, selector) => {
return element.querySelector(selector); if (!('querySelector' in element)) {
throw new Error(
`Could not invoke \`querySelector\` on node of type ${element.nodeName}.`
);
}
return (
element as unknown as {querySelector(selector: string): Element}
).querySelector(selector);
}, },
queryAll: (element: Element | Document, selector: string) => { queryAll: (element, selector) => {
return element.querySelectorAll(selector); if (!('querySelectorAll' in element)) {
throw new Error(
`Could not invoke \`querySelectorAll\` on node of type ${element.nodeName}.`
);
}
return [
...(
element as unknown as {
querySelectorAll(selector: string): NodeList;
}
).querySelectorAll(selector),
];
}, },
}); });
const pierceHandler = makeQueryHandler({ const pierceHandler = createInternalQueryHandler({
queryOne: (element, selector) => { queryOne: (element, selector) => {
let found: Element | null = null; let found: Node | null = null;
const search = (root: Element | ShadowRoot) => { const search = (root: Node) => {
const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT); const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
do { do {
const currentNode = iter.currentNode as HTMLElement; const currentNode = iter.currentNode as HTMLElement;
@ -149,8 +167,8 @@ const pierceHandler = makeQueryHandler({
}, },
queryAll: (element, selector) => { queryAll: (element, selector) => {
const result: Element[] = []; const result: Node[] = [];
const collect = (root: Element | ShadowRoot) => { const collect = (root: Node) => {
const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT); const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
do { do {
const currentNode = iter.currentNode as HTMLElement; const currentNode = iter.currentNode as HTMLElement;
@ -213,7 +231,7 @@ export function registerCustomQueryHandler(
throw new Error(`Custom query handler names may only contain [a-zA-Z]`); throw new Error(`Custom query handler names may only contain [a-zA-Z]`);
} }
const internalHandler = makeQueryHandler(handler); const internalHandler = createInternalQueryHandler(handler);
queryHandlers.set(name, internalHandler); queryHandlers.set(name, internalHandler);
} }

View File

@ -25,7 +25,8 @@ export type Awaitable<T> = T | PromiseLike<T>;
/** /**
* @public * @public
*/ */
export type HandleFor<T> = T extends Element ? ElementHandle<T> : JSHandle<T>; export type HandleFor<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
/** /**
* @public * @public
*/ */
@ -48,3 +49,13 @@ export type InnerParams<T extends unknown[]> = {
export type EvaluateFunc<T extends unknown[]> = ( export type EvaluateFunc<T extends unknown[]> = (
...params: InnerParams<T> ...params: InnerParams<T>
) => Awaitable<unknown>; ) => Awaitable<unknown>;
/**
* @public
*/
export type NodeFor<Selector extends string> =
Selector extends keyof HTMLElementTagNameMap
? HTMLElementTagNameMap[Selector]
: Selector extends keyof SVGElementTagNameMap
? SVGElementTagNameMap[Selector]
: Element;

View File

@ -215,7 +215,7 @@ export async function waitForEvent<T>(
export function createJSHandle( export function createJSHandle(
context: ExecutionContext, context: ExecutionContext,
remoteObject: Protocol.Runtime.RemoteObject remoteObject: Protocol.Runtime.RemoteObject
): JSHandle | ElementHandle { ): JSHandle | ElementHandle<Node> {
const frame = context.frame(); const frame = context.frame();
if (remoteObject.subtype === 'node' && frame) { if (remoteObject.subtype === 'node' && frame) {
const frameManager = frame._frameManager; const frameManager = frame._frameManager;

View File

@ -19,15 +19,15 @@ declare const handle: ElementHandle;
{ {
{ {
expectType<ElementHandle<HTMLAnchorElement>[]>(await handle.$$('a')); expectType<Array<ElementHandle<HTMLAnchorElement>>>(await handle.$$('a'));
expectNotType<ElementHandle<Element>[]>(await handle.$$('a')); expectNotType<Array<ElementHandle<Element>>>(await handle.$$('a'));
} }
{ {
expectType<ElementHandle<HTMLDivElement>[]>(await handle.$$('div')); expectType<Array<ElementHandle<HTMLDivElement>>>(await handle.$$('div'));
expectNotType<ElementHandle<Element>[]>(await handle.$$('div')); expectNotType<Array<ElementHandle<Element>>>(await handle.$$('div'));
} }
{ {
expectType<ElementHandle<Element>[]>(await handle.$$('some-custom')); expectType<Array<ElementHandle<Element>>>(await handle.$$('some-custom'));
} }
} }

View File

@ -1,4 +1,4 @@
import {expectAssignable, expectNotAssignable, expectType} from 'tsd'; import {expectNotAssignable, expectNotType, expectType} from 'tsd';
import {ElementHandle} from '../lib/esm/puppeteer/common/ElementHandle.js'; import {ElementHandle} from '../lib/esm/puppeteer/common/ElementHandle.js';
import {JSHandle} from '../lib/esm/puppeteer/common/JSHandle.js'; import {JSHandle} from '../lib/esm/puppeteer/common/JSHandle.js';
@ -61,16 +61,16 @@ declare const handle2: JSHandle<{test: number}>;
{ {
{ {
expectType<JSHandle<number>>(await handle2.getProperty('test')); expectType<JSHandle<number>>(await handle2.getProperty('test'));
expectNotAssignable<JSHandle<string>>(await handle2.getProperty('test')); expectNotType<JSHandle<unknown>>(await handle2.getProperty('test'));
} }
{ {
expectType<JSHandle<unknown>>( expectType<JSHandle<unknown>>(
await handle2.getProperty('key-doesnt-exist') await handle2.getProperty('key-doesnt-exist')
); );
expectAssignable<JSHandle<string>>( expectNotType<JSHandle<string>>(
await handle2.getProperty('key-doesnt-exist') await handle2.getProperty('key-doesnt-exist')
); );
expectAssignable<JSHandle<number>>( expectNotType<JSHandle<number>>(
await handle2.getProperty('key-doesnt-exist') await handle2.getProperty('key-doesnt-exist')
); );
} }

View File

@ -98,8 +98,10 @@ describeChromeOnly('AriaQueryHandler', () => {
await page.setContent( await page.setContent(
'<div id="div"><button id="btn" role="button">Submit</button></div>' '<div id="div"><button id="btn" role="button">Submit</button></div>'
); );
const button = (await page.$('aria/[role="button"]'))!; const button = (await page.$(
const id = await button!.evaluate((button: Element) => { 'aria/[role="button"]'
)) as ElementHandle<HTMLButtonElement>;
const id = await button!.evaluate(button => {
return button.id; return button.id;
}); });
expect(id).toBe('btn'); expect(id).toBe('btn');
@ -110,8 +112,10 @@ describeChromeOnly('AriaQueryHandler', () => {
await page.setContent( await page.setContent(
'<div id="div"><button id="btn" role="button">Submit</button></div>' '<div id="div"><button id="btn" role="button">Submit</button></div>'
); );
const button = (await page.$('aria/Submit[role="button"]'))!; const button = (await page.$(
const id = await button!.evaluate((button: Element) => { 'aria/Submit[role="button"]'
)) as ElementHandle<HTMLButtonElement>;
const id = await button!.evaluate(button => {
return button.id; return button.id;
}); });
expect(id).toBe('btn'); expect(id).toBe('btn');
@ -125,8 +129,10 @@ describeChromeOnly('AriaQueryHandler', () => {
<div role="menu" id="mnu2" aria-label="menu div"></div> <div role="menu" id="mnu2" aria-label="menu div"></div>
` `
); );
const div = (await page.$('aria/menu div'))!; const div = (await page.$(
const id = await div!.evaluate((div: Element) => { 'aria/menu div'
)) as ElementHandle<HTMLDivElement>;
const id = await div!.evaluate(div => {
return div.id; return div.id;
}); });
expect(id).toBe('mnu1'); expect(id).toBe('mnu1');
@ -140,8 +146,10 @@ describeChromeOnly('AriaQueryHandler', () => {
<div role="menu" id="mnu2" aria-label="menu-label2">menu div</div> <div role="menu" id="mnu2" aria-label="menu-label2">menu div</div>
` `
); );
const menu = (await page.$('aria/menu-label1'))!; const menu = (await page.$(
const id = await menu!.evaluate((div: Element) => { 'aria/menu-label1'
)) as ElementHandle<HTMLDivElement>;
const id = await menu!.evaluate(div => {
return div.id; return div.id;
}); });
expect(id).toBe('mnu1'); expect(id).toBe('mnu1');
@ -155,8 +163,10 @@ describeChromeOnly('AriaQueryHandler', () => {
<div role="menu" id="mnu2" aria-label="menu-label2">menu div</div> <div role="menu" id="mnu2" aria-label="menu-label2">menu div</div>
` `
); );
const menu = (await page.$('aria/menu-label2'))!; const menu = (await page.$(
const id = await menu!.evaluate((div: Element) => { 'aria/menu-label2'
)) as ElementHandle<HTMLDivElement>;
const id = await menu!.evaluate(div => {
return div.id; return div.id;
}); });
expect(id).toBe('mnu2'); expect(id).toBe('mnu2');
@ -172,10 +182,12 @@ describeChromeOnly('AriaQueryHandler', () => {
<div role="menu" id="mnu2" aria-label="menu div"></div> <div role="menu" id="mnu2" aria-label="menu div"></div>
` `
); );
const divs = await page.$$('aria/menu div'); const divs = (await page.$$('aria/menu div')) as Array<
ElementHandle<HTMLDivElement>
>;
const ids = await Promise.all( const ids = await Promise.all(
divs.map(n => { divs.map(n => {
return n.evaluate((div: Element) => { return n.evaluate(div => {
return div.id; return div.id;
}); });
}) })
@ -652,9 +664,9 @@ describeChromeOnly('AriaQueryHandler', () => {
}); });
it('should find by role "button"', async () => { it('should find by role "button"', async () => {
const {page} = getTestState(); const {page} = getTestState();
const found = (await page.$$( const found = (await page.$$('aria/[role="button"]')) as Array<
'aria/[role="button"]' ElementHandle<HTMLButtonElement>
)) as ElementHandle<HTMLButtonElement>[]; >;
const ids = await getIds(found); const ids = await getIds(found);
expect(ids).toEqual([ expect(ids).toEqual([
'node5', 'node5',

View File

@ -16,6 +16,7 @@
import expect from 'expect'; import expect from 'expect';
import sinon from 'sinon'; import sinon from 'sinon';
import {ElementHandle} from '../../lib/cjs/puppeteer/common/ElementHandle.js';
import { import {
describeFailsFirefox, describeFailsFirefox,
getTestState, getTestState,
@ -83,7 +84,9 @@ describe('ElementHandle specs', function () {
<rect id="theRect" x="30" y="50" width="200" height="300"></rect> <rect id="theRect" x="30" y="50" width="200" height="300"></rect>
</svg> </svg>
`); `);
const element = (await page.$('#therect'))!; const element = (await page.$(
'#therect'
)) as ElementHandle<SVGRectElement>;
const pptrBoundingBox = await element.boundingBox(); const pptrBoundingBox = await element.boundingBox();
const webBoundingBox = await page.evaluate(e => { const webBoundingBox = await page.evaluate(e => {
const rect = e.getBoundingClientRect(); const rect = e.getBoundingClientRect();
@ -274,7 +277,9 @@ describe('ElementHandle specs', function () {
describe('Element.waitForSelector', () => { describe('Element.waitForSelector', () => {
it('should wait correctly with waitForSelector on an element', async () => { it('should wait correctly with waitForSelector on an element', async () => {
const {page} = getTestState(); const {page} = getTestState();
const waitFor = page.waitForSelector('.foo'); const waitFor = page.waitForSelector('.foo') as Promise<
ElementHandle<HTMLDivElement>
>;
// Set the page content after the waitFor has been started. // Set the page content after the waitFor has been started.
await page.setContent( await page.setContent(
'<div id="not-foo"></div><div class="bar">bar2</div><div class="foo">Foo1</div>' '<div id="not-foo"></div><div class="bar">bar2</div><div class="foo">Foo1</div>'
@ -282,7 +287,9 @@ describe('ElementHandle specs', function () {
let element = (await waitFor)!; let element = (await waitFor)!;
expect(element).toBeDefined(); expect(element).toBeDefined();
const innerWaitFor = element.waitForSelector('.bar'); const innerWaitFor = element.waitForSelector('.bar') as Promise<
ElementHandle<HTMLDivElement>
>;
await element.evaluate(el => { await element.evaluate(el => {
el.innerHTML = '<div class="bar">bar1</div>'; el.innerHTML = '<div class="bar">bar1</div>';
}); });
@ -312,19 +319,20 @@ describe('ElementHandle specs', function () {
</div>` </div>`
); );
const el2 = (await page.waitForSelector('#el1'))!; const el2 = (await page.waitForSelector(
'#el1'
)) as ElementHandle<HTMLDivElement>;
expect( for (const path of ['//div', './/div']) {
await (await el2.waitForXPath('//div'))!.evaluate(el => { const e = (await el2.waitForXPath(
return el.id; path
}) )) as ElementHandle<HTMLDivElement>;
).toStrictEqual('el2'); expect(
await e.evaluate(el => {
expect( return el.id;
await (await el2.waitForXPath('.//div'))!.evaluate(el => { })
return el.id; ).toStrictEqual('el2');
}) }
).toStrictEqual('el2');
}); });
}); });
@ -398,7 +406,9 @@ describe('ElementHandle specs', function () {
return document.querySelector(`[id="${selector}"]`); return document.querySelector(`[id="${selector}"]`);
}, },
}); });
const element = (await page.$('getById/foo'))!; const element = (await page.$(
'getById/foo'
)) as ElementHandle<HTMLDivElement>;
expect( expect(
await page.evaluate(element => { await page.evaluate(element => {
return element.id; return element.id;
@ -447,10 +457,12 @@ describe('ElementHandle specs', function () {
); );
puppeteer.registerCustomQueryHandler('getByClass', { puppeteer.registerCustomQueryHandler('getByClass', {
queryAll: (_element, selector) => { queryAll: (_element, selector) => {
return document.querySelectorAll(`.${selector}`); return [...document.querySelectorAll(`.${selector}`)];
}, },
}); });
const elements = await page.$$('getByClass/foo'); const elements = (await page.$$('getByClass/foo')) as Array<
ElementHandle<HTMLDivElement>
>;
const classNames = await Promise.all( const classNames = await Promise.all(
elements.map(async element => { elements.map(async element => {
return await page.evaluate(element => { return await page.evaluate(element => {
@ -468,7 +480,7 @@ describe('ElementHandle specs', function () {
); );
puppeteer.registerCustomQueryHandler('getByClass', { puppeteer.registerCustomQueryHandler('getByClass', {
queryAll: (_element, selector) => { queryAll: (_element, selector) => {
return document.querySelectorAll(`.${selector}`); return [...document.querySelectorAll(`.${selector}`)];
}, },
}); });
const elements = await page.$$eval('getByClass/foo', divs => { const elements = await page.$$eval('getByClass/foo', divs => {
@ -481,7 +493,7 @@ describe('ElementHandle specs', function () {
const {page, puppeteer} = getTestState(); const {page, puppeteer} = getTestState();
puppeteer.registerCustomQueryHandler('getByClass', { puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => { queryOne: (element, selector) => {
return element.querySelector(`.${selector}`); return (element as Element).querySelector(`.${selector}`);
}, },
}); });
const waitFor = page.waitForSelector('getByClass/foo'); const waitFor = page.waitForSelector('getByClass/foo');
@ -499,10 +511,12 @@ describe('ElementHandle specs', function () {
const {page, puppeteer} = getTestState(); const {page, puppeteer} = getTestState();
puppeteer.registerCustomQueryHandler('getByClass', { puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => { queryOne: (element, selector) => {
return element.querySelector(`.${selector}`); return (element as Element).querySelector(`.${selector}`);
}, },
}); });
const waitFor = page.waitForSelector('getByClass/foo'); const waitFor = page.waitForSelector('getByClass/foo') as Promise<
ElementHandle<HTMLElement>
>;
// Set the page content after the waitFor has been started. // Set the page content after the waitFor has been started.
await page.setContent( await page.setContent(
@ -511,7 +525,9 @@ describe('ElementHandle specs', function () {
let element = (await waitFor)!; let element = (await waitFor)!;
expect(element).toBeDefined(); expect(element).toBeDefined();
const innerWaitFor = element.waitForSelector('getByClass/bar'); const innerWaitFor = element.waitForSelector('getByClass/bar') as Promise<
ElementHandle<HTMLElement>
>;
await element.evaluate(el => { await element.evaluate(el => {
el.innerHTML = '<div class="bar">bar1</div>'; el.innerHTML = '<div class="bar">bar1</div>';
@ -521,7 +537,7 @@ describe('ElementHandle specs', function () {
expect(element).toBeDefined(); expect(element).toBeDefined();
expect( expect(
await element.evaluate(el => { await element.evaluate(el => {
return (el as HTMLElement).innerText; return el.innerText;
}) })
).toStrictEqual('bar1'); ).toStrictEqual('bar1');
}); });
@ -532,7 +548,7 @@ describe('ElementHandle specs', function () {
const {page, puppeteer} = getTestState(); const {page, puppeteer} = getTestState();
puppeteer.registerCustomQueryHandler('getByClass', { puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => { queryOne: (element, selector) => {
return element.querySelector(`.${selector}`); return (element as Element).querySelector(`.${selector}`);
}, },
}); });
const waitFor = page.waitForSelector('getByClass/foo'); const waitFor = page.waitForSelector('getByClass/foo');
@ -552,10 +568,10 @@ describe('ElementHandle specs', function () {
); );
puppeteer.registerCustomQueryHandler('getByClass', { puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => { queryOne: (element, selector) => {
return element.querySelector(`.${selector}`); return (element as Element).querySelector(`.${selector}`);
}, },
queryAll: (element, selector) => { queryAll: (element, selector) => {
return element.querySelectorAll(`.${selector}`); return [...(element as Element).querySelectorAll(`.${selector}`)];
}, },
}); });
@ -572,10 +588,10 @@ describe('ElementHandle specs', function () {
); );
puppeteer.registerCustomQueryHandler('getByClass', { puppeteer.registerCustomQueryHandler('getByClass', {
queryOne: (element, selector) => { queryOne: (element, selector) => {
return element.querySelector(`.${selector}`); return (element as Element).querySelector(`.${selector}`);
}, },
queryAll: (element, selector) => { queryAll: (element, selector) => {
return element.querySelectorAll(`.${selector}`); return [...(element as Element).querySelectorAll(`.${selector}`)];
}, },
}); });

View File

@ -399,7 +399,7 @@ describe('JSHandle', function () {
itFailsFirefox('should work', async () => { itFailsFirefox('should work', async () => {
const {page} = getTestState(); const {page} = getTestState();
const clicks: [x: number, y: number][] = []; const clicks: Array<[x: number, y: number]> = [];
await page.exposeFunction('reportClick', (x: number, y: number): void => { await page.exposeFunction('reportClick', (x: number, y: number): void => {
clicks.push([x, y]); clicks.push([x, y]);

View File

@ -20,6 +20,7 @@ import {
setupTestPageAndContextHooks, setupTestPageAndContextHooks,
} from './mocha-utils.js'; } from './mocha-utils.js';
import {CustomQueryHandler} from '../../lib/cjs/puppeteer/common/QueryHandler.js'; import {CustomQueryHandler} from '../../lib/cjs/puppeteer/common/QueryHandler.js';
import {ElementHandle} from '../../lib/cjs/puppeteer/common/ElementHandle.js';
describe('querySelector', function () { describe('querySelector', function () {
setupTestBrowserHooks(); setupTestBrowserHooks();
@ -99,18 +100,20 @@ describe('querySelector', function () {
}); });
it('should find first element in shadow', async () => { it('should find first element in shadow', async () => {
const {page} = getTestState(); const {page} = getTestState();
const div = (await page.$('pierce/.foo'))!; const div = (await page.$('pierce/.foo')) as ElementHandle<HTMLElement>;
const text = await div.evaluate((element: Element) => { const text = await div.evaluate(element => {
return element.textContent; return element.textContent;
}); });
expect(text).toBe('Hello'); expect(text).toBe('Hello');
}); });
it('should find all elements in shadow', async () => { it('should find all elements in shadow', async () => {
const {page} = getTestState(); const {page} = getTestState();
const divs = await page.$$('pierce/.foo'); const divs = (await page.$$('pierce/.foo')) as Array<
ElementHandle<HTMLElement>
>;
const text = await Promise.all( const text = await Promise.all(
divs.map(div => { divs.map(div => {
return div.evaluate((element: Element) => { return div.evaluate(element => {
return element.textContent; return element.textContent;
}); });
}) })
@ -120,8 +123,10 @@ describe('querySelector', function () {
it('should find first child element', async () => { it('should find first child element', async () => {
const {page} = getTestState(); const {page} = getTestState();
const parentElement = (await page.$('html > div'))!; const parentElement = (await page.$('html > div'))!;
const childElement = (await parentElement.$('pierce/div'))!; const childElement = (await parentElement.$(
const text = await childElement.evaluate((element: Element) => { 'pierce/div'
)) as ElementHandle<HTMLElement>;
const text = await childElement.evaluate(element => {
return element.textContent; return element.textContent;
}); });
expect(text).toBe('Hello'); expect(text).toBe('Hello');
@ -129,10 +134,12 @@ describe('querySelector', function () {
it('should find all child elements', async () => { it('should find all child elements', async () => {
const {page} = getTestState(); const {page} = getTestState();
const parentElement = (await page.$('html > div'))!; const parentElement = (await page.$('html > div'))!;
const childElements = await parentElement.$$('pierce/div'); const childElements = (await parentElement.$$('pierce/div')) as Array<
ElementHandle<HTMLElement>
>;
const text = await Promise.all( const text = await Promise.all(
childElements.map(div => { childElements.map(div => {
return div.evaluate((element: Element) => { return div.evaluate(element => {
return element.textContent; return element.textContent;
}); });
}) })
@ -456,10 +463,7 @@ describe('querySelector', function () {
describe('QueryAll', function () { describe('QueryAll', function () {
const handler: CustomQueryHandler = { const handler: CustomQueryHandler = {
queryAll: (element, selector) => { queryAll: (element, selector) => {
if (element instanceof Document || element instanceof Element) { return [...(element as Element).querySelectorAll(selector)];
return element.querySelectorAll(selector);
}
return [];
}, },
}; };
before(() => { before(() => {

View File

@ -111,10 +111,7 @@ export async function navigateFrame(
} }
} }
export const dumpFrames = ( export const dumpFrames = (frame: Frame, indentation?: string): string[] => {
frame: Frame,
indentation?: string
): Array<string> => {
indentation = indentation || ''; indentation = indentation || '';
let description = frame.url().replace(/:\d{4,5}\//, ':<PORT>/'); let description = frame.url().replace(/:\d{4,5}\//, ':<PORT>/');
if (frame.name()) { if (frame.name()) {

View File

@ -672,7 +672,7 @@ export class MarkdownDocumenter {
headerTitles: ['Type Alias', 'Description'], headerTitles: ['Type Alias', 'Description'],
}); });
const apiMembers: ReadonlyArray<ApiItem> = const apiMembers: readonly ApiItem[] =
apiContainer.kind === ApiItemKind.Package apiContainer.kind === ApiItemKind.Package
? (apiContainer as ApiPackage).entryPoints[0]!.members ? (apiContainer as ApiPackage).entryPoints[0]!.members
: (apiContainer as ApiNamespace).members; : (apiContainer as ApiNamespace).members;