diff --git a/packages/runner/src/context.ts b/packages/runner/src/context.ts index dcef04bb3755..7dadb6033871 100644 --- a/packages/runner/src/context.ts +++ b/packages/runner/src/context.ts @@ -54,6 +54,13 @@ export function withTimeout any>( function resolve(result: unknown) { clearTimeout(timer) + // if test/hook took too long in microtask, setTimeout won't be triggered, + // but we still need to fail the test, see + // https://github.com/vitest-dev/vitest/issues/2920 + if (now() - startTime >= timeout) { + reject_(new Error(makeTimeoutMsg(isHook, timeout))) + return + } resolve_(result) } @@ -68,20 +75,7 @@ export function withTimeout any>( // the result is a thenable, we don't wrap this in Promise.resolve // to avoid creating new promises if (typeof result === 'object' && result != null && typeof result.then === 'function') { - result.then( - (result) => { - // if sync test/hook took too long, setTimeout won't be triggered, - // but we still need to fail the test, see - // https://github.com/vitest-dev/vitest/issues/2920 - if (now() - startTime >= timeout) { - reject(new Error(makeTimeoutMsg(isHook, timeout))) - } - else { - resolve(result) - } - }, - reject, - ) + result.then(resolve, reject) } else { resolve(result) diff --git a/test/cli/fixtures/fails/test-timeout.test.ts b/test/cli/fixtures/fails/test-timeout.test.ts index afb5b6658c86..91bdfc9e4efe 100644 --- a/test/cli/fixtures/fails/test-timeout.test.ts +++ b/test/cli/fixtures/fails/test-timeout.test.ts @@ -1,4 +1,4 @@ -import { expect, suite, test } from 'vitest' +import { beforeAll, beforeEach, expect, suite, test } from 'vitest' test('hi', async () => { await new Promise(resolve => setTimeout(resolve, 1000)) @@ -11,6 +11,24 @@ test('timeout on long synchronous task', async () => { } }, 15) +suite('timeout beforeAll', () => { + beforeAll(() => { + const start = Date.now(); + while (Date.now() < start + 20) {} + }, 16) + + test("ok", () => {}) +}) + +suite('timeout beforeEach', () => { + beforeEach(() => { + const start = Date.now(); + while (Date.now() < start + 20) {} + }, 17) + + test("ok", () => {}) +}) + suite('suite timeout', { timeout: 100, }, () => { diff --git a/test/cli/test/__snapshots__/fails.test.ts.snap b/test/cli/test/__snapshots__/fails.test.ts.snap index 0d7816f06ea6..38c0ef3e2389 100644 --- a/test/cli/test/__snapshots__/fails.test.ts.snap +++ b/test/cli/test/__snapshots__/fails.test.ts.snap @@ -118,8 +118,10 @@ exports[`should fail test-timeout.test.ts 1`] = ` "Error: Test timed out in 20ms. Error: Test timed out in 200ms. Error: Test timed out in 100ms. +Error: Hook timed out in 17ms. Error: Test timed out in 15ms. -Error: Test timed out in 10ms." +Error: Test timed out in 10ms. +Error: Hook timed out in 16ms." `; exports[`should fail unhandled.test.ts 1`] = `