[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix!: add correct location and snapshot fields in json reporter (#5434)

authored by

Vladimir and committed by
GitHub
(May 7, 2024, 12:36 PM +0200) bcccce6d 31994942

+139 -50
-1
pnpm-lock.yaml
··· 16870 16870 16871 16871 /workbox-google-analytics@7.0.0: 16872 16872 resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} 16873 - 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 16874 16873 dependencies: 16875 16874 workbox-background-sync: 7.0.0 16876 16875 workbox-core: 7.0.0
+1 -1
test/test-utils/package.json
··· 1 1 { 2 - "name": "@vitest/test-helpers", 2 + "name": "@vitest/internal-testing-helpers", 3 3 "type": "module", 4 4 "private": true, 5 5 "main": "./index.ts",
+3
test/reporters/src/context.ts
··· 33 33 config: config as ResolvedConfig, 34 34 server: server as ViteDevServer, 35 35 getProjectByTaskId: () => ({ getBrowserSourceMapModuleById: () => undefined }) as any, 36 + snapshot: { 37 + summary: { added: 100, _test: true }, 38 + } as any, 36 39 } 37 40 38 41 context.logger = {
+14 -10
test/reporters/src/data.ts
··· 16 16 file.file = file 17 17 18 18 const suite: Suite = { 19 - id: '', 19 + id: '1223128da3_0', 20 20 type: 'suite', 21 21 name: 'suite', 22 22 mode: 'run', ··· 47 47 48 48 const tasks: Task[] = [ 49 49 { 50 - id: '1223128da3_0', 50 + id: '1223128da3_0_0', 51 51 type: 'test', 52 52 name: 'Math.sqrt()', 53 53 mode: 'run', ··· 60 60 errors: [error], 61 61 duration: 1.4422860145568848, 62 62 }, 63 + location: { 64 + column: 32, 65 + line: 8, 66 + }, 63 67 context: null as any, 64 68 }, 65 69 { 66 - id: '1223128da3_1', 70 + id: '1223128da3_0_1', 67 71 type: 'test', 68 72 name: 'JSON', 69 73 mode: 'run', ··· 75 79 context: null as any, 76 80 }, 77 81 { 78 - id: '1223128da3_3', 82 + id: '1223128da3_0_3', 79 83 type: 'test', 80 84 name: 'async with timeout', 81 85 mode: 'skip', ··· 87 91 context: null as any, 88 92 }, 89 93 { 90 - id: '1223128da3_4', 94 + id: '1223128da3_0_4', 91 95 type: 'test', 92 96 name: 'timeout', 93 97 mode: 'run', ··· 99 103 context: null as any, 100 104 }, 101 105 { 102 - id: '1223128da3_5', 106 + id: '1223128da3_0_5', 103 107 type: 'test', 104 108 name: 'callback setup success ', 105 109 mode: 'run', ··· 111 115 context: null as any, 112 116 }, 113 117 { 114 - id: '1223128da3_6', 118 + id: '1223128da3_0_6', 115 119 type: 'test', 116 120 name: 'callback test success ', 117 121 mode: 'run', ··· 123 127 context: null as any, 124 128 }, 125 129 { 126 - id: '1223128da3_7', 130 + id: '1223128da3_0_7', 127 131 type: 'test', 128 132 name: 'callback setup success done(false)', 129 133 mode: 'run', ··· 135 139 context: null as any, 136 140 }, 137 141 { 138 - id: '1223128da3_8', 142 + id: '1223128da3_0_8', 139 143 type: 'test', 140 144 name: 'callback test success done(false)', 141 145 mode: 'run', ··· 155 159 ], 156 160 }, 157 161 { 158 - id: '1223128da3_9', 162 + id: '1223128da3_0_9', 159 163 type: 'test', 160 164 name: 'todo test', 161 165 mode: 'todo',
+13 -2
test/reporters/tests/json.test.ts
··· 4 4 import { runVitest } from '../../test-utils' 5 5 6 6 describe('json reporter', async () => { 7 - const root = resolve(__dirname, '../fixtures') 7 + const root = resolve(__dirname, '..', 'fixtures') 8 + const projectRoot = resolve(__dirname, '..', '..', '..') 8 9 9 10 it('generates correct report', async () => { 10 - const { stdout } = await runVitest({ reporters: 'json', root }, ['json-fail']) 11 + const { stdout } = await runVitest({ 12 + reporters: 'json', 13 + root, 14 + includeTaskLocation: true, 15 + }, ['json-fail']) 11 16 12 17 const data = JSON.parse(stdout) 13 18 ··· 24 29 25 30 const result = failedTest.assertionResults[0] 26 31 delete result.duration 32 + const rootRegexp = new RegExp(projectRoot, 'g') 33 + result.failureMessages = result.failureMessages 34 + .map((m: string) => { 35 + const errorStack = m.split('\n').slice(0, 2).join('\n') 36 + return errorStack.replace(/\\/g, '/').replace(rootRegexp, '<root>') 37 + }) 27 38 expect(result).toMatchSnapshot() 28 39 }, 40000) 29 40
+4 -3
test/reporters/tests/__snapshots__/json.test.ts.snap
··· 4 4 { 5 5 "ancestorTitles": [], 6 6 "failureMessages": [ 7 - "expected 2 to deeply equal 1", 7 + "AssertionError: expected 2 to deeply equal 1 8 + at <root>/test/reporters/fixtures/json-fail.test.ts:8:13", 8 9 ], 9 10 "fullName": "should fail", 10 11 "location": { 11 - "column": 13, 12 - "line": 8, 12 + "column": 1, 13 + "line": 5, 13 14 }, 14 15 "status": "failed", 15 16 "title": "should fail",
+90 -6
test/reporters/tests/__snapshots__/reporters.spec.ts.snap
··· 73 73 "numTodoTests": 1, 74 74 "numTotalTestSuites": 2, 75 75 "numTotalTests": 9, 76 + "snapshot": { 77 + "_test": true, 78 + "added": 100, 79 + }, 76 80 "startTime": 1642587001759, 77 81 "success": false, 78 82 "testResults": [ ··· 84 88 ], 85 89 "duration": 1.4422860145568848, 86 90 "failureMessages": [ 87 - "expected 2.23606797749979 to equal 2", 91 + "AssertionError: expected 2.23606797749979 to equal 2 92 + at /vitest/test/core/test/basic.test.ts:8:32 93 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 94 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) 95 + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) 96 + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) 97 + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) 98 + at async /vitest/packages/vitest/dist/entry.js:1798:7 99 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) 100 + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) 101 + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", 88 102 ], 89 103 "fullName": "suite Math.sqrt()", 90 104 "location": { ··· 194 208 "numTodoTests": 1, 195 209 "numTotalTestSuites": 2, 196 210 "numTotalTests": 9, 211 + "snapshot": { 212 + "_test": true, 213 + "added": 100, 214 + }, 197 215 "startTime": 1642587001759, 198 216 "success": false, 199 217 "testResults": [ ··· 205 223 ], 206 224 "duration": 1.4422860145568848, 207 225 "failureMessages": [ 208 - "expected 2.23606797749979 to equal 2", 226 + "AssertionError: expected 2.23606797749979 to equal 2 227 + at /vitest/test/core/test/basic.test.ts:8:32 228 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 229 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) 230 + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) 231 + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) 232 + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) 233 + at async /vitest/packages/vitest/dist/entry.js:1798:7 234 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) 235 + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) 236 + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", 209 237 ], 210 238 "fullName": "suite Math.sqrt()", 211 239 "location": { ··· 320 348 "numTodoTests": 1, 321 349 "numTotalTestSuites": 2, 322 350 "numTotalTests": 9, 351 + "snapshot": { 352 + "_test": true, 353 + "added": 100, 354 + }, 323 355 "startTime": 1642587001759, 324 356 "success": false, 325 357 "testResults": [ ··· 331 363 ], 332 364 "duration": 1.4422860145568848, 333 365 "failureMessages": [ 334 - "expected 2.23606797749979 to equal 2", 366 + "AssertionError: expected 2.23606797749979 to equal 2 367 + at /vitest/test/core/test/basic.test.ts:8:32 368 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 369 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) 370 + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) 371 + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) 372 + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) 373 + at async /vitest/packages/vitest/dist/entry.js:1798:7 374 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) 375 + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) 376 + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", 335 377 ], 336 378 "fullName": "suite Math.sqrt()", 337 379 "location": { ··· 446 488 "numTodoTests": 1, 447 489 "numTotalTestSuites": 2, 448 490 "numTotalTests": 9, 491 + "snapshot": { 492 + "_test": true, 493 + "added": 100, 494 + }, 449 495 "startTime": 1642587001759, 450 496 "success": false, 451 497 "testResults": [ ··· 457 503 ], 458 504 "duration": 1.4422860145568848, 459 505 "failureMessages": [ 460 - "expected 2.23606797749979 to equal 2", 506 + "AssertionError: expected 2.23606797749979 to equal 2 507 + at /vitest/test/core/test/basic.test.ts:8:32 508 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 509 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) 510 + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) 511 + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) 512 + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) 513 + at async /vitest/packages/vitest/dist/entry.js:1798:7 514 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) 515 + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) 516 + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", 461 517 ], 462 518 "fullName": "suite Math.sqrt()", 463 519 "location": { ··· 572 628 "numTodoTests": 1, 573 629 "numTotalTestSuites": 2, 574 630 "numTotalTests": 9, 631 + "snapshot": { 632 + "_test": true, 633 + "added": 100, 634 + }, 575 635 "startTime": 1642587001759, 576 636 "success": false, 577 637 "testResults": [ ··· 583 643 ], 584 644 "duration": 1.4422860145568848, 585 645 "failureMessages": [ 586 - "expected 2.23606797749979 to equal 2", 646 + "AssertionError: expected 2.23606797749979 to equal 2 647 + at /vitest/test/core/test/basic.test.ts:8:32 648 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 649 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) 650 + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) 651 + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) 652 + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) 653 + at async /vitest/packages/vitest/dist/entry.js:1798:7 654 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) 655 + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) 656 + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", 587 657 ], 588 658 "fullName": "suite Math.sqrt()", 589 659 "location": { ··· 698 768 "numTodoTests": 1, 699 769 "numTotalTestSuites": 2, 700 770 "numTotalTests": 9, 771 + "snapshot": { 772 + "_test": true, 773 + "added": 100, 774 + }, 701 775 "startTime": 1642587001759, 702 776 "success": false, 703 777 "testResults": [ ··· 709 783 ], 710 784 "duration": 1.4422860145568848, 711 785 "failureMessages": [ 712 - "expected 2.23606797749979 to equal 2", 786 + "AssertionError: expected 2.23606797749979 to equal 2 787 + at /vitest/test/core/test/basic.test.ts:8:32 788 + at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26 789 + at runTest (/vitest/packages/vitest/dist/entry.js:1689:40) 790 + at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13) 791 + at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5) 792 + at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3) 793 + at async /vitest/packages/vitest/dist/entry.js:1798:7 794 + at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5) 795 + at async run (/vitest/packages/vitest/dist/entry.js:1797:5) 796 + at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20", 713 797 ], 714 798 "fullName": "suite Math.sqrt()", 715 799 "location": {
+14 -27
packages/vitest/src/node/reporters/json.ts
··· 1 1 import { existsSync, promises as fs } from 'node:fs' 2 2 import { dirname, resolve } from 'pathe' 3 3 import type { Vitest } from '../../node' 4 - import type { File, Reporter, Suite, Task, TaskState } from '../../types' 4 + import type { File, Reporter, SnapshotSummary, Suite, TaskState } from '../../types' 5 5 import { getSuites, getTests } from '../../utils' 6 6 import { getOutputFile } from '../../utils/config-helpers' 7 - import { parseErrorStacktrace } from '../../utils/source-map' 8 7 9 8 // for compatibility reasons, the reporter produces a JSON similar to the one produced by the Jest JSON reporter 10 9 // the following types are extracted from the Jest repository (and simplified) ··· 12 11 13 12 type Status = 'passed' | 'failed' | 'skipped' | 'pending' | 'todo' | 'disabled' 14 13 type Milliseconds = number 15 - interface Callsite { line: number; column: number } 14 + interface Callsite { 15 + line: number 16 + column: number 17 + } 18 + 16 19 const StatusMap: Record<TaskState, Status> = { 17 20 fail: 'failed', 18 21 only: 'pending', ··· 28 31 status: Status 29 32 title: string 30 33 duration?: Milliseconds | null 31 - failureMessages: Array<string> 34 + failureMessages: Array<string> | null 32 35 location?: Callsite | null 33 36 } 34 37 ··· 56 59 startTime: number 57 60 success: boolean 58 61 testResults: Array<JsonTestResult> 62 + snapshot: SnapshotSummary 59 63 // coverageMap?: CoverageMap | null | undefined 60 64 // numRuntimeErrorTestSuites: number 61 - // snapshot: SnapshotSummary 62 65 // wasInterrupted: boolean 63 66 } 64 67 ··· 104 107 105 108 const endTime = tests.reduce((prev, next) => Math.max(prev, (next.result?.startTime ?? 0) + (next.result?.duration ?? 0)), startTime) 106 109 const assertionResults = tests.map((t) => { 107 - const ancestorTitles = [] as string[] 110 + const ancestorTitles: string[] = [] 108 111 let iter: Suite | undefined = t.suite 109 112 while (iter) { 110 113 ancestorTitles.push(iter.name) ··· 114 117 115 118 return { 116 119 ancestorTitles, 117 - fullName: ancestorTitles.length > 0 ? `${ancestorTitles.join(' ')} ${t.name}` : t.name, 120 + fullName: t.name ? [...ancestorTitles, t.name].join(' ') : ancestorTitles.join(' '), 118 121 status: StatusMap[t.result?.state || t.mode] || 'skipped', 119 122 title: t.name, 120 123 duration: t.result?.duration, 121 - failureMessages: t.result?.errors?.map(e => e.message) || [], 122 - location: this.getFailureLocation(t), 123 - } as JsonAssertionResult 124 + failureMessages: t.result?.errors?.map(e => e.stack || e.message) || [], 125 + location: t.location, 126 + } satisfies JsonAssertionResult 124 127 }) 125 128 126 129 if (tests.some(t => t.result?.state === 'run')) { ··· 153 156 numFailedTests, 154 157 numPendingTests, 155 158 numTodoTests, 159 + snapshot: this.ctx.snapshot.summary, 156 160 startTime: this.start, 157 161 success, 158 162 testResults, ··· 186 190 else { 187 191 this.ctx.logger.log(report) 188 192 } 189 - } 190 - 191 - protected getFailureLocation(test: Task): Callsite | undefined { 192 - const error = test.result?.errors?.[0] 193 - if (!error) 194 - return 195 - 196 - const project = this.ctx.getProjectByTaskId(test.id) 197 - const stack = parseErrorStacktrace(error, { 198 - getSourceMap: file => project.getBrowserSourceMapModuleById(file), 199 - frameFilter: this.ctx.config.onStackTrace, 200 - }) 201 - const frame = stack[0] 202 - if (!frame) 203 - return 204 - 205 - return { line: frame.line, column: frame.column } 206 193 } 207 194 }