Skip to content

Commit 00c432f

Browse files
authored
fix: report file error as a <failure> on JUnit (#3997)
1 parent 18ae07a commit 00c432f

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ coverage
1010
docs/.vitepress/cache/deps/*.*
1111
test/core/src/self
1212
test/workspaces/results.json
13+
test/reporters/fixtures/with-syntax-error.test.js

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

+17
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ export class JUnitReporter implements Reporter {
216216
skipped: 0,
217217
})
218218

219+
// If there are no tests, but the file failed to load, we still want to report it as a failure
220+
if (tasks.length === 0 && file.result?.state === 'fail') {
221+
stats.failures = 1
222+
223+
tasks.push({
224+
id: file.id,
225+
type: 'test',
226+
name: file.name,
227+
mode: 'run',
228+
result: file.result,
229+
meta: {},
230+
// NOTE: not used in JUnitReporter
231+
context: null as any,
232+
suite: null as any,
233+
} satisfies Task)
234+
}
235+
219236
return {
220237
...file,
221238
tasks,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// NOTE: This file is intentionally not valid JavaScript.
2+
3+
it('should fail', () => {
4+
)

test/reporters/tests/junit.test.ts

+17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import type { Suite, Task, TaskResult } from 'vitest'
22
import { expect, test } from 'vitest'
3+
import { resolve } from 'pathe'
4+
import { runVitest } from '../../test-utils'
35
import { getDuration } from '../../../packages/vitest/src/node/reporters/junit'
46

7+
const root = resolve(__dirname, '../fixtures')
8+
59
test('calc the duration used by junit', () => {
610
const result: TaskResult = { state: 'pass', duration: 0 }
711
const suite: Suite = {
@@ -34,3 +38,16 @@ test('calc the duration used by junit', () => {
3438
result.duration = 12001
3539
expect(getDuration(task)).toBe('12.001')
3640
})
41+
42+
test('emits <failure> if a test has a syntax error', async () => {
43+
const { stdout } = await runVitest({ reporters: 'junit', root }, ['with-syntax-error'])
44+
45+
let xml = stdout
46+
47+
// clear timestamp and hostname
48+
xml = xml.replace(/timestamp="[^"]+"/, 'timestamp="TIMESTAMP"')
49+
xml = xml.replace(/hostname="[^"]+"/, 'hostname="HOSTNAME"')
50+
51+
expect(xml).toContain('<testsuite name="with-syntax-error.test.js" timestamp="TIMESTAMP" hostname="HOSTNAME" tests="1" failures="1" errors="0" skipped="0" time="0">')
52+
expect(xml).toContain('<failure')
53+
})

0 commit comments

Comments
 (0)