diff --git a/packages/playwright/src/worker/testInfo.ts b/packages/playwright/src/worker/testInfo.ts index d28e123958aaf..649f20e19d52b 100644 --- a/packages/playwright/src/worker/testInfo.ts +++ b/packages/playwright/src/worker/testInfo.ts @@ -21,7 +21,7 @@ import type { TestInfoError, TestInfo, TestStatus, FullProject, FullConfig } fro import type { AttachmentPayload, StepBeginPayload, StepEndPayload, WorkerInitParams } from '../common/ipc'; import type { TestCase } from '../common/test'; import { TimeoutManager } from './timeoutManager'; -import type { RunnableType, TimeSlot, RunnableDescription } from './timeoutManager'; +import type { RunnableType, TimeSlot } from './timeoutManager'; import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config'; import type { Location } from '../../types/testReporter'; import { getContainedPath, normalizeAndSaveAttachment, serializeError, trimLongString } from '../util'; @@ -228,12 +228,6 @@ export class TestInfoImpl implements TestInfo { this.duration = this._timeoutManager.defaultSlotTimings().elapsed | 0; } - async _runWithRunnableAndFailOnError(runnable: RunnableDescription, cb: () => Promise): Promise { - return await this._timeoutManager.withRunnable(runnable, async () => { - return await this._runAndFailOnError(cb); - }); - } - async _runAndFailOnError(fn: () => Promise, skips?: 'allowSkips'): Promise { try { await fn(); diff --git a/packages/playwright/src/worker/timeoutManager.ts b/packages/playwright/src/worker/timeoutManager.ts index 56c73c8d2b63a..56b0272ebad9b 100644 --- a/packages/playwright/src/worker/timeoutManager.ts +++ b/packages/playwright/src/worker/timeoutManager.ts @@ -24,7 +24,7 @@ export type TimeSlot = { elapsed: number; }; -export type RunnableType = 'test' | 'beforeAll' | 'afterAll' | 'beforeEach' | 'afterEach' | 'slow' | 'skip' | 'fail' | 'fixme' | 'teardown'; +export type RunnableType = 'test' | 'beforeAll' | 'afterAll' | 'beforeEach' | 'afterEach' | 'afterHooks' | 'slow' | 'skip' | 'fail' | 'fixme' | 'teardown'; export type RunnableDescription = { type: RunnableType; @@ -59,7 +59,9 @@ export class TimeoutManager { async withRunnable(runnable: RunnableDescription, cb: () => Promise): Promise { const existingRunnable = this._runnable; - const effectiveRunnable = { ...this._runnable, ...runnable }; + const effectiveRunnable = { ...runnable }; + if (!effectiveRunnable.slot) + effectiveRunnable.slot = this._runnable.slot; this._updateRunnables(effectiveRunnable, undefined); try { return await cb(); @@ -129,6 +131,7 @@ export class TimeoutManager { let message = ''; const timeout = this._currentSlot().timeout; switch (this._runnable.type) { + case 'afterHooks': case 'test': { if (this._fixture) { if (this._fixture.phase === 'setup') { diff --git a/packages/playwright/src/worker/workerMain.ts b/packages/playwright/src/worker/workerMain.ts index b72b7e3450152..b01414f8895be 100644 --- a/packages/playwright/src/worker/workerMain.ts +++ b/packages/playwright/src/worker/workerMain.ts @@ -411,7 +411,7 @@ export class WorkerMain extends ProcessRunner { // A timed-out test gets a full additional timeout to run after hooks. const afterHooksSlot = testInfo._didTimeout ? { timeout: this._project.project.timeout, elapsed: 0 } : undefined; - await testInfo._runAsStepWithRunnable({ category: 'hook', title: 'After Hooks', runnableType: 'afterEach', runnableSlot: afterHooksSlot }, async step => { + await testInfo._runAsStepWithRunnable({ category: 'hook', title: 'After Hooks', runnableType: 'afterHooks', runnableSlot: afterHooksSlot }, async step => { testInfo._afterHooksStep = step; let firstAfterHooksError: TestInfoError | undefined; await testInfo._runWithTimeout(async () => { @@ -433,7 +433,7 @@ export class WorkerMain extends ProcessRunner { // Teardown test-scoped fixtures. Attribute to 'test' so that users understand // they should probably increase the test timeout to fix this issue. debugTest(`tearing down test scope started`); - const testScopeError = await testInfo._runWithRunnableAndFailOnError({ type: 'test' }, () => { + const testScopeError = await testInfo._runAndFailOnError(() => { return this._fixtureRunner.teardownScope('test', testInfo._timeoutManager); }); debugTest(`tearing down test scope finished`); @@ -463,10 +463,10 @@ export class WorkerMain extends ProcessRunner { debugTest(`running full cleanup after the failure`); const teardownSlot = { timeout: this._project.project.timeout, elapsed: 0 }; - await testInfo._timeoutManager.withRunnable({ type: 'test', slot: teardownSlot }, async () => { + await testInfo._timeoutManager.withRunnable({ type: 'teardown', slot: teardownSlot }, async () => { // Attribute to 'test' so that users understand they should probably increate the test timeout to fix this issue. debugTest(`tearing down test scope started`); - const testScopeError = await testInfo._runWithRunnableAndFailOnError({ type: 'test' }, () => { + const testScopeError = await testInfo._runAndFailOnError(() => { return this._fixtureRunner.teardownScope('test', testInfo._timeoutManager); }); debugTest(`tearing down test scope finished`); @@ -479,7 +479,7 @@ export class WorkerMain extends ProcessRunner { // Attribute to 'teardown' because worker fixtures are not perceived as a part of a test. debugTest(`tearing down worker scope started`); - const workerScopeError = await testInfo._runWithRunnableAndFailOnError({ type: 'teardown' }, () => { + const workerScopeError = await testInfo._runAndFailOnError(() => { return this._fixtureRunner.teardownScope('worker', testInfo._timeoutManager); }); debugTest(`tearing down worker scope finished`);