mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat(types): add types for page.$$eval
(#6139)
* feat(types): add types for `page.$$eval` * Add new-docs for $$eval * fix example * linting
This commit is contained in:
parent
f7857d27c4
commit
5049b83186
@ -11,7 +11,7 @@ If `pageFunction` returns a Promise, then `frame.$$eval` would wait for the prom
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
$$eval<ReturnType extends any>(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise<ReturnType>;
|
$$eval<ReturnType>(selector: string, pageFunction: (elements: Element[], ...args: unknown[]) => ReturnType | Promise<ReturnType>, ...args: SerializableOrJSHandle[]): Promise<WrapElementHandle<ReturnType>>;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
@ -19,12 +19,12 @@ $$eval<ReturnType extends any>(selector: string, pageFunction: EvaluateFn | stri
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| selector | string | |
|
| selector | string | |
|
||||||
| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | |
|
| pageFunction | (elements: Element\[\], ...args: unknown\[\]) => ReturnType \| Promise<ReturnType> | |
|
||||||
| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)<!-- -->\[\] | |
|
| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)<!-- -->\[\] | |
|
||||||
|
|
||||||
<b>Returns:</b>
|
<b>Returns:</b>
|
||||||
|
|
||||||
Promise<ReturnType>
|
Promise<[WrapElementHandle](./puppeteer.wrapelementhandle.md)<!-- --><ReturnType>>
|
||||||
|
|
||||||
## Example 1
|
## Example 1
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
$$eval<ReturnType extends any>(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise<ReturnType>;
|
$$eval<ReturnType>(selector: string, pageFunction: (elements: Element[], ...args: unknown[]) => ReturnType | Promise<ReturnType>, ...args: SerializableOrJSHandle[]): Promise<WrapElementHandle<ReturnType>>;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
@ -15,10 +15,10 @@ $$eval<ReturnType extends any>(selector: string, pageFunction: EvaluateFn | stri
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| selector | string | |
|
| selector | string | |
|
||||||
| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | |
|
| pageFunction | (elements: Element\[\], ...args: unknown\[\]) => ReturnType \| Promise<ReturnType> | |
|
||||||
| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)<!-- -->\[\] | |
|
| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)<!-- -->\[\] | |
|
||||||
|
|
||||||
<b>Returns:</b>
|
<b>Returns:</b>
|
||||||
|
|
||||||
Promise<ReturnType>
|
Promise<[WrapElementHandle](./puppeteer.wrapelementhandle.md)<!-- --><ReturnType>>
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ This method runs `Array.from(document.querySelectorAll(selector))` within the pa
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
$$eval<ReturnType extends any>(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise<ReturnType>;
|
$$eval<ReturnType>(selector: string, pageFunction: (elements: Element[], ...args: unknown[]) => ReturnType | Promise<ReturnType>, ...args: SerializableOrJSHandle[]): Promise<WrapElementHandle<ReturnType>>;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
@ -17,14 +17,14 @@ $$eval<ReturnType extends any>(selector: string, pageFunction: EvaluateFn | stri
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| selector | string | the [selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) to query for |
|
| selector | string | the [selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) to query for |
|
||||||
| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | the function to be evaluated in the page context. Will be passed the result of <code>Array.from(document.querySelectorAll(selector))</code> as its first argument. |
|
| pageFunction | (elements: Element\[\], ...args: unknown\[\]) => ReturnType \| Promise<ReturnType> | the function to be evaluated in the page context. Will be passed the result of <code>Array.from(document.querySelectorAll(selector))</code> as its first argument. |
|
||||||
| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)<!-- -->\[\] | any additional arguments to pass through to <code>pageFunction</code>. |
|
| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)<!-- -->\[\] | any additional arguments to pass through to <code>pageFunction</code>. |
|
||||||
|
|
||||||
<b>Returns:</b>
|
<b>Returns:</b>
|
||||||
|
|
||||||
Promise<ReturnType>
|
Promise<[WrapElementHandle](./puppeteer.wrapelementhandle.md)<!-- --><ReturnType>>
|
||||||
|
|
||||||
The result of calling `pageFunction`<!-- -->.
|
The result of calling `pageFunction`<!-- -->. If it returns an element it is wrapped in an [ElementHandle](./puppeteer.elementhandle.md)<!-- -->, else the raw value itself is returned.
|
||||||
|
|
||||||
## Remarks
|
## Remarks
|
||||||
|
|
||||||
@ -33,17 +33,40 @@ If `pageFunction` returns a promise `$$eval` will wait for the promise to resolv
|
|||||||
## Example 1
|
## Example 1
|
||||||
|
|
||||||
|
|
||||||
```js
|
```
|
||||||
|
// get the amount of divs on the page
|
||||||
const divCount = await page.$$eval('div', divs => divs.length);
|
const divCount = await page.$$eval('div', divs => divs.length);
|
||||||
|
|
||||||
|
// get the text content of all the `.options` elements:
|
||||||
|
const options = await page.$$eval('div > span.options', options => {
|
||||||
|
return options.map(option => option.textContent)
|
||||||
|
});
|
||||||
|
|
||||||
```
|
```
|
||||||
|
If you are using TypeScript, you may have to provide an explicit type to the first argument of the `pageFunction`<!-- -->. By default it is typed as `Element[]`<!-- -->, but you may need to provide a more specific sub-type:
|
||||||
|
|
||||||
## Example 2
|
## Example 2
|
||||||
|
|
||||||
|
|
||||||
```js
|
```
|
||||||
const options = await page.$$eval(
|
// if you don't provide HTMLInputElement here, TS will error
|
||||||
'div > span.options', options => options.map(option => option.textContent));
|
// as `value` is not on `Element`
|
||||||
|
await page.$$eval('input', (elements: HTMLInputElement[]) => {
|
||||||
|
return elements.map(e => e.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
The compiler should be able to infer the return type from the `pageFunction` you provide. If it is unable to, you can use the generic type to tell the compiler what return type you expect from `$$eval`<!-- -->:
|
||||||
|
|
||||||
|
## Example 3
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
// The compiler can infer the return type in this case, but if it can't
|
||||||
|
// or if you want to be more explicit, provide it as the generic type.
|
||||||
|
const allInputValues = await page.$$eval<string[]>(
|
||||||
|
'input', (elements: HTMLInputElement[]) => elements.map(e => e.textContent)
|
||||||
|
);
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import { MouseButton } from './Input';
|
|||||||
import { FrameManager, Frame } from './FrameManager';
|
import { FrameManager, Frame } from './FrameManager';
|
||||||
import { getQueryHandlerAndSelector, QueryHandler } from './QueryHandler';
|
import { getQueryHandlerAndSelector, QueryHandler } from './QueryHandler';
|
||||||
import {
|
import {
|
||||||
EvaluateFn,
|
|
||||||
SerializableOrJSHandle,
|
SerializableOrJSHandle,
|
||||||
EvaluateHandleFn,
|
EvaluateHandleFn,
|
||||||
WrapElementHandle,
|
WrapElementHandle,
|
||||||
@ -172,11 +171,14 @@ export class DOMWorld {
|
|||||||
return document.$eval<ReturnType>(selector, pageFunction, ...args);
|
return document.$eval<ReturnType>(selector, pageFunction, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
async $$eval<ReturnType extends any>(
|
async $$eval<ReturnType>(
|
||||||
selector: string,
|
selector: string,
|
||||||
pageFunction: EvaluateFn | string,
|
pageFunction: (
|
||||||
|
elements: Element[],
|
||||||
|
...args: unknown[]
|
||||||
|
) => ReturnType | Promise<ReturnType>,
|
||||||
...args: SerializableOrJSHandle[]
|
...args: SerializableOrJSHandle[]
|
||||||
): Promise<ReturnType> {
|
): Promise<WrapElementHandle<ReturnType>> {
|
||||||
const document = await this._document();
|
const document = await this._document();
|
||||||
const value = await document.$$eval<ReturnType>(
|
const value = await document.$$eval<ReturnType>(
|
||||||
selector,
|
selector,
|
||||||
|
@ -30,7 +30,6 @@ import { Page } from './Page';
|
|||||||
import { HTTPResponse } from './HTTPResponse';
|
import { HTTPResponse } from './HTTPResponse';
|
||||||
import Protocol from '../protocol';
|
import Protocol from '../protocol';
|
||||||
import {
|
import {
|
||||||
EvaluateFn,
|
|
||||||
SerializableOrJSHandle,
|
SerializableOrJSHandle,
|
||||||
EvaluateHandleFn,
|
EvaluateHandleFn,
|
||||||
WrapElementHandle,
|
WrapElementHandle,
|
||||||
@ -496,11 +495,14 @@ export class Frame {
|
|||||||
return this._mainWorld.$eval<ReturnType>(selector, pageFunction, ...args);
|
return this._mainWorld.$eval<ReturnType>(selector, pageFunction, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
async $$eval<ReturnType extends any>(
|
async $$eval<ReturnType>(
|
||||||
selector: string,
|
selector: string,
|
||||||
pageFunction: EvaluateFn | string,
|
pageFunction: (
|
||||||
|
elements: Element[],
|
||||||
|
...args: unknown[]
|
||||||
|
) => ReturnType | Promise<ReturnType>,
|
||||||
...args: SerializableOrJSHandle[]
|
...args: SerializableOrJSHandle[]
|
||||||
): Promise<ReturnType> {
|
): Promise<WrapElementHandle<ReturnType>> {
|
||||||
return this._mainWorld.$$eval<ReturnType>(selector, pageFunction, ...args);
|
return this._mainWorld.$$eval<ReturnType>(selector, pageFunction, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,11 +882,14 @@ export class ElementHandle<
|
|||||||
* .toEqual(['Hello!', 'Hi!']);
|
* .toEqual(['Hello!', 'Hi!']);
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
async $$eval<ReturnType extends any>(
|
async $$eval<ReturnType>(
|
||||||
selector: string,
|
selector: string,
|
||||||
pageFunction: EvaluateFn | string,
|
pageFunction: (
|
||||||
|
elements: Element[],
|
||||||
|
...args: unknown[]
|
||||||
|
) => ReturnType | Promise<ReturnType>,
|
||||||
...args: SerializableOrJSHandle[]
|
...args: SerializableOrJSHandle[]
|
||||||
): Promise<ReturnType> {
|
): Promise<WrapElementHandle<ReturnType>> {
|
||||||
const defaultHandler = (element: Element, selector: string) =>
|
const defaultHandler = (element: Element, selector: string) =>
|
||||||
Array.from(element.querySelectorAll(selector));
|
Array.from(element.querySelectorAll(selector));
|
||||||
const { updatedSelector, queryHandler } = getQueryHandlerAndSelector(
|
const { updatedSelector, queryHandler } = getQueryHandlerAndSelector(
|
||||||
@ -898,12 +901,17 @@ export class ElementHandle<
|
|||||||
queryHandler,
|
queryHandler,
|
||||||
updatedSelector
|
updatedSelector
|
||||||
);
|
);
|
||||||
const result = await arrayHandle.evaluate<(...args: any[]) => ReturnType>(
|
const result = await arrayHandle.evaluate<
|
||||||
pageFunction,
|
(
|
||||||
...args
|
elements: Element[],
|
||||||
);
|
...args: unknown[]
|
||||||
|
) => ReturnType | Promise<ReturnType>
|
||||||
|
>(pageFunction, ...args);
|
||||||
await arrayHandle.dispose();
|
await arrayHandle.dispose();
|
||||||
return result;
|
/* This as exists for the same reason as the `as` in $eval above.
|
||||||
|
* See the comment there for a ful explanation.
|
||||||
|
*/
|
||||||
|
return result as WrapElementHandle<ReturnType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +43,6 @@ import { ConsoleMessage, ConsoleMessageType } from './ConsoleMessage';
|
|||||||
import { PuppeteerLifeCycleEvent } from './LifecycleWatcher';
|
import { PuppeteerLifeCycleEvent } from './LifecycleWatcher';
|
||||||
import Protocol from '../protocol';
|
import Protocol from '../protocol';
|
||||||
import {
|
import {
|
||||||
EvaluateFn,
|
|
||||||
SerializableOrJSHandle,
|
SerializableOrJSHandle,
|
||||||
EvaluateHandleFn,
|
EvaluateHandleFn,
|
||||||
WrapElementHandle,
|
WrapElementHandle,
|
||||||
@ -795,31 +794,70 @@ export class Page extends EventEmitter {
|
|||||||
* resolve and then return its value.
|
* resolve and then return its value.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```js
|
*
|
||||||
* const divCount = await page.$$eval('div', divs => divs.length);
|
|
||||||
* ```
|
* ```
|
||||||
|
* // get the amount of divs on the page
|
||||||
|
* const divCount = await page.$$eval('div', divs => divs.length);
|
||||||
|
*
|
||||||
|
* // get the text content of all the `.options` elements:
|
||||||
|
* const options = await page.$$eval('div > span.options', options => {
|
||||||
|
* return options.map(option => option.textContent)
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If you are using TypeScript, you may have to provide an explicit type to the
|
||||||
|
* first argument of the `pageFunction`.
|
||||||
|
* By default it is typed as `Element[]`, but you may need to provide a more
|
||||||
|
* specific sub-type:
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```js
|
*
|
||||||
* const options = await page.$$eval(
|
* ```
|
||||||
* 'div > span.options', options => options.map(option => option.textContent));
|
* // if you don't provide HTMLInputElement here, TS will error
|
||||||
|
* // as `value` is not on `Element`
|
||||||
|
* await page.$$eval('input', (elements: HTMLInputElement[]) => {
|
||||||
|
* return elements.map(e => e.value);
|
||||||
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param selector - the
|
* The compiler should be able to infer the return type
|
||||||
|
* from the `pageFunction` you provide. If it is unable to, you can use the generic
|
||||||
|
* type to tell the compiler what return type you expect from `$$eval`:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* // The compiler can infer the return type in this case, but if it can't
|
||||||
|
* // or if you want to be more explicit, provide it as the generic type.
|
||||||
|
* const allInputValues = await page.$$eval<string[]>(
|
||||||
|
* 'input', (elements: HTMLInputElement[]) => elements.map(e => e.textContent)
|
||||||
|
* );
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param selector the
|
||||||
* {@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 for
|
* to query for
|
||||||
* @param pageFunction - the function to be evaluated in the page context.
|
* @param pageFunction the function to be evaluated in the page context. Will
|
||||||
* Will be passed the result of
|
* be passed the result of `Array.from(document.querySelectorAll(selector))`
|
||||||
* `Array.from(document.querySelectorAll(selector))` as its first argument.
|
* as its first argument.
|
||||||
* @param args - any additional arguments to pass through to `pageFunction`.
|
* @param args any additional arguments to pass through to `pageFunction`.
|
||||||
*
|
*
|
||||||
* @returns The result of calling `pageFunction`.
|
* @returns The result of calling `pageFunction`. If it returns an element it
|
||||||
|
* is wrapped in an {@link ElementHandle}, else the raw value itself is
|
||||||
|
* returned.
|
||||||
*/
|
*/
|
||||||
async $$eval<ReturnType extends any>(
|
async $$eval<ReturnType>(
|
||||||
selector: string,
|
selector: string,
|
||||||
pageFunction: EvaluateFn | string,
|
pageFunction: (
|
||||||
|
elements: Element[],
|
||||||
|
/* These have to be typed as unknown[] for the same reason as the $eval
|
||||||
|
* definition above, please see that comment for more details and the TODO
|
||||||
|
* that will improve things.
|
||||||
|
*/
|
||||||
|
...args: unknown[]
|
||||||
|
) => ReturnType | Promise<ReturnType>,
|
||||||
...args: SerializableOrJSHandle[]
|
...args: SerializableOrJSHandle[]
|
||||||
): Promise<ReturnType> {
|
): Promise<WrapElementHandle<ReturnType>> {
|
||||||
return this.mainFrame().$$eval<ReturnType>(selector, pageFunction, ...args);
|
return this.mainFrame().$$eval<ReturnType>(selector, pageFunction, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ describe('querySelector', function () {
|
|||||||
'<html><body><div class="tweet"><div class="like">100</div><div class="like">10</div></div></body></html>'
|
'<html><body><div class="tweet"><div class="like">100</div><div class="like">10</div></div></body></html>'
|
||||||
);
|
);
|
||||||
const tweet = await page.$('.tweet');
|
const tweet = await page.$('.tweet');
|
||||||
const content = await tweet.$$eval('.like', (nodes) =>
|
const content = await tweet.$$eval('.like', (nodes: HTMLElement[]) =>
|
||||||
nodes.map((n) => n.innerText)
|
nodes.map((n) => n.innerText)
|
||||||
);
|
);
|
||||||
expect(content).toEqual(['100', '10']);
|
expect(content).toEqual(['100', '10']);
|
||||||
@ -231,7 +231,7 @@ describe('querySelector', function () {
|
|||||||
'<div class="a">not-a-child-div</div><div id="myId"><div class="a">a1-child-div</div><div class="a">a2-child-div</div></div>';
|
'<div class="a">not-a-child-div</div><div id="myId"><div class="a">a1-child-div</div><div class="a">a2-child-div</div></div>';
|
||||||
await page.setContent(htmlContent);
|
await page.setContent(htmlContent);
|
||||||
const elementHandle = await page.$('#myId');
|
const elementHandle = await page.$('#myId');
|
||||||
const content = await elementHandle.$$eval('.a', (nodes) =>
|
const content = await elementHandle.$$eval('.a', (nodes: HTMLElement[]) =>
|
||||||
nodes.map((n) => n.innerText)
|
nodes.map((n) => n.innerText)
|
||||||
);
|
);
|
||||||
expect(content).toEqual(['a1-child-div', 'a2-child-div']);
|
expect(content).toEqual(['a1-child-div', 'a2-child-div']);
|
||||||
|
Loading…
Reference in New Issue
Block a user