Skip to content

Commit 5ee041d

Browse files
committed
fix(vitest): show beforeAll/afterAll errors in junit reporter
1 parent 09646f1 commit 5ee041d

File tree

5 files changed

+82
-0
lines changed

5 files changed

+82
-0
lines changed

packages/vitest/src/node/reporters/junit.ts

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { dirname, relative, resolve } from 'pathe'
44

55
import type { Task } from '@vitest/runner'
66
import type { ErrorWithDiff } from '@vitest/utils'
7+
import { getSuites } from '@vitest/runner/utils'
78
import type { Vitest } from '../../node'
89
import type { Reporter } from '../../types/reporter'
910
import { parseErrorStacktrace } from '../../utils/source-map'
@@ -219,6 +220,15 @@ export class JUnitReporter implements Reporter {
219220
skipped: 0,
220221
})
221222

223+
// inject failed suites to surface errors during beforeAll/afterAll
224+
const suites = getSuites(file)
225+
for (const suite of suites) {
226+
if (suite.result?.errors) {
227+
tasks.push(suite)
228+
stats.failures += 1
229+
}
230+
}
231+
222232
// If there are no tests, but the file failed to load, we still want to report it as a failure
223233
if (tasks.length === 0 && file.result?.state === 'fail') {
224234
stats.failures = 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {
2+
afterAll,
3+
beforeAll,
4+
describe,
5+
it,
6+
} from 'vitest';
7+
8+
describe('suite with beforeAll', () => {
9+
beforeAll(() => {
10+
throw new Error('beforeAll error');
11+
});
12+
13+
it('ok 1', () => {});
14+
it('ok 2', () => {});
15+
it.skip('skip 1', () => {});
16+
});
17+
18+
describe('suite with afterAll', () => {
19+
afterAll(() => {
20+
throw new Error('afterAll error');
21+
});
22+
23+
it('ok 1', () => {});
24+
it('ok 2', () => {});
25+
it.skip('skip 1', () => {});
26+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { defineConfig } from 'vitest/config'
2+
3+
export default defineConfig({})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`emits <failure> when beforeAll/afterAll failed 1`] = `
4+
"<?xml version="1.0" encoding="UTF-8" ?>
5+
<testsuites name="vitest tests" tests="8" failures="2" errors="0" time="...">
6+
<testsuite name="basic.test.ts" timestamp="..." hostname="..." tests="8" failures="2" errors="0" skipped="2" time="...">
7+
<testcase classname="basic.test.ts" name="suite with beforeAll &gt; ok 1" time="...">
8+
</testcase>
9+
<testcase classname="basic.test.ts" name="suite with beforeAll &gt; ok 2" time="...">
10+
</testcase>
11+
<testcase classname="basic.test.ts" name="suite with beforeAll &gt; skip 1" time="...">
12+
<skipped/>
13+
</testcase>
14+
<testcase classname="basic.test.ts" name="suite with afterAll &gt; ok 1" time="...">
15+
</testcase>
16+
<testcase classname="basic.test.ts" name="suite with afterAll &gt; ok 2" time="...">
17+
</testcase>
18+
<testcase classname="basic.test.ts" name="suite with afterAll &gt; skip 1" time="...">
19+
<skipped/>
20+
</testcase>
21+
<testcase classname="basic.test.ts" name="suite with beforeAll" time="...">
22+
<failure message="beforeAll error" type="Error">
23+
Error: beforeAll error
24+
❯ basic.test.ts:10:11
25+
</failure>
26+
</testcase>
27+
<testcase classname="basic.test.ts" name="suite with afterAll" time="...">
28+
<failure message="afterAll error" type="Error">
29+
Error: afterAll error
30+
❯ basic.test.ts:20:11
31+
</failure>
32+
</testcase>
33+
</testsuite>
34+
</testsuites>
35+
"
36+
`;

test/reporters/tests/junit.test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,10 @@ test('emits <failure> if a test has a syntax error', async () => {
5252
expect(xml).toContain('<testsuite name="with-syntax-error.test.js" timestamp="TIMESTAMP" hostname="HOSTNAME" tests="1" failures="1" errors="0" skipped="0" time="0">')
5353
expect(xml).toContain('<failure')
5454
})
55+
56+
test('emits <failure> when beforeAll/afterAll failed', async () => {
57+
let { stdout } = await runVitest({ reporters: 'junit', root: './fixtures/suite-hook-failure' })
58+
// reduct non-deterministic output
59+
stdout = stdout.replaceAll(/(timestamp|hostname|time)=".*?"/g, '$1="..."')
60+
expect(stdout).toMatchSnapshot()
61+
})

0 commit comments

Comments
 (0)