From 89a0dbd2c3f2002cd2061b660fc7d0bd480e98eb Mon Sep 17 00:00:00 2001 From: Vladlen Kaveev <67223203+vladlenskiy@users.noreply.github.com> Date: Wed, 10 Jun 2026 12:34:23 +0500 Subject: [PATCH 1/2] feat(coverage)!: allow `thresholds.perFile` to accept an object (#10190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ari Perkkiö --- config/coverage.md | 68 ++++++++++++++++++++++++++++++++++++++---- guide/cli-generated.md | 4 +-- guide/migration.md | 21 +++++++++++++ 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/config/coverage.md b/config/coverage.md index 12cb00c1..409d57fd 100644 --- a/config/coverage.md +++ b/config/coverage.md @@ -233,12 +233,67 @@ Global threshold for statements. ### coverage.thresholds.perFile -- **Type:** `boolean` +- **Type:** `boolean | { 100?: boolean, lines?: number, functions?: number, branches?: number, statements?: number }` - **Default:** `false` - **Available for providers:** `'v8' | 'istanbul'` - **CLI:** `--coverage.thresholds.perFile`, `--coverage.thresholds.perFile=false` -Check thresholds per file. +When `true`, each file is checked against the top-level thresholds instead of the project-wide aggregate. When set to an object, both are checked: the aggregate against the top-level thresholds, and every file against these per-file minimums. + + +```ts +{ + coverage: { + thresholds: { + lines: 80, + functions: 80, + branches: 80, + statements: 80, + perFile: { + lines: 50, + functions: 50, + branches: 50, + statements: 50, + }, + } + } +} +``` + +`{ 100: true }` is also accepted inside the object as a shortcut for setting all four metrics to `100`: + + +```ts +{ + coverage: { + thresholds: { + lines: 80, + perFile: { + 100: true, + }, + } + } +} +``` + +`perFile` can also be set on an individual [glob-pattern threshold](/config/coverage#coverage-thresholds-glob-pattern). Glob patterns do **not** inherit the top-level `perFile`; set it on each glob explicitly. + + +```ts +{ + coverage: { + thresholds: { + perFile: true, + lines: 80, + + 'src/utils/**': { + lines: 90, + perFile: true, + }, + } + } +} +``` ### coverage.thresholds.autoUpdate @@ -257,9 +312,6 @@ You can also pass a function for formatting the updated threshold values. The fu { coverage: { thresholds: { - // Update thresholds without decimals - autoUpdate: (newThreshold) => Math.floor(newThreshold), - // Log the change and update without decimals autoUpdate: (newThreshold, previousThreshold) => { console.log(`Updated threshold from ${previousThreshold} to ${newThreshold}`) @@ -285,12 +337,14 @@ Shortcut for `--coverage.thresholds.lines 100 --coverage.thresholds.functions 10 ### coverage.thresholds[glob-pattern] -- **Type:** `{ statements?: number functions?: number branches?: number lines?: number }` +- **Type:** `{ statements?: number, functions?: number, branches?: number, lines?: number, perFile?: boolean | object }` - **Default:** `undefined` - **Available for providers:** `'v8' | 'istanbul'` Sets thresholds for files matching the glob pattern. +Each glob pattern can set its own `perFile` (`boolean | object`), checked exactly like the top-level `perFile` but scoped to the matched files. Glob patterns do not inherit the top-level `perFile` — set it per glob. + ::: tip NOTE Vitest counts all files, including those covered by glob-patterns, into the global coverage thresholds. This is different from Jest behavior. @@ -311,6 +365,8 @@ This is different from Jest behavior. functions: 90, branches: 85, lines: 80, + // each matching file must individually hit the thresholds above + perFile: true, }, // Files matching this pattern will only have lines thresholds set. diff --git a/guide/cli-generated.md b/guide/cli-generated.md index 9fe52871..abb39955 100644 --- a/guide/cli-generated.md +++ b/guide/cli-generated.md @@ -197,10 +197,10 @@ Shortcut to set all coverage thresholds to 100 (default: `false`) ### coverage.thresholds.perFile -- **CLI:** `--coverage.thresholds.perFile` +- **CLI:** `--coverage.thresholds.perFile ` - **Config:** [coverage.thresholds.perFile](/config/coverage#coverage-thresholds-perfile) -Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`) +Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`). Object form is available in config files only. ### coverage.thresholds.autoUpdate diff --git a/guide/migration.md b/guide/migration.md index b428acc2..077640c3 100644 --- a/guide/migration.md +++ b/guide/migration.md @@ -125,6 +125,27 @@ await expect.element(banner).toMatchTextContent(/error/i) // [!code ++] await expect.element(banner).toHaveTextContent('Error!') ``` +### Glob Coverage Thresholds No Longer Inherit `perFile` + +`coverage.thresholds.perFile` previously applied to every threshold set, including files matched by glob-pattern thresholds. Glob patterns now control their own per-file checking and no longer inherit the top-level `perFile` — set `perFile` on each glob that needs it. + +```ts [vitest.config.ts] +export default defineConfig({ + test: { + coverage: { + thresholds: { + 'perFile': true, + + 'src/utils/**': { + lines: 80, + perFile: true, // [!code ++] + }, + }, + }, + }, +}) +``` + ### Config Files Are Not Looked Up From Parent Directories Vitest no longer searches parent directories for config files. If you previously relied on running `vitest` from a subdirectory while using a config file from a parent directory, pass the config explicitly and scope test discovery with `--dir`. For example, From 371e030455d0dfdf1fc0615ee94d206226a2fb61 Mon Sep 17 00:00:00 2001 From: noise Date: Thu, 11 Jun 2026 10:00:44 +0800 Subject: [PATCH 2/2] docs(cn): dissolve the conflict --- config/coverage.md | 39 ++++++--------------------------------- guide/cli-generated.md | 13 +++---------- 2 files changed, 9 insertions(+), 43 deletions(-) diff --git a/config/coverage.md b/config/coverage.md index cd9d933b..f91ac274 100644 --- a/config/coverage.md +++ b/config/coverage.md @@ -233,19 +233,11 @@ npx vitest --coverage.enabled --coverage.provider=istanbul ### coverage.thresholds.perFile -<<<<<<< HEAD -- **类型:** `boolean` +- **类型:** `boolean | { 100?: boolean, lines?: number, functions?: number, branches?: number, statements?: number }` - **默认值:** `false` - **可用的测试提供者:** `'v8' | 'istanbul'` - **命令行终端:** `--coverage.thresholds.perFile`, `--coverage.thresholds.perFile=false` - -按文件检查覆盖率阈值。 -======= -- **Type:** `boolean | { 100?: boolean, lines?: number, functions?: number, branches?: number, statements?: number }` -- **Default:** `false` -- **Available for providers:** `'v8' | 'istanbul'` -- **CLI:** `--coverage.thresholds.perFile`, `--coverage.thresholds.perFile=false` - + When `true`, each file is checked against the top-level thresholds instead of the project-wide aggregate. When set to an object, both are checked: the aggregate against the top-level thresholds, and every file against these per-file minimums. @@ -302,7 +294,6 @@ When `true`, each file is checked against the top-level thresholds instead of th } } ``` ->>>>>>> 89a0dbd2c3f2002cd2061b660fc7d0bd480e98eb ### coverage.thresholds.autoUpdate @@ -313,7 +304,7 @@ When `true`, each file is checked against the top-level thresholds instead of th 当实际覆盖率超过配置阈值时,自动将 `lines`、`functions`、`branches` 和 `statements` 的阈值更新到配置文件中。 此选项适用于覆盖率提高时保持阈值不变。 - + 你也可以通过传入函数自定义阈值更新值的格式,The function receives the new threshold as the first argument and the previous threshold as the second: @@ -321,12 +312,6 @@ When `true`, each file is checked against the top-level thresholds instead of th { coverage: { thresholds: { -<<<<<<< HEAD - // 更新阈值为整数 - autoUpdate: (newThreshold) => Math.floor(newThreshold), - -======= ->>>>>>> 89a0dbd2c3f2002cd2061b660fc7d0bd480e98eb // Log the change and update without decimals autoUpdate: (newThreshold, previousThreshold) => { console.log(`Updated threshold from ${previousThreshold} to ${newThreshold}`) @@ -352,29 +337,17 @@ When `true`, each file is checked against the top-level thresholds instead of th ### coverage.thresholds[glob-pattern] -<<<<<<< HEAD -- **类型:** `{ statements?: number functions?: number branches?: number lines?: number }` +- **类型:** `{ statements?: number, functions?: number, branches?: number, lines?: number, perFile?: boolean | object }` - **默认值:** `undefined` - **可用的测试提供者:** `'v8' | 'istanbul'` -======= -- **Type:** `{ statements?: number, functions?: number, branches?: number, lines?: number, perFile?: boolean | object }` -- **Default:** `undefined` -- **Available for providers:** `'v8' | 'istanbul'` ->>>>>>> 89a0dbd2c3f2002cd2061b660fc7d0bd480e98eb 设置与 glob 模式匹配的文件的阈值。 + +Each glob pattern can set its own `perFile` (`boolean | object`), checked exactly like the top-level `perFile` but scoped to the matched files. Glob patterns do not inherit the top-level `perFile` — set it per glob. -<<<<<<< HEAD ::: tip 注意 Vitest 会将所有文件(包括匹配 glob 模式的文件)计入全局覆盖率阈值计算。 此做法与 Jest 不同。 -======= -Each glob pattern can set its own `perFile` (`boolean | object`), checked exactly like the top-level `perFile` but scoped to the matched files. Glob patterns do not inherit the top-level `perFile` — set it per glob. - -::: tip NOTE -Vitest counts all files, including those covered by glob-patterns, into the global coverage thresholds. -This is different from Jest behavior. ->>>>>>> 89a0dbd2c3f2002cd2061b660fc7d0bd480e98eb ::: diff --git a/guide/cli-generated.md b/guide/cli-generated.md index 1a434428..1eb8cecb 100644 --- a/guide/cli-generated.md +++ b/guide/cli-generated.md @@ -197,17 +197,10 @@ Coverage reporters to use. Visit [`coverage.reporter`](/config/coverage#coverage ### coverage.thresholds.perFile -<<<<<<< HEAD -- **命令行终端:** `--coverage.thresholds.perFile` +- **命令行终端:** `--coverage.thresholds.perFile ` - **配置:** [coverage.thresholds.perFile](/config/coverage#coverage-thresholds-perfile) - -检查每个文件的阈值。 `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches`, `--coverage.thresholds.statements` 为实际阈值(默认值:`false`) -======= -- **CLI:** `--coverage.thresholds.perFile ` -- **Config:** [coverage.thresholds.perFile](/config/coverage#coverage-thresholds-perfile) - -Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`). Object form is available in config files only. ->>>>>>> 89a0dbd2c3f2002cd2061b660fc7d0bd480e98eb + +检查每个文件的阈值。 `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches`, `--coverage.thresholds.statements` 为实际阈值(默认值:`false`)。Object form is available in config files only. ### coverage.thresholds.autoUpdate