diff --git a/.eslintignore b/.eslintignore
index ecb0c8801..ceee5217c 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -5,4 +5,4 @@ node_modules
*.d.ts
coverage
!.vitepress
-test/core/src/self
\ No newline at end of file
+test/core/src/self
diff --git a/.gitignore b/.gitignore
index 5168f474f..6c53c3a54 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ yarn-debug.log*
yarn-error.log*
lib-cov
coverage
+!**/integrations/coverage
node_modules
.env
.cache
diff --git a/README.md b/README.md
index d860d50ed..2608108eb 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)
+- [Native code coverage](https://vitest.dev/guide/features.html#coverage) via [c8](https://github.com/bcoe/c8) or [`istanbul`](https://istanbul.js.org/).
- [Tinyspy](https://github.com/Aslemammad/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 277590a3b..ea64c7de6 100644
--- a/docs/.vitepress/components/FeaturesList.vue
+++ b/docs/.vitepress/components/FeaturesList.vue
@@ -20,7 +20,7 @@
Chai built-in for assertions + Jest expect compatible APIs
Tinyspy built-in for mocking
happy-dom or jsdom for DOM mocking
- Native code coverage via c8
+ Code coverage via c8 or istanbul
Rust-like in-source testing
diff --git a/docs/config/index.md b/docs/config/index.md
index fb668aad8..e10422b5c 100644
--- a/docs/config/index.md
+++ b/docs/config/index.md
@@ -420,10 +420,103 @@ Isolate environment for each test file. Does not work if you disable [`--threads
### coverage
-- **Type:** `C8Options`
+- **Type:** `CoverageC8Options | CoverageIstanbulOptions`
- **Default:** `undefined`
-Coverage options passed to [C8](https://github.com/bcoe/c8).
+You can use [`c8`](https://github.com/bcoe/c8) or [`istanbul`](https://istanbul.js.org/) for coverage collection.
+
+#### provider
+
+- **Type:** `'c8' | 'istanbul'`
+- **Default:** `'c8'`
+
+Use `provider` to select the tool for coverage collection.
+
+#### CoverageC8Options
+
+Used when `provider: 'c8'` is set. Coverage options are passed to [`c8`](https://github.com/bcoe/c8).
+
+#### CoverageIstanbulOptions
+
+Used when `provider: 'istanbul'` is set.
+
+##### exclude
+
+- **Type:** `string[]`
+- **Default:** `[]`
+
+List of files excluded from coverage as glob patterns.
+
+##### skipFull
+
+- **Type:** `boolean`
+- **Default:** `false`
+
+Do not show files with 100% statement, branch, and function coverage.
+
+##### perFile
+
+- **Type:** `boolean`
+- **Default:** `false`
+
+Check thresholds per file.
+
+##### lines
+
+- **Type:** `number`
+
+Threshold for lines.
+
+##### functions
+
+- **Type:** `number`
+
+Threshold for functions.
+
+##### branches
+
+- **Type:** `number`
+
+Threshold for branches.
+
+##### statements
+
+- **Type:** `number`
+
+Threshold for statements.
+
+##### ignoreClassMethods
+
+- **Type:** `string[]`
+- **Default:** []
+
+Set to array of class method names to ignore for coverage.
+
+##### watermarks
+
+- **Type:**
+
+```ts
+{
+ statements?: [number, number],
+ functions?: [number, number],
+ branches?: [number, number],
+ lines?: [number, number]
+}
+```
+
+- **Default:**
+
+```ts
+{
+ statements: [50, 80],
+ functions: [50, 80],
+ branches: [50, 80],
+ lines: [50, 80]
+}
+```
+
+Watermarks for statements, lines, branches and functions.
### testNamePattern
diff --git a/docs/guide/cli.md b/docs/guide/cli.md
index 63cea34b2..ec8b87c29 100644
--- a/docs/guide/cli.md
+++ b/docs/guide/cli.md
@@ -61,7 +61,7 @@ vitest related /src/index.ts /src/hello-world.js
| `--outputTruncateLength ` | Truncate output diff lines up to `` number of characters. |
| `--outputDiffLines ` | Limit number of output diff lines up to ``. |
| `--outputFile ` | Write test results to a file when the `--reporter=json` or `--reporter=junit` option is also specified
Via [cac's dot notation] you can specify individual outputs for multiple reporters |
-| `--coverage` | Use c8 for coverage |
+| `--coverage` | Enable coverage report |
| `--run` | Do not watch |
| `--mode` | Override Vite mode (default: `test`) |
| `--mode ` | Override Vite mode (default: `test`) |
diff --git a/docs/guide/coverage.md b/docs/guide/coverage.md
index b65fac2cd..5e808c10c 100644
--- a/docs/guide/coverage.md
+++ b/docs/guide/coverage.md
@@ -4,13 +4,46 @@ title: Coverage | Guide
# Coverage
-Vitest supports Native code coverage via [`c8`](https://github.com/bcoe/c8). `c8` is an optional peer dependency, to use the coverage feature you will need to install it first by:
+Vitest supports Native code coverage via [`c8`](https://github.com/bcoe/c8) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).
+
+## Coverage Providers
+
+:::tip
+Since Vitest v0.22.0
+:::
+
+Both `c8` and `istanbul` support are optional. By default, `c8` will be used.
+
+You can select the coverage tool by setting `test.coverage.provider` to either `c8` or `istanbul`:
+
+```ts
+// vite.config.ts
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ coverage: {
+ provider: 'istanbul' // or 'c8'
+ },
+ },
+})
+```
+
+When you start the Vitest process, it will prompt you to install the corresponding support package automatically.
+
+Or if you prefer to install them manually:
```bash
-npm i -D c8
+# For c8
+npm i -D @vitest/coverage-c8
+
+# For istanbul
+npm i -D @vitest/coverage-istanbul
```
-Then you could get the coverage by passing the `--coverage` flag in CLI.
+## Coverage Setup
+
+To test with coverage enabled, you can pass the `--coverage` flag in CLI.
```json
{
@@ -35,3 +68,23 @@ export default defineConfig({
},
})
```
+
+## Custom Coverage Provider
+
+It's also possible to provide your custom coverage provider by passing an object to the `test.coverage.provider`:
+
+```ts
+// vite.config.ts
+import { defineConfig } from 'vitest/config'
+import CustomCoverageProvider from 'my-custom-coverage-provider'
+
+export default defineConfig({
+ test: {
+ coverage: {
+ provider: CustomCoverageProvider()
+ },
+ },
+})
+```
+
+Please refer to the type definition for more details.
diff --git a/docs/guide/features.md b/docs/guide/features.md
index 16b3c7419..b7ae12f10 100644
--- a/docs/guide/features.md
+++ b/docs/guide/features.md
@@ -136,7 +136,7 @@ Learn more at [Mocking](/guide/mocking).
## Coverage
-Vitest supports Native code coverage via [c8](https://github.com/bcoe/c8).
+Vitest supports Native code coverage via [`c8`](https://github.com/bcoe/c8) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).
```json
{
@@ -147,20 +147,7 @@ Vitest supports Native code coverage via [c8](https://github.com/bcoe/c8).
}
```
-To configure it, set `test.coverage` options in your config file:
-
-```ts
-// vite.config.ts
-import { defineConfig } from 'vitest/config'
-
-export default defineConfig({
- test: {
- coverage: {
- reporter: ['text', 'json', 'html'],
- },
- },
-})
-```
+Learn more at [Coverage](/guide/coverage).
## In-source testing
diff --git a/package.json b/package.json
index 3287a0912..dc0f612ef 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,8 @@
"@types/node": "^18.7.3",
"@types/ws": "^8.5.3",
"@vitest/browser": "workspace:*",
+ "@vitest/coverage-c8": "workspace:*",
+ "@vitest/coverage-istanbul": "workspace:*",
"@vitest/ui": "workspace:*",
"bumpp": "^8.2.1",
"c8": "^7.12.0",
@@ -64,6 +66,7 @@
"rollup-plugin-esbuild": "^4.9.3",
"rollup-plugin-license": "^2.8.1",
"simple-git-hooks": "^2.8.0",
+ "tsup": "^6.2.2",
"typescript": "^4.7.4",
"vite": "^3.0.7",
"vitest": "workspace:*",
diff --git a/packages/coverage-c8/package.json b/packages/coverage-c8/package.json
new file mode 100644
index 000000000..d1ebaeb23
--- /dev/null
+++ b/packages/coverage-c8/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "@vitest/coverage-c8",
+ "type": "module",
+ "version": "0.0.0",
+ "description": "C8 coverage provider for Vitest",
+ "author": "Anthony Fu ",
+ "license": "MIT",
+ "funding": "https://github.com/sponsors/antfu",
+ "homepage": "https://github.com/vitest-dev/vitest#readme",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vitest-dev/vitest.git",
+ "directory": "packages/coverage-c8"
+ },
+ "bugs": {
+ "url": "https://github.com/vitest-dev/vitest/issues"
+ },
+ "keywords": [
+ "vite",
+ "vitest",
+ "test",
+ "coverage",
+ "c8"
+ ],
+ "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/**"
+ },
+ "dependencies": {
+ "c8": "^7.12.0",
+ "vitest": "workspace:*"
+ },
+ "devDependencies": {
+ "vite-node": "workspace:*"
+ }
+}
diff --git a/packages/coverage-c8/rollup.config.js b/packages/coverage-c8/rollup.config.js
new file mode 100644
index 000000000..50cfe07d4
--- /dev/null
+++ b/packages/coverage-c8/rollup.config.js
@@ -0,0 +1,62 @@
+import { builtinModules } from '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'
+
+const entries = {
+ index: 'src/index.ts',
+}
+
+const external = [
+ ...builtinModules,
+ ...Object.keys(pkg.dependencies || {}),
+ ...Object.keys(pkg.peerDependencies || {}),
+ 'c8/lib/report.js',
+ 'c8/lib/commands/check-coverage.js',
+ 'vitest',
+ 'vitest/node',
+ 'vitest/config',
+]
+
+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-c8/src/index.ts b/packages/coverage-c8/src/index.ts
new file mode 100644
index 000000000..ddc09359a
--- /dev/null
+++ b/packages/coverage-c8/src/index.ts
@@ -0,0 +1,6 @@
+export * from './takeCoverage'
+
+export async function getProvider() {
+ const { C8CoverageProvider } = await import('./provider')
+ return new C8CoverageProvider()
+}
diff --git a/packages/coverage-c8/src/provider.ts b/packages/coverage-c8/src/provider.ts
new file mode 100644
index 000000000..3c05da7b9
--- /dev/null
+++ b/packages/coverage-c8/src/provider.ts
@@ -0,0 +1,126 @@
+import { existsSync, promises as fs } from 'fs'
+import _url from 'url'
+import type { Profiler } from 'inspector'
+import { takeCoverage } from 'v8'
+import { resolve } from 'pathe'
+import type { RawSourceMap } from 'vite-node'
+import { configDefaults } from 'vitest/config'
+// eslint-disable-next-line no-restricted-imports
+import type { CoverageC8Options, CoverageProvider, ResolvedCoverageOptions } from 'vitest'
+import type { Vitest } from 'vitest/node'
+// @ts-expect-error missing types
+import createReport from 'c8/lib/report.js'
+// @ts-expect-error missing types
+import { checkCoverages } from 'c8/lib/commands/check-coverage.js'
+
+export class C8CoverageProvider implements CoverageProvider {
+ name = 'c8'
+
+ ctx!: Vitest
+ options!: ResolvedCoverageOptions & { provider: 'c8' }
+
+ initialize(ctx: Vitest) {
+ this.ctx = ctx
+ this.options = resolveC8Options(ctx.config.coverage, ctx.config.root)
+ }
+
+ resolveOptions() {
+ return this.options
+ }
+
+ onBeforeFilesRun() {
+ process.env.NODE_V8_COVERAGE ||= this.options.tempDirectory
+ }
+
+ async clean(clean = true) {
+ if (clean && existsSync(this.options.reportsDirectory))
+ await fs.rm(this.options.reportsDirectory, { recursive: true, force: true })
+
+ if (!existsSync(this.options.tempDirectory))
+ await fs.mkdir(this.options.tempDirectory, { recursive: true })
+ }
+
+ onAfterSuiteRun() {
+ takeCoverage()
+ }
+
+ async reportCoverage() {
+ takeCoverage()
+ const report = createReport(this.ctx.config.coverage)
+
+ // add source maps
+ const sourceMapMeta: Record = {}
+ await Promise.all(Array
+ .from(this.ctx.vitenode.fetchCache.entries())
+ .filter(i => !i[0].includes('/node_modules/'))
+ .map(async ([file, { result }]) => {
+ const map = result.map
+ if (!map)
+ return
+
+ const url = _url.pathToFileURL(file).href
+
+ let code: string | undefined
+ try {
+ code = (await fs.readFile(file)).toString()
+ }
+ catch { }
+
+ // Vite does not report full path in sourcemap sources
+ // so use an actual file path
+ const sources = [url]
+
+ sourceMapMeta[url] = {
+ source: result.code,
+ map: {
+ sourcesContent: code ? [code] : undefined,
+ ...map,
+ sources,
+ },
+ }
+ }))
+
+ // This is a magic number. It corresponds to the amount of code
+ // that we add in packages/vite-node/src/client.ts:114 (vm.runInThisContext)
+ // TODO: Include our transformations in sourcemaps
+ const offset = 224
+
+ report._getSourceMap = (coverage: Profiler.ScriptCoverage) => {
+ const path = _url.pathToFileURL(coverage.url).href
+ const data = sourceMapMeta[path]
+
+ if (!data)
+ return {}
+
+ return {
+ sourceMap: {
+ sourcemap: data.map,
+ },
+ source: Array(offset).fill('.').join('') + data.source,
+ }
+ }
+
+ await report.run()
+ await checkCoverages(this.options, report)
+ }
+}
+function resolveC8Options(options: CoverageC8Options, root: string) {
+ const resolved = {
+ ...configDefaults.coverage,
+ ...options as any,
+ }
+
+ if (options['100']) {
+ resolved.lines = 100
+ resolved.functions = 100
+ resolved.branches = 100
+ resolved.statements = 100
+ }
+
+ resolved.reporter = resolved.reporter || []
+ resolved.reporter = Array.isArray(resolved.reporter) ? resolved.reporter : [resolved.reporter]
+ resolved.reportsDirectory = resolve(root, resolved.reportsDirectory)
+ resolved.tempDirectory = process.env.NODE_V8_COVERAGE || resolve(resolved.reportsDirectory, 'tmp')
+
+ return resolved
+}
diff --git a/packages/coverage-c8/src/takeCoverage.ts b/packages/coverage-c8/src/takeCoverage.ts
new file mode 100644
index 000000000..5669b1088
--- /dev/null
+++ b/packages/coverage-c8/src/takeCoverage.ts
@@ -0,0 +1,10 @@
+import v8 from 'v8'
+
+// Flush coverage to disk
+
+export function takeCoverage() {
+ if (v8.takeCoverage == null)
+ console.warn('[Vitest] takeCoverage is not available in this NodeJs version.\nCoverage could be incomplete. Update to NodeJs 14.18.')
+ else
+ v8.takeCoverage()
+}
diff --git a/packages/coverage-istanbul/package.json b/packages/coverage-istanbul/package.json
new file mode 100644
index 000000000..1c6e0d2e8
--- /dev/null
+++ b/packages/coverage-istanbul/package.json
@@ -0,0 +1,60 @@
+{
+ "name": "@vitest/coverage-istanbul",
+ "type": "module",
+ "version": "0.0.0",
+ "description": "Istanbul coverage provider for Vitest",
+ "author": "Anthony Fu ",
+ "license": "MIT",
+ "funding": "https://github.com/sponsors/antfu",
+ "homepage": "https://github.com/vitest-dev/vitest#readme",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vitest-dev/vitest.git",
+ "directory": "packages/coverage-istanbul"
+ },
+ "bugs": {
+ "url": "https://github.com/vitest-dev/vitest/issues"
+ },
+ "keywords": [
+ "vite",
+ "vitest",
+ "test",
+ "coverage",
+ "istanbul"
+ ],
+ "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/**"
+ },
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.2.0",
+ "istanbul-lib-instrument": "^5.2.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.1",
+ "istanbul-reports": "^3.1.5",
+ "test-exclude": "^6.0.0",
+ "vitest": "workspace:*"
+ },
+ "devDependencies": {
+ "@types/istanbul-lib-coverage": "^2.0.4",
+ "@types/istanbul-lib-instrument": "^1.7.4",
+ "@types/istanbul-lib-report": "^3.0.0",
+ "@types/istanbul-lib-source-maps": "^4.0.1",
+ "@types/istanbul-reports": "^3.0.1",
+ "pathe": "^0.2.0"
+ }
+}
diff --git a/packages/coverage-istanbul/rollup.config.js b/packages/coverage-istanbul/rollup.config.js
new file mode 100644
index 000000000..66fbbd080
--- /dev/null
+++ b/packages/coverage-istanbul/rollup.config.js
@@ -0,0 +1,60 @@
+import { builtinModules } from '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'
+
+const entries = {
+ index: 'src/index.ts',
+}
+
+const external = [
+ ...builtinModules,
+ ...Object.keys(pkg.dependencies || {}),
+ ...Object.keys(pkg.peerDependencies || {}),
+ 'vitest',
+ 'vitest/node',
+ 'vitest/config',
+]
+
+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-istanbul/src/constants.ts b/packages/coverage-istanbul/src/constants.ts
new file mode 100644
index 000000000..1f81d8ad9
--- /dev/null
+++ b/packages/coverage-istanbul/src/constants.ts
@@ -0,0 +1 @@
+export const COVERAGE_STORE_KEY = '__VITEST_COVERAGE__'
diff --git a/packages/coverage-istanbul/src/index.ts b/packages/coverage-istanbul/src/index.ts
new file mode 100644
index 000000000..a88aae227
--- /dev/null
+++ b/packages/coverage-istanbul/src/index.ts
@@ -0,0 +1,11 @@
+import { COVERAGE_STORE_KEY } from './constants'
+
+export async function getProvider() {
+ const { IstanbulCoverageProvider } = await import('./provider')
+ return new IstanbulCoverageProvider()
+}
+
+export function takeCoverage() {
+ // @ts-expect-error -- untyped global
+ return globalThis[COVERAGE_STORE_KEY]
+}
diff --git a/packages/coverage-istanbul/src/provider.ts b/packages/coverage-istanbul/src/provider.ts
new file mode 100644
index 000000000..285a0fc10
--- /dev/null
+++ b/packages/coverage-istanbul/src/provider.ts
@@ -0,0 +1,190 @@
+/* eslint-disable no-restricted-imports */
+import { existsSync, promises as fs } from 'fs'
+import { relative, resolve } from 'pathe'
+import type { TransformPluginContext } from 'rollup'
+import type { AfterSuiteRunMeta, CoverageIstanbulOptions, CoverageProvider, ResolvedCoverageOptions, Vitest } from 'vitest'
+import { configDefaults, defaultExclude, defaultInclude } from 'vitest/config'
+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 { type Instrumenter, createInstrumenter } from 'istanbul-lib-instrument'
+// @ts-expect-error missing types
+import _TestExclude from 'test-exclude'
+import { COVERAGE_STORE_KEY } from './constants'
+
+type Threshold = 'lines' | 'functions' | 'statements' | 'branches'
+
+interface TestExclude {
+ new(opts: {
+ cwd?: string | string[]
+ include?: string | string[]
+ exclude?: string | string[]
+ extension?: string | string[]
+ excludeNodeModules?: boolean
+ }): { shouldInstrument(filePath: string): boolean }
+}
+
+export class IstanbulCoverageProvider implements CoverageProvider {
+ name = 'istanbul'
+
+ ctx!: Vitest
+ options!: ResolvedCoverageOptions & CoverageIstanbulOptions & { provider: 'istanbul' }
+ instrumenter!: Instrumenter
+ testExclude!: InstanceType
+
+ /**
+ * Coverage objects collected from workers.
+ * Some istanbul utilizers write these into file system instead of storing in memory.
+ * If storing in memory causes issues, we can simply write these into fs in `onAfterSuiteRun`
+ * and read them back when merging coverage objects in `onAfterAllFilesRun`.
+ */
+ coverages: any[] = []
+
+ initialize(ctx: Vitest) {
+ this.ctx = ctx
+ this.options = resolveIstanbulOptions(ctx.config.coverage, ctx.config.root)
+
+ this.instrumenter = createInstrumenter({
+ produceSourceMap: true,
+ autoWrap: false,
+ esModules: true,
+ coverageVariable: COVERAGE_STORE_KEY,
+ // @ts-expect-error missing type
+ coverageGlobalScope: 'globalThis',
+ coverageGlobalScopeFunc: false,
+ ignoreClassMethods: this.options.ignoreClassMethods,
+ })
+
+ this.testExclude = new _TestExclude({
+ cwd: ctx.config.root,
+ exclude: [...defaultExclude, ...defaultInclude, ...this.options.exclude],
+ excludeNodeModules: true,
+ extension: configDefaults.coverage.extension,
+ })
+ }
+
+ resolveOptions(): ResolvedCoverageOptions {
+ return this.options
+ }
+
+ onFileTransform(sourceCode: string, id: string, pluginCtx: TransformPluginContext) {
+ if (!this.testExclude.shouldInstrument(id))
+ return
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- ignoreRestSiblings should be enabled
+ const { sourcesContent, ...sourceMap } = pluginCtx.getCombinedSourcemap()
+ const code = this.instrumenter.instrumentSync(sourceCode, id, sourceMap as any)
+ const map = this.instrumenter.lastSourceMap() as any
+
+ return { code, map }
+ }
+
+ onAfterSuiteRun({ coverage }: AfterSuiteRunMeta) {
+ this.coverages.push(coverage)
+ }
+
+ async clean(clean = true) {
+ if (clean && existsSync(this.options.reportsDirectory))
+ await fs.rm(this.options.reportsDirectory, { recursive: true, force: true })
+
+ this.coverages = []
+ }
+
+ async reportCoverage() {
+ const mergedCoverage = this.coverages.reduce((coverage, previousCoverageMap) => {
+ const map = libCoverage.createCoverageMap(coverage)
+ map.merge(previousCoverageMap)
+ return map
+ }, {})
+
+ 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 as any, {
+ skipFull: this.options.skipFull,
+ }).execute(context)
+ }
+
+ if (this.options.branches
+ || 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,
+ })
+ }
+ }
+
+ 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)
+ }
+ }
+ }
+ }
+ }
+}
+
+function resolveIstanbulOptions(options: CoverageIstanbulOptions, root: string) {
+ const reportsDirectory = resolve(root, options.reportsDirectory || configDefaults.coverage.reportsDirectory!)
+
+ const resolved = {
+ ...configDefaults.coverage,
+ ...options,
+ provider: 'istanbul',
+ reportsDirectory,
+ tempDirectory: resolve(reportsDirectory, 'tmp'),
+ }
+
+ return resolved as ResolvedCoverageOptions & { provider: 'istanbul' }
+}
diff --git a/packages/ui/client/composables/summary.ts b/packages/ui/client/composables/summary.ts
index 534b01c8e..07f1518ac 100644
--- a/packages/ui/client/composables/summary.ts
+++ b/packages/ui/client/composables/summary.ts
@@ -52,6 +52,7 @@ function toArray(array?: Nullable>): Array {
return array
return [array]
}
+
function getTests(suite: Arrayable): Test[] {
return toArray(suite).flatMap(s => s.type === 'test' ? [s] : s.tasks.flatMap(c => c.type === 'test' ? [c] : getTests(c)))
}
diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts
index 308f3fa4f..f53e97a32 100644
--- a/packages/vite-node/src/client.ts
+++ b/packages/vite-node/src/client.ts
@@ -216,7 +216,7 @@ export class ViteNodeRunner {
// Be careful when changing this
// changing context will change amount of code added on line :114 (vm.runInThisContext)
// this messes up sourcemaps for coverage
- // adjust `offset` variable in packages/vitest/src/integrations/coverage.ts#L100 if you do change this
+ // adjust `offset` variable in packages/vitest/src/integrations/coverage/c8.ts#86 if you do change this
const context = this.prepareContext({
// esm transformed by Vite
__vite_ssr_import__: request,
diff --git a/packages/vitest/LICENSE.md b/packages/vitest/LICENSE.md
index bb9148d8a..f4efaa8ab 100644
--- a/packages/vitest/LICENSE.md
+++ b/packages/vitest/LICENSE.md
@@ -898,7 +898,7 @@ Repository: ehmicky/human-signals
> same "printed page" as the copyright notice for easier
> identification within third-party archives.
>
-> Copyright 2019 ehmicky
+> Copyright 2021 ehmicky
>
> Licensed under the Apache License, Version 2.0 (the "License");
> you may not use this file except in compliance with the License.
@@ -1310,7 +1310,7 @@ Repository: sindresorhus/npm-run-path
> MIT License
>
-> Copyright (c) Sindre Sorhus (sindresorhus.com)
+> Copyright (c) Sindre Sorhus (https://sindresorhus.com)
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
@@ -1395,7 +1395,7 @@ Repository: sindresorhus/path-key
> MIT License
>
-> Copyright (c) Sindre Sorhus (sindresorhus.com)
+> Copyright (c) Sindre Sorhus (https://sindresorhus.com)
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
@@ -1911,7 +1911,7 @@ Repository: sindresorhus/strip-final-newline
> MIT License
>
-> Copyright (c) Sindre Sorhus (sindresorhus.com)
+> Copyright (c) Sindre Sorhus (https://sindresorhus.com)
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
diff --git a/packages/vitest/package.json b/packages/vitest/package.json
index 146639cdf..27996eba8 100644
--- a/packages/vitest/package.json
+++ b/packages/vitest/package.json
@@ -16,6 +16,7 @@
"keywords": [
"vite",
"vite-node",
+ "vitest",
"test",
"jest"
],
@@ -70,7 +71,6 @@
"@edge-runtime/vm": "*",
"@vitest/browser": "*",
"@vitest/ui": "*",
- "c8": "*",
"happy-dom": "*",
"jsdom": "*"
},
@@ -81,9 +81,6 @@
"@vitest/browser": {
"optional": true
},
- "c8": {
- "optional": true
- },
"happy-dom": {
"optional": true
},
@@ -117,7 +114,6 @@
"@types/sinonjs__fake-timers": "^8.1.2",
"@vitest/ui": "workspace:*",
"birpc": "^0.2.3",
- "c8": "^7.12.0",
"cac": "^6.7.12",
"chai-subset": "^1.6.0",
"cli-truncate": "^3.1.0",
diff --git a/packages/vitest/src/config.ts b/packages/vitest/src/config.ts
index 5b783a22f..dc18055c8 100644
--- a/packages/vitest/src/config.ts
+++ b/packages/vitest/src/config.ts
@@ -5,7 +5,7 @@ export interface UserConfig extends ViteUserConfig {
}
// will import vitest declare test in module 'vite'
-export { configDefaults } from './defaults'
+export { configDefaults, defaultInclude, defaultExclude } from './defaults'
export type { ConfigEnv }
export type UserConfigFn = (env: ConfigEnv) => UserConfig | Promise
diff --git a/packages/vitest/src/defaults.ts b/packages/vitest/src/defaults.ts
index 63add24a3..54d16961b 100644
--- a/packages/vitest/src/defaults.ts
+++ b/packages/vitest/src/defaults.ts
@@ -1,4 +1,4 @@
-import type { ResolvedC8Options, UserConfig } from './types'
+import type { ResolvedCoverageOptions, UserConfig } from './types'
export const defaultInclude = ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']
export const defaultExclude = ['**/node_modules/**', '**/dist/**', '**/cypress/**', '**/.{idea,git,cache,output,temp}/**']
@@ -19,6 +19,7 @@ const defaultCoverageExcludes = [
]
const coverageConfigDefaults = {
+ provider: 'c8',
enabled: false,
clean: true,
cleanOnRerun: false,
@@ -30,7 +31,7 @@ const coverageConfigDefaults = {
// default extensions used by c8, plus '.vue' and '.svelte'
// see https://github.com/istanbuljs/schema/blob/master/default-extension.js
extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx', '.vue', '.svelte'],
-} as ResolvedC8Options
+} as ResolvedCoverageOptions
export const fakeTimersDefaults = {
loopLimit: 10_000,
diff --git a/packages/vitest/src/integrations/coverage.ts b/packages/vitest/src/integrations/coverage.ts
index 76c95a476..a14b4d5dc 100644
--- a/packages/vitest/src/integrations/coverage.ts
+++ b/packages/vitest/src/integrations/coverage.ts
@@ -1,115 +1,34 @@
-import { existsSync, promises as fs } from 'fs'
-import { createRequire } from 'module'
-import _url from 'url'
-import type { Profiler } from 'inspector'
-import { resolve } from 'pathe'
-import type { RawSourceMap } from 'vite-node'
-import type { Vitest } from '../node'
-import { toArray } from '../utils'
-import type { C8Options, ResolvedC8Options } from '../types'
-import { configDefaults } from '../defaults'
+import { importModule } from 'local-pkg'
+import type { CoverageOptions, CoverageProvider, CoverageProviderModule } from '../types'
-export function resolveC8Options(options: C8Options, root: string): ResolvedC8Options {
- const resolved: ResolvedC8Options = {
- ...configDefaults.coverage,
- ...options as any,
- }
-
- resolved.reporter = toArray(resolved.reporter)
- resolved.reportsDirectory = resolve(root, resolved.reportsDirectory)
- resolved.tempDirectory = process.env.NODE_V8_COVERAGE || resolve(resolved.reportsDirectory, 'tmp')
-
- return resolved as ResolvedC8Options
-}
-
-export async function cleanCoverage(options: ResolvedC8Options, clean = true) {
- if (clean && existsSync(options.reportsDirectory))
- await fs.rm(options.reportsDirectory, { recursive: true, force: true })
-
- if (!existsSync(options.tempDirectory))
- await fs.mkdir(options.tempDirectory, { recursive: true })
+export const CoverageProviderMap = {
+ c8: '@vitest/coverage-c8',
+ istanbul: '@vitest/coverage-istanbul',
}
-const require = createRequire(import.meta.url)
-
-// Flush coverage to disk
-export function takeCoverage() {
- const v8 = require('v8')
- if (v8.takeCoverage == null)
- console.warn('[Vitest] takeCoverage is not available in this NodeJs version.\nCoverage could be incomplete. Update to NodeJs 14.18.')
- else
- v8.takeCoverage()
+export async function resolveCoverageProvider(provider: NonNullable) {
+ if (typeof provider === 'string') {
+ const pkg = CoverageProviderMap[provider]
+ if (!pkg)
+ throw new Error(`Unknown coverage provider: ${provider}`)
+ return await importModule(pkg)
+ }
+ else {
+ return provider
+ }
}
-export async function reportCoverage(ctx: Vitest) {
- takeCoverage()
-
- const createReport = require('c8/lib/report')
- const report = createReport(ctx.config.coverage)
-
- // add source maps
- const sourceMapMeta: Record = {}
- await Promise.all(Array
- .from(ctx.vitenode.fetchCache.entries())
- .filter(i => !i[0].includes('/node_modules/'))
- .map(async ([file, { result }]) => {
- const map = result.map
- if (!map)
- return
-
- const url = _url.pathToFileURL(file).href
-
- let code: string | undefined
- try {
- code = (await fs.readFile(file)).toString()
- }
- catch {}
-
- // Vite does not report full path in sourcemap sources
- // so use an actual file path
- const sources = [url]
-
- sourceMapMeta[url] = {
- source: result.code,
- map: {
- sourcesContent: code ? [code] : undefined,
- ...map,
- sources,
- },
- }
- }))
-
- // This is a magic number. It corresponds to the amount of code
- // that we add in packages/vite-node/src/client.ts:114 (vm.runInThisContext)
- // TODO: Include our transformations in sourcemaps
- const offset = 224
-
- report._getSourceMap = (coverage: Profiler.ScriptCoverage) => {
- const path = _url.pathToFileURL(coverage.url).href
- const data = sourceMapMeta[path]
-
- if (!data)
- return {}
-
- return {
- sourceMap: {
- sourcemap: data.map,
- },
- source: Array(offset).fill('.').join('') + data.source,
- }
+export async function getCoverageProvider(options?: CoverageOptions): Promise {
+ if (options?.enabled && options?.provider) {
+ const { getProvider } = await resolveCoverageProvider(options.provider)
+ return await getProvider()
}
+ return null
+}
- await report.run()
-
- if (ctx.config.coverage.enabled) {
- if (ctx.config.coverage['100']) {
- ctx.config.coverage.lines = 100
- ctx.config.coverage.functions = 100
- ctx.config.coverage.branches = 100
- ctx.config.coverage.statements = 100
- }
-
- const { checkCoverages } = require('c8/lib/commands/check-coverage')
- await checkCoverages(ctx.config.coverage, report)
+export async function takeCoverageInsideWorker(options: CoverageOptions) {
+ if (options.enabled && options.provider) {
+ const { takeCoverage } = await resolveCoverageProvider(options.provider)
+ return await takeCoverage?.()
}
}
diff --git a/packages/vitest/src/node/cli-api.ts b/packages/vitest/src/node/cli-api.ts
index db60a8138..6106cdb60 100644
--- a/packages/vitest/src/node/cli-api.ts
+++ b/packages/vitest/src/node/cli-api.ts
@@ -1,5 +1,6 @@
import { resolve } from 'pathe'
import type { UserConfig as ViteUserConfig } from 'vite'
+import { CoverageProviderMap } from '../integrations/coverage'
import { envPackageNames } from '../integrations/env'
import type { UserConfig } from '../types'
import { ensurePackageInstalled } from '../utils'
@@ -37,9 +38,14 @@ export async function startVitest(cliFilters: string[], options: CliOptions, vit
const ctx = await createVitest(options, viteOverrides)
if (ctx.config.coverage.enabled) {
- if (!await ensurePackageInstalled('c8', root)) {
- process.exitCode = 1
- return false
+ const provider = ctx.config.coverage.provider || 'c8'
+ if (typeof provider === 'string') {
+ const requiredPackages = CoverageProviderMap[provider]
+
+ if (!await ensurePackageInstalled(requiredPackages, root)) {
+ process.exitCode = 1
+ return false
+ }
}
}
diff --git a/packages/vitest/src/node/cli.ts b/packages/vitest/src/node/cli.ts
index ba72347d6..c42b4fd6d 100644
--- a/packages/vitest/src/node/cli.ts
+++ b/packages/vitest/src/node/cli.ts
@@ -25,7 +25,7 @@ cli
.option('--outputTruncateLength ', 'diff output length (default: 80)')
.option('--outputDiffLines ', 'number of diff output lines (default: 15)')
.option('--outputFile ', 'write test results to a file when the --reporter=json or --reporter=junit option is also specified, use cac\'s dot notation for individual outputs of mutliple reporters')
- .option('--coverage', 'use c8 for coverage')
+ .option('--coverage', 'enable coverage report')
.option('--run', 'do not watch')
.option('--mode ', 'override Vite mode (default: test)')
.option('--globals', 'inject apis globally')
diff --git a/packages/vitest/src/node/config.ts b/packages/vitest/src/node/config.ts
index e2543ac6c..4e1b6ddba 100644
--- a/packages/vitest/src/node/config.ts
+++ b/packages/vitest/src/node/config.ts
@@ -6,7 +6,6 @@ import type { ResolvedConfig as ResolvedViteConfig } from 'vite'
import type { ApiConfig, ResolvedConfig, UserConfig } from '../types'
import { defaultPort } from '../constants'
import { configDefaults } from '../defaults'
-import { resolveC8Options } from '../integrations/coverage'
import { toArray } from '../utils'
import { VitestCache } from './cache'
import { BaseSequencer } from './sequencers/BaseSequencer'
@@ -93,8 +92,6 @@ export function resolveConfig(
if (viteConfig.base !== '/')
resolved.base = viteConfig.base
- resolved.coverage = resolveC8Options(options.coverage || {}, resolved.root)
-
if (options.shard) {
if (resolved.watch)
throw new Error('You cannot use --shard option with enabled watch')
diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts
index 49b7e361e..ac8aa7da9 100644
--- a/packages/vitest/src/node/core.ts
+++ b/packages/vitest/src/node/core.ts
@@ -6,10 +6,10 @@ import mm from 'micromatch'
import c from 'picocolors'
import { ViteNodeRunner } from 'vite-node/client'
import { ViteNodeServer } from 'vite-node/server'
-import type { ArgumentsType, Reporter, ResolvedConfig, UserConfig } from '../types'
+import type { ArgumentsType, CoverageProvider, Reporter, ResolvedConfig, UserConfig } from '../types'
import { SnapshotManager } from '../integrations/snapshot/manager'
import { clearTimeout, deepMerge, hasFailed, noop, setTimeout, slash } from '../utils'
-import { cleanCoverage, reportCoverage } from '../integrations/coverage'
+import { getCoverageProvider } from '../integrations/coverage'
import { createPool } from './pool'
import type { WorkerPool } from './pool'
import { createReporters } from './reporters/utils'
@@ -29,6 +29,7 @@ export class Vitest {
snapshot: SnapshotManager = undefined!
cache: VitestCache = undefined!
reporters: Reporter[] = undefined!
+ coverageProvider: CoverageProvider | null | undefined
logger: Logger
pool: WorkerPool | undefined
@@ -86,8 +87,7 @@ export class Vitest {
this._onRestartListeners.forEach(fn => fn())
- if (resolved.coverage.enabled)
- await cleanCoverage(resolved.coverage, resolved.coverage.clean)
+ await this.coverageProvider?.clean(this.config.coverage.clean)
this.cache.results.setConfig(resolved.root, resolved.cache)
try {
@@ -98,6 +98,17 @@ export class Vitest {
}
}
+ async initCoverageProvider() {
+ if (this.coverageProvider !== undefined)
+ return
+ this.coverageProvider = await getCoverageProvider(this.config.coverage)
+ if (this.coverageProvider) {
+ await this.coverageProvider.initialize(this)
+ this.config.coverage = this.coverageProvider.resolveOptions()
+ }
+ return this.coverageProvider
+ }
+
getSerializableConfig() {
return deepMerge({
...this.config,
@@ -117,6 +128,14 @@ export class Vitest {
}
async start(filters?: string[]) {
+ try {
+ await this.initCoverageProvider()
+ }
+ catch (e) {
+ this.logger.error(e)
+ process.exit(1)
+ }
+
await this.report('onInit', this)
const files = await this.filterTestsBySource(
@@ -136,8 +155,10 @@ export class Vitest {
await this.runFiles(files)
- if (this.config.coverage.enabled)
- await reportCoverage(this)
+ if (this.coverageProvider) {
+ this.logger.log(c.blue(' % ') + c.dim('Coverage report from ') + c.yellow(this.coverageProvider.name))
+ await this.coverageProvider.reportCoverage()
+ }
if (this.config.watch && !this.config.browser)
await this.report('onWatcherStart')
@@ -321,15 +342,14 @@ export class Vitest {
const files = Array.from(this.changedTests)
this.changedTests.clear()
- if (this.config.coverage.enabled && this.config.coverage.cleanOnRerun)
- await cleanCoverage(this.config.coverage)
+ if (this.coverageProvider && this.config.coverage.cleanOnRerun)
+ await this.coverageProvider.clean()
await this.report('onWatcherRerun', files, triggerId)
await this.runFiles(files)
- if (this.config.coverage.enabled)
- await reportCoverage(this)
+ await this.coverageProvider?.reportCoverage()
if (!this.config.browser)
await this.report('onWatcherStart')
diff --git a/packages/vitest/src/node/logger.ts b/packages/vitest/src/node/logger.ts
index c4a613522..5509c161c 100644
--- a/packages/vitest/src/node/logger.ts
+++ b/packages/vitest/src/node/logger.ts
@@ -102,6 +102,9 @@ export class Logger {
else if (this.ctx.config.api)
this.log(c.dim(c.green(` API started at http://${this.ctx.config.api?.host || 'localhost'}:${c.bold(`${this.ctx.config.api.port}`)}`)))
+ if (this.ctx.coverageProvider)
+ this.log(c.dim(' Coverage enabled with ') + c.yellow(this.ctx.coverageProvider.name))
+
this.log()
}
diff --git a/packages/vitest/src/node/plugins/coverageTransform.ts b/packages/vitest/src/node/plugins/coverageTransform.ts
new file mode 100644
index 000000000..f31d19762
--- /dev/null
+++ b/packages/vitest/src/node/plugins/coverageTransform.ts
@@ -0,0 +1,12 @@
+import type { Plugin as VitePlugin } from 'vite'
+
+import type { Vitest } from '../core'
+
+export function CoverageTransform(ctx: Vitest): VitePlugin | null {
+ return {
+ name: 'vitest:coverage-transform',
+ transform(srcCode, id) {
+ return ctx.coverageProvider?.onFileTransform?.(srcCode, id, this)
+ },
+ }
+}
diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts
index d722baa94..a2a826615 100644
--- a/packages/vitest/src/node/plugins/index.ts
+++ b/packages/vitest/src/node/plugins/index.ts
@@ -8,6 +8,7 @@ import { EnvReplacerPlugin } from './envRelacer'
import { GlobalSetupPlugin } from './globalSetup'
import { MocksPlugin } from './mock'
import { CSSEnablerPlugin } from './cssEnabler'
+import { CoverageTransform } from './coverageTransform'
export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest()): Promise {
let haveStarted = false
@@ -169,6 +170,7 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest())
? await BrowserPlugin()
: []),
CSSEnablerPlugin(ctx),
+ CoverageTransform(ctx),
options.ui
? await UIPlugin()
: null,
diff --git a/packages/vitest/src/node/pool.ts b/packages/vitest/src/node/pool.ts
index 0f1b116b8..6b0d6e07d 100644
--- a/packages/vitest/src/node/pool.ts
+++ b/packages/vitest/src/node/pool.ts
@@ -64,8 +64,7 @@ export function createPool(ctx: Vitest): WorkerPool {
options.minThreads = 1
}
- if (ctx.config.coverage.enabled)
- process.env.NODE_V8_COVERAGE ||= ctx.config.coverage.tempDirectory
+ ctx.coverageProvider?.onBeforeFilesRun?.()
options.env = {
TEST: 'true',
@@ -171,6 +170,9 @@ function createChannel(ctx: Vitest) {
ctx.state.collectFiles(files)
ctx.report('onCollected', files)
},
+ onAfterSuiteRun(meta) {
+ ctx.coverageProvider?.onAfterSuiteRun(meta)
+ },
onTaskUpdate(packs) {
ctx.state.updateTasks(packs)
ctx.report('onTaskUpdate', packs)
diff --git a/packages/vitest/src/runtime/run.ts b/packages/vitest/src/runtime/run.ts
index 9dcb5601e..fb019a302 100644
--- a/packages/vitest/src/runtime/run.ts
+++ b/packages/vitest/src/runtime/run.ts
@@ -2,9 +2,9 @@ import limit from 'p-limit'
import type { File, HookCleanupCallback, HookListener, ResolvedConfig, Suite, SuiteHooks, Task, TaskResult, TaskState, Test } from '../types'
import { vi } from '../integrations/vi'
import { clearTimeout, getFullName, getWorkerState, hasFailed, hasTests, isBrowser, isNode, partitionSuiteChildren, setTimeout, shuffle } from '../utils'
-import { takeCoverage } from '../integrations/coverage'
import { getState, setState } from '../integrations/chai/jest-expect'
import { GLOBAL_EXPECT } from '../integrations/chai/constants'
+import { takeCoverageInsideWorker } from '../integrations/coverage'
import { getFn, getHooks } from './map'
import { rpc } from './rpc'
import { collectTests } from './collect'
@@ -316,7 +316,8 @@ async function startTestsNode(paths: string[], config: ResolvedConfig) {
await runFiles(files, config)
- takeCoverage()
+ const coverage = await takeCoverageInsideWorker(config.coverage)
+ rpc().onAfterSuiteRun({ coverage })
await getSnapshotClient().saveCurrent()
diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts
index 8258f2426..aa63e8274 100644
--- a/packages/vitest/src/types/config.ts
+++ b/packages/vitest/src/types/config.ts
@@ -3,7 +3,7 @@ import type { PrettyFormatOptions } from 'pretty-format'
import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers'
import type { BuiltinReporters } from '../node/reporters'
import type { TestSequencerConstructor } from '../node/sequencers/types'
-import type { C8Options, ResolvedC8Options } from './coverage'
+import type { CoverageOptions, ResolvedCoverageOptions } from './coverage'
import type { JSDOMOptions } from './jsdom-options'
import type { Reporter } from './reporter'
import type { SnapshotStateOptions } from './snapshot'
@@ -242,7 +242,7 @@ export interface InlineConfig {
/**
* Coverage options
*/
- coverage?: C8Options
+ coverage?: CoverageOptions
/**
* run test names with the specified pattern
@@ -478,7 +478,7 @@ export interface ResolvedConfig extends Omit, 'config' | 'f
testNamePattern?: RegExp
related?: string[]
- coverage: ResolvedC8Options
+ coverage: ResolvedCoverageOptions
snapshotOptions: SnapshotStateOptions
reporters: (Reporter | BuiltinReporters)[]
diff --git a/packages/vitest/src/types/coverage.ts b/packages/vitest/src/types/coverage.ts
index f65cfac9a..d2c14d7e6 100644
--- a/packages/vitest/src/types/coverage.ts
+++ b/packages/vitest/src/types/coverage.ts
@@ -1,4 +1,37 @@
+import type { TransformPluginContext, TransformResult } from 'rollup'
+import type { Vitest } from '../node'
import type { Arrayable } from './general'
+import type { AfterSuiteRunMeta } from './worker'
+
+export interface CoverageProvider {
+ name: string
+ initialize(ctx: Vitest): Promise | void
+
+ resolveOptions(): ResolvedCoverageOptions
+ clean(clean?: boolean): void | Promise
+
+ onBeforeFilesRun?(): void | Promise
+ onAfterSuiteRun(meta: AfterSuiteRunMeta): void | Promise
+
+ reportCoverage(): void | Promise
+
+ onFileTransform?(
+ sourceCode: string,
+ id: string,
+ pluginCtx: TransformPluginContext
+ ): TransformResult | Promise
+}
+
+export interface CoverageProviderModule {
+ /**
+ * Factory for creating a new coverage provider
+ */
+ getProvider(): CoverageProvider | Promise
+ /**
+ * Executed on after each run in the worker thread. Possible to return a payload passed to the provider
+ */
+ takeCoverage?(): unknown | Promise
+}
export type CoverageReporter =
| 'clover'
@@ -15,68 +48,122 @@ export type CoverageReporter =
| 'text-summary'
| 'text'
-export interface C8Options {
+export type CoverageOptions =
+ | BaseCoverageOptions & { provider?: null | CoverageProviderModule }
+ | CoverageC8Options & { provider?: 'c8' }
+ | CoverageIstanbulOptions & { provider?: 'istanbul' }
+
+export type ResolvedCoverageOptions =
+ & { tempDirectory: string }
+ & Required
+
+export interface BaseCoverageOptions {
/**
* Enable coverage, pass `--coverage` to enable
*
* @default false
*/
enabled?: boolean
- /**
- * Directory to write coverage report to
- */
- reportsDirectory?: string
+
/**
* Clean coverage before running tests
*
* @default true
*/
clean?: boolean
+
/**
* Clean coverage report on watch rerun
*
* @default false
*/
cleanOnRerun?: boolean
+
+ /**
+ * Directory to write coverage report to
+ */
+ reportsDirectory?: string
+
+ /**
+ * Reporters
+ *
+ * @default 'text'
+ */
+ reporter?: Arrayable
+
+ /**
+ * List of files excluded from coverage as glob patterns
+ */
+ exclude?: string[]
+
+ /**
+ * Do not show files with 100% statement, branch, and function coverage
+ */
+ skipFull?: boolean
+
/**
* Check thresholds per file
*
* @default false
*/
perFile?: boolean
+
+ /**
+ * Threshold for lines
+ */
+ lines?: number
+
+ /**
+ * Threshold for functions
+ */
+ functions?: number
+
+ /**
+ * Threshold for branches
+ */
+ branches?: number
+
+ /**
+ * Threshold for statements
+ */
+ statements?: number
+
+ /**
+ * Extensions for files to be included in coverage
+ */
+ extension?: string | string[]
+}
+
+export interface CoverageIstanbulOptions extends BaseCoverageOptions {
+ /* Set to array of class method names to ignore for coverage */
+ ignoreClassMethods?: string[]
+
+ /* Watermarks for statements, lines, branches and functions */
+ watermarks?: {
+ statements?: [number, number]
+ functions?: [number, number]
+ branches?: [number, number]
+ lines?: [number, number]
+ }
+}
+
+export interface CoverageC8Options extends BaseCoverageOptions {
/**
* Allow files from outside of your cwd.
*
* @default false
*/
allowExternal?: any
- /**
- * Reporters
- *
- * @default 'text'
- */
- reporter?: Arrayable
/**
* Exclude coverage under /node_modules/
*
* @default true
*/
excludeNodeModules?: boolean
- exclude?: string[]
include?: string[]
- skipFull?: boolean
- extension?: string | string[]
all?: boolean
src?: string[]
100?: boolean
- lines?: number
- functions?: number
- branches?: number
- statements?: number
-}
-
-export interface ResolvedC8Options extends Required {
- tempDirectory: string
}
diff --git a/packages/vitest/src/types/worker.ts b/packages/vitest/src/types/worker.ts
index 2e49a77c1..4b4b984cf 100644
--- a/packages/vitest/src/types/worker.ts
+++ b/packages/vitest/src/types/worker.ts
@@ -17,6 +17,10 @@ export interface WorkerContext {
export type ResolveIdFunction = (id: string, importer?: string) => Promise
+export interface AfterSuiteRunMeta {
+ coverage?: unknown
+}
+
export interface WorkerRPC {
fetch: FetchFunction
resolveId: ResolveIdFunction
@@ -28,6 +32,7 @@ export interface WorkerRPC {
onUserConsoleLog: (log: UserConsoleLog) => void
onUnhandledRejection: (err: unknown) => void
onCollected: (files: File[]) => void
+ onAfterSuiteRun: (meta: AfterSuiteRunMeta) => void
onTaskUpdate: (pack: TaskResultPack[]) => void
snapshotSaved: (snapshot: SnapshotResult) => void
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 590ce36f3..3a1a76c48 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -21,6 +21,8 @@ importers:
'@types/node': ^18.7.3
'@types/ws': ^8.5.3
'@vitest/browser': workspace:*
+ '@vitest/coverage-c8': workspace:*
+ '@vitest/coverage-istanbul': workspace:*
'@vitest/ui': workspace:*
bumpp: ^8.2.1
c8: ^7.12.0
@@ -43,6 +45,7 @@ importers:
rollup-plugin-esbuild: ^4.9.3
rollup-plugin-license: ^2.8.1
simple-git-hooks: ^2.8.0
+ tsup: ^6.2.2
typescript: ^4.7.4
vite: ^3.0.7
vitest: workspace:*
@@ -59,6 +62,8 @@ importers:
'@types/node': 18.7.3
'@types/ws': 8.5.3
'@vitest/browser': link:packages/browser
+ '@vitest/coverage-c8': link:packages/coverage-c8
+ '@vitest/coverage-istanbul': link:packages/coverage-istanbul
'@vitest/ui': link:packages/ui
bumpp: 8.2.1
c8: 7.12.0
@@ -81,6 +86,7 @@ importers:
rollup-plugin-esbuild: 4.9.3_2xvlthrg5p5laozpkponua2u2i
rollup-plugin-license: 2.8.1_rollup@2.77.3
simple-git-hooks: 2.8.0
+ tsup: 6.2.2_typescript@4.7.4
typescript: 4.7.4
vite: 3.0.7
vitest: link:packages/vitest
@@ -210,7 +216,7 @@ importers:
react-dom: 18.0.0_react@18.0.0
devDependencies:
'@testing-library/react': 13.2.0_zpnidt7m3osuk7shl3s4oenomq
- '@types/node': 18.7.3
+ '@types/node': 18.7.4
'@types/react': 18.0.17
'@vitejs/plugin-react': 2.0.1
jsdom: 20.0.0
@@ -608,6 +614,48 @@ importers:
rollup: 2.77.3
vitest: link:../vitest
+ packages/coverage-c8:
+ specifiers:
+ c8: ^7.12.0
+ vite-node: workspace:*
+ vitest: workspace:*
+ dependencies:
+ c8: 7.12.0
+ vitest: link:../vitest
+ devDependencies:
+ vite-node: link:../vite-node
+
+ packages/coverage-istanbul:
+ specifiers:
+ '@types/istanbul-lib-coverage': ^2.0.4
+ '@types/istanbul-lib-instrument': ^1.7.4
+ '@types/istanbul-lib-report': ^3.0.0
+ '@types/istanbul-lib-source-maps': ^4.0.1
+ '@types/istanbul-reports': ^3.0.1
+ istanbul-lib-coverage: ^3.2.0
+ istanbul-lib-instrument: ^5.2.0
+ istanbul-lib-report: ^3.0.0
+ istanbul-lib-source-maps: ^4.0.1
+ istanbul-reports: ^3.1.5
+ pathe: ^0.2.0
+ test-exclude: ^6.0.0
+ vitest: workspace:*
+ dependencies:
+ istanbul-lib-coverage: 3.2.0
+ istanbul-lib-instrument: 5.2.0
+ istanbul-lib-report: 3.0.0
+ istanbul-lib-source-maps: 4.0.1
+ istanbul-reports: 3.1.5
+ test-exclude: 6.0.0
+ vitest: link:../vitest
+ devDependencies:
+ '@types/istanbul-lib-coverage': 2.0.4
+ '@types/istanbul-lib-instrument': 1.7.4
+ '@types/istanbul-lib-report': 3.0.0
+ '@types/istanbul-lib-source-maps': 4.0.1
+ '@types/istanbul-reports': 3.0.1
+ pathe: 0.2.0
+
packages/ui:
specifiers:
'@faker-js/faker': ^7.4.0
@@ -710,7 +758,6 @@ importers:
'@types/sinonjs__fake-timers': ^8.1.2
'@vitest/ui': workspace:*
birpc: ^0.2.3
- c8: ^7.12.0
cac: ^6.7.12
chai: ^4.3.6
chai-subset: ^1.6.0
@@ -766,7 +813,6 @@ importers:
'@types/sinonjs__fake-timers': 8.1.2
'@vitest/ui': link:../ui
birpc: 0.2.3
- c8: 7.12.0
cac: 6.7.12
chai-subset: 1.6.0
cli-truncate: 3.1.0
@@ -1111,7 +1157,6 @@ packages:
dependencies:
'@jridgewell/gen-mapping': 0.1.1
'@jridgewell/trace-mapping': 0.3.13
- dev: true
/@antfu/eslint-config-basic/0.26.1_yy5c4q6zhpajzhorvwhnwvctfe:
resolution: {integrity: sha512-MPos0lb8VJztb2tBf8ZYWopXkXQ/PM3Ub9k+8fRTt3nHiVo5UvkxUGV2dMvhJC1XkUE4Ym6yr1wZZz9BSdlkpQ==}
@@ -1295,7 +1340,6 @@ packages:
/@babel/compat-data/7.18.8:
resolution: {integrity: sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==}
engines: {node: '>=6.9.0'}
- dev: true
/@babel/core/7.12.9:
resolution: {integrity: sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==}
@@ -1342,7 +1386,6 @@ packages:
semver: 6.3.0
transitivePeerDependencies:
- supports-color
- dev: true
/@babel/core/7.18.2:
resolution: {integrity: sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==}
@@ -1397,7 +1440,6 @@ packages:
'@babel/types': 7.18.10
'@jridgewell/gen-mapping': 0.3.2
jsesc: 2.5.2
- dev: true
/@babel/generator/7.18.2:
resolution: {integrity: sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==}
@@ -1463,7 +1505,6 @@ packages:
'@babel/helper-validator-option': 7.18.6
browserslist: 4.20.3
semver: 6.3.0
- dev: true
/@babel/helper-compilation-targets/7.18.9_@babel+core@7.18.2:
resolution: {integrity: sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==}
@@ -1647,7 +1688,6 @@ packages:
/@babel/helper-environment-visitor/7.18.9:
resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==}
engines: {node: '>=6.9.0'}
- dev: true
/@babel/helper-explode-assignable-expression/7.16.7:
resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==}
@@ -1670,7 +1710,6 @@ packages:
dependencies:
'@babel/template': 7.18.10
'@babel/types': 7.18.10
- dev: true
/@babel/helper-hoist-variables/7.16.7:
resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==}
@@ -1684,7 +1723,6 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.18.10
- dev: true
/@babel/helper-member-expression-to-functions/7.17.7:
resolution: {integrity: sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==}
@@ -1718,7 +1756,6 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.18.10
- dev: true
/@babel/helper-module-transforms/7.18.0:
resolution: {integrity: sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==}
@@ -1750,7 +1787,6 @@ packages:
'@babel/types': 7.18.10
transitivePeerDependencies:
- supports-color
- dev: true
/@babel/helper-optimise-call-expression/7.16.7:
resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==}
@@ -1828,7 +1864,6 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.18.10
- dev: true
/@babel/helper-skip-transparent-expression-wrappers/7.16.0:
resolution: {integrity: sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==}
@@ -1849,7 +1884,6 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.18.10
- dev: true
/@babel/helper-string-parser/7.18.10:
resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==}
@@ -1871,7 +1905,6 @@ packages:
/@babel/helper-validator-option/7.18.6:
resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==}
engines: {node: '>=6.9.0'}
- dev: true
/@babel/helper-wrap-function/7.16.8:
resolution: {integrity: sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==}
@@ -1905,7 +1938,6 @@ packages:
'@babel/types': 7.18.10
transitivePeerDependencies:
- supports-color
- dev: true
/@babel/highlight/7.17.12:
resolution: {integrity: sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==}
@@ -1938,14 +1970,6 @@ packages:
dependencies:
'@babel/types': 7.18.4
- /@babel/parser/7.18.9:
- resolution: {integrity: sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==}
- engines: {node: '>=6.0.0'}
- hasBin: true
- dependencies:
- '@babel/types': 7.18.9
- dev: true
-
/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.18.2:
resolution: {integrity: sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==}
engines: {node: '>=6.9.0'}
@@ -3918,7 +3942,6 @@ packages:
'@babel/code-frame': 7.18.6
'@babel/parser': 7.18.11
'@babel/types': 7.18.10
- dev: true
/@babel/template/7.18.6:
resolution: {integrity: sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==}
@@ -3945,7 +3968,6 @@ packages:
globals: 11.12.0
transitivePeerDependencies:
- supports-color
- dev: true
/@babel/traverse/7.18.2:
resolution: {integrity: sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==}
@@ -4020,7 +4042,6 @@ packages:
/@bcoe/v8-coverage/0.2.3:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
- dev: true
/@cnakazawa/watch/1.0.4:
resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==}
@@ -4480,7 +4501,6 @@ packages:
/@istanbuljs/schema/0.1.3:
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
engines: {node: '>=8'}
- dev: true
/@jest/transform/26.6.2:
resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==}
@@ -4536,7 +4556,6 @@ packages:
dependencies:
'@jridgewell/set-array': 1.1.0
'@jridgewell/sourcemap-codec': 1.4.13
- dev: true
/@jridgewell/gen-mapping/0.3.1:
resolution: {integrity: sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==}
@@ -4554,28 +4573,23 @@ packages:
'@jridgewell/set-array': 1.1.0
'@jridgewell/sourcemap-codec': 1.4.13
'@jridgewell/trace-mapping': 0.3.13
- dev: true
/@jridgewell/resolve-uri/3.0.7:
resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==}
engines: {node: '>=6.0.0'}
- dev: true
/@jridgewell/set-array/1.1.0:
resolution: {integrity: sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==}
engines: {node: '>=6.0.0'}
- dev: true
/@jridgewell/sourcemap-codec/1.4.13:
resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==}
- dev: true
/@jridgewell/trace-mapping/0.3.13:
resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==}
dependencies:
'@jridgewell/resolve-uri': 3.0.7
'@jridgewell/sourcemap-codec': 1.4.13
- dev: true
/@jsdevtools/ez-spawn/3.0.4:
resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==}
@@ -7084,6 +7098,10 @@ packages:
resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==}
dev: true
+ /@types/babel-types/7.0.11:
+ resolution: {integrity: sha512-pkPtJUUY+Vwv6B1inAz55rQvivClHJxc9aVEPPmaq2cbyeMLCiDpbKpcKyX4LAwpNGi+SHBv0tHv6+0gXv0P2A==}
+ dev: true
+
/@types/braces/3.0.1:
resolution: {integrity: sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==}
dev: true
@@ -7113,7 +7131,7 @@ packages:
/@types/concat-stream/1.6.1:
resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==}
dependencies:
- '@types/node': 18.7.3
+ '@types/node': 18.7.4
dev: true
/@types/cookie/0.4.1:
@@ -7155,7 +7173,7 @@ packages:
/@types/form-data/0.0.33:
resolution: {integrity: sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=}
dependencies:
- '@types/node': 18.7.3
+ '@types/node': 18.7.4
dev: true
/@types/fs-extra/9.0.13:
@@ -7193,6 +7211,13 @@ packages:
/@types/istanbul-lib-coverage/2.0.4:
resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==}
+
+ /@types/istanbul-lib-instrument/1.7.4:
+ resolution: {integrity: sha512-1i1VVkU2KrpZCmti+t5J/zBb2KLKxHgU1EYL+0QtnDnVyZ59aSKcpnG6J0I6BZGDON566YzPNIlNfk7m+9l1JA==}
+ dependencies:
+ '@types/babel-types': 7.0.11
+ '@types/istanbul-lib-coverage': 2.0.4
+ source-map: 0.6.1
dev: true
/@types/istanbul-lib-report/3.0.0:
@@ -7201,6 +7226,13 @@ packages:
'@types/istanbul-lib-coverage': 2.0.4
dev: true
+ /@types/istanbul-lib-source-maps/4.0.1:
+ resolution: {integrity: sha512-WH6e5naLXI3vB2Px3whNeYxzDgm6S6sk3Ht8e3/BiWwEnzZi72wja3bWzWwcgbFTFp8hBLB7NT2p3lNJgxCxvA==}
+ dependencies:
+ '@types/istanbul-lib-coverage': 2.0.4
+ source-map: 0.6.1
+ dev: true
+
/@types/istanbul-reports/3.0.1:
resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==}
dependencies:
@@ -7293,6 +7325,10 @@ packages:
resolution: {integrity: sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w==}
dev: true
+ /@types/node/18.7.4:
+ resolution: {integrity: sha512-RzRcw8c0B8LzryWOR4Wj7YOTFXvdYKwvrb6xQQyuDfnlTxwYXGCV5RZ/TEbq5L5kn+w3rliHAUyRcG1RtbmTFg==}
+ dev: true
+
/@types/node/8.10.66:
resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==}
dev: true
@@ -8559,7 +8595,6 @@ packages:
/ansi-regex/5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
- dev: true
/ansi-regex/6.0.1:
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
@@ -8582,7 +8617,6 @@ packages:
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
- dev: true
/ansi-styles/5.2.0:
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
@@ -8610,6 +8644,10 @@ packages:
entities: 2.2.0
dev: true
+ /any-promise/1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+ dev: true
+
/anymatch/2.0.0:
resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==}
dependencies:
@@ -9369,7 +9407,6 @@ packages:
escalade: 3.1.1
node-releases: 2.0.3
picocolors: 1.0.0
- dev: true
/bser/2.1.1:
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
@@ -9432,6 +9469,16 @@ packages:
semver: 7.3.7
dev: true
+ /bundle-require/3.0.4_esbuild@0.14.47:
+ resolution: {integrity: sha512-VXG6epB1yrLAvWVQpl92qF347/UXmncQj7J3U8kZEbdVZ1ZkQyr4hYeL/9RvcE8vVVdp53dY78Fd/3pqfRqI1A==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ peerDependencies:
+ esbuild: '>=0.13'
+ dependencies:
+ esbuild: 0.14.47
+ load-tsconfig: 0.2.3
+ dev: true
+
/bytes/3.0.0:
resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==}
engines: {node: '>= 0.8'}
@@ -9472,13 +9519,12 @@ packages:
foreground-child: 2.0.0
istanbul-lib-coverage: 3.2.0
istanbul-lib-report: 3.0.0
- istanbul-reports: 3.1.4
+ istanbul-reports: 3.1.5
rimraf: 3.0.2
test-exclude: 6.0.0
v8-to-istanbul: 9.0.0
yargs: 16.2.0
yargs-parser: 20.2.9
- dev: true
/cac/6.7.12:
resolution: {integrity: sha512-rM7E2ygtMkJqD9c7WnFU6fruFcN3xe4FM5yUmgxhZzIKJk4uHl9U/fhwdajGFQbQuv43FAUo1Fe8gX/oIKDeSA==}
@@ -9903,7 +9949,6 @@ packages:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
- dev: true
/clone-deep/4.0.1:
resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
@@ -9959,14 +10004,12 @@ packages:
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
- dev: true
/color-name/1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
/color-name/1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- dev: true
/color-support/1.1.3:
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
@@ -10296,7 +10339,6 @@ packages:
path-key: 3.1.1
shebang-command: 2.0.0
which: 2.0.2
- dev: true
/crypto-browserify/3.12.0:
resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==}
@@ -11088,7 +11130,6 @@ packages:
/electron-to-chromium/1.4.118:
resolution: {integrity: sha512-maZIKjnYDvF7Fs35nvVcyr44UcKNwybr93Oba2n3HkKDFAtk0svERkLN/HyczJDS3Fo4wU9th9fUQd09ZLtj1w==}
- dev: true
/elliptic/6.5.4:
resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==}
@@ -11104,7 +11145,6 @@ packages:
/emoji-regex/8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
- dev: true
/emoji-regex/9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
@@ -11488,7 +11528,6 @@ packages:
/escalade/3.1.1:
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
engines: {node: '>=6'}
- dev: true
/escape-html/1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
@@ -12380,7 +12419,6 @@ packages:
dependencies:
locate-path: 6.0.0
path-exists: 4.0.0
- dev: true
/find-up/6.3.0:
resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
@@ -12443,7 +12481,6 @@ packages:
dependencies:
cross-spawn: 7.0.3
signal-exit: 3.0.7
- dev: true
/forever-agent/0.6.1:
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
@@ -12686,12 +12723,10 @@ packages:
/gensync/1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
- dev: true
/get-caller-file/2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
- dev: true
/get-func-name/2.0.0:
resolution: {integrity: sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=}
@@ -12835,6 +12870,17 @@ packages:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
dev: true
+ /glob/7.1.6:
+ resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
/glob/7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
dependencies:
@@ -12862,7 +12908,6 @@ packages:
/globals/11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
- dev: true
/globals/13.15.0:
resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==}
@@ -12997,7 +13042,6 @@ packages:
/has-flag/4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
- dev: true
/has-glob/1.0.0:
resolution: {integrity: sha512-D+8A457fBShSEI3tFCj65PAbT++5sKiFtdCdOam0gnfBgw9D277OERk+HM9qYJXmdVLZ/znez10SqHN0BBQ50g==}
@@ -13217,7 +13261,6 @@ packages:
/html-escaper/2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
- dev: true
/html-minifier-terser/5.1.1:
resolution: {integrity: sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==}
@@ -13732,7 +13775,6 @@ packages:
/is-fullwidth-code-point/3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
- dev: true
/is-fullwidth-code-point/4.0.0:
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
@@ -13998,7 +14040,6 @@ packages:
/isexe/2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
- dev: true
/isobject/2.1.0:
resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==}
@@ -14033,20 +14074,18 @@ packages:
/istanbul-lib-coverage/3.2.0:
resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==}
engines: {node: '>=8'}
- dev: true
/istanbul-lib-instrument/5.2.0:
resolution: {integrity: sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==}
engines: {node: '>=8'}
dependencies:
- '@babel/core': 7.18.9
- '@babel/parser': 7.18.9
+ '@babel/core': 7.18.10
+ '@babel/parser': 7.18.11
'@istanbuljs/schema': 0.1.3
istanbul-lib-coverage: 3.2.0
semver: 6.3.0
transitivePeerDependencies:
- supports-color
- dev: true
/istanbul-lib-report/3.0.0:
resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==}
@@ -14055,7 +14094,17 @@ packages:
istanbul-lib-coverage: 3.2.0
make-dir: 3.1.0
supports-color: 7.2.0
- dev: true
+
+ /istanbul-lib-source-maps/4.0.1:
+ resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==}
+ engines: {node: '>=10'}
+ dependencies:
+ debug: 4.3.4
+ istanbul-lib-coverage: 3.2.0
+ source-map: 0.6.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
/istanbul-reports/3.1.4:
resolution: {integrity: sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==}
@@ -14065,6 +14114,13 @@ packages:
istanbul-lib-report: 3.0.0
dev: true
+ /istanbul-reports/3.1.5:
+ resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==}
+ engines: {node: '>=8'}
+ dependencies:
+ html-escaper: 2.0.2
+ istanbul-lib-report: 3.0.0
+
/iterate-iterator/1.0.2:
resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==}
dev: true
@@ -14293,7 +14349,6 @@ packages:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'}
hasBin: true
- dev: true
/json-parse-better-errors/1.0.2:
resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
@@ -14333,7 +14388,6 @@ packages:
resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==}
engines: {node: '>=6'}
hasBin: true
- dev: true
/jsonc-eslint-parser/2.1.0:
resolution: {integrity: sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==}
@@ -14594,6 +14648,11 @@ packages:
strip-bom: 3.0.0
dev: true
+ /load-tsconfig/0.2.3:
+ resolution: {integrity: sha512-iyT2MXws+dc2Wi6o3grCFtGXpeMvHmJqS27sMPGtV2eUu4PeFnG+33I8BlFK1t1NWMjOpcx9bridn5yxLDX2gQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
/loader-runner/2.4.0:
resolution: {integrity: sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==}
engines: {node: '>=4.3.0 <5.0.0 || >=5.10'}
@@ -14654,7 +14713,6 @@ packages:
engines: {node: '>=10'}
dependencies:
p-locate: 5.0.0
- dev: true
/locate-path/7.1.0:
resolution: {integrity: sha512-HNx5uOnYeK4SxEoid5qnhRfprlJeGMzFRKPLCf/15N3/B4AiofNwC/yq7VBKdVk9dx7m+PiYCJOGg55JYTAqoQ==}
@@ -14811,7 +14869,6 @@ packages:
engines: {node: '>=8'}
dependencies:
semver: 6.3.0
- dev: true
/makeerror/1.0.12:
resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
@@ -15306,6 +15363,14 @@ packages:
resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==}
dev: true
+ /mz/2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+ dev: true
+
/nan/2.15.0:
resolution: {integrity: sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==}
requiresBuild: true
@@ -15484,7 +15549,6 @@ packages:
/node-releases/2.0.3:
resolution: {integrity: sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==}
- dev: true
/nopt/5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
@@ -15883,7 +15947,6 @@ packages:
engines: {node: '>=10'}
dependencies:
yocto-queue: 0.1.0
- dev: true
/p-limit/4.0.0:
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
@@ -15918,7 +15981,6 @@ packages:
engines: {node: '>=10'}
dependencies:
p-limit: 3.1.0
- dev: true
/p-locate/6.0.0:
resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==}
@@ -16105,7 +16167,6 @@ packages:
/path-exists/4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
- dev: true
/path-exists/5.0.0:
resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==}
@@ -16124,7 +16185,6 @@ packages:
/path-key/3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
- dev: true
/path-key/4.0.0:
resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
@@ -16358,6 +16418,22 @@ packages:
postcss: 7.0.39
dev: true
+ /postcss-load-config/3.1.4:
+ resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
+ engines: {node: '>= 10'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ dependencies:
+ lilconfig: 2.0.5
+ yaml: 1.10.2
+ dev: true
+
/postcss-loader/4.3.0_gzaxsinx64nntyd3vmdqwl7coe:
resolution: {integrity: sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==}
engines: {node: '>= 10.13.0'}
@@ -17462,7 +17538,6 @@ packages:
/require-directory/2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
- dev: true
/require-from-string/2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
@@ -17811,7 +17886,6 @@ packages:
/semver/6.3.0:
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
hasBin: true
- dev: true
/semver/7.0.0:
resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==}
@@ -17935,7 +18009,6 @@ packages:
engines: {node: '>=8'}
dependencies:
shebang-regex: 3.0.0
- dev: true
/shebang-regex/1.0.0:
resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==}
@@ -17945,7 +18018,6 @@ packages:
/shebang-regex/3.0.0:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
- dev: true
/shell-quote/1.7.3:
resolution: {integrity: sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==}
@@ -17973,7 +18045,6 @@ packages:
/signal-exit/3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
- dev: true
/simple-git-hooks/2.8.0:
resolution: {integrity: sha512-ocmZQORwa6x9mxg+gVIAp5o4wXiWOHGXyrDBA0+UxGKIEKOyFtL4LWNKkP/2ornQPdlnlDGDteVeYP5FjhIoWA==}
@@ -18354,7 +18425,6 @@ packages:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
- dev: true
/string-width/5.1.2:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
@@ -18454,7 +18524,6 @@ packages:
engines: {node: '>=8'}
dependencies:
ansi-regex: 5.0.1
- dev: true
/strip-ansi/7.0.1:
resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==}
@@ -18560,6 +18629,19 @@ packages:
resolution: {integrity: sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==}
dev: false
+ /sucrase/3.25.0:
+ resolution: {integrity: sha512-WxTtwEYXSmZArPGStGBicyRsg5TBEFhT5b7N+tF+zauImP0Acy+CoUK0/byJ8JNPK/5lbpWIVuFagI4+0l85QQ==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dependencies:
+ commander: 4.1.1
+ glob: 7.1.6
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.5
+ ts-interface-checker: 0.1.13
+ dev: true
+
/supports-color/2.0.0:
resolution: {integrity: sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=}
engines: {node: '>=0.8.0'}
@@ -18576,7 +18658,6 @@ packages:
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
- dev: true
/supports-color/8.1.1:
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
@@ -18798,7 +18879,6 @@ packages:
'@istanbuljs/schema': 0.1.3
glob: 7.2.3
minimatch: 3.1.2
- dev: true
/text-table/0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@@ -18821,6 +18901,19 @@ packages:
qs: 6.10.3
dev: true
+ /thenify-all/1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ thenify: 3.3.1
+ dev: true
+
+ /thenify/3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ dependencies:
+ any-promise: 1.3.0
+ dev: true
+
/throttleit/1.0.0:
resolution: {integrity: sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==}
dev: true
@@ -18958,6 +19051,11 @@ packages:
punycode: 2.1.1
dev: true
+ /tree-kill/1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+ dev: true
+
/trim-newlines/1.0.0:
resolution: {integrity: sha1-WIeWa7WCpFA6QetST301ARgVphM=}
engines: {node: '>=0.10.0'}
@@ -18986,6 +19084,10 @@ packages:
engines: {node: '>=14'}
dev: true
+ /ts-interface-checker/0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+ dev: true
+
/ts-invariant/0.10.3:
resolution: {integrity: sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==}
engines: {node: '>=8'}
@@ -19025,6 +19127,42 @@ packages:
/tslib/2.4.0:
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
+ /tsup/6.2.2_typescript@4.7.4:
+ resolution: {integrity: sha512-vJ9IAdif4GKAz2XMZzjX1hNqhBezJWXjm0qeQEoI7y//a64cxgCF8178eTMV4jBu7YNKnfAPpPSuyXW4mN+9rA==}
+ engines: {node: '>=14'}
+ hasBin: true
+ peerDependencies:
+ '@swc/core': ^1
+ postcss: ^8.4.12
+ typescript: ^4.1.0
+ peerDependenciesMeta:
+ '@swc/core':
+ optional: true
+ postcss:
+ optional: true
+ typescript:
+ optional: true
+ dependencies:
+ bundle-require: 3.0.4_esbuild@0.14.47
+ cac: 6.7.12
+ chokidar: 3.5.3
+ debug: 4.3.4
+ esbuild: 0.14.47
+ execa: 5.1.1
+ globby: 11.1.0
+ joycon: 3.1.1
+ postcss-load-config: 3.1.4
+ resolve-from: 5.0.0
+ rollup: 2.77.3
+ source-map: 0.8.0-beta.0
+ sucrase: 3.25.0
+ tree-kill: 1.2.2
+ typescript: 4.7.4
+ transitivePeerDependencies:
+ - supports-color
+ - ts-node
+ dev: true
+
/tsutils/3.21.0_typescript@4.7.4:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'}
@@ -19743,7 +19881,6 @@ packages:
'@jridgewell/trace-mapping': 0.3.13
'@types/istanbul-lib-coverage': 2.0.4
convert-source-map: 1.8.0
- dev: true
/validate-npm-package-license/3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
@@ -20281,7 +20418,6 @@ packages:
hasBin: true
dependencies:
isexe: 2.0.0
- dev: true
/wide-align/1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
@@ -20490,7 +20626,6 @@ packages:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
- dev: true
/wrap-ansi/8.0.1:
resolution: {integrity: sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==}
@@ -20579,7 +20714,6 @@ packages:
/y18n/5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
- dev: true
/yallist/2.1.2:
resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
@@ -20614,7 +20748,6 @@ packages:
/yargs-parser/20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
- dev: true
/yargs-parser/21.0.1:
resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==}
@@ -20632,7 +20765,6 @@ packages:
string-width: 4.2.3
y18n: 5.0.8
yargs-parser: 20.2.9
- dev: true
/yargs/17.4.1:
resolution: {integrity: sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==}
@@ -20657,7 +20789,6 @@ packages:
/yocto-queue/0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
- dev: true
/yocto-queue/1.0.0:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
diff --git a/test/core/vitest.config.ts b/test/core/vitest.config.ts
index abbb0fa1c..a0acc8939 100644
--- a/test/core/vitest.config.ts
+++ b/test/core/vitest.config.ts
@@ -43,6 +43,7 @@ export default defineConfig({
],
testNamePattern: '^((?!does not include test that).)*$',
coverage: {
+ provider: 'istanbul',
reporter: ['text', 'html'],
},
env: {
diff --git a/test/coverage-test/coverage-test/coverage.test.ts b/test/coverage-test/coverage-test/coverage.c8.test.ts
similarity index 90%
rename from test/coverage-test/coverage-test/coverage.test.ts
rename to test/coverage-test/coverage-test/coverage.c8.test.ts
index 1cf396507..75b544526 100644
--- a/test/coverage-test/coverage-test/coverage.test.ts
+++ b/test/coverage-test/coverage-test/coverage.c8.test.ts
@@ -2,7 +2,7 @@ import fs from 'fs'
import { resolve } from 'pathe'
import { expect, test } from 'vitest'
-test('coverage', async () => {
+test('coverage c8', async () => {
const coveragePath = resolve('./coverage/tmp/')
const stat = fs.statSync(coveragePath)
expect(stat.isDirectory()).toBe(true)
diff --git a/test/coverage-test/coverage-test/coverage.istanbul.test.ts b/test/coverage-test/coverage-test/coverage.istanbul.test.ts
new file mode 100644
index 000000000..c2188e16e
--- /dev/null
+++ b/test/coverage-test/coverage-test/coverage.istanbul.test.ts
@@ -0,0 +1,24 @@
+import fs from 'fs'
+import { resolve } from 'pathe'
+import { expect, test } from 'vitest'
+
+test('istanbul html report', async () => {
+ const coveragePath = resolve('./coverage')
+ const files = fs.readdirSync(coveragePath)
+
+ expect(files).toContain('index.html')
+ expect(files).toContain('index.ts.html')
+ expect(files).toContain('Hello.vue.html')
+})
+
+test('istanbul lcov report', async () => {
+ const coveragePath = resolve('./coverage')
+ const files = fs.readdirSync(coveragePath)
+
+ expect(files).toContain('lcov.info')
+
+ const lcovReport = resolve('./coverage/lcov-report')
+ const lcovReportFiles = fs.readdirSync(lcovReport)
+
+ expect(lcovReportFiles).toContain('index.html')
+})
diff --git a/test/coverage-test/package.json b/test/coverage-test/package.json
index a2f285024..5c5e123f7 100644
--- a/test/coverage-test/package.json
+++ b/test/coverage-test/package.json
@@ -2,12 +2,19 @@
"name": "@vitest/test-coverage",
"private": true,
"scripts": {
- "test": "npm run test:thread && npm run test:nothread",
- "coverage": "vitest run --coverage",
- "coverage:thread": "cross-env THREAD=true vitest run --coverage",
- "coverage-test": "vitest -c vitest.config-coverage.ts run",
- "test:thread": "npm run coverage:thread && npm run coverage-test",
- "test:nothread": "npm run coverage && npm run coverage-test"
+ "test": "npm run test:c8 && npm run test:istanbul",
+ "test:c8": "npm run test:thread:c8 && npm run test:nothread:c8",
+ "coverage:c8": "vitest run --coverage.provider c8",
+ "coverage:thread:c8": "cross-env THREAD=true vitest run --coverage.provider c8",
+ "coverage-test:c8": "vitest -c vitest.config-c8-coverage.ts run",
+ "test:thread:c8": "npm run coverage:thread:c8 && npm run coverage-test:c8",
+ "test:nothread:c8": "npm run coverage:c8 && npm run coverage-test:c8",
+ "test:istanbul": "npm run test:thread:istanbul && npm run test:nothread:istanbul",
+ "coverage:istanbul": "vitest run --coverage.provider istanbul",
+ "coverage:thread:istanbul": "cross-env THREAD=true vitest run --coverage.provider istanbul",
+ "coverage-test:istanbul": "vitest -c vitest.config-istanbul-coverage.ts run",
+ "test:thread:istanbul": "npm run coverage:thread:istanbul && npm run coverage-test:istanbul",
+ "test:nothread:istanbul": "npm run coverage:istanbul && npm run coverage-test:istanbul"
},
"devDependencies": {
"@vitejs/plugin-vue": "latest",
diff --git a/test/coverage-test/vitest.config-coverage.ts b/test/coverage-test/vitest.config-c8-coverage.ts
similarity index 73%
rename from test/coverage-test/vitest.config-coverage.ts
rename to test/coverage-test/vitest.config-c8-coverage.ts
index cf8df9d72..0e9e69239 100644
--- a/test/coverage-test/vitest.config-coverage.ts
+++ b/test/coverage-test/vitest.config-c8-coverage.ts
@@ -3,7 +3,7 @@ import { defineConfig } from 'vite'
export default defineConfig({
test: {
include: [
- './coverage-test/*.test.ts',
+ './coverage-test/*.c8.test.ts',
],
},
})
diff --git a/test/coverage-test/vitest.config-istanbul-coverage.ts b/test/coverage-test/vitest.config-istanbul-coverage.ts
new file mode 100644
index 000000000..620af8701
--- /dev/null
+++ b/test/coverage-test/vitest.config-istanbul-coverage.ts
@@ -0,0 +1,9 @@
+import { defineConfig } from 'vite'
+
+export default defineConfig({
+ test: {
+ include: [
+ './coverage-test/*.istanbul.test.ts',
+ ],
+ },
+})
diff --git a/test/coverage-test/vitest.config.ts b/test/coverage-test/vitest.config.ts
index 3944cd39f..3d4e9cf64 100644
--- a/test/coverage-test/vitest.config.ts
+++ b/test/coverage-test/vitest.config.ts
@@ -16,5 +16,10 @@ export default defineConfig({
exclude: [
'coverage-test/*.test.ts',
],
+ coverage: {
+ enabled: true,
+ clean: true,
+ reporter: ['html', 'text', 'lcov'],
+ },
},
})
diff --git a/tsconfig.json b/tsconfig.json
index d301f57e8..972ba657f 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -30,6 +30,7 @@
"vite-node/utils": ["./packages/vite-node/src/utils.ts"]
},
"types": [
+ "node",
"vite/client"
]
},