refactor: include the cause into locator abort and timeout errors (#12207)

This commit is contained in:
Alex Rudenko 2024-04-05 11:18:24 +02:00 committed by GitHub
parent bb10e45696
commit 17e9fee77b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 20 additions and 11 deletions

View File

@ -172,19 +172,23 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
});
},
retryAndRaceWithSignalAndTimer: <T>(
signal?: AbortSignal
signal?: AbortSignal,
cause?: Error
): OperatorFunction<T, T> => {
const candidates = [];
if (signal) {
candidates.push(
fromEvent(signal, 'abort').pipe(
map(() => {
if (signal.reason instanceof Error) {
signal.reason.cause = cause;
}
throw signal.reason;
})
)
);
}
candidates.push(timeout(this._timeout));
candidates.push(timeout(this._timeout, cause));
return pipe(
retry({delay: RETRY_DELAY}),
raceWith<T, never[]>(...candidates)
@ -368,6 +372,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
options?: Readonly<LocatorClickOptions>
): Observable<void> {
const signal = options?.signal;
const cause = new Error('Locator.click');
return this._wait(options).pipe(
this.operators.conditions(
[
@ -388,7 +393,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
})
);
}),
this.operators.retryAndRaceWithSignalAndTimer(signal)
this.operators.retryAndRaceWithSignalAndTimer(signal, cause)
);
}
@ -398,6 +403,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
options?: Readonly<ActionOptions>
): Observable<void> {
const signal = options?.signal;
const cause = new Error('Locator.fill');
return this._wait(options).pipe(
this.operators.conditions(
[
@ -521,7 +527,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
})
);
}),
this.operators.retryAndRaceWithSignalAndTimer(signal)
this.operators.retryAndRaceWithSignalAndTimer(signal, cause)
);
}
@ -530,6 +536,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
options?: Readonly<ActionOptions>
): Observable<void> {
const signal = options?.signal;
const cause = new Error('Locator.hover');
return this._wait(options).pipe(
this.operators.conditions(
[
@ -549,7 +556,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
})
);
}),
this.operators.retryAndRaceWithSignalAndTimer(signal)
this.operators.retryAndRaceWithSignalAndTimer(signal, cause)
);
}
@ -558,6 +565,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
options?: Readonly<LocatorScrollOptions>
): Observable<void> {
const signal = options?.signal;
const cause = new Error('Locator.scroll');
return this._wait(options).pipe(
this.operators.conditions(
[
@ -590,7 +598,7 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
})
);
}),
this.operators.retryAndRaceWithSignalAndTimer(signal)
this.operators.retryAndRaceWithSignalAndTimer(signal, cause)
);
}
@ -617,9 +625,10 @@ export abstract class Locator<T> extends EventEmitter<LocatorEvents> {
* @public
*/
async waitHandle(options?: Readonly<ActionOptions>): Promise<HandleFor<T>> {
const cause = new Error('Locator.waitHandle');
return await firstValueFrom(
this._wait(options).pipe(
this.operators.retryAndRaceWithSignalAndTimer(options?.signal)
this.operators.retryAndRaceWithSignalAndTimer(options?.signal, cause)
)
);
}

View File

@ -13,8 +13,8 @@ export class PuppeteerError extends Error {
/**
* @internal
*/
constructor(message?: string) {
super(message);
constructor(message?: string, options?: ErrorOptions) {
super(message, options);
this.name = this.constructor.name;
}

View File

@ -312,12 +312,12 @@ export function validateDialogType(
/**
* @internal
*/
export function timeout(ms: number): Observable<never> {
export function timeout(ms: number, cause?: Error): Observable<never> {
return ms === 0
? NEVER
: timer(ms).pipe(
map(() => {
throw new TimeoutError(`Timed out after waiting ${ms}ms`);
throw new TimeoutError(`Timed out after waiting ${ms}ms`, {cause});
})
);
}