diff --git a/docs/guide/reporters.md b/docs/guide/reporters.md index 95612f070..72a86146e 100644 --- a/docs/guide/reporters.md +++ b/docs/guide/reporters.md @@ -417,6 +417,20 @@ Example of a JSON report: Since Vitest 3, the JSON reporter includes coverage information in `coverageMap` if coverage is enabled. ::: +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: + +```ts +export default defineConfig({ + test: { + reporters: [ + ['json', { + filterMeta: (key, value) => key !== 'internalField', + }] + ] + }, +}) +``` + ### HTML Reporter 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. diff --git a/packages/vitest/src/node/reporters/json.ts b/packages/vitest/src/node/reporters/json.ts index 11f71f7ee..1b63f17cc 100644 --- a/packages/vitest/src/node/reporters/json.ts +++ b/packages/vitest/src/node/reporters/json.ts @@ -74,6 +74,8 @@ export interface JsonTestResults { export interface JsonOptions { outputFile?: string + /** @experimental */ + filterMeta?: (key: string, value: unknown) => unknown } export class JsonReporter implements Reporter { @@ -121,6 +123,7 @@ export class JsonReporter implements Reporter { const testResults: Array = [] const success = !!(files.length > 0 || this.ctx.config.passWithNoTests) && numFailedTestSuites === 0 && numFailedTests === 0 + const { filterMeta } = this.options for (const file of files) { const tests = getTests([file]) @@ -161,7 +164,18 @@ export class JsonReporter implements Reporter { failureMessages: t.result?.errors?.map(e => e.stack || e.message) || [], location: t.location, - meta: t.meta, + meta: filterMeta + ? (() => { + const filtered: Record = {} + for (const key in t.meta) { + const value = t.meta[key as keyof TaskMeta] + if (filterMeta(key, value)) { + filtered[key] = value + } + } + return filtered + })() + : t.meta, tags: t.tags || [], } satisfies JsonAssertionResult }) diff --git a/test/cli/fixtures/reporters/json-meta.test.ts b/test/cli/fixtures/reporters/json-meta.test.ts new file mode 100644 index 000000000..2599908b5 --- /dev/null +++ b/test/cli/fixtures/reporters/json-meta.test.ts @@ -0,0 +1,5 @@ +import { expect, test } from 'vitest' + +test('pass', ({ task }) => { + task.meta.custom = 'Passing test added this' +}) diff --git a/test/cli/test/reporters/json.test.ts b/test/cli/test/reporters/json.test.ts index f718712a0..ee9864a64 100644 --- a/test/cli/test/reporters/json.test.ts +++ b/test/cli/test/reporters/json.test.ts @@ -138,4 +138,35 @@ describe('json reporter', async () => { expect(data.testResults).toHaveLength(1) expect(data.testResults[0].status).toBe(expected) }) + + it('includes all meta fields when filterMeta is not set', async () => { + const { stdout } = await runVitest({ + reporters: 'json', + root, + include: ['**/json-meta.test.ts'], + }) + + const data = JSON.parse(stdout) + const results = data.testResults[0].assertionResults + const passing = results.find((r: any) => r.title === 'pass') + + expect(passing.meta).toEqual({ custom: 'Passing test added this' }) + }) + + it('filterMeta filters meta fields by key', async () => { + const { stdout } = await runVitest({ + reporters: [['json', { + filterMeta: key => key !== 'custom', + }]], + root, + include: ['**/json-meta.test.ts'], + }) + + const data = JSON.parse(stdout) + const results = data.testResults[0].assertionResults + + for (const result of results) { + expect(result.meta).toEqual({}) + } + }) })