diff --git a/README.md b/README.md
index ff4a86614302..9f60e47d91fb 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ A blazing fast unit test framework powered by Vite.
- [Jest Snapshot](https://jestjs.io/docs/snapshot-testing)
- [Chai](https://www.chaijs.com/) built-in for assertions, with [Jest expect](https://jestjs.io/docs/expect) compatible APIs.
- [Smart & instant watch mode](https://vitest.dev/guide/features.html#watch-mode), like HMR for tests!
-- [Native code coverage](https://vitest.dev/guide/features.html#coverage) via [c8](https://github.com/bcoe/c8) or [`istanbul`](https://istanbul.js.org/).
+- [Native code coverage](https://vitest.dev/guide/features.html#coverage) via [`v8`](https://v8.dev/blog/javascript-code-coverage) or [`istanbul`](https://istanbul.js.org/).
- [Tinyspy](https://github.com/tinylibs/tinyspy) built-in for mocking, stubbing, and spies.
- [JSDOM](https://github.com/jsdom/jsdom) and [happy-dom](https://github.com/capricorn86/happy-dom) for DOM and browser API mocking
- Components testing ([Vue](./examples/vue), [React](./examples/react), [Svelte](./examples/svelte), [Lit](./examples/lit), [Vitesse](./examples/vitesse))
diff --git a/docs/.vitepress/components/FeaturesList.vue b/docs/.vitepress/components/FeaturesList.vue
index add0417bcb08..fef14975f7f2 100644
--- a/docs/.vitepress/components/FeaturesList.vue
+++ b/docs/.vitepress/components/FeaturesList.vue
@@ -22,7 +22,7 @@
Chai built-in for assertions + Jest expect compatible APIs
Tinyspy built-in for mocking
happy-dom or jsdom for DOM mocking
- Code coverage via c8 or istanbul
+ Code coverage via v8 or istanbul
Rust-like in-source testing
Type Testing via expect-type
diff --git a/docs/advanced/api.md b/docs/advanced/api.md
index 68e8720b2dc4..fa4990699fda 100644
--- a/docs/advanced/api.md
+++ b/docs/advanced/api.md
@@ -19,7 +19,7 @@ await vitest?.close()
`startVitest` function returns `Vitest` instance if tests can be started. It returns `undefined`, if one of the following occurs:
- Vitest didn't find "vite" package (usually installed with Vitest)
-- If coverage is enabled and run mode is "test", but the coverage package is not installed (`@vitest/coverage-c8` or `@vitest/coverage-istanbul`)
+- If coverage is enabled and run mode is "test", but the coverage package is not installed (`@vitest/coverage-v8` or `@vitest/coverage-istanbul`)
- If the environment package is not installed (`jsdom`/`happy-dom`/`@edge-runtime/vm`)
If `undefined` is returned or tests failed during the run, Vitest sets `process.exitCode` to `1`.
diff --git a/docs/config/index.md b/docs/config/index.md
index b26dd6dfc701..432fe7657127 100644
--- a/docs/config/index.md
+++ b/docs/config/index.md
@@ -665,7 +665,11 @@ Isolate environment for each test file. Does not work if you disable [`--threads
### coverage
-You can use [`c8`](https://github.com/bcoe/c8), [`istanbul`](https://istanbul.js.org/) or [a custom coverage solution](/guide/coverage#custom-coverage-provider) for coverage collection.
+You 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.
+
+::: info
+The `c8` provider is being replaced by the `v8` provider. It will be deprecated in the next major version.
+:::
You can provide coverage options to CLI with dot notation:
@@ -679,8 +683,8 @@ If you are using coverage options with dot notation, don't forget to specify `--
#### coverage.provider
-- **Type:** `'c8' | 'istanbul' | 'custom'`
-- **Default:** `'c8'`
+- **Type:** `'c8' | 'v8' | 'istanbul' | 'custom'`
+- **Default:** `'v8'`
- **CLI:** `--coverage.provider=`
Use `provider` to select the tool for coverage collection.
@@ -689,7 +693,7 @@ Use `provider` to select the tool for coverage collection.
- **Type:** `boolean`
- **Default:** `false`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.enabled`, `--coverage.enabled=false`
Enables coverage collection. Can be overridden using `--coverage` CLI option.
@@ -698,7 +702,7 @@ Enables coverage collection. Can be overridden using `--coverage` CLI option.
- **Type:** `string[]`
- **Default:** `['**']`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.include=`, `--coverage.include= --coverage.include=`
List of files included in coverage as glob patterns
@@ -707,7 +711,7 @@ List of files included in coverage as glob patterns
- **Type:** `string | string[]`
- **Default:** `['.js', '.cjs', '.mjs', '.ts', '.mts', '.cts', '.tsx', '.jsx', '.vue', '.svelte']`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.extension=`, `--coverage.extension= --coverage.extension=`
#### coverage.exclude
@@ -729,7 +733,7 @@ List of files included in coverage as glob patterns
'**/.{eslint,mocha,prettier}rc.{?(c|m)js,yml}',
]
```
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.exclude=`, `--coverage.exclude= --coverage.exclude=`
List of files excluded from coverage as glob patterns.
@@ -738,7 +742,7 @@ List of files excluded from coverage as glob patterns.
- **Type:** `boolean`
- **Default:** `false`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.all`, `--coverage.all=false`
Whether to include all files, including the untested ones into report.
@@ -747,7 +751,7 @@ Whether to include all files, including the untested ones into report.
- **Type:** `boolean`
- **Default:** `true`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.clean`, `--coverage.clean=false`
Clean coverage results before running tests
@@ -756,7 +760,7 @@ Clean coverage results before running tests
- **Type:** `boolean`
- **Default:** `true`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.cleanOnRerun`, `--coverage.cleanOnRerun=false`
Clean coverage report on watch rerun
@@ -765,7 +769,7 @@ Clean coverage report on watch rerun
- **Type:** `string`
- **Default:** `'./coverage'`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.reportsDirectory=`
Directory to write coverage report to.
@@ -774,7 +778,7 @@ Directory to write coverage report to.
- **Type:** `string | string[] | [string, {}][]`
- **Default:** `['text', 'html', 'clover', 'json']`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.reporter=`, `--coverage.reporter= --coverage.reporter=`
Coverage 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.
@@ -801,7 +805,7 @@ Since Vitest 0.31.0, you can check your coverage report in Vitest UI: check [Vit
- **Type:** `boolean`
- **Default:** `true`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.reportOnFailure`, `--coverage.reportOnFailure=false`
- **Version:** Since Vitest 0.31.2
@@ -811,7 +815,7 @@ Generate coverage report even when tests fail.
- **Type:** `boolean`
- **Default:** `false`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.skipFull`, `--coverage.skipFull=false`
Do not show files with 100% statement, branch, and function coverage.
@@ -820,7 +824,7 @@ Do not show files with 100% statement, branch, and function coverage.
- **Type:** `boolean`
- **Default:** `false`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.perFile`, `--coverage.perFile=false`
Check thresholds per file.
@@ -830,7 +834,7 @@ See `lines`, `functions`, `branches` and `statements` for the actual thresholds.
- **Type:** `boolean`
- **Default:** `false`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.thresholdAutoUpdate=`
Update threshold values `lines`, `functions`, `branches` and `statements` to configuration file when current coverage is above the configured thresholds.
@@ -839,7 +843,7 @@ This option helps to maintain thresholds when coverage is improved.
#### coverage.lines
- **Type:** `number`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.lines=`
Threshold for lines.
@@ -848,7 +852,7 @@ See [istanbul documentation](https://github.com/istanbuljs/nyc#coverage-threshol
#### coverage.functions
- **Type:** `number`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.functions=`
Threshold for functions.
@@ -857,7 +861,7 @@ See [istanbul documentation](https://github.com/istanbuljs/nyc#coverage-threshol
#### coverage.branches
- **Type:** `number`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.branches=`
Threshold for branches.
@@ -866,7 +870,7 @@ See [istanbul documentation](https://github.com/istanbuljs/nyc#coverage-threshol
#### coverage.statements
- **Type:** `number`
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
- **CLI:** `--coverage.statements=`
Threshold for statements.
@@ -903,7 +907,7 @@ Specifies the directories that are used when `--all` is enabled.
- **Type:** `boolean`
- **Default:** `false`
-- **Available for providers:** `'c8'`
+- **Available for providers:** `'c8' | 'v8'`
- **CLI:** `--coverage.100`, `--coverage.100=false`
Shortcut for `--check-coverage --lines 100 --functions 100 --branches 100 --statements 100`.
@@ -942,7 +946,7 @@ See [istanbul documentation](https://github.com/istanbuljs/nyc#ignoring-methods)
}
```
-- **Available for providers:** `'c8' | 'istanbul'`
+- **Available for providers:** `'c8' | 'v8' | 'istanbul'`
Watermarks for statements, lines, branches and functions. See [istanbul documentation](https://github.com/istanbuljs/nyc#high-and-low-watermarks) for more information.
diff --git a/docs/guide/coverage.md b/docs/guide/coverage.md
index 14e5ea3ebc63..8bc72938723f 100644
--- a/docs/guide/coverage.md
+++ b/docs/guide/coverage.md
@@ -4,7 +4,11 @@ title: Coverage | Guide
# Coverage
-Vitest supports Native code coverage via [`c8`](https://github.com/bcoe/c8) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).
+Vitest supports Native code coverage via [`v8`](https://v8.dev/blog/javascript-code-coverage) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).
+
+:::info
+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.
+:::
## Coverage Providers
@@ -12,9 +16,9 @@ Vitest supports Native code coverage via [`c8`](https://github.com/bcoe/c8) and
Since Vitest v0.22.0
:::
-Both `c8` and `istanbul` support are optional. By default, `c8` will be used.
+Both `v8` and `istanbul` support are optional. By default, `v8` will be used.
-You can select the coverage tool by setting `test.coverage.provider` to either `c8` or `istanbul`:
+You can select the coverage tool by setting `test.coverage.provider` to `v8` or `istanbul`:
```ts
// vite.config.ts
@@ -23,7 +27,7 @@ import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
coverage: {
- provider: 'istanbul' // or 'c8'
+ provider: 'istanbul' // or 'v8'
},
},
})
@@ -34,8 +38,8 @@ When you start the Vitest process, it will prompt you to install the correspondi
Or if you prefer to install them manually:
```bash
-# For c8
-npm i -D @vitest/coverage-c8
+# For v8
+npm i -D @vitest/coverage-v8
# For istanbul
npm i -D @vitest/coverage-istanbul
@@ -138,7 +142,7 @@ export default defineConfig({
Both coverage providers have their own ways how to ignore code from coverage reports:
-- [`c8`](https://github.com/bcoe/c8#ignoring-uncovered-lines-functions-and-blocks)
+- [`v8`](https://github.com/istanbuljs/v8-to-istanbul#ignoring-uncovered-lines)
- [`ìstanbul`](https://github.com/istanbuljs/nyc#parsing-hints-ignoring-lines)
When using TypeScript the source codes are transpiled using `esbuild`, which strips all comments from the source codes ([esbuild#516](https://github.com/evanw/esbuild/issues/516)).
@@ -153,7 +157,7 @@ Beware that these ignore hints may now be included in final production build as
if (condition) {
```
-For `c8` this does not cause any issues. You can use `c8 ignore` comments with Typescript as usual:
+For `v8` this does not cause any issues. You can use `c8 ignore` comments with Typescript as usual:
```ts
diff --git a/docs/guide/features.md b/docs/guide/features.md
index a2387f838dde..f1f8f66fa7ab 100644
--- a/docs/guide/features.md
+++ b/docs/guide/features.md
@@ -143,7 +143,7 @@ Learn more at [Mocking](/guide/mocking).
## Coverage
-Vitest supports Native code coverage via [`c8`](https://github.com/bcoe/c8) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).
+Vitest supports Native code coverage via [`v8`](https://v8.dev/blog/javascript-code-coverage) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).
```json
{
diff --git a/package.json b/package.json
index ab985a33d905..4dff5cc81e80 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"@vitest/browser": "workspace:*",
"@vitest/coverage-c8": "workspace:*",
"@vitest/coverage-istanbul": "workspace:*",
+ "@vitest/coverage-v8": "workspace:*",
"@vitest/ui": "workspace:*",
"bumpp": "^9.1.0",
"esbuild": "^0.17.18",
diff --git a/packages/coverage-c8/src/provider.ts b/packages/coverage-c8/src/provider.ts
index 8fc0e8a2d388..8ac20792c0f6 100644
--- a/packages/coverage-c8/src/provider.ts
+++ b/packages/coverage-c8/src/provider.ts
@@ -54,6 +54,15 @@ export class C8CoverageProvider extends BaseCoverageProvider implements Coverage
branches: config['100'] ? 100 : config.branches,
statements: config['100'] ? 100 : config.statements,
}
+
+ const banner = ' DEPRECATION '
+ this.ctx.logger.log(
+ c.bgYellow(c.black((banner))),
+ c.yellow('@vitest/coverage-c8 is being replaced by @vitest/coverage-v8.'),
+ c.yellow(`\n${' '.repeat(banner.length)} See`),
+ c.blue(c.underline('https://github.com/vitest-dev/vitest/pull/3339')),
+ c.yellow('for more information.'),
+ )
}
resolveOptions() {
diff --git a/packages/coverage-istanbul/package.json b/packages/coverage-istanbul/package.json
index 4ee8a2ca1b7b..f9c43b235a7d 100644
--- a/packages/coverage-istanbul/package.json
+++ b/packages/coverage-istanbul/package.json
@@ -42,7 +42,7 @@
"prepublishOnly": "pnpm build"
},
"peerDependencies": {
- "vitest": ">=0.30.0 <1"
+ "vitest": ">=0.32.0 <1"
},
"dependencies": {
"istanbul-lib-coverage": "^3.2.0",
diff --git a/packages/coverage-istanbul/src/provider.ts b/packages/coverage-istanbul/src/provider.ts
index 12e490d202ee..84af13763de9 100644
--- a/packages/coverage-istanbul/src/provider.ts
+++ b/packages/coverage-istanbul/src/provider.ts
@@ -1,5 +1,5 @@
import { existsSync, promises as fs } from 'node:fs'
-import { relative, resolve } from 'pathe'
+import { resolve } from 'pathe'
import type { AfterSuiteRunMeta, CoverageIstanbulOptions, CoverageProvider, ReportContext, ResolvedCoverageOptions, Vitest } from 'vitest'
import { coverageConfigDefaults, defaultExclude, defaultInclude } from 'vitest/config'
import { BaseCoverageProvider } from 'vitest/coverage'
@@ -16,8 +16,6 @@ import { COVERAGE_STORE_KEY } from './constants'
type Options = ResolvedCoverageOptions<'istanbul'>
-type Threshold = 'lines' | 'functions' | 'statements' | 'branches'
-
interface TestExclude {
new(opts: {
cwd?: string | string[]
@@ -146,11 +144,15 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co
|| this.options.functions
|| this.options.lines
|| this.options.statements) {
- this.checkThresholds(coverageMap, {
- branches: this.options.branches,
- functions: this.options.functions,
- lines: this.options.lines,
- statements: this.options.statements,
+ this.checkThresholds({
+ coverageMap,
+ thresholds: {
+ branches: this.options.branches,
+ functions: this.options.functions,
+ lines: this.options.lines,
+ statements: this.options.statements,
+ },
+ perFile: this.options.perFile,
})
}
@@ -169,52 +171,6 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co
}
}
- checkThresholds(coverageMap: CoverageMap, thresholds: Record) {
- // Construct list of coverage summaries where thresholds are compared against
- const summaries = this.options.perFile
- ? coverageMap.files()
- .map((file: string) => ({
- file,
- summary: coverageMap.fileCoverageFor(file).toSummary(),
- }))
- : [{
- file: null,
- summary: coverageMap.getCoverageSummary(),
- }]
-
- // Check thresholds of each summary
- for (const { summary, file } of summaries) {
- for (const thresholdKey of ['lines', 'functions', 'statements', 'branches'] as const) {
- const threshold = thresholds[thresholdKey]
-
- if (threshold !== undefined) {
- const coverage = summary.data[thresholdKey].pct
-
- if (coverage < threshold) {
- process.exitCode = 1
-
- /*
- * Generate error message based on perFile flag:
- * - ERROR: Coverage for statements (33.33%) does not meet threshold (85%) for src/math.ts
- * - ERROR: Coverage for statements (50%) does not meet global threshold (85%)
- */
- let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet`
-
- if (!this.options.perFile)
- errorMessage += ' global'
-
- errorMessage += ` threshold (${threshold}%)`
-
- if (this.options.perFile && file)
- errorMessage += ` for ${relative('./', file).replace(/\\/g, '/')}`
-
- console.error(errorMessage)
- }
- }
- }
- }
- }
-
async includeUntestedFiles(coverageMap: CoverageMap) {
// Load, instrument and collect empty coverages from all files which
// are not already in the coverage map
diff --git a/packages/coverage-v8/package.json b/packages/coverage-v8/package.json
new file mode 100644
index 000000000000..5ec20790e5c9
--- /dev/null
+++ b/packages/coverage-v8/package.json
@@ -0,0 +1,69 @@
+{
+ "name": "@vitest/coverage-v8",
+ "type": "module",
+ "version": "0.31.3",
+ "description": "V8 coverage provider for Vitest",
+ "author": "Anthony Fu ",
+ "license": "MIT",
+ "funding": "https://opencollective.com/vitest",
+ "homepage": "https://github.com/vitest-dev/vitest/tree/main/packages/coverage-v8#readme",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vitest-dev/vitest.git",
+ "directory": "packages/coverage-v8"
+ },
+ "bugs": {
+ "url": "https://github.com/vitest-dev/vitest/issues"
+ },
+ "keywords": [
+ "vite",
+ "vitest",
+ "test",
+ "coverage",
+ "v8"
+ ],
+ "sideEffects": false,
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js"
+ },
+ "./*": "./*"
+ },
+ "main": "./dist/index.js",
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "build": "rimraf dist && rollup -c",
+ "dev": "rollup -c --watch --watch.include 'src/**'",
+ "prepublishOnly": "pnpm build"
+ },
+ "peerDependencies": {
+ "vitest": ">=0.32.0 <1"
+ },
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.1",
+ "@bcoe/v8-coverage": "^0.2.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.1",
+ "istanbul-reports": "^3.1.5",
+ "magic-string": "^0.30.0",
+ "picocolors": "^1.0.0",
+ "std-env": "^3.3.2",
+ "test-exclude": "^6.0.0",
+ "v8-to-istanbul": "^9.1.0"
+ },
+ "devDependencies": {
+ "@types/istanbul-lib-coverage": "^2.0.4",
+ "@types/istanbul-lib-report": "^3.0.0",
+ "@types/istanbul-lib-source-maps": "^4.0.1",
+ "@types/istanbul-reports": "^3.0.1",
+ "pathe": "^1.1.0",
+ "vite-node": "workspace:*",
+ "vitest": "workspace:*"
+ }
+}
diff --git a/packages/coverage-v8/rollup.config.js b/packages/coverage-v8/rollup.config.js
new file mode 100644
index 000000000000..15844d9de912
--- /dev/null
+++ b/packages/coverage-v8/rollup.config.js
@@ -0,0 +1,63 @@
+import { builtinModules } from 'node:module'
+import esbuild from 'rollup-plugin-esbuild'
+import dts from 'rollup-plugin-dts'
+import commonjs from '@rollup/plugin-commonjs'
+import json from '@rollup/plugin-json'
+import alias from '@rollup/plugin-alias'
+import nodeResolve from '@rollup/plugin-node-resolve'
+import { join } from 'pathe'
+import pkg from './package.json' assert { type: 'json' }
+
+const entries = {
+ index: 'src/index.ts',
+ provider: 'src/provider.ts',
+}
+
+const external = [
+ ...builtinModules,
+ ...Object.keys(pkg.dependencies || {}),
+ ...Object.keys(pkg.peerDependencies || {}),
+ 'node:inspector',
+ 'vitest',
+ 'vitest/node',
+ 'vitest/config',
+ 'vitest/coverage',
+]
+
+const plugins = [
+ alias({
+ entries: [
+ { find: /^node:(.+)$/, replacement: '$1' },
+ ],
+ }),
+ nodeResolve(),
+ json(),
+ commonjs(),
+ esbuild({
+ target: 'node14',
+ }),
+]
+
+export default () => [
+ {
+ input: entries,
+ output: {
+ dir: 'dist',
+ format: 'esm',
+ },
+ external,
+ plugins,
+ },
+ {
+ input: entries,
+ output: {
+ dir: join(process.cwd(), 'dist'),
+ entryFileNames: '[name].d.ts',
+ format: 'esm',
+ },
+ external,
+ plugins: [
+ dts({ respectExternal: true }),
+ ],
+ },
+]
diff --git a/packages/coverage-v8/src/index.ts b/packages/coverage-v8/src/index.ts
new file mode 100644
index 000000000000..cbdedfa38ef8
--- /dev/null
+++ b/packages/coverage-v8/src/index.ts
@@ -0,0 +1,11 @@
+import * as coverage from './takeCoverage'
+
+export default {
+ ...coverage,
+ async getProvider() {
+ // to not bundle the provider
+ const name = './provider.js'
+ const { V8CoverageProvider } = await import(name) as typeof import('./provider')
+ return new V8CoverageProvider()
+ },
+}
diff --git a/packages/coverage-v8/src/provider.ts b/packages/coverage-v8/src/provider.ts
new file mode 100644
index 000000000000..b9fe8a97f174
--- /dev/null
+++ b/packages/coverage-v8/src/provider.ts
@@ -0,0 +1,263 @@
+import { existsSync, promises as fs } from 'node:fs'
+import type { Profiler } from 'node:inspector'
+import { fileURLToPath, pathToFileURL } from 'node:url'
+import v8ToIstanbul from 'v8-to-istanbul'
+import { mergeProcessCovs } from '@bcoe/v8-coverage'
+import libReport from 'istanbul-lib-report'
+import reports from 'istanbul-reports'
+import type { CoverageMap } from 'istanbul-lib-coverage'
+import libCoverage from 'istanbul-lib-coverage'
+import libSourceMaps from 'istanbul-lib-source-maps'
+import MagicString from 'magic-string'
+import remapping from '@ampproject/remapping'
+import { normalize, resolve } from 'pathe'
+import c from 'picocolors'
+import { provider } from 'std-env'
+import type { EncodedSourceMap } from 'vite-node'
+import { coverageConfigDefaults, defaultExclude, defaultInclude } from 'vitest/config'
+import { BaseCoverageProvider } from 'vitest/coverage'
+import type { AfterSuiteRunMeta, CoverageProvider, CoverageV8Options, ReportContext, ResolvedCoverageOptions } from 'vitest'
+import type { Vitest } from 'vitest/node'
+
+// @ts-expect-error missing types
+import _TestExclude from 'test-exclude'
+
+interface TestExclude {
+ new(opts: {
+ cwd?: string | string[]
+ include?: string | string[]
+ exclude?: string | string[]
+ extension?: string | string[]
+ excludeNodeModules?: boolean
+ }): {
+ shouldInstrument(filePath: string): boolean
+ glob(cwd: string): Promise
+ }
+}
+
+type Options = ResolvedCoverageOptions<'v8'>
+
+// TODO: vite-node should export this
+const WRAPPER_LENGTH = 185
+
+// Note that this needs to match the line ending as well
+const VITE_EXPORTS_LINE_PATTERN = /Object\.defineProperty\(__vite_ssr_exports__.*\n/g
+
+export class V8CoverageProvider extends BaseCoverageProvider implements CoverageProvider {
+ name = 'v8'
+
+ ctx!: Vitest
+ options!: Options
+ testExclude!: InstanceType
+ coverages: Profiler.TakePreciseCoverageReturnType[] = []
+
+ initialize(ctx: Vitest) {
+ const config: CoverageV8Options = ctx.config.coverage
+
+ this.ctx = ctx
+ this.options = {
+ ...coverageConfigDefaults,
+
+ // User's options
+ ...config,
+
+ // Resolved fields
+ provider: 'v8',
+ reporter: this.resolveReporters(config.reporter || coverageConfigDefaults.reporter),
+ reportsDirectory: resolve(ctx.config.root, config.reportsDirectory || coverageConfigDefaults.reportsDirectory),
+ lines: config['100'] ? 100 : config.lines,
+ functions: config['100'] ? 100 : config.functions,
+ branches: config['100'] ? 100 : config.branches,
+ statements: config['100'] ? 100 : config.statements,
+ }
+
+ this.testExclude = new _TestExclude({
+ cwd: ctx.config.root,
+ include: typeof this.options.include === 'undefined' ? undefined : [...this.options.include],
+ exclude: [...defaultExclude, ...defaultInclude, ...this.options.exclude],
+ excludeNodeModules: true,
+ extension: this.options.extension,
+ })
+ }
+
+ resolveOptions() {
+ return this.options
+ }
+
+ async clean(clean = true) {
+ if (clean && existsSync(this.options.reportsDirectory))
+ await fs.rm(this.options.reportsDirectory, { recursive: true, force: true, maxRetries: 10 })
+
+ this.coverages = []
+ }
+
+ onAfterSuiteRun({ coverage }: AfterSuiteRunMeta) {
+ this.coverages.push(coverage as Profiler.TakePreciseCoverageReturnType)
+ }
+
+ async reportCoverage({ allTestsRun }: ReportContext = {}) {
+ if (provider === 'stackblitz')
+ this.ctx.logger.log(c.blue(' % ') + c.yellow('@vitest/coverage-v8 does not work on Stackblitz. Report will be empty.'))
+
+ const merged = mergeProcessCovs(this.coverages)
+ const scriptCoverages = merged.result.filter(result => this.testExclude.shouldInstrument(fileURLToPath(result.url)))
+
+ if (this.options.all && allTestsRun) {
+ const coveredFiles = Array.from(scriptCoverages.map(r => r.url))
+ const untestedFiles = await this.getUntestedFiles(coveredFiles)
+
+ scriptCoverages.push(...untestedFiles)
+ }
+
+ const converted = await Promise.all(scriptCoverages.map(async ({ url, functions }) => {
+ const sources = await this.getSources(url)
+
+ // If no source map was found from vite-node we can assume this file was not run in the wrapper
+ const wrapperLength = sources.sourceMap ? WRAPPER_LENGTH : 0
+
+ const converter = v8ToIstanbul(url, wrapperLength, sources)
+ await converter.load()
+
+ converter.applyCoverage(functions)
+ return converter.toIstanbul()
+ }))
+
+ const mergedCoverage = converted.reduce((coverage, previousCoverageMap) => {
+ const map = libCoverage.createCoverageMap(coverage)
+ map.merge(previousCoverageMap)
+ return map
+ }, libCoverage.createCoverageMap({}))
+
+ const sourceMapStore = libSourceMaps.createSourceMapStore()
+ const coverageMap: CoverageMap = await sourceMapStore.transformCoverage(mergedCoverage)
+
+ const context = libReport.createContext({
+ dir: this.options.reportsDirectory,
+ coverageMap,
+ sourceFinder: sourceMapStore.sourceFinder,
+ watermarks: this.options.watermarks,
+ })
+
+ for (const reporter of this.options.reporter) {
+ reports.create(reporter[0], {
+ skipFull: this.options.skipFull,
+ projectRoot: this.ctx.config.root,
+ ...reporter[1],
+ }).execute(context)
+ }
+
+ if (this.options.branches
+ || this.options.functions
+ || this.options.lines
+ || this.options.statements) {
+ this.checkThresholds({
+ coverageMap,
+ thresholds: {
+ branches: this.options.branches,
+ functions: this.options.functions,
+ lines: this.options.lines,
+ statements: this.options.statements,
+ },
+ perFile: this.options.perFile,
+ })
+ }
+
+ if (this.options.thresholdAutoUpdate && allTestsRun) {
+ this.updateThresholds({
+ coverageMap,
+ thresholds: {
+ branches: this.options.branches,
+ functions: this.options.functions,
+ lines: this.options.lines,
+ statements: this.options.statements,
+ },
+ perFile: this.options.perFile,
+ configurationFile: this.ctx.server.config.configFile,
+ })
+ }
+ }
+
+ private async getUntestedFiles(testedFiles: string[]): Promise {
+ const includedFiles = await this.testExclude.glob(this.ctx.config.root)
+ const uncoveredFiles = includedFiles
+ .map(file => pathToFileURL(resolve(this.ctx.config.root, file)))
+ .filter(file => !testedFiles.includes(file.href))
+
+ return await Promise.all(uncoveredFiles.map(async (uncoveredFile) => {
+ const { source } = await this.getSources(uncoveredFile.href)
+
+ return {
+ url: uncoveredFile.href,
+ scriptId: '0',
+ // Create a made up function to mark whole file as uncovered. Note that this does not exist in source maps.
+ functions: [{
+ ranges: [{
+ startOffset: 0,
+ endOffset: source.length,
+ count: 0,
+ }],
+ isBlockCoverage: true,
+ // This is magical value that indicates an empty report: https://github.com/istanbuljs/v8-to-istanbul/blob/fca5e6a9e6ef38a9cdc3a178d5a6cf9ef82e6cab/lib/v8-to-istanbul.js#LL131C40-L131C40
+ functionName: '(empty-report)',
+ }],
+ }
+ }))
+ }
+
+ private async getSources(url: string): Promise<{
+ source: string
+ originalSource?: string
+ sourceMap?: { sourcemap: EncodedSourceMap }
+ }> {
+ const filePath = normalize(fileURLToPath(url))
+ const transformResult = this.ctx.projects
+ .map(project => project.vitenode.fetchCache.get(filePath)?.result)
+ .filter(Boolean)
+ .shift()
+
+ const map = transformResult?.map
+ const code = transformResult?.code
+ const sourcesContent = map?.sourcesContent?.[0] || await fs.readFile(filePath, 'utf-8')
+
+ // These can be uncovered files included by "all: true" or files that are loaded outside vite-node
+ if (!map)
+ return { source: code || sourcesContent }
+
+ return {
+ originalSource: sourcesContent,
+ source: code || sourcesContent,
+ sourceMap: {
+ sourcemap: removeViteHelpersFromSourceMaps(code, {
+ ...map,
+ version: 3,
+ sources: [url],
+ sourcesContent: [sourcesContent],
+ }),
+ },
+ }
+ }
+}
+
+/**
+ * Remove generated code from the source maps:
+ * - Vite's export helpers: e.g. `Object.defineProperty(__vite_ssr_exports__, "sum", { enumerable: true, configurable: true, get(){ return sum }});`
+ */
+function removeViteHelpersFromSourceMaps(source: string | undefined, map: EncodedSourceMap) {
+ if (!source || !source.match(VITE_EXPORTS_LINE_PATTERN))
+ return map
+
+ const sourceWithoutHelpers = new MagicString(source)
+ sourceWithoutHelpers.replaceAll(VITE_EXPORTS_LINE_PATTERN, '\n')
+
+ const mapWithoutHelpers = sourceWithoutHelpers.generateMap({
+ hires: true,
+ })
+
+ // A merged source map where the first one excludes helpers
+ const combinedMap = remapping(
+ [{ ...mapWithoutHelpers, version: 3 }, map],
+ () => null,
+ )
+
+ return combinedMap as EncodedSourceMap
+}
diff --git a/packages/coverage-v8/src/takeCoverage.ts b/packages/coverage-v8/src/takeCoverage.ts
new file mode 100644
index 000000000000..ea49e52e17ea
--- /dev/null
+++ b/packages/coverage-v8/src/takeCoverage.ts
@@ -0,0 +1,51 @@
+/*
+ * For details about the Profiler.* messages see https://chromedevtools.github.io/devtools-protocol/v8/Profiler/
+*/
+
+import inspector from 'node:inspector'
+import type { Profiler } from 'node:inspector'
+import { provider } from 'std-env'
+
+const session = new inspector.Session()
+
+export function startCoverage() {
+ session.connect()
+ session.post('Profiler.enable')
+ session.post('Profiler.startPreciseCoverage', {
+ callCount: true,
+ detailed: true,
+ })
+}
+
+export async function takeCoverage() {
+ return new Promise((resolve, reject) => {
+ session.post('Profiler.takePreciseCoverage', async (error, coverage) => {
+ if (error)
+ return reject(error)
+
+ // Reduce amount of data sent over rpc by doing some early result filtering
+ const result = coverage.result.filter(filterResult)
+
+ resolve({ result })
+ })
+
+ if (provider === 'stackblitz')
+ resolve({ result: [] })
+ })
+}
+
+export function stopCoverage() {
+ session.post('Profiler.stopPreciseCoverage')
+ session.post('Profiler.disable')
+ session.disconnect()
+}
+
+function filterResult(coverage: Profiler.ScriptCoverage): boolean {
+ if (!coverage.url.startsWith('file://'))
+ return false
+
+ if (coverage.url.includes('/node_modules/'))
+ return false
+
+ return true
+}
diff --git a/packages/vitest/src/defaults.ts b/packages/vitest/src/defaults.ts
index e422d315b38e..b75f658eb304 100644
--- a/packages/vitest/src/defaults.ts
+++ b/packages/vitest/src/defaults.ts
@@ -26,7 +26,7 @@ const defaultCoverageExcludes = [
// These are the generic defaults for coverage. Providers may also set some provider specific defaults.
export const coverageConfigDefaults: ResolvedCoverageOptions = {
- provider: 'c8',
+ provider: 'v8',
enabled: false,
clean: true,
cleanOnRerun: true,
diff --git a/packages/vitest/src/integrations/coverage.ts b/packages/vitest/src/integrations/coverage.ts
index 983334fafd20..db35ec79cbdc 100644
--- a/packages/vitest/src/integrations/coverage.ts
+++ b/packages/vitest/src/integrations/coverage.ts
@@ -6,6 +6,7 @@ interface Loader {
export const CoverageProviderMap: Record = {
c8: '@vitest/coverage-c8',
+ v8: '@vitest/coverage-v8',
istanbul: '@vitest/coverage-istanbul',
}
@@ -15,7 +16,7 @@ async function resolveCoverageProviderModule(options: CoverageOptions | undefine
const provider = options.provider
- if (provider === 'c8' || provider === 'istanbul') {
+ if (provider === 'c8' || provider === 'v8' || provider === 'istanbul') {
const { default: coverageModule } = await loader.executeId(CoverageProviderMap[provider])
if (!coverageModule)
diff --git a/packages/vitest/src/node/cli-api.ts b/packages/vitest/src/node/cli-api.ts
index 542a6e61982c..84b280f79b1d 100644
--- a/packages/vitest/src/node/cli-api.ts
+++ b/packages/vitest/src/node/cli-api.ts
@@ -59,11 +59,21 @@ export async function startVitest(
const ctx = await createVitest(mode, options, viteOverrides)
if (mode === 'test' && ctx.config.coverage.enabled) {
- const provider = ctx.config.coverage.provider || 'c8'
+ const provider = ctx.config.coverage.provider || 'v8'
const requiredPackages = CoverageProviderMap[provider]
if (requiredPackages) {
- if (!await ensurePackageInstalled(requiredPackages, root)) {
+ // Remove this message once support for @vitest/coverage-c8 has been removed completely
+ const defaultProviderInfo = 'Default coverage provider has changed from "c8" to "v8". '
+ + 'New package is required to be installed. '
+ + 'To use the old deprecated coverage provider use "--coverage.provider c8" option.\n'
+ + 'See https://github.com/vitest-dev/vitest/pull/3339 for more information.\n\n'
+
+ const isUsingDefaultProvider
+ = ctx.server.config.test?.coverage?.provider === undefined
+ && options.coverage?.provider === undefined
+
+ if (!await ensurePackageInstalled(requiredPackages, root, isUsingDefaultProvider ? defaultProviderInfo : undefined)) {
process.exitCode = 1
return ctx
}
diff --git a/packages/vitest/src/node/config.ts b/packages/vitest/src/node/config.ts
index e1648daccc8f..7351dc070ede 100644
--- a/packages/vitest/src/node/config.ts
+++ b/packages/vitest/src/node/config.ts
@@ -120,6 +120,9 @@ export function resolveConfig(
if (resolved.coverage.provider === 'c8' && resolved.coverage.enabled && isBrowserEnabled(resolved))
throw new Error('@vitest/coverage-c8 does not work with --browser. Use @vitest/coverage-istanbul instead')
+ if (resolved.coverage.provider === 'v8' && resolved.coverage.enabled && isBrowserEnabled(resolved))
+ throw new Error('@vitest/coverage-v8 does not work with --browser. Use @vitest/coverage-istanbul instead')
+
resolved.deps = resolved.deps || {}
// vitenode will try to import such file with native node,
// but then our mocker will not work properly
diff --git a/packages/vitest/src/node/pkg.ts b/packages/vitest/src/node/pkg.ts
index f1de8b90d01c..36475498107a 100644
--- a/packages/vitest/src/node/pkg.ts
+++ b/packages/vitest/src/node/pkg.ts
@@ -9,12 +9,16 @@ const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
export async function ensurePackageInstalled(
dependency: string,
root: string,
+ errorMessage?: string,
) {
if (isPackageExists(dependency, { paths: [root, __dirname] }))
return true
const promptInstall = !isCI && process.stdout.isTTY
+ if (errorMessage)
+ process.stderr.write(c.red(errorMessage))
+
process.stderr.write(c.red(`${c.inverse(c.red(' MISSING DEP '))} Can not find dependency '${dependency}'\n\n`))
if (!promptInstall)
diff --git a/packages/vitest/src/types/coverage.ts b/packages/vitest/src/types/coverage.ts
index 65cf0d9e800b..48d983813673 100644
--- a/packages/vitest/src/types/coverage.ts
+++ b/packages/vitest/src/types/coverage.ts
@@ -61,13 +61,14 @@ type CoverageReporterWithOptions]
: never
-type Provider = 'c8' | 'istanbul' | 'custom' | undefined
+type Provider = 'c8' | 'v8' | 'istanbul' | 'custom' | undefined
export type CoverageOptions =
T extends 'istanbul' ? ({ provider: T } & CoverageIstanbulOptions) :
T extends 'c8' ? ({ provider: T } & CoverageC8Options) :
- T extends 'custom' ? ({ provider: T } & CustomProviderOptions) :
- ({ provider?: T } & (CoverageC8Options))
+ T extends 'v8' ? ({ provider: T } & CoverageV8Options) :
+ T extends 'custom' ? ({ provider: T } & CustomProviderOptions) :
+ ({ provider?: T } & (CoverageC8Options))
/** Fields that have default values. Internally these will always be defined. */
type FieldsWithDefaultValues =
@@ -257,6 +258,15 @@ export interface CoverageC8Options extends BaseCoverageOptions {
100?: boolean
}
+export interface CoverageV8Options extends BaseCoverageOptions {
+ /**
+ * Shortcut for `--check-coverage --lines 100 --functions 100 --branches 100 --statements 100`
+ *
+ * @default false
+ */
+ 100?: boolean
+}
+
export interface CustomProviderOptions extends Pick {
/** Name of the module or path to a file to load the custom provider from */
customProviderModule: string
diff --git a/packages/vitest/src/utils/coverage.ts b/packages/vitest/src/utils/coverage.ts
index 20ff0a709ff1..7379243fd584 100644
--- a/packages/vitest/src/utils/coverage.ts
+++ b/packages/vitest/src/utils/coverage.ts
@@ -1,4 +1,5 @@
import { readFileSync, writeFileSync } from 'node:fs'
+import { relative } from 'pathe'
import type { CoverageMap } from 'istanbul-lib-coverage'
import type { BaseCoverageOptions, ResolvedCoverageOptions } from '../types'
@@ -61,6 +62,59 @@ export class BaseCoverageProvider {
}
}
+ /**
+ * Checked collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached.
+ */
+ checkThresholds({ coverageMap, thresholds, perFile }: {
+ coverageMap: CoverageMap
+ thresholds: Record
+ perFile?: boolean
+ }) {
+ // Construct list of coverage summaries where thresholds are compared against
+ const summaries = perFile
+ ? coverageMap.files()
+ .map((file: string) => ({
+ file,
+ summary: coverageMap.fileCoverageFor(file).toSummary(),
+ }))
+ : [{
+ file: null,
+ summary: coverageMap.getCoverageSummary(),
+ }]
+
+ // Check thresholds of each summary
+ for (const { summary, file } of summaries) {
+ for (const thresholdKey of ['lines', 'functions', 'statements', 'branches'] as const) {
+ const threshold = thresholds[thresholdKey]
+
+ if (threshold !== undefined) {
+ const coverage = summary.data[thresholdKey].pct
+
+ if (coverage < threshold) {
+ process.exitCode = 1
+
+ /*
+ * Generate error message based on perFile flag:
+ * - ERROR: Coverage for statements (33.33%) does not meet threshold (85%) for src/math.ts
+ * - ERROR: Coverage for statements (50%) does not meet global threshold (85%)
+ */
+ let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet`
+
+ if (!perFile)
+ errorMessage += ' global'
+
+ errorMessage += ` threshold (${threshold}%)`
+
+ if (perFile && file)
+ errorMessage += ` for ${relative('./', file).replace(/\\/g, '/')}`
+
+ console.error(errorMessage)
+ }
+ }
+ }
+ }
+ }
+
/**
* Resolve reporters from various configuration options
*/
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0cb6dcb68d31..6b00a8ea56f1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -51,6 +51,9 @@ importers:
'@vitest/coverage-istanbul':
specifier: workspace:*
version: link:packages/coverage-istanbul
+ '@vitest/coverage-v8':
+ specifier: workspace:*
+ version: link:packages/coverage-v8
'@vitest/ui':
specifier: workspace:*
version: link:packages/ui
@@ -958,6 +961,64 @@ importers:
specifier: workspace:*
version: link:../vitest
+ packages/coverage-v8:
+ dependencies:
+ '@ampproject/remapping':
+ specifier: ^2.2.1
+ version: 2.2.1
+ '@bcoe/v8-coverage':
+ specifier: ^0.2.3
+ version: 0.2.3
+ istanbul-lib-coverage:
+ specifier: ^3.2.0
+ version: 3.2.0
+ istanbul-lib-report:
+ specifier: ^3.0.0
+ version: 3.0.0
+ istanbul-lib-source-maps:
+ specifier: ^4.0.1
+ version: 4.0.1
+ istanbul-reports:
+ specifier: ^3.1.5
+ version: 3.1.5
+ magic-string:
+ specifier: ^0.30.0
+ version: 0.30.0
+ picocolors:
+ specifier: ^1.0.0
+ version: 1.0.0
+ std-env:
+ specifier: ^3.3.2
+ version: 3.3.2
+ test-exclude:
+ specifier: ^6.0.0
+ version: 6.0.0
+ v8-to-istanbul:
+ specifier: ^9.1.0
+ version: 9.1.0
+ devDependencies:
+ '@types/istanbul-lib-coverage':
+ specifier: ^2.0.4
+ version: 2.0.4
+ '@types/istanbul-lib-report':
+ specifier: ^3.0.0
+ version: 3.0.0
+ '@types/istanbul-lib-source-maps':
+ specifier: ^4.0.1
+ version: 4.0.1
+ '@types/istanbul-reports':
+ specifier: ^3.0.1
+ version: 3.0.1
+ pathe:
+ specifier: ^1.1.0
+ version: 1.1.0
+ vite-node:
+ specifier: workspace:*
+ version: link:../vite-node
+ vitest:
+ specifier: workspace:*
+ version: link:../vitest
+
packages/expect:
dependencies:
'@vitest/spy':
@@ -1528,6 +1589,15 @@ importers:
'@vitest/browser':
specifier: workspace:*
version: link:../../packages/browser
+ '@vitest/coverage-c8':
+ specifier: workspace:*
+ version: link:../../packages/coverage-c8
+ '@vitest/coverage-istanbul':
+ specifier: workspace:*
+ version: link:../../packages/coverage-istanbul
+ '@vitest/coverage-v8':
+ specifier: workspace:*
+ version: link:../../packages/coverage-v8
'@vue/test-utils':
specifier: latest
version: 2.3.2(vue@3.3.4)
@@ -11363,7 +11433,7 @@ packages:
istanbul-reports: 3.1.5
rimraf: 3.0.2
test-exclude: 6.0.0
- v8-to-istanbul: 9.0.1
+ v8-to-istanbul: 9.1.0
yargs: 16.2.0
yargs-parser: 20.2.9
dev: true
@@ -11382,7 +11452,7 @@ packages:
istanbul-reports: 3.1.5
rimraf: 3.0.2
test-exclude: 6.0.0
- v8-to-istanbul: 9.0.1
+ v8-to-istanbul: 9.1.0
yargs: 16.2.0
yargs-parser: 20.2.9
@@ -23949,8 +24019,8 @@ packages:
source-map: 0.7.4
dev: true
- /v8-to-istanbul@9.0.1:
- resolution: {integrity: sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==}
+ /v8-to-istanbul@9.1.0:
+ resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==}
engines: {node: '>=10.12.0'}
dependencies:
'@jridgewell/trace-mapping': 0.3.18
diff --git a/test/config/test/failures.test.ts b/test/config/test/failures.test.ts
index 0ad3abf50ed9..0ad1bf064faa 100644
--- a/test/config/test/failures.test.ts
+++ b/test/config/test/failures.test.ts
@@ -49,11 +49,17 @@ test('inspect-brk cannot be used with threads', async () => {
})
test('c8 coverage provider cannot be used with browser', async () => {
- const { stderr } = await runVitest({ coverage: { enabled: true }, browser: { enabled: true, name: 'chrome' } })
+ const { stderr } = await runVitest({ coverage: { enabled: true, provider: 'c8' }, browser: { enabled: true, name: 'chrome' } })
expect(stderr).toMatch('Error: @vitest/coverage-c8 does not work with --browser. Use @vitest/coverage-istanbul instead')
})
+test('v8 coverage provider cannot be used with browser', async () => {
+ const { stderr } = await runVitest({ coverage: { enabled: true }, browser: { enabled: true, name: 'chrome' } })
+
+ expect(stderr).toMatch('Error: @vitest/coverage-v8 does not work with --browser. Use @vitest/coverage-istanbul instead')
+})
+
test('version number is printed when coverage provider fails to load', async () => {
const { stderr, stdout } = await runVitest({
coverage: {
diff --git a/test/coverage-test/coverage-report-tests/__snapshots__/v8.report.test.ts.snap b/test/coverage-test/coverage-report-tests/__snapshots__/v8.report.test.ts.snap
new file mode 100644
index 000000000000..24a6118f7547
--- /dev/null
+++ b/test/coverage-test/coverage-report-tests/__snapshots__/v8.report.test.ts.snap
@@ -0,0 +1,3323 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`v8 json report 1`] = `
+{
+ "/src/Counter/Counter.component.ts": {
+ "all": false,
+ "b": {
+ "0": [
+ 1,
+ ],
+ "1": [
+ 2,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 6,
+ "loc": {
+ "end": {
+ "column": 4,
+ "line": 9,
+ },
+ "start": {
+ "column": 2,
+ "line": 6,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 4,
+ "line": 9,
+ },
+ "start": {
+ "column": 2,
+ "line": 6,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ "1": {
+ "line": 16,
+ "loc": {
+ "end": {
+ "column": 6,
+ "line": 18,
+ },
+ "start": {
+ "column": 4,
+ "line": 16,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 6,
+ "line": 18,
+ },
+ "start": {
+ "column": 4,
+ "line": 16,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 1,
+ "1": 0,
+ "2": 2,
+ "3": 0,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 4,
+ "line": 9,
+ },
+ "start": {
+ "column": 2,
+ "line": 6,
+ },
+ },
+ "line": 6,
+ "loc": {
+ "end": {
+ "column": 4,
+ "line": 9,
+ },
+ "start": {
+ "column": 2,
+ "line": 6,
+ },
+ },
+ "name": "setup",
+ },
+ "1": {
+ "decl": {
+ "end": {
+ "column": 6,
+ "line": 14,
+ },
+ "start": {
+ "column": 4,
+ "line": 12,
+ },
+ },
+ "line": 12,
+ "loc": {
+ "end": {
+ "column": 6,
+ "line": 14,
+ },
+ "start": {
+ "column": 4,
+ "line": 12,
+ },
+ },
+ "name": "uncoveredMethod",
+ },
+ "2": {
+ "decl": {
+ "end": {
+ "column": 6,
+ "line": 18,
+ },
+ "start": {
+ "column": 4,
+ "line": 16,
+ },
+ },
+ "line": 16,
+ "loc": {
+ "end": {
+ "column": 6,
+ "line": 18,
+ },
+ "start": {
+ "column": 4,
+ "line": 16,
+ },
+ },
+ "name": "coveredMethod",
+ },
+ "3": {
+ "decl": {
+ "end": {
+ "column": 6,
+ "line": 22,
+ },
+ "start": {
+ "column": 4,
+ "line": 20,
+ },
+ },
+ "line": 20,
+ "loc": {
+ "end": {
+ "column": 6,
+ "line": 22,
+ },
+ "start": {
+ "column": 4,
+ "line": 20,
+ },
+ },
+ "name": "uncoveredMethodUsingImportMeta",
+ },
+ },
+ "path": "/src/Counter/Counter.component.ts",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "10": 1,
+ "11": 1,
+ "12": 0,
+ "13": 0,
+ "14": 1,
+ "15": 1,
+ "16": 2,
+ "17": 2,
+ "18": 1,
+ "19": 1,
+ "2": 1,
+ "20": 0,
+ "21": 0,
+ "22": 1,
+ "23": 1,
+ "3": 1,
+ "4": 1,
+ "5": 1,
+ "6": 1,
+ "7": 1,
+ "8": 1,
+ "9": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 42,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 0,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "10": {
+ "end": {
+ "column": 12,
+ "line": 11,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "11": {
+ "end": {
+ "column": 23,
+ "line": 12,
+ },
+ "start": {
+ "column": 0,
+ "line": 12,
+ },
+ },
+ "12": {
+ "end": {
+ "column": 46,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 13,
+ },
+ },
+ "13": {
+ "end": {
+ "column": 6,
+ "line": 14,
+ },
+ "start": {
+ "column": 0,
+ "line": 14,
+ },
+ },
+ "14": {
+ "end": {
+ "column": 0,
+ "line": 15,
+ },
+ "start": {
+ "column": 0,
+ "line": 15,
+ },
+ },
+ "15": {
+ "end": {
+ "column": 21,
+ "line": 16,
+ },
+ "start": {
+ "column": 0,
+ "line": 16,
+ },
+ },
+ "16": {
+ "end": {
+ "column": 42,
+ "line": 17,
+ },
+ "start": {
+ "column": 0,
+ "line": 17,
+ },
+ },
+ "17": {
+ "end": {
+ "column": 6,
+ "line": 18,
+ },
+ "start": {
+ "column": 0,
+ "line": 18,
+ },
+ },
+ "18": {
+ "end": {
+ "column": 0,
+ "line": 19,
+ },
+ "start": {
+ "column": 0,
+ "line": 19,
+ },
+ },
+ "19": {
+ "end": {
+ "column": 38,
+ "line": 20,
+ },
+ "start": {
+ "column": 0,
+ "line": 20,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 32,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "20": {
+ "end": {
+ "column": 94,
+ "line": 21,
+ },
+ "start": {
+ "column": 0,
+ "line": 21,
+ },
+ },
+ "21": {
+ "end": {
+ "column": 6,
+ "line": 22,
+ },
+ "start": {
+ "column": 0,
+ "line": 22,
+ },
+ },
+ "22": {
+ "end": {
+ "column": 4,
+ "line": 23,
+ },
+ "start": {
+ "column": 0,
+ "line": 23,
+ },
+ },
+ "23": {
+ "end": {
+ "column": 2,
+ "line": 24,
+ },
+ "start": {
+ "column": 0,
+ "line": 24,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 18,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 0,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 11,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 24,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 20,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ "8": {
+ "end": {
+ "column": 4,
+ "line": 9,
+ },
+ "start": {
+ "column": 0,
+ "line": 9,
+ },
+ },
+ "9": {
+ "end": {
+ "column": 0,
+ "line": 10,
+ },
+ "start": {
+ "column": 0,
+ "line": 10,
+ },
+ },
+ },
+ },
+ "/src/Counter/Counter.vue": {
+ "all": false,
+ "b": {
+ "0": [
+ 1,
+ ],
+ "1": [
+ 1,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 8,
+ "loc": {
+ "end": {
+ "column": 25,
+ "line": 8,
+ },
+ "start": {
+ "column": 18,
+ "line": 8,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 25,
+ "line": 8,
+ },
+ "start": {
+ "column": 18,
+ "line": 8,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ "1": {
+ "line": 8,
+ "loc": {
+ "end": {
+ "column": 25,
+ "line": 8,
+ },
+ "start": {
+ "column": 18,
+ "line": 8,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 25,
+ "line": 8,
+ },
+ "start": {
+ "column": 18,
+ "line": 8,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 1,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 25,
+ "line": 8,
+ },
+ "start": {
+ "column": 18,
+ "line": 8,
+ },
+ },
+ "line": 8,
+ "loc": {
+ "end": {
+ "column": 25,
+ "line": 8,
+ },
+ "start": {
+ "column": 18,
+ "line": 8,
+ },
+ },
+ "name": "__vite_ssr_import_1__.createElementBlock.__vite_ssr_import_1__.createElementVNode.onClick._cache.._cache.",
+ },
+ },
+ "path": "/src/Counter/Counter.vue",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "10": 1,
+ "11": 1,
+ "12": 1,
+ "13": 1,
+ "2": 1,
+ "3": 1,
+ "4": 1,
+ "5": 1,
+ "6": 1,
+ "7": 1,
+ "8": 1,
+ "9": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 56,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 0,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "10": {
+ "end": {
+ "column": 14,
+ "line": 11,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "11": {
+ "end": {
+ "column": 25,
+ "line": 12,
+ },
+ "start": {
+ "column": 0,
+ "line": 12,
+ },
+ },
+ "12": {
+ "end": {
+ "column": 8,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 13,
+ },
+ },
+ "13": {
+ "end": {
+ "column": 11,
+ "line": 14,
+ },
+ "start": {
+ "column": 0,
+ "line": 14,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 10,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 27,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 15,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 11,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 0,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 25,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ "8": {
+ "end": {
+ "column": 27,
+ "line": 9,
+ },
+ "start": {
+ "column": 0,
+ "line": 9,
+ },
+ },
+ "9": {
+ "end": {
+ "column": 8,
+ "line": 10,
+ },
+ "start": {
+ "column": 0,
+ "line": 10,
+ },
+ },
+ },
+ },
+ "/src/Counter/index.ts": {
+ "all": false,
+ "b": {},
+ "branchMap": {},
+ "f": {},
+ "fnMap": {},
+ "path": "/src/Counter/index.ts",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "2": 1,
+ "3": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 50,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 38,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 0,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 39,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ },
+ },
+ "/src/Defined.vue": {
+ "all": false,
+ "b": {
+ "0": [
+ 0,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 6,
+ "loc": {
+ "end": {
+ "column": 36,
+ "line": 8,
+ },
+ "start": {
+ "column": 33,
+ "line": 6,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 36,
+ "line": 8,
+ },
+ "start": {
+ "column": 33,
+ "line": 6,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {},
+ "fnMap": {},
+ "path": "/src/Defined.vue",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "10": 1,
+ "11": 1,
+ "12": 1,
+ "13": 1,
+ "14": 1,
+ "15": 1,
+ "16": 1,
+ "17": 1,
+ "18": 1,
+ "19": 1,
+ "2": 1,
+ "3": 1,
+ "4": 1,
+ "5": 1,
+ "6": 0,
+ "7": 0,
+ "8": 1,
+ "9": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 24,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 27,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "10": {
+ "end": {
+ "column": 10,
+ "line": 11,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "11": {
+ "end": {
+ "column": 15,
+ "line": 12,
+ },
+ "start": {
+ "column": 0,
+ "line": 12,
+ },
+ },
+ "12": {
+ "end": {
+ "column": 11,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 13,
+ },
+ },
+ "13": {
+ "end": {
+ "column": 0,
+ "line": 14,
+ },
+ "start": {
+ "column": 0,
+ "line": 14,
+ },
+ },
+ "14": {
+ "end": {
+ "column": 90,
+ "line": 15,
+ },
+ "start": {
+ "column": 0,
+ "line": 15,
+ },
+ },
+ "15": {
+ "end": {
+ "column": 25,
+ "line": 16,
+ },
+ "start": {
+ "column": 0,
+ "line": 16,
+ },
+ },
+ "16": {
+ "end": {
+ "column": 6,
+ "line": 17,
+ },
+ "start": {
+ "column": 0,
+ "line": 17,
+ },
+ },
+ "17": {
+ "end": {
+ "column": 25,
+ "line": 18,
+ },
+ "start": {
+ "column": 0,
+ "line": 18,
+ },
+ },
+ "18": {
+ "end": {
+ "column": 1,
+ "line": 19,
+ },
+ "start": {
+ "column": 0,
+ "line": 19,
+ },
+ },
+ "19": {
+ "end": {
+ "column": 8,
+ "line": 20,
+ },
+ "start": {
+ "column": 0,
+ "line": 20,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 0,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 31,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 12,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 34,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 4,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 36,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ "8": {
+ "end": {
+ "column": 9,
+ "line": 9,
+ },
+ "start": {
+ "column": 0,
+ "line": 9,
+ },
+ },
+ "9": {
+ "end": {
+ "column": 0,
+ "line": 10,
+ },
+ "start": {
+ "column": 0,
+ "line": 10,
+ },
+ },
+ },
+ },
+ "/src/Hello.vue": {
+ "all": false,
+ "b": {
+ "0": [
+ 3,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 7,
+ "loc": {
+ "end": {
+ "column": 55,
+ "line": 7,
+ },
+ "start": {
+ "column": 24,
+ "line": 7,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 55,
+ "line": 7,
+ },
+ "start": {
+ "column": 24,
+ "line": 7,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {},
+ "fnMap": {},
+ "path": "/src/Hello.vue",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "10": 1,
+ "11": 1,
+ "12": 1,
+ "13": 1,
+ "14": 1,
+ "15": 1,
+ "16": 1,
+ "2": 1,
+ "3": 1,
+ "4": 1,
+ "5": 1,
+ "6": 1,
+ "7": 1,
+ "8": 1,
+ "9": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 24,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 35,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "10": {
+ "end": {
+ "column": 0,
+ "line": 11,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "11": {
+ "end": {
+ "column": 10,
+ "line": 12,
+ },
+ "start": {
+ "column": 0,
+ "line": 12,
+ },
+ },
+ "12": {
+ "end": {
+ "column": 53,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 13,
+ },
+ },
+ "13": {
+ "end": {
+ "column": 30,
+ "line": 14,
+ },
+ "start": {
+ "column": 0,
+ "line": 14,
+ },
+ },
+ "14": {
+ "end": {
+ "column": 6,
+ "line": 15,
+ },
+ "start": {
+ "column": 0,
+ "line": 15,
+ },
+ },
+ "15": {
+ "end": {
+ "column": 11,
+ "line": 16,
+ },
+ "start": {
+ "column": 0,
+ "line": 16,
+ },
+ },
+ "16": {
+ "end": {
+ "column": 11,
+ "line": 17,
+ },
+ "start": {
+ "column": 0,
+ "line": 17,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 0,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 46,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 0,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 20,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 56,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 0,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ "8": {
+ "end": {
+ "column": 19,
+ "line": 9,
+ },
+ "start": {
+ "column": 0,
+ "line": 9,
+ },
+ },
+ "9": {
+ "end": {
+ "column": 9,
+ "line": 10,
+ },
+ "start": {
+ "column": 0,
+ "line": 10,
+ },
+ },
+ },
+ },
+ "/src/function-count.ts": {
+ "all": false,
+ "b": {
+ "0": [
+ 1,
+ ],
+ "1": [
+ 1,
+ ],
+ "2": [
+ 1,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 11,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ "1": {
+ "line": 18,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 21,
+ },
+ "start": {
+ "column": 7,
+ "line": 18,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 21,
+ },
+ "start": {
+ "column": 7,
+ "line": 18,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ "2": {
+ "line": 34,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 36,
+ },
+ "start": {
+ "column": 0,
+ "line": 34,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 36,
+ },
+ "start": {
+ "column": 0,
+ "line": 34,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 1,
+ "1": 1,
+ "2": 0,
+ "3": 0,
+ "4": 1,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "line": 11,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "name": "first",
+ },
+ "1": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 21,
+ },
+ "start": {
+ "column": 7,
+ "line": 18,
+ },
+ },
+ "line": 18,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 21,
+ },
+ "start": {
+ "column": 7,
+ "line": 18,
+ },
+ },
+ "name": "second",
+ },
+ "2": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 26,
+ },
+ "start": {
+ "column": 7,
+ "line": 24,
+ },
+ },
+ "line": 24,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 26,
+ },
+ "start": {
+ "column": 7,
+ "line": 24,
+ },
+ },
+ "name": "third",
+ },
+ "3": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 31,
+ },
+ "start": {
+ "column": 0,
+ "line": 29,
+ },
+ },
+ "line": 29,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 31,
+ },
+ "start": {
+ "column": 0,
+ "line": 29,
+ },
+ },
+ "name": "fourth",
+ },
+ "4": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 36,
+ },
+ "start": {
+ "column": 0,
+ "line": 34,
+ },
+ },
+ "line": 34,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 36,
+ },
+ "start": {
+ "column": 0,
+ "line": 34,
+ },
+ },
+ "name": "fifth",
+ },
+ },
+ "path": "/src/function-count.ts",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "10": 1,
+ "11": 1,
+ "12": 1,
+ "13": 1,
+ "14": 1,
+ "15": 1,
+ "16": 1,
+ "17": 1,
+ "18": 1,
+ "19": 1,
+ "2": 1,
+ "20": 1,
+ "21": 1,
+ "22": 1,
+ "23": 1,
+ "24": 0,
+ "25": 0,
+ "26": 1,
+ "27": 1,
+ "28": 0,
+ "29": 0,
+ "3": 1,
+ "30": 0,
+ "31": 1,
+ "32": 1,
+ "33": 1,
+ "34": 1,
+ "35": 1,
+ "4": 1,
+ "5": 1,
+ "6": 1,
+ "7": 1,
+ "8": 1,
+ "9": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 2,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 25,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "10": {
+ "end": {
+ "column": 18,
+ "line": 11,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "11": {
+ "end": {
+ "column": 10,
+ "line": 12,
+ },
+ "start": {
+ "column": 0,
+ "line": 12,
+ },
+ },
+ "12": {
+ "end": {
+ "column": 1,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 13,
+ },
+ },
+ "13": {
+ "end": {
+ "column": 0,
+ "line": 14,
+ },
+ "start": {
+ "column": 0,
+ "line": 14,
+ },
+ },
+ "14": {
+ "end": {
+ "column": 7,
+ "line": 15,
+ },
+ "start": {
+ "column": 0,
+ "line": 15,
+ },
+ },
+ "15": {
+ "end": {
+ "column": 0,
+ "line": 16,
+ },
+ "start": {
+ "column": 0,
+ "line": 16,
+ },
+ },
+ "16": {
+ "end": {
+ "column": 27,
+ "line": 17,
+ },
+ "start": {
+ "column": 0,
+ "line": 17,
+ },
+ },
+ "17": {
+ "end": {
+ "column": 26,
+ "line": 18,
+ },
+ "start": {
+ "column": 0,
+ "line": 18,
+ },
+ },
+ "18": {
+ "end": {
+ "column": 9,
+ "line": 19,
+ },
+ "start": {
+ "column": 0,
+ "line": 19,
+ },
+ },
+ "19": {
+ "end": {
+ "column": 10,
+ "line": 20,
+ },
+ "start": {
+ "column": 0,
+ "line": 20,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 25,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "20": {
+ "end": {
+ "column": 1,
+ "line": 21,
+ },
+ "start": {
+ "column": 0,
+ "line": 21,
+ },
+ },
+ "21": {
+ "end": {
+ "column": 0,
+ "line": 22,
+ },
+ "start": {
+ "column": 0,
+ "line": 22,
+ },
+ },
+ "22": {
+ "end": {
+ "column": 31,
+ "line": 23,
+ },
+ "start": {
+ "column": 0,
+ "line": 23,
+ },
+ },
+ "23": {
+ "end": {
+ "column": 25,
+ "line": 24,
+ },
+ "start": {
+ "column": 0,
+ "line": 24,
+ },
+ },
+ "24": {
+ "end": {
+ "column": 46,
+ "line": 25,
+ },
+ "start": {
+ "column": 0,
+ "line": 25,
+ },
+ },
+ "25": {
+ "end": {
+ "column": 1,
+ "line": 26,
+ },
+ "start": {
+ "column": 0,
+ "line": 26,
+ },
+ },
+ "26": {
+ "end": {
+ "column": 0,
+ "line": 27,
+ },
+ "start": {
+ "column": 0,
+ "line": 27,
+ },
+ },
+ "27": {
+ "end": {
+ "column": 31,
+ "line": 28,
+ },
+ "start": {
+ "column": 0,
+ "line": 28,
+ },
+ },
+ "28": {
+ "end": {
+ "column": 19,
+ "line": 29,
+ },
+ "start": {
+ "column": 0,
+ "line": 29,
+ },
+ },
+ "29": {
+ "end": {
+ "column": 10,
+ "line": 30,
+ },
+ "start": {
+ "column": 0,
+ "line": 30,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 24,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "30": {
+ "end": {
+ "column": 1,
+ "line": 31,
+ },
+ "start": {
+ "column": 0,
+ "line": 31,
+ },
+ },
+ "31": {
+ "end": {
+ "column": 0,
+ "line": 32,
+ },
+ "start": {
+ "column": 0,
+ "line": 32,
+ },
+ },
+ "32": {
+ "end": {
+ "column": 27,
+ "line": 33,
+ },
+ "start": {
+ "column": 0,
+ "line": 33,
+ },
+ },
+ "33": {
+ "end": {
+ "column": 18,
+ "line": 34,
+ },
+ "start": {
+ "column": 0,
+ "line": 34,
+ },
+ },
+ "34": {
+ "end": {
+ "column": 10,
+ "line": 35,
+ },
+ "start": {
+ "column": 0,
+ "line": 35,
+ },
+ },
+ "35": {
+ "end": {
+ "column": 1,
+ "line": 36,
+ },
+ "start": {
+ "column": 0,
+ "line": 36,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 26,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 3,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 0,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 50,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ "8": {
+ "end": {
+ "column": 0,
+ "line": 9,
+ },
+ "start": {
+ "column": 0,
+ "line": 9,
+ },
+ },
+ "9": {
+ "end": {
+ "column": 27,
+ "line": 10,
+ },
+ "start": {
+ "column": 0,
+ "line": 10,
+ },
+ },
+ },
+ },
+ "/src/implicitElse.ts": {
+ "all": false,
+ "b": {
+ "0": [
+ 1,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 8,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 8,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 1,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 8,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 8,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "name": "implicitElse",
+ },
+ },
+ "path": "/src/implicitElse.ts",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "2": 1,
+ "3": 1,
+ "4": 1,
+ "5": 1,
+ "6": 1,
+ "7": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 50,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 11,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 0,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 16,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 9,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 0,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 10,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 1,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ },
+ },
+ "/src/importEnv.ts": {
+ "all": false,
+ "b": {
+ "0": [
+ 1,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 1,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "name": "useImportEnv",
+ },
+ },
+ "path": "/src/importEnv.ts",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "2": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 32,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 46,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ },
+ },
+ "/src/index.mts": {
+ "all": false,
+ "b": {
+ "0": [
+ 1,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 5,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 1,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ "line": 5,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ "name": "pythagoras",
+ },
+ },
+ "path": "/src/index.mts",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "2": 1,
+ "3": 1,
+ "4": 1,
+ "5": 1,
+ "6": 1,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 45,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 0,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 23,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 0,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 50,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 50,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ },
+ },
+ "/src/untested-file.ts": {
+ "all": true,
+ "b": {
+ "0": [
+ 0,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 33,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 33,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 0,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 33,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 33,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "name": "(empty-report)",
+ },
+ },
+ "path": "/src/untested-file.ts",
+ "s": {
+ "0": 0,
+ "1": 0,
+ "10": 0,
+ "11": 0,
+ "12": 0,
+ "13": 0,
+ "14": 0,
+ "15": 0,
+ "16": 0,
+ "17": 0,
+ "18": 0,
+ "19": 0,
+ "2": 0,
+ "20": 0,
+ "21": 0,
+ "22": 0,
+ "23": 0,
+ "24": 0,
+ "25": 0,
+ "26": 0,
+ "27": 0,
+ "28": 0,
+ "29": 0,
+ "3": 0,
+ "30": 0,
+ "31": 0,
+ "32": 0,
+ "4": 0,
+ "5": 0,
+ "6": 0,
+ "7": 0,
+ "8": 0,
+ "9": 0,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 2,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 68,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "10": {
+ "end": {
+ "column": 36,
+ "line": 11,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "11": {
+ "end": {
+ "column": 14,
+ "line": 12,
+ },
+ "start": {
+ "column": 0,
+ "line": 12,
+ },
+ },
+ "12": {
+ "end": {
+ "column": 1,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 13,
+ },
+ },
+ "13": {
+ "end": {
+ "column": 0,
+ "line": 14,
+ },
+ "start": {
+ "column": 0,
+ "line": 14,
+ },
+ },
+ "14": {
+ "end": {
+ "column": 41,
+ "line": 15,
+ },
+ "start": {
+ "column": 0,
+ "line": 15,
+ },
+ },
+ "15": {
+ "end": {
+ "column": 36,
+ "line": 16,
+ },
+ "start": {
+ "column": 0,
+ "line": 16,
+ },
+ },
+ "16": {
+ "end": {
+ "column": 14,
+ "line": 17,
+ },
+ "start": {
+ "column": 0,
+ "line": 17,
+ },
+ },
+ "17": {
+ "end": {
+ "column": 1,
+ "line": 18,
+ },
+ "start": {
+ "column": 0,
+ "line": 18,
+ },
+ },
+ "18": {
+ "end": {
+ "column": 0,
+ "line": 19,
+ },
+ "start": {
+ "column": 0,
+ "line": 19,
+ },
+ },
+ "19": {
+ "end": {
+ "column": 65,
+ "line": 20,
+ },
+ "start": {
+ "column": 0,
+ "line": 20,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 25,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "20": {
+ "end": {
+ "column": 25,
+ "line": 21,
+ },
+ "start": {
+ "column": 0,
+ "line": 21,
+ },
+ },
+ "21": {
+ "end": {
+ "column": 38,
+ "line": 22,
+ },
+ "start": {
+ "column": 0,
+ "line": 22,
+ },
+ },
+ "22": {
+ "end": {
+ "column": 25,
+ "line": 23,
+ },
+ "start": {
+ "column": 0,
+ "line": 23,
+ },
+ },
+ "23": {
+ "end": {
+ "column": 3,
+ "line": 24,
+ },
+ "start": {
+ "column": 0,
+ "line": 24,
+ },
+ },
+ "24": {
+ "end": {
+ "column": 0,
+ "line": 25,
+ },
+ "start": {
+ "column": 0,
+ "line": 25,
+ },
+ },
+ "25": {
+ "end": {
+ "column": 25,
+ "line": 26,
+ },
+ "start": {
+ "column": 0,
+ "line": 26,
+ },
+ },
+ "26": {
+ "end": {
+ "column": 38,
+ "line": 27,
+ },
+ "start": {
+ "column": 0,
+ "line": 27,
+ },
+ },
+ "27": {
+ "end": {
+ "column": 20,
+ "line": 28,
+ },
+ "start": {
+ "column": 0,
+ "line": 28,
+ },
+ },
+ "28": {
+ "end": {
+ "column": 3,
+ "line": 29,
+ },
+ "start": {
+ "column": 0,
+ "line": 29,
+ },
+ },
+ "29": {
+ "end": {
+ "column": 0,
+ "line": 30,
+ },
+ "start": {
+ "column": 0,
+ "line": 30,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 2,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "30": {
+ "end": {
+ "column": 36,
+ "line": 31,
+ },
+ "start": {
+ "column": 0,
+ "line": 31,
+ },
+ },
+ "31": {
+ "end": {
+ "column": 41,
+ "line": 32,
+ },
+ "start": {
+ "column": 0,
+ "line": 32,
+ },
+ },
+ "32": {
+ "end": {
+ "column": 1,
+ "line": 33,
+ },
+ "start": {
+ "column": 0,
+ "line": 33,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 0,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 40,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 72,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 1,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ "8": {
+ "end": {
+ "column": 0,
+ "line": 9,
+ },
+ "start": {
+ "column": 0,
+ "line": 9,
+ },
+ },
+ "9": {
+ "end": {
+ "column": 36,
+ "line": 10,
+ },
+ "start": {
+ "column": 0,
+ "line": 10,
+ },
+ },
+ },
+ },
+ "/src/utils.ts": {
+ "all": false,
+ "b": {
+ "0": [
+ 1,
+ ],
+ "1": [
+ 2,
+ ],
+ "2": [
+ 1,
+ ],
+ "3": [
+ 0,
+ ],
+ },
+ "branchMap": {
+ "0": {
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ "1": {
+ "line": 5,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ "2": {
+ "line": 14,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 19,
+ },
+ "start": {
+ "column": 7,
+ "line": 14,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 1,
+ "line": 19,
+ },
+ "start": {
+ "column": 7,
+ "line": 14,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ "3": {
+ "line": 16,
+ "loc": {
+ "end": {
+ "column": 51,
+ "line": 16,
+ },
+ "start": {
+ "column": 4,
+ "line": 16,
+ },
+ },
+ "locations": [
+ {
+ "end": {
+ "column": 51,
+ "line": 16,
+ },
+ "start": {
+ "column": 4,
+ "line": 16,
+ },
+ },
+ ],
+ "type": "branch",
+ },
+ },
+ "f": {
+ "0": 1,
+ "1": 2,
+ "2": 0,
+ "3": 1,
+ "4": 0,
+ "5": 1,
+ },
+ "fnMap": {
+ "0": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "line": 1,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ },
+ },
+ "name": "add",
+ },
+ "1": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ "line": 5,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 7,
+ "line": 5,
+ },
+ },
+ "name": "multiply",
+ },
+ "2": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 12,
+ },
+ "start": {
+ "column": 7,
+ "line": 9,
+ },
+ },
+ "line": 9,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 12,
+ },
+ "start": {
+ "column": 7,
+ "line": 9,
+ },
+ },
+ "name": "divide",
+ },
+ "3": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 19,
+ },
+ "start": {
+ "column": 7,
+ "line": 14,
+ },
+ },
+ "line": 14,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 19,
+ },
+ "start": {
+ "column": 7,
+ "line": 14,
+ },
+ },
+ "name": "sqrt",
+ },
+ "4": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 24,
+ },
+ "start": {
+ "column": 7,
+ "line": 21,
+ },
+ },
+ "line": 21,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 24,
+ },
+ "start": {
+ "column": 7,
+ "line": 21,
+ },
+ },
+ "name": "run",
+ },
+ "5": {
+ "decl": {
+ "end": {
+ "column": 1,
+ "line": 30,
+ },
+ "start": {
+ "column": 7,
+ "line": 28,
+ },
+ },
+ "line": 28,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 30,
+ },
+ "start": {
+ "column": 7,
+ "line": 28,
+ },
+ },
+ "name": "ignoredFunction",
+ },
+ },
+ "path": "/src/utils.ts",
+ "s": {
+ "0": 1,
+ "1": 1,
+ "10": 0,
+ "11": 0,
+ "12": 1,
+ "13": 1,
+ "14": 1,
+ "15": 1,
+ "16": 1,
+ "17": 1,
+ "18": 1,
+ "19": 1,
+ "2": 1,
+ "20": 1,
+ "21": 0,
+ "22": 0,
+ "23": 0,
+ "24": 1,
+ "25": 1,
+ "26": 1,
+ "27": 1,
+ "28": 1,
+ "29": 1,
+ "3": 1,
+ "4": 1,
+ "5": 2,
+ "6": 2,
+ "7": 1,
+ "8": 1,
+ "9": 0,
+ },
+ "statementMap": {
+ "0": {
+ "end": {
+ "column": 43,
+ "line": 1,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ },
+ },
+ "1": {
+ "end": {
+ "column": 14,
+ "line": 2,
+ },
+ "start": {
+ "column": 0,
+ "line": 2,
+ },
+ },
+ "10": {
+ "end": {
+ "column": 14,
+ "line": 11,
+ },
+ "start": {
+ "column": 0,
+ "line": 11,
+ },
+ },
+ "11": {
+ "end": {
+ "column": 1,
+ "line": 12,
+ },
+ "start": {
+ "column": 0,
+ "line": 12,
+ },
+ },
+ "12": {
+ "end": {
+ "column": 0,
+ "line": 13,
+ },
+ "start": {
+ "column": 0,
+ "line": 13,
+ },
+ },
+ "13": {
+ "end": {
+ "column": 33,
+ "line": 14,
+ },
+ "start": {
+ "column": 0,
+ "line": 14,
+ },
+ },
+ "14": {
+ "end": {
+ "column": 12,
+ "line": 15,
+ },
+ "start": {
+ "column": 0,
+ "line": 15,
+ },
+ },
+ "15": {
+ "end": {
+ "column": 51,
+ "line": 16,
+ },
+ "start": {
+ "column": 0,
+ "line": 16,
+ },
+ },
+ "16": {
+ "end": {
+ "column": 0,
+ "line": 17,
+ },
+ "start": {
+ "column": 0,
+ "line": 17,
+ },
+ },
+ "17": {
+ "end": {
+ "column": 21,
+ "line": 18,
+ },
+ "start": {
+ "column": 0,
+ "line": 18,
+ },
+ },
+ "18": {
+ "end": {
+ "column": 1,
+ "line": 19,
+ },
+ "start": {
+ "column": 0,
+ "line": 19,
+ },
+ },
+ "19": {
+ "end": {
+ "column": 0,
+ "line": 20,
+ },
+ "start": {
+ "column": 0,
+ "line": 20,
+ },
+ },
+ "2": {
+ "end": {
+ "column": 1,
+ "line": 3,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ },
+ },
+ "20": {
+ "end": {
+ "column": 23,
+ "line": 21,
+ },
+ "start": {
+ "column": 0,
+ "line": 21,
+ },
+ },
+ "21": {
+ "end": {
+ "column": 31,
+ "line": 22,
+ },
+ "start": {
+ "column": 0,
+ "line": 22,
+ },
+ },
+ "22": {
+ "end": {
+ "column": 14,
+ "line": 23,
+ },
+ "start": {
+ "column": 0,
+ "line": 23,
+ },
+ },
+ "23": {
+ "end": {
+ "column": 1,
+ "line": 24,
+ },
+ "start": {
+ "column": 0,
+ "line": 24,
+ },
+ },
+ "24": {
+ "end": {
+ "column": 0,
+ "line": 25,
+ },
+ "start": {
+ "column": 0,
+ "line": 25,
+ },
+ },
+ "25": {
+ "end": {
+ "column": 22,
+ "line": 26,
+ },
+ "start": {
+ "column": 0,
+ "line": 26,
+ },
+ },
+ "26": {
+ "end": {
+ "column": 39,
+ "line": 27,
+ },
+ "start": {
+ "column": 0,
+ "line": 27,
+ },
+ },
+ "27": {
+ "end": {
+ "column": 35,
+ "line": 28,
+ },
+ "start": {
+ "column": 0,
+ "line": 28,
+ },
+ },
+ "28": {
+ "end": {
+ "column": 62,
+ "line": 29,
+ },
+ "start": {
+ "column": 0,
+ "line": 29,
+ },
+ },
+ "29": {
+ "end": {
+ "column": 1,
+ "line": 30,
+ },
+ "start": {
+ "column": 0,
+ "line": 30,
+ },
+ },
+ "3": {
+ "end": {
+ "column": 0,
+ "line": 4,
+ },
+ "start": {
+ "column": 0,
+ "line": 4,
+ },
+ },
+ "4": {
+ "end": {
+ "column": 48,
+ "line": 5,
+ },
+ "start": {
+ "column": 0,
+ "line": 5,
+ },
+ },
+ "5": {
+ "end": {
+ "column": 14,
+ "line": 6,
+ },
+ "start": {
+ "column": 0,
+ "line": 6,
+ },
+ },
+ "6": {
+ "end": {
+ "column": 1,
+ "line": 7,
+ },
+ "start": {
+ "column": 0,
+ "line": 7,
+ },
+ },
+ "7": {
+ "end": {
+ "column": 0,
+ "line": 8,
+ },
+ "start": {
+ "column": 0,
+ "line": 8,
+ },
+ },
+ "8": {
+ "end": {
+ "column": 46,
+ "line": 9,
+ },
+ "start": {
+ "column": 0,
+ "line": 9,
+ },
+ },
+ "9": {
+ "end": {
+ "column": 31,
+ "line": 10,
+ },
+ "start": {
+ "column": 0,
+ "line": 10,
+ },
+ },
+ },
+ },
+}
+`;
diff --git a/test/coverage-test/coverage-report-tests/v8.report.test.ts b/test/coverage-test/coverage-report-tests/v8.report.test.ts
new file mode 100644
index 000000000000..30d8c64873ce
--- /dev/null
+++ b/test/coverage-test/coverage-report-tests/v8.report.test.ts
@@ -0,0 +1,31 @@
+/*
+ * V8 coverage provider specific test cases
+ */
+
+import { expect, test } from 'vitest'
+import { readCoverageJson } from './utils'
+
+test('v8 json report', async () => {
+ const jsonReport = await readCoverageJson()
+
+ // If this fails, you can use "npx live-server@1.2.1 ./coverage" to see coverage report
+ expect(jsonReport).toMatchSnapshot()
+})
+
+test('ignored code is marked as covered in the report', async () => {
+ const functionName = 'ignoredFunction'
+ const filename = '/src/utils.ts'
+
+ const coverageMap = await readCoverageJson()
+ const fileCoverage = coverageMap[filename]
+
+ const [functionKey] = Object.entries(fileCoverage.fnMap).find(([, fn]) => fn.name === functionName)!
+ const functionCallCount = fileCoverage.f[functionKey]
+
+ // v8-to-istanbul marks excluded lines as covered, instead of removing them from report completely
+ expect(functionCallCount).toBe(1)
+
+ // Function should still be found from the actual sources
+ const utils = await import('../src/utils')
+ expect(utils[functionName]).toBeTypeOf('function')
+})
diff --git a/test/coverage-test/package.json b/test/coverage-test/package.json
index 4350eb240295..fb82f0c9c7d5 100644
--- a/test/coverage-test/package.json
+++ b/test/coverage-test/package.json
@@ -2,8 +2,9 @@
"name": "@vitest/test-coverage",
"private": true,
"scripts": {
- "test": "pnpm test:c8 && pnpm test:istanbul && pnpm test:custom && pnpm test:browser && pnpm test:types",
+ "test": "pnpm test:c8 && pnpm test:v8 && pnpm test:istanbul && pnpm test:custom && pnpm test:browser && pnpm test:types",
"test:c8": "node ./testing.mjs --provider c8",
+ "test:v8": "node ./testing.mjs --provider v8",
"test:custom": "node ./testing.mjs --provider custom",
"test:istanbul": "node ./testing.mjs --provider istanbul",
"test:browser": "node ./testing.mjs --browser --provider istanbul",
@@ -13,6 +14,9 @@
"@types/istanbul-lib-coverage": "^2.0.4",
"@vitejs/plugin-vue": "latest",
"@vitest/browser": "workspace:*",
+ "@vitest/coverage-c8": "workspace:*",
+ "@vitest/coverage-istanbul": "workspace:*",
+ "@vitest/coverage-v8": "workspace:*",
"@vue/test-utils": "latest",
"happy-dom": "latest",
"istanbul-lib-coverage": "^3.2.0",
diff --git a/test/coverage-test/test/configuration-options.test-d.ts b/test/coverage-test/test/configuration-options.test-d.ts
index d9f17e107fa6..144fdc266fce 100644
--- a/test/coverage-test/test/configuration-options.test-d.ts
+++ b/test/coverage-test/test/configuration-options.test-d.ts
@@ -8,6 +8,7 @@ type Coverage = NonNullable
test('providers, built-in', () => {
assertType({ provider: 'c8' })
+ assertType({ provider: 'v8' })
assertType({ provider: 'istanbul' })
// @ts-expect-error -- String options must be known ones only
@@ -32,6 +33,16 @@ test('provider options, generic', () => {
},
})
+ assertType({
+ provider: 'v8',
+ enabled: true,
+ include: ['string'],
+ watermarks: {
+ functions: [80, 95],
+ lines: [80, 95],
+ },
+ })
+
assertType({
provider: 'istanbul',
enabled: true,
@@ -58,6 +69,19 @@ test('provider specific options, c8', () => {
})
})
+test('provider specific options, v8', () => {
+ assertType({
+ provider: 'v8',
+ 100: true,
+ })
+
+ assertType({
+ provider: 'v8',
+ // @ts-expect-error -- Istanbul-only option is not allowed
+ ignoreClassMethods: ['string'],
+ })
+})
+
test('provider specific options, istanbul', () => {
assertType({
provider: 'istanbul',
@@ -66,8 +90,8 @@ test('provider specific options, istanbul', () => {
assertType({
provider: 'istanbul',
- // @ts-expect-error -- C8-only option is not allowed
- src: ['string'],
+ // @ts-expect-error -- V8-only option is not allowed
+ 100: true,
})
})
diff --git a/test/coverage-test/testing.mjs b/test/coverage-test/testing.mjs
index 059b7aeb274d..8689470a16c4 100644
--- a/test/coverage-test/testing.mjs
+++ b/test/coverage-test/testing.mjs
@@ -32,7 +32,7 @@ const configs = [
// Run tests for checking coverage report contents.
['coverage-report-tests', {
include: [
- ['c8', 'istanbul'].includes(provider) && './coverage-report-tests/generic.report.test.ts',
+ ['c8', 'v8', 'istanbul'].includes(provider) && './coverage-report-tests/generic.report.test.ts',
`./coverage-report-tests/${provider}.report.test.ts`,
].filter(Boolean),
coverage: { enabled: false, clean: false },