Skip to content

fix: coverageConfigDefaults#9940

Merged
AriPerkkio merged 7 commits intovitest-dev:mainfrom
Arthie:refactor-coverage-option-typings-and-document-missing-CLI-flags
Mar 25, 2026
Merged

fix: coverageConfigDefaults#9940
AriPerkkio merged 7 commits intovitest-dev:mainfrom
Arthie:refactor-coverage-option-typings-and-document-missing-CLI-flags

Conversation

@Arthie
Copy link
Contributor

@Arthie Arthie commented Mar 21, 2026

Description

Was reading the coverage options code and here are some small typing suggestions:

  • CoverageConfigDefaults should not use the resolved config type and values, adjusted shared coverage defaults to use the base coverage shape
  • Move deprecated BaseCoverageOptions usage to CoverageOptions

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. If the feature is substantial or introduces breaking changes without a discussion, PR might be closed.
  • Ideally, include a test that fails without this PR but passes with it.
  • Please, don't make changes to pnpm-lock.yaml unless you introduce a new test example.
  • Please check Allow edits by maintainers to make review process faster. Note that this option is not available for repositories that are owned by Github organizations.

Tests

  • Run the tests with pnpm test:ci.

Documentation

  • If you introduce new functionality, document it. You can run documentation with pnpm run docs command.

Changesets

  • Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with feat:, fix:, perf:, docs:, or chore:.

@netlify
Copy link

netlify bot commented Mar 21, 2026

Deploy Preview for vitest-dev ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 5b7ffe9
🔍 Latest deploy log https://app.netlify.com/projects/vitest-dev/deploys/69c3b5a26b610b00083f8d1c
😎 Deploy Preview https://deploy-preview-9940--vitest-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Member

@AriPerkkio AriPerkkio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you resolve conflicts?

@Arthie
Copy link
Contributor Author

Arthie commented Mar 22, 2026

@AriPerkkio conflicts are resolved! I didn't see there was a PR already addressing some of the changes so updated the PR title and Description! Moved the deprecated BaseCoverageOptions usage to CoverageOptions. Thanks!

@Arthie Arthie changed the title refactor: coverage option typings and document missing CLI flags refactor: coverageConfigDefaults typing Mar 22, 2026
Copy link
Member

@AriPerkkio AriPerkkio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about changing coverageConfigDefaults types. Otherwise looks good.


