Skip to content

Commit ef1aa89

Browse files
authoredJan 17, 2025··
fix: don't await an empty timeout after every test (#7281)
1 parent 450de3b commit ef1aa89

File tree

3 files changed

+60
-16
lines changed

3 files changed

+60
-16
lines changed
 

‎packages/runner/src/context.ts

+51-13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import type {
99
import { getSafeTimers } from '@vitest/utils'
1010
import { PendingError } from './errors'
1111

12+
const now = Date.now
13+
1214
export const collectorContext: RuntimeContext = {
1315
tasks: [],
1416
currentSuite: null,
@@ -41,19 +43,55 @@ export function withTimeout<T extends (...args: any[]) => any>(
4143

4244
// this function name is used to filter error in test/cli/test/fails.test.ts
4345
return (function runWithTimeout(...args: T extends (...args: infer A) => any ? A : never) {
44-
return Promise.race([
45-
new Promise((resolve, reject) => {
46-
const timer = setTimeout(() => {
47-
clearTimeout(timer)
48-
reject(new Error(makeTimeoutMsg(isHook, timeout)))
49-
}, timeout)
50-
// `unref` might not exist in browser
51-
timer.unref?.()
52-
}),
53-
Promise.resolve(fn(...args)).then((result) => {
54-
return new Promise(resolve => setTimeout(resolve, 0, result))
55-
}),
56-
]) as Awaitable<void>
46+
const startTime = now()
47+
return new Promise((resolve_, reject_) => {
48+
const timer = setTimeout(() => {
49+
clearTimeout(timer)
50+
reject(new Error(makeTimeoutMsg(isHook, timeout)))
51+
}, timeout)
52+
// `unref` might not exist in browser
53+
timer.unref?.()
54+
55+
function resolve(result: unknown) {
56+
clearTimeout(timer)
57+
resolve_(result)
58+
}
59+
60+
function reject(error: unknown) {
61+
clearTimeout(timer)
62+
reject_(error)
63+
}
64+
65+
// sync test/hook will be caught by try/catch
66+
try {
67+
const result = fn(...args) as PromiseLike<unknown>
68+
// the result is a thenable, we don't wrap this in Promise.resolve
69+
// to avoid creating new promises
70+
if (typeof result === 'object' && result != null && typeof result.then === 'function') {
71+
result.then(
72+
(result) => {
73+
// if sync test/hook took too long, setTimeout won't be triggered,
74+
// but we still need to fail the test, see
75+
// https://github.com/vitest-dev/vitest/issues/2920
76+
if (now() - startTime >= timeout) {
77+
reject(new Error(makeTimeoutMsg(isHook, timeout)))
78+
}
79+
else {
80+
resolve(result)
81+
}
82+
},
83+
reject,
84+
)
85+
}
86+
else {
87+
resolve(result)
88+
}
89+
}
90+
// user sync test/hook throws an error
91+
catch (error) {
92+
reject(error)
93+
}
94+
})
5795
}) as T
5896
}
5997

‎test/cli/test/__snapshots__/fails.test.ts.snap

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@ exports[`should fail async-assertion.test.ts 1`] = `
77
AssertionError: expected 'xx' to be 'yy' // Object.is equality"
88
`;
99

10-
exports[`should fail concurrent-suite-deadlock.test.ts 1`] = `"Error: Test timed out in 500ms."`;
10+
exports[`should fail concurrent-suite-deadlock.test.ts 1`] = `
11+
"Error: Test timed out in 500ms.
12+
Error: Test timed out in 500ms."
13+
`;
1114

12-
exports[`should fail concurrent-test-deadlock.test.ts 1`] = `"Error: Test timed out in 500ms."`;
15+
exports[`should fail concurrent-test-deadlock.test.ts 1`] = `
16+
"Error: Test timed out in 500ms.
17+
Error: Test timed out in 500ms."
18+
`;
1319

1420
exports[`should fail each-timeout.test.ts 1`] = `"Error: Test timed out in 10ms."`;
1521

‎test/cli/test/fails.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ it.each(files)('should fail %s', async (file) => {
1818
const msg = String(stderr)
1919
.split(/\n/g)
2020
.reverse()
21-
.filter(i => i.includes('Error: ') && !i.includes('Command failed') && !i.includes('stackStr') && !i.includes('at runTest') && !i.includes('at runWithTimeout'))
21+
.filter(i => i.includes('Error: ') && !i.includes('Command failed') && !i.includes('stackStr') && !i.includes('at runTest') && !i.includes('at runWithTimeout') && !i.includes('file:'))
2222
.map(i => i.trim().replace(root, '<rootDir>'),
2323
)
2424
.join('\n')

0 commit comments

Comments
 (0)
Please sign in to comment.