···667667668668You can use [`v8`](https://v8.dev/blog/javascript-code-coverage), [`istanbul`](https://istanbul.js.org/) or [a custom coverage solution](/guide/coverage#custom-coverage-provider) for coverage collection.
669669670670-::: info
671671-The `c8` provider is being replaced by the `v8` provider. It will be deprecated in the next major version.
672672-:::
673673-674670You can provide coverage options to CLI with dot notation:
675671676672```sh
···683679684680#### coverage.provider
685681686686-- **Type:** `'c8' | 'v8' | 'istanbul' | 'custom'`
682682+- **Type:** `'v8' | 'istanbul' | 'custom'`
687683- **Default:** `'v8'`
688684- **CLI:** `--coverage.provider=<provider>`
689685···693689694690- **Type:** `boolean`
695691- **Default:** `false`
696696-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
692692+- **Available for providers:** `'v8' | 'istanbul'`
697693- **CLI:** `--coverage.enabled`, `--coverage.enabled=false`
698694699695Enables coverage collection. Can be overridden using `--coverage` CLI option.
···702698703699- **Type:** `string[]`
704700- **Default:** `['**']`
705705-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
701701+- **Available for providers:** `'v8' | 'istanbul'`
706702- **CLI:** `--coverage.include=<path>`, `--coverage.include=<path1> --coverage.include=<path2>`
707703708704List of files included in coverage as glob patterns
···711707712708- **Type:** `string | string[]`
713709- **Default:** `['.js', '.cjs', '.mjs', '.ts', '.mts', '.cts', '.tsx', '.jsx', '.vue', '.svelte']`
714714-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
710710+- **Available for providers:** `'v8' | 'istanbul'`
715711- **CLI:** `--coverage.extension=<extension>`, `--coverage.extension=<extension1> --coverage.extension=<extension2>`
716712717713#### coverage.exclude
···733729 '**/.{eslint,mocha,prettier}rc.{?(c|m)js,yml}',
734730]
735731```
736736-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
732732+- **Available for providers:** `'v8' | 'istanbul'`
737733- **CLI:** `--coverage.exclude=<path>`, `--coverage.exclude=<path1> --coverage.exclude=<path2>`
738734739735List of files excluded from coverage as glob patterns.
···742738743739- **Type:** `boolean`
744740- **Default:** `false`
745745-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
741741+- **Available for providers:** `'v8' | 'istanbul'`
746742- **CLI:** `--coverage.all`, `--coverage.all=false`
747743748744Whether to include all files, including the untested ones into report.
···751747752748- **Type:** `boolean`
753749- **Default:** `true`
754754-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
750750+- **Available for providers:** `'v8' | 'istanbul'`
755751- **CLI:** `--coverage.clean`, `--coverage.clean=false`
756752757753Clean coverage results before running tests
···760756761757- **Type:** `boolean`
762758- **Default:** `true`
763763-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
759759+- **Available for providers:** `'v8' | 'istanbul'`
764760- **CLI:** `--coverage.cleanOnRerun`, `--coverage.cleanOnRerun=false`
765761766762Clean coverage report on watch rerun
···769765770766- **Type:** `string`
771767- **Default:** `'./coverage'`
772772-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
768768+- **Available for providers:** `'v8' | 'istanbul'`
773769- **CLI:** `--coverage.reportsDirectory=<path>`
774770775771Directory to write coverage report to.
···778774779775- **Type:** `string | string[] | [string, {}][]`
780776- **Default:** `['text', 'html', 'clover', 'json']`
781781-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
777777+- **Available for providers:** `'v8' | 'istanbul'`
782778- **CLI:** `--coverage.reporter=<reporter>`, `--coverage.reporter=<reporter1> --coverage.reporter=<reporter2>`
783779784780Coverage reporters to use. See [istanbul documentation](https://istanbul.js.org/docs/advanced/alternative-reporters/) for detailed list of all reporters. See [`@types/istanbul-reporter`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/276d95e4304b3670eaf6e8e5a7ea9e265a14e338/types/istanbul-reports/index.d.ts) for details about reporter specific options.
···805801806802- **Type:** `boolean`
807803- **Default:** `false` (since Vitest `0.34.0`)
808808-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
804804+- **Available for providers:** `'v8' | 'istanbul'`
809805- **CLI:** `--coverage.reportOnFailure`, `--coverage.reportOnFailure=false`
810806- **Version:** Since Vitest 0.31.2
811807···815811816812- **Type:** `boolean`
817813- **Default:** `false`
818818-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
814814+- **Available for providers:** `'v8' | 'istanbul'`
819815- **CLI:** `--coverage.skipFull`, `--coverage.skipFull=false`
820816821817Do not show files with 100% statement, branch, and function coverage.
···824820825821- **Type:** `boolean`
826822- **Default:** `false`
827827-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
823823+- **Available for providers:** `'v8' | 'istanbul'`
828824- **CLI:** `--coverage.perFile`, `--coverage.perFile=false`
829825830826Check thresholds per file.
···834830835831- **Type:** `boolean`
836832- **Default:** `false`
837837-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
833833+- **Available for providers:** `'v8' | 'istanbul'`
838834- **CLI:** `--coverage.thresholdAutoUpdate=<boolean>`
839835840836Update threshold values `lines`, `functions`, `branches` and `statements` to configuration file when current coverage is above the configured thresholds.
···843839#### coverage.lines
844840845841- **Type:** `number`
846846-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
842842+- **Available for providers:** `'v8' | 'istanbul'`
847843- **CLI:** `--coverage.lines=<number>`
848844849845Threshold for lines.
···852848#### coverage.functions
853849854850- **Type:** `number`
855855-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
851851+- **Available for providers:** `'v8' | 'istanbul'`
856852- **CLI:** `--coverage.functions=<number>`
857853858854Threshold for functions.
···861857#### coverage.branches
862858863859- **Type:** `number`
864864-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
860860+- **Available for providers:** `'v8' | 'istanbul'`
865861- **CLI:** `--coverage.branches=<number>`
866862867863Threshold for branches.
···870866#### coverage.statements
871867872868- **Type:** `number`
873873-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
869869+- **Available for providers:** `'v8' | 'istanbul'`
874870- **CLI:** `--coverage.statements=<number>`
875871876872Threshold for statements.
877873See [istanbul documentation](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information.
878874879879-#### coverage.allowExternal
880880-881881-- **Type:** `boolean`
882882-- **Default:** `false`
883883-- **Available for providers:** `'c8'`
884884-- **CLI:** `--coverage.allowExternal`, `--coverage.allowExternal=false`
885885-886886-Allow files from outside of your cwd.
887887-888888-#### coverage.excludeNodeModules
889889-890890-- **Type:** `boolean`
891891-- **Default:** `true`
892892-- **Available for providers:** `'c8'`
893893-- **CLI:** `--coverage.excludeNodeModules`, `--coverage.excludeNodeModules=false`
894894-895895-Exclude coverage under `/node_modules/`.
896896-897897-#### coverage.src
898898-899899-- **Type:** `string[]`
900900-- **Default:** `process.cwd()`
901901-- **Available for providers:** `'c8'`
902902-- **CLI:** `--coverage.src=<path>`
903903-904904-Specifies the directories that are used when `--all` is enabled.
905905-906875#### coverage.100
907876908877- **Type:** `boolean`
909878- **Default:** `false`
910910-- **Available for providers:** `'c8' | 'v8'`
879879+- **Available for providers:** `'v8'`
911880- **CLI:** `--coverage.100`, `--coverage.100=false`
912881913882Shortcut for `--check-coverage --lines 100 --functions 100 --branches 100 --statements 100`.
···946915}
947916```
948917949949-- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
918918+- **Available for providers:** `'v8' | 'istanbul'`
950919951920Watermarks for statements, lines, branches and functions. See [istanbul documentation](https://github.com/istanbuljs/nyc#high-and-low-watermarks) for more information.
952921
-4
docs/guide/coverage.md
···6677Vitest supports Native code coverage via [`v8`](https://v8.dev/blog/javascript-code-coverage) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).
8899-:::info
1010-The `c8` provider is being replaced by the [`v8`](https://v8.dev/blog/javascript-code-coverage) provider. It will be deprecated in the next major version.
1111-:::
1212-139## Coverage Providers
14101511:::tip
···11-import * as coverage from './takeCoverage'
22-33-export default {
44- ...coverage,
55- async getProvider() {
66- // to not bundle the provider
77- const name = './provider.js'
88- const { C8CoverageProvider } = await import(name) as typeof import('./provider')
99- return new C8CoverageProvider()
1010- },
1111-}
-238
packages/coverage-c8/src/provider.ts
···11-import { existsSync, promises as fs } from 'node:fs'
22-import _url from 'node:url'
33-import type { Profiler } from 'node:inspector'
44-import MagicString from 'magic-string'
55-import remapping from '@ampproject/remapping'
66-import { extname, resolve } from 'pathe'
77-import c from 'picocolors'
88-import { provider } from 'std-env'
99-import type { EncodedSourceMap } from 'vite-node'
1010-import { coverageConfigDefaults } from 'vitest/config'
1111-import { BaseCoverageProvider } from 'vitest/coverage'
1212-import type { AfterSuiteRunMeta, CoverageC8Options, CoverageProvider, ReportContext, ResolvedCoverageOptions } from 'vitest'
1313-import type { Vitest } from 'vitest/node'
1414-import type { Report } from 'c8'
1515-1616-// @ts-expect-error missing types
1717-import createReport from 'c8/lib/report.js'
1818-1919-// @ts-expect-error missing types
2020-import { checkCoverages } from 'c8/lib/commands/check-coverage.js'
2121-2222-type Options = ResolvedCoverageOptions<'c8'>
2323-2424-// Note that this needs to match the line ending as well
2525-const VITE_EXPORTS_LINE_PATTERN = /Object\.defineProperty\(__vite_ssr_exports__.*\n/g
2626-2727-export class C8CoverageProvider extends BaseCoverageProvider implements CoverageProvider {
2828- name = 'c8'
2929-3030- ctx!: Vitest
3131- options!: Options
3232- coverages: Profiler.TakePreciseCoverageReturnType[] = []
3333-3434- initialize(ctx: Vitest) {
3535- const config: CoverageC8Options = ctx.config.coverage
3636-3737- this.ctx = ctx
3838- this.options = {
3939- ...coverageConfigDefaults,
4040-4141- // Provider specific defaults
4242- excludeNodeModules: true,
4343- allowExternal: false,
4444-4545- // User's options
4646- ...config,
4747-4848- // Resolved fields
4949- provider: 'c8',
5050- reporter: this.resolveReporters(config.reporter || coverageConfigDefaults.reporter),
5151- reportsDirectory: resolve(ctx.config.root, config.reportsDirectory || coverageConfigDefaults.reportsDirectory),
5252- lines: config['100'] ? 100 : config.lines,
5353- functions: config['100'] ? 100 : config.functions,
5454- branches: config['100'] ? 100 : config.branches,
5555- statements: config['100'] ? 100 : config.statements,
5656- }
5757-5858- const banner = ' DEPRECATION '
5959- this.ctx.logger.log(
6060- c.bgYellow(c.black((banner))),
6161- c.yellow('@vitest/coverage-c8 is being replaced by @vitest/coverage-v8.'),
6262- c.yellow(`\n${' '.repeat(banner.length)} See`),
6363- c.blue(c.underline('https://github.com/vitest-dev/vitest/pull/3339')),
6464- c.yellow('for more information.'),
6565- )
6666- }
6767-6868- resolveOptions() {
6969- return this.options
7070- }
7171-7272- async clean(clean = true) {
7373- if (clean && existsSync(this.options.reportsDirectory))
7474- await fs.rm(this.options.reportsDirectory, { recursive: true, force: true, maxRetries: 10 })
7575-7676- this.coverages = []
7777- }
7878-7979- onAfterSuiteRun({ coverage }: AfterSuiteRunMeta) {
8080- this.coverages.push(coverage as Profiler.TakePreciseCoverageReturnType)
8181- }
8282-8383- async reportCoverage({ allTestsRun }: ReportContext = {}) {
8484- if (provider === 'stackblitz')
8585- this.ctx.logger.log(c.blue(' % ') + c.yellow('@vitest/coverage-c8 does not work on Stackblitz. Report will be empty.'))
8686-8787- const options: ConstructorParameters<typeof Report>[0] = {
8888- ...this.options,
8989- all: this.options.all && allTestsRun,
9090- reporter: this.options.reporter.map(([reporterName]) => reporterName),
9191- reporterOptions: this.options.reporter.reduce((all, [name, options]) => ({
9292- ...all,
9393- [name]: {
9494- skipFull: this.options.skipFull,
9595- projectRoot: this.ctx.config.root,
9696- ...options,
9797- },
9898- }), {}),
9999- }
100100-101101- const report = createReport(options)
102102-103103- // Overwrite C8's loader as results are in memory instead of file system
104104- report._loadReports = () => this.coverages
105105-106106- interface MapAndSource { map: EncodedSourceMap; source: string | undefined }
107107- type SourceMapMeta = { url: string; filepath: string } & MapAndSource
108108-109109- // add source maps
110110- const sourceMapMeta: Record<SourceMapMeta['url'], MapAndSource> = {}
111111- const extensions = Array.isArray(this.options.extension) ? this.options.extension : [this.options.extension]
112112-113113- const fetchCache = this.ctx.projects.map(project =>
114114- Array.from(project.vitenode.fetchCache.entries()),
115115- ).flat()
116116-117117- const entries = Array
118118- .from(fetchCache)
119119- .filter(entry => report._shouldInstrument(entry[0]))
120120- .map(([file, { result }]) => {
121121- if (!result.map)
122122- return null
123123-124124- const filepath = file.split('?')[0]
125125- const url = _url.pathToFileURL(filepath).href
126126- const extension = extname(file) || extname(url)
127127-128128- return {
129129- filepath,
130130- url,
131131- extension,
132132- map: result.map,
133133- source: result.code,
134134- }
135135- })
136136- .filter((entry) => {
137137- if (!entry)
138138- return false
139139-140140- if (!extensions.includes(entry.extension))
141141- return false
142142-143143- // Mappings and sourcesContent are needed for C8 to work
144144- return (
145145- entry.map.mappings.length > 0
146146- && entry.map.sourcesContent
147147- && entry.map.sourcesContent.length > 0
148148- && entry.map.sourcesContent[0]
149149- && entry.map.sourcesContent[0].length > 0
150150- )
151151- }) as SourceMapMeta[]
152152-153153- await Promise.all(entries.map(async ({ url, source, map, filepath }) => {
154154- if (url in sourceMapMeta)
155155- return
156156-157157- let code: string | undefined
158158- try {
159159- code = (await fs.readFile(filepath)).toString()
160160- }
161161- catch { }
162162-163163- // Vite does not report full path in sourcemap sources
164164- // so use an actual file path
165165- const sources = [url]
166166-167167- sourceMapMeta[url] = {
168168- source,
169169- map: {
170170- sourcesContent: code ? [code] : undefined,
171171- ...map,
172172- sources,
173173- },
174174- }
175175- }))
176176-177177- // This is a magic number. It corresponds to the amount of code
178178- // that we add in packages/vite-node/src/client.ts:114 (vm.runInThisContext)
179179- // TODO: Include our transformations in sourcemaps
180180- const offset = 185
181181-182182- report._getSourceMap = (coverage: Profiler.ScriptCoverage) => {
183183- const path = _url.pathToFileURL(coverage.url.split('?')[0]).href
184184- const data = sourceMapMeta[path]
185185-186186- if (!data)
187187- return {}
188188-189189- return {
190190- sourceMap: {
191191- sourcemap: removeViteHelpersFromSourceMaps(data.source, data.map),
192192- },
193193- source: Array(offset).fill('.').join('') + data.source,
194194- }
195195- }
196196-197197- await report.run()
198198- await checkCoverages(options, report)
199199-200200- if (this.options.thresholdAutoUpdate && allTestsRun) {
201201- this.updateThresholds({
202202- coverageMap: await report.getCoverageMapFromAllCoverageFiles(),
203203- thresholds: {
204204- branches: this.options.branches,
205205- functions: this.options.functions,
206206- lines: this.options.lines,
207207- statements: this.options.statements,
208208- },
209209- perFile: this.options.perFile,
210210- configurationFile: this.ctx.server.config.configFile,
211211- })
212212- }
213213- }
214214-}
215215-216216-/**
217217- * Remove generated code from the source maps:
218218- * - Vite's export helpers: e.g. `Object.defineProperty(__vite_ssr_exports__, "sum", { enumerable: true, configurable: true, get(){ return sum }});`
219219- */
220220-function removeViteHelpersFromSourceMaps(source: string | undefined, map: EncodedSourceMap) {
221221- if (!source || !source.match(VITE_EXPORTS_LINE_PATTERN))
222222- return map
223223-224224- const sourceWithoutHelpers = new MagicString(source)
225225- sourceWithoutHelpers.replaceAll(VITE_EXPORTS_LINE_PATTERN, '\n')
226226-227227- const mapWithoutHelpers = sourceWithoutHelpers.generateMap({
228228- hires: true,
229229- })
230230-231231- // A merged source map where the first one excludes helpers
232232- const combinedMap = remapping(
233233- [{ ...mapWithoutHelpers, version: 3 }, map],
234234- () => null,
235235- )
236236-237237- return combinedMap
238238-}
-51
packages/coverage-c8/src/takeCoverage.ts
···11-/*
22- * For details about the Profiler.* messages see https://chromedevtools.github.io/devtools-protocol/v8/Profiler/
33-*/
44-55-import inspector from 'node:inspector'
66-import type { Profiler } from 'node:inspector'
77-import { provider } from 'std-env'
88-99-const session = new inspector.Session()
1010-1111-export function startCoverage() {
1212- session.connect()
1313- session.post('Profiler.enable')
1414- session.post('Profiler.startPreciseCoverage', {
1515- callCount: true,
1616- detailed: true,
1717- })
1818-}
1919-2020-export async function takeCoverage() {
2121- return new Promise((resolve, reject) => {
2222- session.post('Profiler.takePreciseCoverage', async (error, coverage) => {
2323- if (error)
2424- return reject(error)
2525-2626- // Reduce amount of data sent over rpc by doing some early result filtering
2727- const result = coverage.result.filter(filterResult)
2828-2929- resolve({ result })
3030- })
3131-3232- if (provider === 'stackblitz')
3333- resolve({ result: [] })
3434- })
3535-}
3636-3737-export function stopCoverage() {
3838- session.post('Profiler.stopPreciseCoverage')
3939- session.post('Profiler.disable')
4040- session.disconnect()
4141-}
4242-4343-function filterResult(coverage: Profiler.ScriptCoverage): boolean {
4444- if (!coverage.url.startsWith('file://'))
4545- return false
4646-4747- if (coverage.url.includes('/node_modules/'))
4848- return false
4949-5050- return true
5151-}
+1-1
packages/vite-node/src/client.ts
···384384 // Be careful when changing this
385385 // changing context will change amount of code added on line :114 (vm.runInThisContext)
386386 // this messes up sourcemaps for coverage
387387- // adjust `offset` variable in packages/coverage-c8/src/provider.ts#86 if you do change this
387387+ // adjust `WRAPPER_LENGTH` variable in packages/coverage-v8/src/provider.ts if you do change this
388388 const context = this.prepareContext({
389389 // esm transformed by Vite
390390 __vite_ssr_import__: request,
-2
packages/vitest/src/defaults.ts
···3434 exclude: defaultCoverageExcludes,
3535 reportOnFailure: false,
3636 reporter: [['text', {}], ['html', {}], ['clover', {}], ['json', {}]],
3737- // default extensions used by c8, plus '.vue' and '.svelte'
3838- // see https://github.com/istanbuljs/schema/blob/master/default-extension.js
3937 extension: ['.js', '.cjs', '.mjs', '.ts', '.mts', '.cts', '.tsx', '.jsx', '.vue', '.svelte'],
4038}
4139
+4-3
test/config/test/failures.test.ts
···4848 expect(stderr).toMatch('Error: You cannot use --inspect-brk without "threads: false" or "singleThread: true"')
4949})
50505151-test('c8 coverage provider cannot be used with browser', async () => {
5252- const { stderr } = await runVitest({ coverage: { enabled: true, provider: 'c8' }, browser: { enabled: true, name: 'chrome' } })
5151+test('c8 coverage provider is not supported', async () => {
5252+ // @ts-expect-error -- check for removed API option
5353+ const { stderr } = await runVitest({ coverage: { enabled: true, provider: 'c8' } })
53545454- expect(stderr).toMatch('Error: @vitest/coverage-c8 does not work with --browser. Use @vitest/coverage-istanbul instead')
5555+ expect(stderr).toMatch('Error: "coverage.provider: c8" is not supported anymore. Use "coverage.provider: v8" instead')
5556})
56575758test('v8 coverage provider cannot be used with browser', async () => {
···11-/*
22- * C8 coverage provider specific test cases
33- */
44-55-import { expect, test } from 'vitest'
66-import { readCoverageJson } from './utils'
77-88-test('c8 json report', async () => {
99- const jsonReport = await readCoverageJson()
1010-1111- // If this fails, you can use "npx live-server@1.2.1 ./coverage" to see coverage report
1212- expect(jsonReport).toMatchSnapshot()
1313-})
1414-1515-test('ignored code is marked as covered in the report', async () => {
1616- const functionName = 'ignoredFunction'
1717- const filename = '<process-cwd>/src/utils.ts'
1818-1919- const coverageMap = await readCoverageJson()
2020- const fileCoverage = coverageMap[filename]
2121-2222- const [functionKey] = Object.entries(fileCoverage.fnMap).find(([, fn]) => fn.name === functionName)!
2323- const functionCallCount = fileCoverage.f[functionKey]
2424-2525- // C8 marks excluded lines as covered, instead of removing them from report completely
2626- expect(functionCallCount).toBe(1)
2727-2828- // Function should still be found from the actual sources
2929- const utils = await import('../src/utils')
3030- expect(utils[functionName]).toBeTypeOf('function')
3131-})
···6363 const requiredPackages = CoverageProviderMap[provider]
64646565 if (requiredPackages) {
6666- // Remove this message once support for @vitest/coverage-c8 has been removed completely
6767- const defaultProviderInfo = 'Default coverage provider has changed from "c8" to "v8". '
6868- + 'New package is required to be installed. '
6969- + 'To use the old deprecated coverage provider use "--coverage.provider c8" option.\n'
7070- + 'See https://github.com/vitest-dev/vitest/pull/3339 for more information.\n\n'
7171-7272- const isUsingDefaultProvider
7373- = ctx.server.config.test?.coverage?.provider === undefined
7474- && options.coverage?.provider === undefined
7575-7676- if (!await ensurePackageInstalled(requiredPackages, root, isUsingDefaultProvider ? defaultProviderInfo : undefined)) {
6666+ if (!await ensurePackageInstalled(requiredPackages, root)) {
7767 process.exitCode = 1
7868 return ctx
7969 }
+1-4
packages/vitest/src/node/cli.ts
···33import c from 'picocolors'
44import { version } from '../../package.json'
55import { toArray } from '../utils'
66-import type { BaseCoverageOptions, CoverageC8Options, CoverageIstanbulOptions, Vitest, VitestRunMode } from '../types'
66+import type { BaseCoverageOptions, CoverageIstanbulOptions, Vitest, VitestRunMode } from '../types'
77import type { CliOptions } from './cli-api'
88import { startVitest } from './cli-api'
99import { divider } from './reporters/renderers/utils'
···159159160160 if ((coverage as CoverageIstanbulOptions).ignoreClassMethods)
161161 (coverage as CoverageIstanbulOptions).ignoreClassMethods = toArray((coverage as CoverageIstanbulOptions).ignoreClassMethods)
162162-163163- if ((coverage as CoverageC8Options).src)
164164- (coverage as CoverageC8Options).src = toArray((coverage as CoverageC8Options).src)
165162 }
166163 return argv
167164}
+3-2
packages/vitest/src/node/config.ts
···117117 }
118118 }
119119120120- if (resolved.coverage.provider === 'c8' && resolved.coverage.enabled && isBrowserEnabled(resolved))
121121- throw new Error('@vitest/coverage-c8 does not work with --browser. Use @vitest/coverage-istanbul instead')
120120+ // @ts-expect-error -- check for removed API option
121121+ if (resolved.coverage.provider === 'c8')
122122+ throw new Error('"coverage.provider: c8" is not supported anymore. Use "coverage.provider: v8" instead')
122123123124 if (resolved.coverage.provider === 'v8' && resolved.coverage.enabled && isBrowserEnabled(resolved))
124125 throw new Error('@vitest/coverage-v8 does not work with --browser. Use @vitest/coverage-istanbul instead')
-4
packages/vitest/src/node/pkg.ts
···99export async function ensurePackageInstalled(
1010 dependency: string,
1111 root: string,
1212- errorMessage?: string,
1312) {
1413 if (isPackageExists(dependency, { paths: [root, __dirname] }))
1514 return true
16151716 const promptInstall = !isCI && process.stdout.isTTY
1818-1919- if (errorMessage)
2020- process.stderr.write(c.red(errorMessage))
21172218 process.stderr.write(c.red(`${c.inverse(c.red(' MISSING DEP '))} Can not find dependency '${dependency}'\n\n`))
2319
+4-35
packages/vitest/src/types/coverage.ts
···6161 : [ReporterName, Partial<ReportOptions[ReporterName]>]
6262 : never
63636464-type Provider = 'c8' | 'v8' | 'istanbul' | 'custom' | undefined
6464+type Provider = 'v8' | 'istanbul' | 'custom' | undefined
65656666export type CoverageOptions<T extends Provider = Provider> =
6767 T extends 'istanbul' ? ({ provider: T } & CoverageIstanbulOptions) :
6868- T extends 'c8' ? ({ provider: T } & CoverageC8Options) :
6969- T extends 'v8' ? ({ provider: T } & CoverageV8Options) :
7070- T extends 'custom' ? ({ provider: T } & CustomProviderOptions) :
7171- ({ provider?: T } & (CoverageC8Options))
6868+ T extends 'v8' ? ({ provider: T } & CoverageV8Options) :
6969+ T extends 'custom' ? ({ provider: T } & CustomProviderOptions) :
7070+ ({ provider?: T } & (CoverageV8Options))
72717372/** Fields that have default values. Internally these will always be defined. */
7473type FieldsWithDefaultValues =
···226225 * @default []
227226 */
228227 ignoreClassMethods?: string[]
229229-}
230230-231231-export interface CoverageC8Options extends BaseCoverageOptions {
232232- /**
233233- * Allow files from outside of your cwd.
234234- *
235235- * @default false
236236- */
237237- allowExternal?: boolean
238238-239239- /**
240240- * Exclude coverage under `/node_modules/`
241241- *
242242- * @default true
243243- */
244244- excludeNodeModules?: boolean
245245-246246- /**
247247- * Specifies the directories that are used when `--all` is enabled.
248248- *
249249- * @default cwd
250250- */
251251- src?: string[]
252252-253253- /**
254254- * Shortcut for `--check-coverage --lines 100 --functions 100 --branches 100 --statements 100`
255255- *
256256- * @default false
257257- */
258258- 100?: boolean
259228}
260229261230export interface CoverageV8Options extends BaseCoverageOptions {