diff --git a/packages/vitest/src/node/reporters/json.ts b/packages/vitest/src/node/reporters/json.ts index c9041c811acf..13497c42bd9b 100644 --- a/packages/vitest/src/node/reporters/json.ts +++ b/packages/vitest/src/node/reporters/json.ts @@ -4,7 +4,7 @@ import type { Vitest } from '../../node' import type { File, Reporter, Suite, TaskState, Test } from '../../types' import { getSuites, getTests } from '../../utils' import { getOutputFile } from '../../utils/config-helpers' -import { parseStacktrace } from '../../utils/source-map' +import { interpretSourcePos, parseStacktrace } from '../../utils/source-map' // for compatibility reasons, the reporter produces a JSON similar to the one produced by the Jest JSON reporter // the following types are extracted from the Jest repository (and simplified) @@ -94,7 +94,7 @@ export class JsonReporter implements Reporter { startTime = this.start const endTime = tests.reduce((prev, next) => Math.max(prev, (next.result?.startTime ?? 0) + (next.result?.duration ?? 0)), startTime) - const assertionResults = tests.map((t) => { + const assertionResults = await Promise.all(tests.map(async (t) => { const ancestorTitles = [] as string[] let iter: Suite | undefined = t.suite while (iter) { @@ -110,9 +110,9 @@ export class JsonReporter implements Reporter { title: t.name, duration: t.result?.duration, failureMessages: t.result?.error?.message == null ? [] : [t.result.error.message], - location: this.getFailureLocation(t), + location: await this.getFailureLocation(t), } as FormattedAssertionResult - }) + })) if (tests.some(t => t.result?.state === 'run')) { this.ctx.logger.warn('WARNING: Some tests are still running when generating the JSON report.' @@ -180,12 +180,13 @@ export class JsonReporter implements Reporter { } } - protected getFailureLocation(test: Test): Callsite | undefined { + protected async getFailureLocation(test: Test): Promise { const error = test.result?.error if (!error) return const stack = parseStacktrace(error) + await interpretSourcePos(stack, this.ctx) const frame = stack[stack.length - 1] if (!frame) return diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ac0708e2651..6b735dea72ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,7 +123,7 @@ importers: unocss: 0.45.13_vite@3.0.7 unplugin-vue-components: 0.22.4_vite@3.0.7+vue@3.2.37 vite: 3.0.7 - vite-plugin-pwa: 0.12.3_vtbnhijtt34ozcbtxu53ekyo5y + vite-plugin-pwa: 0.12.3_vite@3.0.7 vitepress: 1.0.0-alpha.12 workbox-window: 6.5.4 @@ -19992,11 +19992,10 @@ packages: - supports-color dev: true - /vite-plugin-pwa/0.12.3_vtbnhijtt34ozcbtxu53ekyo5y: + /vite-plugin-pwa/0.12.3_vite@3.0.7: resolution: {integrity: sha512-gmYdIVXpmBuNjzbJFPZFzxWYrX4lHqwMAlOtjmXBbxApiHjx9QPXKQPJjSpeTeosLKvVbNcKSAAhfxMda0QVNQ==} peerDependencies: vite: ^2.0.0 || ^3.0.0-0 - workbox-window: ^6.4.0 dependencies: debug: 4.3.4 fast-glob: 3.2.11 diff --git a/test/reporters/fixtures/json-fail.test.ts b/test/reporters/fixtures/json-fail.test.ts new file mode 100644 index 000000000000..093f0e1bcfc6 --- /dev/null +++ b/test/reporters/fixtures/json-fail.test.ts @@ -0,0 +1,7 @@ +import { expect, test } from 'vitest' + +// I am comment1 +// I am comment2 +test('should fail', () => { + expect(2).toEqual(1) +}) diff --git a/test/reporters/fixtures/vitest.config.ts b/test/reporters/fixtures/vitest.config.ts new file mode 100644 index 000000000000..1b3a79748ed4 --- /dev/null +++ b/test/reporters/fixtures/vitest.config.ts @@ -0,0 +1,4 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ +}) diff --git a/test/reporters/src/context.ts b/test/reporters/src/context.ts index 363f98b8e69f..38c67c54067d 100644 --- a/test/reporters/src/context.ts +++ b/test/reporters/src/context.ts @@ -1,3 +1,4 @@ +import type { ModuleGraph, ViteDevServer } from 'vite' import type { Logger } from '../../../packages/vitest/src/node/logger' import type { Vitest } from '../../../packages/vitest/src/node' import type { StateManager } from '../../../packages/vitest/src/node/state' @@ -15,6 +16,14 @@ export function getContext(): Context { root: '/', } + const moduleGraph: Partial = { + getModuleById: () => undefined, + } + + const server: Partial = { + moduleGraph: moduleGraph as ModuleGraph, + } + const state: Partial = { filesMap: new Map(), } @@ -22,6 +31,7 @@ export function getContext(): Context { const context: Partial = { state: state as StateManager, config: config as ResolvedConfig, + server: server as ViteDevServer, } context.logger = { diff --git a/test/reporters/tests/__snapshots__/json.test.ts.snap b/test/reporters/tests/__snapshots__/json.test.ts.snap new file mode 100644 index 000000000000..9cdc37ea070f --- /dev/null +++ b/test/reporters/tests/__snapshots__/json.test.ts.snap @@ -0,0 +1,19 @@ +// Vitest Snapshot v1 + +exports[`json reporter > generates correct report 1`] = ` +{ + "ancestorTitles": [ + "", + ], + "failureMessages": [ + "expected 2 to deeply equal 1", + ], + "fullName": " should fail", + "location": { + "column": 12, + "line": 6, + }, + "status": "failed", + "title": "should fail", +} +`; diff --git a/test/reporters/tests/json.test.ts b/test/reporters/tests/json.test.ts new file mode 100644 index 000000000000..3963d9dfc405 --- /dev/null +++ b/test/reporters/tests/json.test.ts @@ -0,0 +1,30 @@ +import { resolve } from 'pathe' +import { execa } from 'execa' +import { describe, expect, it } from 'vitest' + +describe('json reporter', async () => { + const root = resolve(__dirname, '../fixtures') + + const skip = (process.platform === 'win32' || process.platform === 'darwin') && process.env.CI + + it.skipIf(skip)('generates correct report', async () => { + const { stdout } = await execa('npx', ['vitest', 'run', 'json-fail', '--reporter=json'], { + cwd: root, + env: { + ...process.env, + CI: 'true', + NO_COLOR: 'true', + }, + stdio: 'pipe', + }).catch(e => e) + + const data = JSON.parse(stdout) + + expect(data.testResults).toHaveLength(1) + expect(data.testResults[0].assertionResults).toHaveLength(1) + + const result = data.testResults[0].assertionResults[0] + delete result.duration + expect(result).toMatchSnapshot() + }, 40000) +}) diff --git a/test/reporters/vitest.config.ts b/test/reporters/vitest.config.ts new file mode 100644 index 000000000000..5abcd0981b0c --- /dev/null +++ b/test/reporters/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + exclude: ['node_modules', 'fixtures', 'dist'], + testTimeout: 100000, + }, +})