refactor: use generic implementation for waitForRequest (#11753)

This commit is contained in:
jrandolf 2024-01-25 14:52:11 +01:00 committed by GitHub
parent 3698fa8aec
commit 08f761486e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 34 additions and 86 deletions

View File

@ -8,21 +8,19 @@ sidebar_label: Page.waitForRequest
```typescript ```typescript
class Page { class Page {
abstract waitForRequest( waitForRequest(
urlOrPredicate: string | ((req: HTTPRequest) => boolean | Promise<boolean>), urlOrPredicate: string | AwaitablePredicate<HTTPRequest>,
options?: { options?: WaitTimeoutOptions
timeout?: number;
}
): Promise<HTTPRequest>; ): Promise<HTTPRequest>;
} }
``` ```
## Parameters ## Parameters
| Parameter | Type | Description | | Parameter | Type | Description |
| -------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------- | | -------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------- |
| urlOrPredicate | string \| ((req: [HTTPRequest](./puppeteer.httprequest.md)) =&gt; boolean \| Promise&lt;boolean&gt;) | A URL or predicate to wait for | | urlOrPredicate | string \| [AwaitablePredicate](./puppeteer.awaitablepredicate.md)&lt;[HTTPRequest](./puppeteer.httprequest.md)&gt; | A URL or predicate to wait for |
| options | &#123; timeout?: number; &#125; | _(Optional)_ Optional waiting parameters | | options | [WaitTimeoutOptions](./puppeteer.waittimeoutoptions.md) | _(Optional)_ Optional waiting parameters |
**Returns:** **Returns:**

View File

@ -1621,10 +1621,30 @@ export abstract class Page extends EventEmitter<PageEvents> {
* `0` to disable the timeout. The default value can be changed by using the * `0` to disable the timeout. The default value can be changed by using the
* {@link Page.setDefaultTimeout} method. * {@link Page.setDefaultTimeout} method.
*/ */
abstract waitForRequest( waitForRequest(
urlOrPredicate: string | ((req: HTTPRequest) => boolean | Promise<boolean>), urlOrPredicate: string | AwaitablePredicate<HTTPRequest>,
options?: {timeout?: number} options: WaitTimeoutOptions = {}
): Promise<HTTPRequest>; ): Promise<HTTPRequest> {
const {timeout: ms = this._timeoutSettings.timeout()} = options;
if (typeof urlOrPredicate === 'string') {
const url = urlOrPredicate;
urlOrPredicate = (request: HTTPRequest) => {
return request.url() === url;
};
}
const observable$ = fromEmitterEvent(this, PageEvent.Request).pipe(
filterAsync(urlOrPredicate),
raceWith(
timeout(ms),
fromEmitterEvent(this, PageEvent.Close).pipe(
map(() => {
throw new TargetCloseError('Page closed!');
})
)
)
);
return firstValueFrom(observable$);
}
/** /**
* @param urlOrPredicate - A URL or predicate to wait for. * @param urlOrPredicate - A URL or predicate to wait for.
@ -1660,8 +1680,8 @@ export abstract class Page extends EventEmitter<PageEvents> {
const {timeout: ms = this._timeoutSettings.timeout()} = options; const {timeout: ms = this._timeoutSettings.timeout()} = options;
if (typeof urlOrPredicate === 'string') { if (typeof urlOrPredicate === 'string') {
const url = urlOrPredicate; const url = urlOrPredicate;
urlOrPredicate = (request: HTTPResponse) => { urlOrPredicate = (response: HTTPResponse) => {
return request.url() === url; return response.url() === url;
}; };
} }
const observable$ = fromEmitterEvent(this, PageEvent.Response).pipe( const observable$ = fromEmitterEvent(this, PageEvent.Response).pipe(

View File

@ -51,7 +51,6 @@ import {
parsePDFOptions, parsePDFOptions,
timeout, timeout,
validateDialogType, validateDialogType,
waitForHTTP,
} from '../common/util.js'; } from '../common/util.js';
import type {Viewport} from '../common/Viewport.js'; import type {Viewport} from '../common/Viewport.js';
import {assert} from '../util/assert.js'; import {assert} from '../util/assert.js';
@ -702,22 +701,6 @@ export class BidiPage extends Page {
return data; return data;
} }
override async waitForRequest(
urlOrPredicate:
| string
| ((req: BidiHTTPRequest) => boolean | Promise<boolean>),
options: {timeout?: number} = {}
): Promise<BidiHTTPRequest> {
const {timeout = this._timeoutSettings.timeout()} = options;
return await waitForHTTP(
this.#networkManager,
NetworkManagerEvent.Request,
urlOrPredicate,
timeout,
this.#closedDeferred
);
}
override async waitForNetworkIdle( override async waitForNetworkIdle(
options: {idleTime?: number; timeout?: number} = {} options: {idleTime?: number; timeout?: number} = {}
): Promise<void> { ): Promise<void> {

View File

@ -46,7 +46,6 @@ import {
parsePDFOptions, parsePDFOptions,
timeout, timeout,
validateDialogType, validateDialogType,
waitForHTTP,
} from '../common/util.js'; } from '../common/util.js';
import type {Viewport} from '../common/Viewport.js'; import type {Viewport} from '../common/Viewport.js';
import {assert} from '../util/assert.js'; import {assert} from '../util/assert.js';
@ -910,20 +909,6 @@ export class CdpPage extends Page {
return await this.target().createCDPSession(); return await this.target().createCDPSession();
} }
override async waitForRequest(
urlOrPredicate: string | ((req: HTTPRequest) => boolean | Promise<boolean>),
options: {timeout?: number} = {}
): Promise<HTTPRequest> {
const {timeout = this._timeoutSettings.timeout()} = options;
return await waitForHTTP(
this.#frameManager.networkManager,
NetworkManagerEvent.Request,
urlOrPredicate,
timeout,
this.#sessionCloseDeferred
);
}
override async waitForNetworkIdle( override async waitForNetworkIdle(
options: {idleTime?: number; timeout?: number} = {} options: {idleTime?: number; timeout?: number} = {}
): Promise<void> { ): Promise<void> {

View File

@ -7,26 +7,15 @@
import type FS from 'fs/promises'; import type FS from 'fs/promises';
import type {Readable} from 'stream'; import type {Readable} from 'stream';
import { import {map, NEVER, Observable, timer} from '../../third_party/rxjs/rxjs.js';
filterAsync,
firstValueFrom,
from,
map,
NEVER,
Observable,
raceWith,
timer,
} from '../../third_party/rxjs/rxjs.js';
import type {CDPSession} from '../api/CDPSession.js'; import type {CDPSession} from '../api/CDPSession.js';
import {isNode} from '../environment.js'; import {isNode} from '../environment.js';
import {assert} from '../util/assert.js'; import {assert} from '../util/assert.js';
import type {Deferred} from '../util/Deferred.js';
import {isErrorLike} from '../util/ErrorLike.js'; import {isErrorLike} from '../util/ErrorLike.js';
import {debug} from './Debug.js'; import {debug} from './Debug.js';
import {TimeoutError} from './Errors.js'; import {TimeoutError} from './Errors.js';
import type {EventEmitter, EventType} from './EventEmitter.js'; import type {EventEmitter, EventType} from './EventEmitter.js';
import type {NetworkManagerEvents} from './NetworkManagerEvents.js';
import type { import type {
LowerCasePaperFormat, LowerCasePaperFormat,
ParsedPDFOptions, ParsedPDFOptions,
@ -338,33 +327,6 @@ export function getSourceUrlComment(url: string): string {
return `//# sourceURL=${url}`; return `//# sourceURL=${url}`;
} }
/**
* @internal
*/
export async function waitForHTTP<T extends {url(): string}>(
networkManager: EventEmitter<NetworkManagerEvents>,
eventName: EventType,
urlOrPredicate: string | ((res: T) => boolean | Promise<boolean>),
/** Time after the function will timeout */
ms: number,
cancelation: Deferred<never>
): Promise<T> {
return await firstValueFrom(
(fromEmitterEvent(networkManager, eventName) as Observable<T>).pipe(
filterAsync(async http => {
if (isString(urlOrPredicate)) {
return urlOrPredicate === http.url();
}
if (typeof urlOrPredicate === 'function') {
return !!(await urlOrPredicate(http));
}
return false;
}),
raceWith(timeout(ms), from(cancelation.valueOrThrow()))
)
);
}
/** /**
* @internal * @internal
*/ */