chore(test runner): make timeout error an Error (#29515)

This commit is contained in:
Dmitry Gozman 2024-02-15 11:38:13 -08:00 committed by GitHub
parent bd5403dcad
commit 08afb34c14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 17 additions and 16 deletions

View File

@ -31,13 +31,14 @@ const PLAYWRIGHT_TEST_PATH = path.join(__dirname, '..');
const PLAYWRIGHT_CORE_PATH = path.dirname(require.resolve('playwright-core/package.json')); const PLAYWRIGHT_CORE_PATH = path.dirname(require.resolve('playwright-core/package.json'));
export function filterStackTrace(e: Error): { message: string, stack: string } { export function filterStackTrace(e: Error): { message: string, stack: string } {
const name = e.name ? e.name + ': ' : '';
if (process.env.PWDEBUGIMPL) if (process.env.PWDEBUGIMPL)
return { message: e.name + ': ' + e.message, stack: e.stack || '' }; return { message: name + e.message, stack: e.stack || '' };
const stackLines = stringifyStackFrames(filteredStackTrace(e.stack?.split('\n') || [])); const stackLines = stringifyStackFrames(filteredStackTrace(e.stack?.split('\n') || []));
return { return {
message: e.name + ': ' + e.message, message: name + e.message,
stack: `${e.name}: ${e.message}\n${stackLines.join('\n')}` stack: `${name}${e.message}${stackLines.map(line => '\n' + line).join('')}`
}; };
} }

View File

@ -226,8 +226,9 @@ export class TestInfoImpl implements TestInfo {
// consider it a timeout. // consider it a timeout.
if (!this._wasInterrupted && timeoutError && !this._didTimeout) { if (!this._wasInterrupted && timeoutError && !this._didTimeout) {
this._didTimeout = true; this._didTimeout = true;
this.errors.push(timeoutError); const serialized = serializeError(timeoutError);
this._tracing.appendForError(timeoutError); this.errors.push(serialized);
this._tracing.appendForError(serialized);
// Do not overwrite existing failure upon hook/teardown timeout. // Do not overwrite existing failure upon hook/teardown timeout.
if (this.status === 'passed' || this.status === 'skipped') if (this.status === 'passed' || this.status === 'skipped')
this.status = 'timedOut'; this.status = 'timedOut';

View File

@ -16,7 +16,6 @@
import { colors } from 'playwright-core/lib/utilsBundle'; import { colors } from 'playwright-core/lib/utilsBundle';
import { TimeoutRunner, TimeoutRunnerError } from 'playwright-core/lib/utils'; import { TimeoutRunner, TimeoutRunnerError } from 'playwright-core/lib/utils';
import type { TestInfoError } from '../../types/test';
import type { Location } from '../../types/testReporter'; import type { Location } from '../../types/testReporter';
export type TimeSlot = { export type TimeSlot = {
@ -86,7 +85,7 @@ export class TimeoutManager {
this._timeoutRunner.updateTimeout(slot.timeout); this._timeoutRunner.updateTimeout(slot.timeout);
} }
async runWithTimeout(cb: () => Promise<any>): Promise<TestInfoError | undefined> { async runWithTimeout(cb: () => Promise<any>): Promise<Error | undefined> {
try { try {
await this._timeoutRunner.run(cb); await this._timeoutRunner.run(cb);
} catch (error) { } catch (error) {
@ -127,7 +126,7 @@ export class TimeoutManager {
this._timeoutRunner.updateTimeout(slot.timeout, slot.elapsed); this._timeoutRunner.updateTimeout(slot.timeout, slot.elapsed);
} }
private _createTimeoutError(): TestInfoError { private _createTimeoutError(): Error {
let message = ''; let message = '';
const timeout = this._currentSlot().timeout; const timeout = this._currentSlot().timeout;
switch (this._runnable.type) { switch (this._runnable.type) {
@ -174,10 +173,10 @@ export class TimeoutManager {
message = `Fixture "${fixtureWithSlot.title}" timeout of ${timeout}ms exceeded during ${fixtureWithSlot.phase}.`; message = `Fixture "${fixtureWithSlot.title}" timeout of ${timeout}ms exceeded during ${fixtureWithSlot.phase}.`;
message = colors.red(message); message = colors.red(message);
const location = (fixtureWithSlot || this._runnable).location; const location = (fixtureWithSlot || this._runnable).location;
return { const error = new Error(message);
message, error.name = '';
// Include location for hooks, modifiers and fixtures to distinguish between them. // Include location for hooks, modifiers and fixtures to distinguish between them.
stack: location ? message + `\n at ${location.file}:${location.line}:${location.column}` : undefined error.stack = message + (location ? `\n at ${location.file}:${location.line}:${location.column}` : '');
}; return error;
} }
} }

View File

@ -170,7 +170,7 @@ export class WorkerMain extends ProcessRunner {
await this._fixtureRunner.teardownScope('worker', timeoutManager, e => this._fatalErrors.push(serializeError(e))); await this._fixtureRunner.teardownScope('worker', timeoutManager, e => this._fatalErrors.push(serializeError(e)));
}); });
if (timeoutError) if (timeoutError)
this._fatalErrors.push(timeoutError); this._fatalErrors.push(serializeError(timeoutError));
}); });
} }

View File

@ -354,7 +354,7 @@ test('should not report nested after hooks', async ({ runInlineTest }) => {
{ {
error: { error: {
message: 'Test timeout of 2000ms exceeded.', message: 'Test timeout of 2000ms exceeded.',
stack: '' stack: 'Test timeout of 2000ms exceeded.',
}, },
}, },
]); ]);
@ -981,7 +981,7 @@ test('should not mark page.close as failed when page.click fails', async ({ runI
{ {
error: { error: {
message: 'Test timeout of 2000ms exceeded.', message: 'Test timeout of 2000ms exceeded.',
stack: '', stack: 'Test timeout of 2000ms exceeded.',
}, },
}, },
{ {