diff --git a/packages/coverage-istanbul/src/provider.ts b/packages/coverage-istanbul/src/provider.ts index dc731d784..6cc6ba50f 100644 --- a/packages/coverage-istanbul/src/provider.ts +++ b/packages/coverage-istanbul/src/provider.ts @@ -2,7 +2,7 @@ import type { CoverageMap } from 'istanbul-lib-coverage' import type { Instrumenter } from 'istanbul-lib-instrument' import type { ProxifiedModule } from 'magicast' import type { CoverageProvider, ReportContext, ResolvedCoverageOptions, Vite, Vitest } from 'vitest/node' -import { promises as fs } from 'node:fs' +import { existsSync, promises as fs } from 'node:fs' // @ts-expect-error missing types import { defaults as istanbulDefaults } from '@istanbuljs/schema' import createDebug from 'debug' @@ -15,7 +15,6 @@ import { parseModule } from 'magicast' import c from 'tinyrainbow' import { BaseCoverageProvider } from 'vitest/coverage' import { isCSSRequest } from 'vitest/node' - import { version } from '../package.json' with { type: 'json' } import { COVERAGE_STORE_KEY } from './constants' @@ -118,9 +117,15 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider this.isIncluded(filename)) - } + coverageMap.filter((filename) => { + const exists = existsSync(filename) + + if (this.options.excludeAfterRemap) { + return exists && this.isIncluded(filename) + } + + return exists + }) if (debug.enabled) { debug('Generate coverage total time %d ms', (performance.now() - start!).toFixed()) diff --git a/packages/coverage-v8/src/provider.ts b/packages/coverage-v8/src/provider.ts index 71a88ae40..3d6dd02b6 100644 --- a/packages/coverage-v8/src/provider.ts +++ b/packages/coverage-v8/src/provider.ts @@ -2,7 +2,7 @@ import type { CoverageMap } from 'istanbul-lib-coverage' import type { ProxifiedModule } from 'magicast' import type { Profiler } from 'node:inspector' import type { CoverageProvider, ReportContext, ResolvedCoverageOptions, TestProject, Vite, Vitest } from 'vitest/node' -import { promises as fs } from 'node:fs' +import { existsSync, promises as fs } from 'node:fs' import { fileURLToPath } from 'node:url' // @ts-expect-error -- untyped import { mergeProcessCovs } from '@bcoe/v8-coverage' @@ -86,9 +86,15 @@ export class V8CoverageProvider extends BaseCoverageProvider this.isIncluded(filename)) - } + coverageMap.filter((filename) => { + const exists = existsSync(filename) + + if (this.options.excludeAfterRemap) { + return exists && this.isIncluded(filename) + } + + return exists + }) if (debug.enabled) { debug(`Generate coverage total time ${(performance.now() - start!).toFixed()} ms`) diff --git a/packages/vitest/src/node/coverage.ts b/packages/vitest/src/node/coverage.ts index 6f492177e..7b501bc01 100644 --- a/packages/vitest/src/node/coverage.ts +++ b/packages/vitest/src/node/coverage.ts @@ -6,7 +6,7 @@ import type { SerializedCoverageConfig } from '../runtime/config' import type { AfterSuiteRunMeta } from '../types/general' import { existsSync, promises as fs, readdirSync, writeFileSync } from 'node:fs' import path from 'node:path' -import { cleanUrl, slash } from '@vitest/utils/helpers' +import { slash } from '@vitest/utils/helpers' import { relative, resolve } from 'pathe' import pm from 'picomatch' import { glob } from 'tinyglobby' @@ -161,19 +161,12 @@ export class BaseCoverageProvider { - const options: pm.PicomatchOptions = { - contains: true, - dot: true, - cwd: root, - ignore: this.options.exclude, - } - - return pm.isMatch(filename, glob, options) + const included = pm.isMatch(filename, glob, { + contains: true, + dot: true, + ignore: this.options.exclude, }) - included &&= existsSync(cleanUrl(filename)) - this.globCache.set(filename, included) return included diff --git a/test/coverage-test/fixtures/configs/vitest.config.virtual-files.ts b/test/coverage-test/fixtures/configs/vitest.config.virtual-files.ts index f2849dc5b..27e553564 100644 --- a/test/coverage-test/fixtures/configs/vitest.config.virtual-files.ts +++ b/test/coverage-test/fixtures/configs/vitest.config.virtual-files.ts @@ -1,4 +1,7 @@ +import { readFileSync } from 'node:fs' +import { resolve } from 'node:path' import { Plugin, defineConfig, mergeConfig } from 'vitest/config' +import { transformWithEsbuild } from 'vite' import base from './vitest.config' @@ -22,6 +25,10 @@ function VirtualFilesPlugin(): Plugin { if (id === '\0vitest-custom-virtual-file-2') { return 'src/\0vitest-custom-virtual-file-2.ts' } + + if (id.includes('vitest-custom-virtual:math')) { + return resolve(import.meta.dirname, "../src/vitest-custom-virtual:math") + } }, load(id) { if (id === 'src/virtual:vitest-custom-virtual-file-1.ts') { @@ -38,6 +45,13 @@ function VirtualFilesPlugin(): Plugin { export default virtualFile; ` } + + if(id.includes("vitest-custom-virtual:math")) { + const filename = resolve(import.meta.dirname, "../src/math.ts"); + const sources = readFileSync(filename, "utf8") + + return transformWithEsbuild(sources, filename) + } }, } -} \ No newline at end of file +} diff --git a/test/coverage-test/fixtures/src/virtual-files.ts b/test/coverage-test/fixtures/src/virtual-files.ts index 3d8201be7..32d4e3324 100644 --- a/test/coverage-test/fixtures/src/virtual-files.ts +++ b/test/coverage-test/fixtures/src/virtual-files.ts @@ -1,10 +1,12 @@ // @ts-expect-error -- untyped virtual file provided by custom plugin import virtualFile1 from 'virtual:vitest-custom-virtual-file-1' - // @ts-expect-error -- untyped virtual file provided by custom plugin import virtualFile2 from '\0vitest-custom-virtual-file-2' +// @ts-expect-error -- untyped virtual file provided by custom plugin +import * as virtualMath from 'vitest-custom-virtual:math' + export function getVirtualFileImports() { - return { virtualFile1, virtualFile2 } + return { virtualFile1, virtualFile2, virtualMath } } diff --git a/test/coverage-test/fixtures/test/virtual-files-fixture.test.ts b/test/coverage-test/fixtures/test/virtual-files-fixture.test.ts index 97df806dc..cfe932eef 100644 --- a/test/coverage-test/fixtures/test/virtual-files-fixture.test.ts +++ b/test/coverage-test/fixtures/test/virtual-files-fixture.test.ts @@ -2,9 +2,11 @@ import { expect, test } from 'vitest' import { getVirtualFileImports} from '../src/virtual-files' test("verify virtual files work", () => { - const {virtualFile1, virtualFile2} = getVirtualFileImports() + const {virtualFile1, virtualFile2, virtualMath} = getVirtualFileImports() expect(virtualFile1).toBe('This file should be excluded from coverage report #1') expect(virtualFile2).toBe('This file should be excluded from coverage report #2') -}) \ No newline at end of file + expect(virtualMath).toHaveProperty('sum') + expect(virtualMath.sum(50, 65)).toBe(115) +}) diff --git a/test/coverage-test/test/virtual-files.test.ts b/test/coverage-test/test/virtual-files.test.ts index 174a5ce6b..4e229d0bf 100644 --- a/test/coverage-test/test/virtual-files.test.ts +++ b/test/coverage-test/test/virtual-files.test.ts @@ -26,4 +26,16 @@ test('virtual files should be excluded', async () => { // Vitest browser expect(file).not.toContain('\x00') } + + expect(files).toContain('/fixtures/src/math.ts') + + const fileCoverage = coverageMap.fileCoverageFor('/fixtures/src/math.ts') + expect(fileCoverage).toMatchInlineSnapshot(` + { + "branches": "0/0 (100%)", + "functions": "1/4 (25%)", + "lines": "1/4 (25%)", + "statements": "1/4 (25%)", + } + `) })