Skip to content

Commit 3c00c87

Browse files
authored
fix(runner): correctly call test hooks and teardown functions (#7775)
1 parent 033ccc7 commit 3c00c87

File tree

3 files changed

+120
-19
lines changed

3 files changed

+120
-19
lines changed

packages/runner/src/run.ts

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,31 @@ export function updateTask(event: TaskUpdateEvent, task: Task, runner: VitestRun
221221
sendTasksUpdateThrottled(runner)
222222
}
223223

224-
async function callCleanupHooks(cleanups: unknown[]) {
225-
await Promise.all(
226-
cleanups.map(async (fn) => {
224+
async function callCleanupHooks(runner: VitestRunner, cleanups: unknown[]) {
225+
const sequence = runner.config.sequence.hooks
226+
227+
if (sequence === 'stack') {
228+
cleanups = cleanups.slice().reverse()
229+
}
230+
231+
if (sequence === 'parallel') {
232+
await Promise.all(
233+
cleanups.map(async (fn) => {
234+
if (typeof fn !== 'function') {
235+
return
236+
}
237+
await fn()
238+
}),
239+
)
240+
}
241+
else {
242+
for (const fn of cleanups) {
227243
if (typeof fn !== 'function') {
228-
return
244+
continue
229245
}
230246
await fn()
231-
}),
232-
)
247+
}
248+
}
233249
}
234250

235251
export async function runTest(test: Test, runner: VitestRunner): Promise<void> {
@@ -314,15 +330,6 @@ export async function runTest(test: Test, runner: VitestRunner): Promise<void> {
314330
failTask(test.result, e, runner.config.diffOptions)
315331
}
316332

317-
// skipped with new PendingError
318-
if (test.result?.pending || test.result?.state === 'skip') {
319-
test.mode = 'skip'
320-
test.result = { state: 'skip', note: test.result?.note, pending: true }
321-
updateTask('test-finished', test, runner)
322-
setCurrentTest(undefined)
323-
return
324-
}
325-
326333
try {
327334
await runner.onTaskFinished?.(test)
328335
}
@@ -335,7 +342,7 @@ export async function runTest(test: Test, runner: VitestRunner): Promise<void> {
335342
test.context,
336343
suite,
337344
])
338-
await callCleanupHooks(beforeEachCleanups)
345+
await callCleanupHooks(runner, beforeEachCleanups)
339346
await callFixtureCleanup(test.context)
340347
}
341348
catch (e) {
@@ -356,6 +363,20 @@ export async function runTest(test: Test, runner: VitestRunner): Promise<void> {
356363
test.onFailed = undefined
357364
test.onFinished = undefined
358365

366+
// skipped with new PendingError
367+
if (test.result?.pending || test.result?.state === 'skip') {
368+
test.mode = 'skip'
369+
test.result = {
370+
state: 'skip',
371+
note: test.result?.note,
372+
pending: true,
373+
duration: now() - start,
374+
}
375+
updateTask('test-finished', test, runner)
376+
setCurrentTest(undefined)
377+
return
378+
}
379+
359380
if (test.result.state === 'pass') {
360381
break
361382
}
@@ -504,7 +525,7 @@ export async function runSuite(suite: Suite, runner: VitestRunner): Promise<void
504525

505526
try {
506527
await callSuiteHook(suite, suite, 'afterAll', runner, [suite])
507-
await callCleanupHooks(beforeAllCleanups)
528+
await callCleanupHooks(runner, beforeAllCleanups)
508529
}
509530
catch (e) {
510531
failTask(suite.result, e, runner.config.diffOptions)

test/cli/test/skip-note.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test.for([
1717
})
1818

1919
expect(stderr).toBe('')
20-
expect(stdout).toContain('my skipped test [custom message]')
20+
expect(stdout).toMatch(/my skipped test (?:\d+ms )?\[custom message\]/)
2121

2222
expect(ctx).toBeDefined()
2323
const testTask = ctx!.state.getFiles()[0].tasks[0]

test/core/test/hooks.test.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { afterAll, afterEach, beforeAll, beforeEach, expect, it, suite } from 'vitest'
1+
import { afterAll, afterEach, beforeAll, beforeEach, expect, it, onTestFinished, suite } from 'vitest'
22

33
let count = -1
44

@@ -103,3 +103,83 @@ suite('hooks cleanup', () => {
103103
expect(cleanUpCount).toBe(0)
104104
})
105105
})
106+
107+
suite('hooks cleanup order', () => {
108+
const order: string[] = []
109+
110+
beforeEach(() => {
111+
order.push('[a] beforeEach')
112+
return () => {
113+
order.push('[a] cleanup')
114+
}
115+
})
116+
117+
beforeEach(() => {
118+
order.push('[b] beforeEach')
119+
return () => {
120+
order.push('[b] cleanup')
121+
}
122+
})
123+
124+
it('one', () => {
125+
expect(order).toEqual([
126+
'[a] beforeEach',
127+
'[b] beforeEach',
128+
])
129+
})
130+
131+
afterAll(() => {
132+
expect(order).toEqual([
133+
'[a] beforeEach',
134+
'[b] beforeEach',
135+
'[b] cleanup',
136+
'[a] cleanup',
137+
])
138+
})
139+
})
140+
141+
suite('hooks are called for dynamically skipped tests', () => {
142+
const order: string[] = []
143+
144+
suite('tests', () => {
145+
beforeEach(() => {
146+
order.push('beforeEach')
147+
return () => {
148+
order.push('beforeEach cleanup')
149+
}
150+
})
151+
afterEach(() => {
152+
order.push('afterEach')
153+
})
154+
155+
beforeAll(() => {
156+
order.push('beforeAll')
157+
return () => {
158+
order.push('beforeAll cleanup')
159+
}
160+
})
161+
162+
afterAll(() => {
163+
order.push('afterAll')
164+
})
165+
166+
it('skipped', (ctx) => {
167+
onTestFinished(() => {
168+
order.push('onTestFinished')
169+
})
170+
ctx.skip()
171+
})
172+
})
173+
174+
it('order is correct', () => {
175+
expect(order).toEqual([
176+
'beforeAll',
177+
'beforeEach',
178+
'afterEach',
179+
'beforeEach cleanup',
180+
'onTestFinished',
181+
'afterAll',
182+
'beforeAll cleanup',
183+
])
184+
})
185+
})

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy