Skip to content

Commit

Permalink
fix: always run onTestFinished in reverse order (#5598)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Apr 23, 2024
1 parent 780b187 commit 23f29ce
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
4 changes: 4 additions & 0 deletions docs/api/index.md
Expand Up @@ -1010,6 +1010,10 @@ test('performs an organization query', async () => {
})
```

::: tip
This hook is always called in reverse order and is not affected by [`sequence.hooks`](/config/#sequence-hooks) option.
:::

### onTestFailed

This hook is called only after the test has failed. It is called after `afterEach` hooks since they can influence the test result. It receives a `TaskResult` object with the current test result. This hook is useful for debugging.
Expand Down
4 changes: 4 additions & 0 deletions docs/config/index.md
Expand Up @@ -1865,6 +1865,10 @@ Changes the order in which hooks are executed.
- `list` will order all hooks in the order they are defined
- `parallel` will run hooks in a single group in parallel (hooks in parent suites will still run before the current suite's hooks)

::: tip
This option doesn't affect [`onTestFinished`](/api/#ontestfinished). It is always called in reverse order.
:::

#### sequence.setupFiles <Badge type="info">0.29.3+</Badge> {#sequence-setupfiles}

- **Type**: `'list' | 'parallel'`
Expand Down
18 changes: 16 additions & 2 deletions packages/runner/src/run.ts
@@ -1,4 +1,5 @@
import limit from 'p-limit'
import type { Awaitable } from '@vitest/utils'
import { getSafeTimers, shuffle } from '@vitest/utils'
import { processError } from '@vitest/utils/error'
import type { DiffOptions } from '@vitest/utils/diff'
Expand Down Expand Up @@ -33,6 +34,19 @@ function getSuiteHooks(suite: Suite, name: keyof SuiteHooks, sequence: SequenceH
return hooks
}

async function callTaskHooks(task: Task, hooks: ((result: TaskResult) => Awaitable<void>)[], sequence: SequenceHooks) {
if (sequence === 'stack')
hooks = hooks.slice().reverse()

if (sequence === 'parallel') {
await Promise.all(hooks.map(fn => fn(task.result!)))
}
else {
for (const fn of hooks)
await fn(task.result!)
}
}

export async function callSuiteHook<T extends keyof SuiteHooks>(
suite: Suite,
currentTask: Task,
Expand Down Expand Up @@ -211,15 +225,15 @@ export async function runTest(test: Test | Custom, runner: VitestRunner) {
}

try {
await Promise.all(test.onFinished?.map(fn => fn(test.result!)) || [])
await callTaskHooks(test, test.onFinished || [], 'stack')
}
catch (e) {
failTask(test.result, e, runner.config.diffOptions)
}

if (test.result.state === 'fail') {
try {
await Promise.all(test.onFailed?.map(fn => fn(test.result!)) || [])
await callTaskHooks(test, test.onFailed || [], runner.config.sequence.hooks)
}
catch (e) {
failTask(test.result, e, runner.config.diffOptions)
Expand Down
18 changes: 18 additions & 0 deletions test/core/test/on-finished.test.ts
@@ -1,6 +1,7 @@
import { expect, it, onTestFinished } from 'vitest'

const collected: any[] = []
const multiple: any[] = []

it('on-finished regular', () => {
collected.push(1)
Expand Down Expand Up @@ -38,6 +39,23 @@ it.fails('failed finish context', (t) => {
collected.push(null)
})

it('multiple on-finished', () => {
onTestFinished(() => {
multiple.push(1)
})
onTestFinished(() => {
multiple.push(2)
})
onTestFinished(async () => {
await new Promise(r => setTimeout(r, 100))
multiple.push(3)
})
onTestFinished(() => {
multiple.push(4)
})
})

it('after', () => {
expect(collected).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
expect(multiple).toEqual([4, 3, 2, 1])
})

0 comments on commit 23f29ce

Please sign in to comment.