diff --git a/packages/vitest/src/node/reporters/json.ts b/packages/vitest/src/node/reporters/json.ts index 34623841b902..dc050c07fd2b 100644 --- a/packages/vitest/src/node/reporters/json.ts +++ b/packages/vitest/src/node/reporters/json.ts @@ -1,10 +1,9 @@ import { existsSync, promises as fs } from 'node:fs' import { dirname, resolve } from 'pathe' import type { Vitest } from '../../node' -import type { File, Reporter, Suite, Task, TaskState } from '../../types' +import type { File, Reporter, SnapshotSummary, Suite, TaskState } from '../../types' import { getSuites, getTests } from '../../utils' import { getOutputFile } from '../../utils/config-helpers' -import { parseErrorStacktrace } 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) @@ -12,7 +11,11 @@ import { parseErrorStacktrace } from '../../utils/source-map' type Status = 'passed' | 'failed' | 'skipped' | 'pending' | 'todo' | 'disabled' type Milliseconds = number -interface Callsite { line: number; column: number } +interface Callsite { + line: number + column: number +} + const StatusMap: Record = { fail: 'failed', only: 'pending', @@ -28,7 +31,7 @@ export interface JsonAssertionResult { status: Status title: string duration?: Milliseconds | null - failureMessages: Array + failureMessages: Array | null location?: Callsite | null } @@ -56,9 +59,9 @@ export interface JsonTestResults { startTime: number success: boolean testResults: Array + snapshot: SnapshotSummary // coverageMap?: CoverageMap | null | undefined // numRuntimeErrorTestSuites: number - // snapshot: SnapshotSummary // wasInterrupted: boolean } @@ -104,7 +107,7 @@ export class JsonReporter implements Reporter { const endTime = tests.reduce((prev, next) => Math.max(prev, (next.result?.startTime ?? 0) + (next.result?.duration ?? 0)), startTime) const assertionResults = tests.map((t) => { - const ancestorTitles = [] as string[] + const ancestorTitles: string[] = [] let iter: Suite | undefined = t.suite while (iter) { ancestorTitles.push(iter.name) @@ -114,13 +117,13 @@ export class JsonReporter implements Reporter { return { ancestorTitles, - fullName: ancestorTitles.length > 0 ? `${ancestorTitles.join(' ')} ${t.name}` : t.name, + fullName: t.name ? [...ancestorTitles, t.name].join(' ') : ancestorTitles.join(' '), status: StatusMap[t.result?.state || t.mode] || 'skipped', title: t.name, duration: t.result?.duration, - failureMessages: t.result?.errors?.map(e => e.message) || [], - location: this.getFailureLocation(t), - } as JsonAssertionResult + failureMessages: t.result?.errors?.map(e => e.stack || e.message) || [], + location: t.location, + } satisfies JsonAssertionResult }) if (tests.some(t => t.result?.state === 'run')) { @@ -153,6 +156,7 @@ export class JsonReporter implements Reporter { numFailedTests, numPendingTests, numTodoTests, + snapshot: this.ctx.snapshot.summary, startTime: this.start, success, testResults, @@ -187,21 +191,4 @@ export class JsonReporter implements Reporter { this.ctx.logger.log(report) } } - - protected getFailureLocation(test: Task): Callsite | undefined { - const error = test.result?.errors?.[0] - if (!error) - return - - const project = this.ctx.getProjectByTaskId(test.id) - const stack = parseErrorStacktrace(error, { - getSourceMap: file => project.getBrowserSourceMapModuleById(file), - frameFilter: this.ctx.config.onStackTrace, - }) - const frame = stack[0] - if (!frame) - return - - return { line: frame.line, column: frame.column } - } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 435b20876ddc..9734f54d6463 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16870,7 +16870,6 @@ packages: /workbox-google-analytics@7.0.0: resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} - deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained dependencies: workbox-background-sync: 7.0.0 workbox-core: 7.0.0 diff --git a/test/reporters/src/context.ts b/test/reporters/src/context.ts index 08dc96d3d10f..e6703ebb18a2 100644 --- a/test/reporters/src/context.ts +++ b/test/reporters/src/context.ts @@ -33,6 +33,9 @@ export function getContext(): Context { config: config as ResolvedConfig, server: server as ViteDevServer, getProjectByTaskId: () => ({ getBrowserSourceMapModuleById: () => undefined }) as any, + snapshot: { + summary: { added: 100, _test: true }, + } as any, } context.logger = { diff --git a/test/reporters/src/data.ts b/test/reporters/src/data.ts index cba908cde209..fa7ae29d0b09 100644 --- a/test/reporters/src/data.ts +++ b/test/reporters/src/data.ts @@ -16,7 +16,7 @@ const file: File = { file.file = file const suite: Suite = { - id: '', + id: '1223128da3_0', type: 'suite', name: 'suite', mode: 'run', @@ -47,7 +47,7 @@ error.stack = 'AssertionError: expected 2.23606797749979 to equal 2\n' const tasks: Task[] = [ { - id: '1223128da3_0', + id: '1223128da3_0_0', type: 'test', name: 'Math.sqrt()', mode: 'run', @@ -60,10 +60,14 @@ const tasks: Task[] = [ errors: [error], duration: 1.4422860145568848, }, + location: { + column: 32, + line: 8, + }, context: null as any, }, { - id: '1223128da3_1', + id: '1223128da3_0_1', type: 'test', name: 'JSON', mode: 'run', @@ -75,7 +79,7 @@ const tasks: Task[] = [ context: null as any, }, { - id: '1223128da3_3', + id: '1223128da3_0_3', type: 'test', name: 'async with timeout', mode: 'skip', @@ -87,7 +91,7 @@ const tasks: Task[] = [ context: null as any, }, { - id: '1223128da3_4', + id: '1223128da3_0_4', type: 'test', name: 'timeout', mode: 'run', @@ -99,7 +103,7 @@ const tasks: Task[] = [ context: null as any, }, { - id: '1223128da3_5', + id: '1223128da3_0_5', type: 'test', name: 'callback setup success ', mode: 'run', @@ -111,7 +115,7 @@ const tasks: Task[] = [ context: null as any, }, { - id: '1223128da3_6', + id: '1223128da3_0_6', type: 'test', name: 'callback test success ', mode: 'run', @@ -123,7 +127,7 @@ const tasks: Task[] = [ context: null as any, }, { - id: '1223128da3_7', + id: '1223128da3_0_7', type: 'test', name: 'callback setup success done(false)', mode: 'run', @@ -135,7 +139,7 @@ const tasks: Task[] = [ context: null as any, }, { - id: '1223128da3_8', + id: '1223128da3_0_8', type: 'test', name: 'callback test success done(false)', mode: 'run', @@ -155,7 +159,7 @@ const tasks: Task[] = [ ], }, { - id: '1223128da3_9', + id: '1223128da3_0_9', type: 'test', name: 'todo test', mode: 'todo', diff --git a/test/reporters/tests/__snapshots__/json.test.ts.snap b/test/reporters/tests/__snapshots__/json.test.ts.snap index ed1ca9b34363..1db05f14ca18 100644 --- a/test/reporters/tests/__snapshots__/json.test.ts.snap +++ b/test/reporters/tests/__snapshots__/json.test.ts.snap @@ -4,12 +4,13 @@ exports[`json reporter > generates correct report 1`] = ` { "ancestorTitles": [], "failureMessages": [ - "expected 2 to deeply equal 1", + "AssertionError: expected 2 to deeply equal 1 + at /test/reporters/fixtures/json-fail.test.ts:8:13", ], "fullName": "should fail", "location": { - "column": 13, - "line": 8, + "column": 1, + "line": 5, }, "status": "failed", "title": "should fail", diff --git a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap index bb65ce023b30..012c01f704be 100644 --- a/test/reporters/tests/__snapshots__/reporters.spec.ts.snap +++ b/test/reporters/tests/__snapshots__/reporters.spec.ts.snap @@ -73,6 +73,10 @@ exports[`json reporter (no outputFile entry) 1`] = ` "numTodoTests": 1, "numTotalTestSuites": 2, "numTotalTests": 9, + "snapshot": { + "_test": true, + "added": 100, + }, "startTime": 1642587001759, "success": false, "testResults": [ @@ -84,7 +88,17 @@ exports[`json reporter (no outputFile entry) 1`] = ` ], "duration": 1.4422860145568848, "failureMessages": [ - "expected 2.23606797749979 to equal 2", + "AssertionError: expected 2.23606797749979 to equal 2 + at /vitest/test/core/test/basic.test.ts:8:32 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) + at async /vitest/packages/vitest/dist/entry.js:1798:7 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", ], "fullName": "suite Math.sqrt()", "location": { @@ -194,6 +208,10 @@ exports[`json reporter 1`] = ` "numTodoTests": 1, "numTotalTestSuites": 2, "numTotalTests": 9, + "snapshot": { + "_test": true, + "added": 100, + }, "startTime": 1642587001759, "success": false, "testResults": [ @@ -205,7 +223,17 @@ exports[`json reporter 1`] = ` ], "duration": 1.4422860145568848, "failureMessages": [ - "expected 2.23606797749979 to equal 2", + "AssertionError: expected 2.23606797749979 to equal 2 + at /vitest/test/core/test/basic.test.ts:8:32 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) + at async /vitest/packages/vitest/dist/entry.js:1798:7 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", ], "fullName": "suite Math.sqrt()", "location": { @@ -320,6 +348,10 @@ exports[`json reporter with outputFile 2`] = ` "numTodoTests": 1, "numTotalTestSuites": 2, "numTotalTests": 9, + "snapshot": { + "_test": true, + "added": 100, + }, "startTime": 1642587001759, "success": false, "testResults": [ @@ -331,7 +363,17 @@ exports[`json reporter with outputFile 2`] = ` ], "duration": 1.4422860145568848, "failureMessages": [ - "expected 2.23606797749979 to equal 2", + "AssertionError: expected 2.23606797749979 to equal 2 + at /vitest/test/core/test/basic.test.ts:8:32 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) + at async /vitest/packages/vitest/dist/entry.js:1798:7 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", ], "fullName": "suite Math.sqrt()", "location": { @@ -446,6 +488,10 @@ exports[`json reporter with outputFile in non-existing directory 2`] = ` "numTodoTests": 1, "numTotalTestSuites": 2, "numTotalTests": 9, + "snapshot": { + "_test": true, + "added": 100, + }, "startTime": 1642587001759, "success": false, "testResults": [ @@ -457,7 +503,17 @@ exports[`json reporter with outputFile in non-existing directory 2`] = ` ], "duration": 1.4422860145568848, "failureMessages": [ - "expected 2.23606797749979 to equal 2", + "AssertionError: expected 2.23606797749979 to equal 2 + at /vitest/test/core/test/basic.test.ts:8:32 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) + at async /vitest/packages/vitest/dist/entry.js:1798:7 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", ], "fullName": "suite Math.sqrt()", "location": { @@ -572,6 +628,10 @@ exports[`json reporter with outputFile object 2`] = ` "numTodoTests": 1, "numTotalTestSuites": 2, "numTotalTests": 9, + "snapshot": { + "_test": true, + "added": 100, + }, "startTime": 1642587001759, "success": false, "testResults": [ @@ -583,7 +643,17 @@ exports[`json reporter with outputFile object 2`] = ` ], "duration": 1.4422860145568848, "failureMessages": [ - "expected 2.23606797749979 to equal 2", + "AssertionError: expected 2.23606797749979 to equal 2 + at /vitest/test/core/test/basic.test.ts:8:32 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) + at async /vitest/packages/vitest/dist/entry.js:1798:7 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", ], "fullName": "suite Math.sqrt()", "location": { @@ -698,6 +768,10 @@ exports[`json reporter with outputFile object in non-existing directory 2`] = ` "numTodoTests": 1, "numTotalTestSuites": 2, "numTotalTests": 9, + "snapshot": { + "_test": true, + "added": 100, + }, "startTime": 1642587001759, "success": false, "testResults": [ @@ -709,7 +783,17 @@ exports[`json reporter with outputFile object in non-existing directory 2`] = ` ], "duration": 1.4422860145568848, "failureMessages": [ - "expected 2.23606797749979 to equal 2", + "AssertionError: expected 2.23606797749979 to equal 2 + at /vitest/test/core/test/basic.test.ts:8:32 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) + at async /vitest/packages/vitest/dist/entry.js:1798:7 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", ], "fullName": "suite Math.sqrt()", "location": { diff --git a/test/reporters/tests/json.test.ts b/test/reporters/tests/json.test.ts index 7edd5319e0c9..70bd4f104b92 100644 --- a/test/reporters/tests/json.test.ts +++ b/test/reporters/tests/json.test.ts @@ -4,10 +4,15 @@ import { describe, expect, it } from 'vitest' import { runVitest } from '../../test-utils' describe('json reporter', async () => { - const root = resolve(__dirname, '../fixtures') + const root = resolve(__dirname, '..', 'fixtures') + const projectRoot = resolve(__dirname, '..', '..', '..') it('generates correct report', async () => { - const { stdout } = await runVitest({ reporters: 'json', root }, ['json-fail']) + const { stdout } = await runVitest({ + reporters: 'json', + root, + includeTaskLocation: true, + }, ['json-fail']) const data = JSON.parse(stdout) @@ -24,6 +29,12 @@ describe('json reporter', async () => { const result = failedTest.assertionResults[0] delete result.duration + const rootRegexp = new RegExp(projectRoot, 'g') + result.failureMessages = result.failureMessages + .map((m: string) => { + const errorStack = m.split('\n').slice(0, 2).join('\n') + return errorStack.replace(/\\/g, '/').replace(rootRegexp, '') + }) expect(result).toMatchSnapshot() }, 40000) diff --git a/test/test-utils/package.json b/test/test-utils/package.json index bbc16902b5fa..e5e2cd12abeb 100644 --- a/test/test-utils/package.json +++ b/test/test-utils/package.json @@ -1,5 +1,5 @@ { - "name": "@vitest/test-helpers", + "name": "@vitest/internal-testing-helpers", "type": "module", "private": true, "main": "./index.ts",