diff --git a/docs/config/reporters.md b/docs/config/reporters.md index 2098d8f66..989ac0e2e 100644 --- a/docs/config/reporters.md +++ b/docs/config/reporters.md @@ -14,7 +14,7 @@ interface UserConfig { type ConfigReporter = string | Reporter | [string, object?] ``` -- **Default:** [`'default'`](/guide/reporters#default-reporter) (or [['default'](/guide/reporters#default-reporter), ['github-actions'](/guide/reporters#github-actions-reporter)] when `process.env.GITHUB_ACTIONS === 'true'`) +- **Default:** [`'default'`](/guide/reporters#default-reporter). See [Default Reporters](/guide/reporters#default-reporters) for environment-specific behavior. - **CLI:** - `--reporter=tap` for a single reporter - `--reporter=verbose --reporter=github-actions` for multiple reporters @@ -49,14 +49,14 @@ Note that the [coverage](/guide/coverage) feature uses a different [`coverage.re ::: code-group ```js [vitest.config.js] -import { defineConfig } from 'vitest/config' +import { configDefaults, defineConfig } from 'vitest/config' export default defineConfig({ test: { reporters: [ - 'default', + ...configDefaults.reporters, // conditional reporter - process.env.CI ? 'github-actions' : {}, + ...(process.env.CI ? ['html'] : []), // custom reporter from npm package // options are passed down as a tuple [ diff --git a/docs/guide/reporters.md b/docs/guide/reporters.md index 34307954f..e423ef3dc 100644 --- a/docs/guide/reporters.md +++ b/docs/guide/reporters.md @@ -5,7 +5,7 @@ outline: deep # Reporters -Vitest provides several built-in reporters to display test output in different formats, as well as the ability to use custom reporters. You can select different reporters either by using the `--reporter` command line option, or by including a `reporters` property in your [configuration file](/config/reporters). If no reporter is specified, Vitest will use the `default` reporter as described below. +Vitest provides several built-in reporters to display test output in different formats, as well as the ability to use custom reporters. You can select different reporters either by using the `--reporter` command line option, or by including a `reporters` property in your [configuration file](/config/reporters). If no reporter is specified, Vitest [auto-selects reporters](#default-configuration) based on the environment. Using reporters via command line: @@ -38,6 +38,26 @@ export default defineConfig({ }) ``` +## Default Configuration + +When `reporters` is not configured, Vitest uses the following reporters: + +- [`default`](#default-reporter) in normal terminal runs +- [`minimal`](#minimal-reporter) when Vitest detects an AI coding agent +- [`github-actions`](#github-actions-reporter) is added when `process.env.GITHUB_ACTIONS === 'true'` + +If you configure your own reporters, the configured list replaces the default list. To add a reporter while keeping Vitest's defaults, extend `configDefaults.reporters`: + +```ts +import { configDefaults, defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + reporters: ['json', ...configDefaults.reporters], + }, +}) +``` + ## Reporter Output By default, Vitest's reporters will print their output to the terminal. When using the `json`, `html` or `junit` reporters, you can instead write your tests' output to a file by including an `outputFile` [configuration option](/config/outputfile) either in your Vite configuration file or via CLI. @@ -66,9 +86,11 @@ npx vitest --reporter=json --reporter=default ``` ```ts +import { configDefaults, defineConfig } from 'vitest/config' + export default defineConfig({ test: { - reporters: ['json', 'default'], + reporters: ['json', ...configDefaults.reporters], outputFile: './test-output.json' }, }) @@ -96,11 +118,7 @@ This example will write separate JSON and XML reports as well as printing a verb ### Default Reporter -By default (i.e. if no reporter is specified), Vitest will display summary of running tests and their status at the bottom. Once a suite passes, its status will be reported on top of the summary. - -::: tip -When Vitest detects it is running inside an AI coding agent, the [`minimal`](#minimal-reporter) reporter is used instead to reduce output and minimize token usage. You can override this by explicitly configuring the [`reporters`](/config/reporters) option. -::: +The `default` reporter displays summary of running tests and their status at the bottom. Once a suite passes, its status will be reported on top of the summary. You can disable the summary by configuring the reporter: @@ -550,21 +568,11 @@ export default defineConfig({ ### GitHub Actions Reporter {#github-actions-reporter} Output [workflow commands](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message) -to provide annotations for test failures. This reporter is automatically enabled when the `reporters` option is not configured and `process.env.GITHUB_ACTIONS === 'true'` (on GitHub Actions environment). +to provide annotations for test failures. This reporter is [enabled automatically](#default-configuration) when `process.env.GITHUB_ACTIONS === 'true'` (on GitHub Actions environment). GitHub Actions GitHub Actions -If you configure reporters, you need to explicitly add `github-actions`. - -```ts -export default defineConfig({ - test: { - reporters: process.env.GITHUB_ACTIONS === 'true' ? ['dot', 'github-actions'] : ['dot'], - }, -}) -``` - You can customize the file paths that are printed in [GitHub's annotation command format](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions) by using the `onWritePath` option. This is useful when running Vitest in a containerized environment, such as Docker, where the file paths may not match the paths in the GitHub Actions environment. ```ts @@ -662,7 +670,7 @@ export default defineConfig({ Outputs a minimal report containing only failed tests and their error messages. Console logs from passing tests and the summary section are also suppressed. ::: tip Agent Reporter -This reporter is well optimized for AI coding assistants and LLM-based workflows to reduce token usage. It is automatically enabled when no `reporters` option is configured and Vitest detects it is running inside an AI coding agent. If you configure custom reporters, you can explicitly add `minimal` or `agent`: +This reporter is well optimized for AI coding assistants and LLM-based workflows to reduce token usage. It is [enabled automatically](#default-configuration) when Vitest detects it is running inside an AI coding agent. :::code-group ```bash [CLI] diff --git a/docs/guide/ui.md b/docs/guide/ui.md index 780308562..d6c15437d 100644 --- a/docs/guide/ui.md +++ b/docs/guide/ui.md @@ -40,7 +40,7 @@ export default defineConfig({ You can check your coverage report in Vitest UI: see [Vitest UI Coverage](/guide/coverage#vitest-ui) for more details. ::: warning -If you still want to see how your tests are running in real time in the terminal, don't forget to add `default` reporter to `reporters` option: `['default', 'html']`. +If you still want to see how your tests are running in real time in the terminal, add `configDefaults.reporters` to the `reporters` option: `['html', ...configDefaults.reporters]`. ::: ::: tip diff --git a/packages/vitest/src/defaults.ts b/packages/vitest/src/defaults.ts index 5d44007c0..77bf14ffe 100644 --- a/packages/vitest/src/defaults.ts +++ b/packages/vitest/src/defaults.ts @@ -77,7 +77,7 @@ export const configDefaults: Readonly<{ teardownTimeout: number forceRerunTriggers: string[] update: boolean - reporters: never[] + reporters: string[] silent: boolean hideSkippedTests: boolean api: boolean @@ -116,7 +116,10 @@ export const configDefaults: Readonly<{ teardownTimeout: 10000, forceRerunTriggers: ['**/package.json/**', '**/{vitest,vite}.config.*/**'], update: false, - reporters: [], + reporters: [ + isAgent ? 'minimal' : 'default', + ...(process.env.GITHUB_ACTIONS === 'true' ? ['github-actions'] : []), + ], silent: false, hideSkippedTests: false, api: false, diff --git a/packages/vitest/src/node/config/resolveConfig.ts b/packages/vitest/src/node/config/resolveConfig.ts index 3470fe63c..f26dbfff9 100644 --- a/packages/vitest/src/node/config/resolveConfig.ts +++ b/packages/vitest/src/node/config/resolveConfig.ts @@ -692,22 +692,23 @@ export function resolveConfig( * { reporter: [[ 'json' ], 'html'] } * { reporter: [[ 'json', { outputFile: 'test.json' } ], 'html'] } */ - if (options.reporters) { - if (!Array.isArray(options.reporters)) { + if (resolved.reporters) { + if (!Array.isArray(resolved.reporters)) { // Reporter name, e.g. { reporters: 'json' } - if (typeof options.reporters === 'string') { - resolved.reporters = [[options.reporters, {}]] + if (typeof resolved.reporters === 'string') { + resolved.reporters = [[resolved.reporters, {}]] } // Inline reporter e.g. { reporters: { onFinish() { method() } } } else { - resolved.reporters = [options.reporters] + resolved.reporters = [resolved.reporters] } } // It's an array of reporters else { + const reporters = resolved.reporters resolved.reporters = [] - for (const reporter of options.reporters) { + for (const reporter of reporters) { if (Array.isArray(reporter)) { // Reporter with options, e.g. { reporters: [ [ 'json', { outputFile: 'test.json' } ] ] } resolved.reporters.push([reporter[0], reporter[1] as Record || {}]) @@ -759,15 +760,6 @@ export function resolveConfig( } } - if (!resolved.reporters.length) { - resolved.reporters.push([isAgent ? 'agent' : 'default', {}]) - - // also enable github-actions reporter as a default - if (process.env.GITHUB_ACTIONS === 'true') { - resolved.reporters.push(['github-actions', {}]) - } - } - if (resolved.changed) { resolved.passWithNoTests ??= true } diff --git a/test/config/test/public.test.ts b/test/config/test/public.test.ts index 4537ba12d..e18ed08ef 100644 --- a/test/config/test/public.test.ts +++ b/test/config/test/public.test.ts @@ -1,6 +1,7 @@ import type { CoverageOptions } from 'vitest/node' import { resolve } from 'pathe' import { expect, test } from 'vitest' +import { configDefaults } from 'vitest/config' import { resolveConfig } from 'vitest/node' test('resolves the test config', async () => { @@ -30,7 +31,7 @@ test('respects root', async () => { }) expect(viteConfig.configFile).toBe(resolve(configRoot, 'vitest.config.ts')) expect(vitestConfig.name).toBe('root config') - expect(vitestConfig.reporters).toEqual([['default', {}]]) + expect(vitestConfig.reporters).toEqual(configDefaults.reporters.map(v => [v, {}])) }) test('respects custom config', async () => { @@ -41,7 +42,7 @@ test('respects custom config', async () => { }) expect(viteConfig.configFile).toBe(config) expect(vitestConfig.name).toBe('custom config') - expect(vitestConfig.reporters).toEqual([['default', {}]]) + expect(vitestConfig.reporters).toEqual(configDefaults.reporters.map(v => [v, {}])) }) test('default value changes of coverage.exclude do not reflect to test.exclude', async () => {