Skip to content

Commit 819e62d

Browse files
committed
fix(tests): keep a real-wait flagged before the fake-timer install in its own hook
A beforeEach/beforeAll that installs fake timers covered its whole suite, including waits earlier in the same hook body, which run on the real clock. Only waits after the install in that hook are exempt now; tests and other hooks in the suite keep the exemption.
1 parent 0d30805 commit 819e62d

2 files changed

Lines changed: 29 additions & 5 deletions

File tree

‎scripts/check-test-patterns.test.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,20 @@ describe('real-wait', () => {
146146
],
147147
['sleep() #1'],
148148
],
149+
[
150+
'a sleep before the install in the hook that installs fake timers',
151+
[
152+
HELPERS,
153+
"describe('d', () => {",
154+
' beforeEach(async () => {',
155+
' await sleep(100)',
156+
' vi.useFakeTimers()',
157+
' })',
158+
" it('t', async () => { await sleep(10) })",
159+
'})',
160+
],
161+
['sleep() #1'],
162+
],
149163
[
150164
'every occurrence, numbered per kind',
151165
[HELPERS, 'await sleep(10)', 'await new Promise((r) => setTimeout(r, 5))', 'await sleep(20)'],
@@ -201,6 +215,10 @@ describe('real-wait', () => {
201215
'a sleep under a module-level beforeAll that installs fake timers',
202216
[HELPERS, "it('t', async () => { await sleep(10) })", 'beforeAll(() => vi.useFakeTimers())'],
203217
],
218+
[
219+
'a sleep after the install in the hook that installs fake timers',
220+
[HELPERS, 'beforeAll(async () => {', ' vi.useFakeTimers()', ' await sleep(100)', '})'],
221+
],
204222
])('ignores %s', (_name, lines) => {
205223
expect(waits(lines.join('\n'))).toEqual([])
206224
})

‎scripts/check-test-patterns.ts‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ function isTimedPromise(node: Node): boolean {
329329
* Vitest's fake clock fakes each of these whenever it fakes `setTimeout`, and then the wait costs
330330
* no wall-clock time. Fake timers are in scope when the call sits inside a function (or
331331
* the module) that installed them in an earlier statement, or inside a `describe` (or the module)
332-
* whose `beforeEach`/`beforeAll` installs them. A file that mocks `@sim/utils/helpers` gets the
332+
* whose `beforeEach`/`beforeAll` installs them, except before the install in that hook's own body. A file that mocks `@sim/utils/helpers` gets the
333333
* mock's `sleep`, so its imports are not real waits. Each occurrence is its own numbered entry, so
334334
* the baseline caps the count per file.
335335
*/
@@ -363,7 +363,8 @@ export function findRealWaitViolations(
363363
}
364364

365365
const programRange: [number, number] = [program.start ?? 0, program.end ?? 0]
366-
const fakeClocks: Array<{ scope: [number, number]; after: number }> = []
366+
// `real` is the stretch of the scope that runs before the clock is installed.
367+
const fakeClocks: Array<{ scope: [number, number]; real: [number, number] }> = []
367368
const waits: Array<{ node: Node; label: string }> = []
368369
walkWithAncestors(program, (node, ancestors) => {
369370
if (isViCall(node, 'useFakeTimers') && fakesSetTimeout(node)) {
@@ -380,9 +381,13 @@ export function findRealWaitViolations(
380381
(hook.arguments as Node[])[0] === fn
381382
) {
382383
const owner = ancestors[nearestFunctionIndex(ancestors, fnIndex - 1)]
383-
fakeClocks.push({ scope: owner ? nodeRange(owner) : programRange, after: -1 })
384+
fakeClocks.push({
385+
scope: owner ? nodeRange(owner) : programRange,
386+
real: [fn.start as number, node.start as number],
387+
})
384388
} else {
385-
fakeClocks.push({ scope: fn ? nodeRange(fn) : programRange, after: node.start as number })
389+
const scope = fn ? nodeRange(fn) : programRange
390+
fakeClocks.push({ scope, real: [scope[0], node.start as number] })
386391
}
387392
return
388393
}
@@ -399,7 +404,8 @@ export function findRealWaitViolations(
399404
for (const { node, label } of waits) {
400405
const start = node.start as number
401406
const faked = fakeClocks.some(
402-
({ scope, after }) => scope[0] <= start && start < scope[1] && start > after
407+
({ scope, real }) =>
408+
scope[0] <= start && start < scope[1] && !(real[0] <= start && start < real[1])
403409
)
404410
if (faked) continue
405411
const count = (counts.get(label) ?? 0) + 1

0 commit comments

Comments
 (0)