[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.

feat(reporter): add filterMeta option to json reporter (#10078)

Co-authored-by: Vladimir Sheremet <sleuths.slews0s@icloud.com>

authored by

yugo innami
Vladimir Sheremet
and committed by
GitHub
(Apr 9, 2026, 8:56 AM +0200) b77de968 6d989d8a

+65 -1
+14
docs/guide/reporters.md
··· 417 417 Since Vitest 3, the JSON reporter includes coverage information in `coverageMap` if coverage is enabled. 418 418 ::: 419 419 420 + The `meta` field in each assertion result can be filtered via the `filterMeta` reporter option. It receives the key and value of each field and should return a falsy value to exclude the field from the report: 421 + 422 + ```ts 423 + export default defineConfig({ 424 + test: { 425 + reporters: [ 426 + ['json', { 427 + filterMeta: (key, value) => key !== 'internalField', 428 + }] 429 + ] 430 + }, 431 + }) 432 + ``` 433 + 420 434 ### HTML Reporter 421 435 422 436 Generates an HTML file to view test results through an interactive [GUI](/guide/ui). After the file has been generated, Vitest will keep a local development server running and provide a link to view the report in a browser.
+5
test/cli/fixtures/reporters/json-meta.test.ts
··· 1 + import { expect, test } from 'vitest' 2 + 3 + test('pass', ({ task }) => { 4 + task.meta.custom = 'Passing test added this' 5 + })
+31
test/cli/test/reporters/json.test.ts
··· 138 138 expect(data.testResults).toHaveLength(1) 139 139 expect(data.testResults[0].status).toBe(expected) 140 140 }) 141 + 142 + it('includes all meta fields when filterMeta is not set', async () => { 143 + const { stdout } = await runVitest({ 144 + reporters: 'json', 145 + root, 146 + include: ['**/json-meta.test.ts'], 147 + }) 148 + 149 + const data = JSON.parse(stdout) 150 + const results = data.testResults[0].assertionResults 151 + const passing = results.find((r: any) => r.title === 'pass') 152 + 153 + expect(passing.meta).toEqual({ custom: 'Passing test added this' }) 154 + }) 155 + 156 + it('filterMeta filters meta fields by key', async () => { 157 + const { stdout } = await runVitest({ 158 + reporters: [['json', { 159 + filterMeta: key => key !== 'custom', 160 + }]], 161 + root, 162 + include: ['**/json-meta.test.ts'], 163 + }) 164 + 165 + const data = JSON.parse(stdout) 166 + const results = data.testResults[0].assertionResults 167 + 168 + for (const result of results) { 169 + expect(result.meta).toEqual({}) 170 + } 171 + }) 141 172 })
+15 -1
packages/vitest/src/node/reporters/json.ts
··· 74 74 75 75 export interface JsonOptions { 76 76 outputFile?: string 77 + /** @experimental */ 78 + filterMeta?: (key: string, value: unknown) => unknown 77 79 } 78 80 79 81 export class JsonReporter implements Reporter { ··· 121 123 const testResults: Array<JsonTestResult> = [] 122 124 123 125 const success = !!(files.length > 0 || this.ctx.config.passWithNoTests) && numFailedTestSuites === 0 && numFailedTests === 0 126 + const { filterMeta } = this.options 124 127 125 128 for (const file of files) { 126 129 const tests = getTests([file]) ··· 161 164 failureMessages: 162 165 t.result?.errors?.map(e => e.stack || e.message) || [], 163 166 location: t.location, 164 - meta: t.meta, 167 + meta: filterMeta 168 + ? (() => { 169 + const filtered: Record<string, unknown> = {} 170 + for (const key in t.meta) { 171 + const value = t.meta[key as keyof TaskMeta] 172 + if (filterMeta(key, value)) { 173 + filtered[key] = value 174 + } 175 + } 176 + return filtered 177 + })() 178 + : t.meta, 165 179 tags: t.tags || [], 166 180 } satisfies JsonAssertionResult 167 181 })