diff --git a/packages/playwright-test/src/workerRunner.ts b/packages/playwright-test/src/workerRunner.ts index 1aca6598aa..3e0fc66042 100644 --- a/packages/playwright-test/src/workerRunner.ts +++ b/packages/playwright-test/src/workerRunner.ts @@ -286,7 +286,9 @@ export class WorkerRunner extends EventEmitter { setCurrentTestInfo(testInfo); this.emit('testBegin', buildTestBeginPayload(testInfo)); - if (testInfo.expectedStatus === 'skipped') { + const isSkipped = testInfo.expectedStatus === 'skipped'; + if (isSkipped && nextTest) { + // Fast path - this test and skipped, and there are more tests that will handle cleanup. testInfo.status = 'skipped'; this.emit('testEnd', buildTestEndPayload(testInfo)); return; @@ -300,9 +302,11 @@ export class WorkerRunner extends EventEmitter { let shouldRunAfterEachHooks = false; await testInfo._runWithTimeout(async () => { - if (this._isStopped) { - // Getting here means that worker is requested to stop, but was not able to - // run full cleanup yet. Skip the test, but run the cleanup. + if (this._isStopped || isSkipped) { + // Two reasons to get here: + // - Last test is skipped, so we should not run the test, but run the cleanup. + // - Worker is requested to stop, but was not able to run full cleanup yet. + // We should skip the test, but run the cleanup. testInfo.status = 'skipped'; didFailBeforeAllForSuite = undefined; return; diff --git a/tests/playwright-test/hooks.spec.ts b/tests/playwright-test/hooks.spec.ts index 1734b8ab2c..15c0269a36 100644 --- a/tests/playwright-test/hooks.spec.ts +++ b/tests/playwright-test/hooks.spec.ts @@ -783,3 +783,33 @@ test('beforeAll failure should only prevent tests that are affected', async ({ r '%%test3', ]); }); + +test('afterAll should run if last test was skipped', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.js': ` + const { test } = pwt; + test.afterAll(() => console.log('after-all')); + test('test1', () => {}); + test.skip('test2', () => {}); + `, + }); + expect(result.exitCode).toBe(0); + expect(result.skipped).toBe(1); + expect(result.passed).toBe(1); + expect(result.output).toContain('after-all'); +}); + +test('afterAll should run if last test was skipped 2', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.js': ` + const { test } = pwt; + test.afterAll(() => console.log('after-all')); + test('test1', () => {}); + test('test2', () => { test.skip(); }); + `, + }); + expect(result.exitCode).toBe(0); + expect(result.skipped).toBe(1); + expect(result.passed).toBe(1); + expect(result.output).toContain('after-all'); +});