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).
-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 () => {