// These are the generic defaults for coverage. Providers may also set some provider specific defaults.
export const coverageConfigDefaults: ResolvedCoverageOptions = {
export const coverageConfigDefaults: Required<Omit<CoverageOptions, 'include' | 'skipFull' | 'thresholds' | 'watermarks' | 'ignoreClassMethods' | 'htmlDir' | 'changed' | 'customProviderModule'>> = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you reason about this change? Why shouldn't default values match with the shape of resolved ones?

Copy link
Contributor Author

@Arthie Arthie Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since coverageConfigDefaults is available externally, I was under the impression that it should represent the raw/default config values and not the fully normalized/resolved runtime config values. If this is the wrong impression let me know.

External usage

import { coverageConfigDefaults } from 'vitest/config';
// OR
import { coverageConfigDefaults } from "vite-plus";

We have to typecast it to as CoverageOptions on line 119 in configDefaults. This skips some typescript checks.

coverage: coverageConfigDefaults as CoverageV8Options, // line 119
                    ^--- ResolvedCoverageOptions

In the docs the default value for coverage.reporter doesn't match with the actual value. The expected value is not possible with ResolvedCoverageOptions since it's more restrictive.

   // expeted value according to the docs
   reporter: [
    'text',
    'html',
    'clover',
    'json',
  ],
  // actual value 
  reporter: [
    ['text', {}],
    ['html', {}],
    ['clover', {}],
    ['json', {}],
  ],

coverageConfigDefaults now aligns with the code style of benchmarkConfigDefaults above it.

export const benchmarkConfigDefaults: Required<
  Omit<BenchmarkUserOptions, 'outputFile' | 'compare' | 'outputJson'>
>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that makes sense. Also by not exposing the resolved types it allows us to use something completely different type internally in future, if ever needed.

I think we should use here FieldsWithDefaultValues so that we don't create two separate source of truth that can be out-of-sync:

/** Fields that have default values. Internally these will always be defined. */
type FieldsWithDefaultValues
= | 'provider'
| 'enabled'
| 'clean'
| 'cleanOnRerun'
| 'reportsDirectory'
| 'exclude'
| 'reportOnFailure'
| 'allowExternal'
| 'processingConcurrency'

We should also define default values for following properties here:

include
ignoreClassMethods
changed
skipFull
thresholds
watermarks

Copy link
Contributor Author

@Arthie Arthie Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok just tried updating the type with FieldsWithDefaultValues and adding the suggested properties.

/** Fields that have default values. Internally these will always be defined. */
export type FieldsWithDefaultValues // added export
  = | 'provider'
    | 'enabled'
    | 'clean'
    | 'cleanOnRerun'
    | 'reportsDirectory'
    | 'exclude'
    | 'reportOnFailure'
    | 'allowExternal'
    | 'processingConcurrency'
// added fields below
    | 'reporter' // required for no ts errors in packages/vitest/src/node/coverage.ts
    | 'excludeAfterRemap' // required for no ts errors in packages/vitest/src/node/coverage.ts
    | 'include'
    | 'ignoreClassMethods'
    | 'changed'
    | 'skipFull'
    // | 'thresholds' // default value is undefined?
    | 'watermarks'

and

// These are the generic defaults for coverage. Providers may also set some provider specific defaults.
export const coverageConfigDefaults: Required<Pick<CoverageOptions, FieldsWithDefaultValues>> = {
  provider: 'v8',
  enabled: false,
  clean: true,
  cleanOnRerun: true,
  reportsDirectory: './coverage',
  exclude: [],
  reportOnFailure: false,
  reporter: [
    'text',
    'html',
    'clover',
    'json',
  ],
  allowExternal: false,
  excludeAfterRemap: false,
  processingConcurrency: Math.min(
    20,
    os.availableParallelism?.() ?? os.cpus().length,
  ),
  include: [], // Default: Files that were imported during test run
  ignoreClassMethods: [],
  changed: false,
  skipFull: false,
  // thresholds: undefined,
  watermarks: {
    statements: [50, 80],
    functions: [50, 80],
    branches: [50, 80],
    lines: [50, 80],
  },
}

The issues / changes:

  • adding export to FieldsWithDefaultValues
  • 'reporter' and 'excludeAfterRemap' need to be also defined otherwise we get tsc errors in packages/vitest/src/node/coverage.ts
  • include has as default 'Files that were imported during test run' is setting include: [] correct in coverageConfigDefaults?
  • thresholds seems to have undefined as default? So it should not be part of FieldsWithDefaultValues?

Not sure about include and thresholds fields

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'reporter' and 'excludeAfterRemap' need to be also defined otherwise we get tsc errors in packages/vitest/src/node/coverage.ts

Sounds correct.

Looks like incude and thresholds should actually not have default values. So let's leave them out of FieldsWithDefaultValues. These checks should not pass when user does not define values there:

// Include untested files when all tests were run (not a single file re-run)
// or if previous results are preserved by "cleanOnRerun: false"
if (this.options.include != null && (allTestsRun || !this.options.cleanOnRerun)) {

if (this.options.thresholds) {
await this.reportThresholds(coverageMap, allTestsRun)
}

Otherwise looks good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes leaving out include and thresholds is also what I was thinking.

We also have to leave out changed since its default value is actually undefined and not false (Inherits the default value from test.changed). I've also fixed the changed comment and removed the @default: false.

Think this PR is good to go!

@Arthie Arthie changed the title refactor: coverageConfigDefaults typing fix: coverageConfigDefaults Mar 25, 2026
Copy link
Member

@AriPerkkio AriPerkkio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!

@AriPerkkio AriPerkkio merged commit b3c992c into vitest-dev:main Mar 25, 2026
16 checks passed
@Arthie Arthie deleted the refactor-coverage-option-typings-and-document-missing-CLI-flags branch March 25, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants