Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,18 @@ Generate coverage report even when tests fail.

Collect coverage of files outside the [project `root`](#root).

#### coverage.excludeAfterRemap <Version>2.1.0</Version> {#coverage-exclude-after-remap}

- **Type:** `boolean`
- **Default:** `false`
- **Available for providers:** `'v8' | 'istanbul'`
- **CLI:** `--coverage.excludeAfterRemap`, `--coverage.excludeAfterRemap=false`

Apply exclusions again after coverage has been remapped to original sources.
This is useful when your source files are transpiled and may contain source maps of non-source files.

Use this option when you are seeing files that show up in report even if they match your `coverage.exclude` patterns.

#### coverage.skipFull

- **Type:** `boolean`
Expand Down
8 changes: 5 additions & 3 deletions packages/coverage-istanbul/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,7 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co
lines: config.thresholds['100'] ? 100 : config.thresholds.lines,
branches: config.thresholds['100'] ? 100 : config.thresholds.branches,
functions: config.thresholds['100'] ? 100 : config.thresholds.functions,
statements: config.thresholds['100']
? 100
: config.thresholds.statements,
statements: config.thresholds['100'] ? 100 : config.thresholds.statements,
},
}

Expand Down Expand Up @@ -291,6 +289,10 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co
coverageMap.merge(await transformCoverage(uncoveredCoverage))
}

if (this.options.excludeAfterRemap) {
coverageMap.filter(filename => this.testExclude.shouldInstrument(filename))
}

return coverageMap
}

Expand Down
4 changes: 4 additions & 0 deletions packages/coverage-v8/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
coverageMap.merge(await transformCoverage(converted))
}

if (this.options.excludeAfterRemap) {
coverageMap.filter(filename => this.testExclude.shouldInstrument(filename))
}

return coverageMap
}

Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const coverageConfigDefaults: ResolvedCoverageOptions = {
'.marko',
],
allowExternal: false,
excludeAfterRemap: false,
ignoreEmptyLines: true,
processingConcurrency: Math.min(
20,
Expand Down
12 changes: 12 additions & 0 deletions packages/vitest/src/node/types/coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,18 @@ export interface BaseCoverageOptions {
*/
allowExternal?: boolean

/**
* Apply exclusions again after coverage has been remapped to original sources.
* This is useful when your source files are transpiled and may contain source maps
* of non-source files.
*
* Use this option when you are seeing files that show up in report even if they
* match your `coverage.exclude` patterns.
*
* @default false
*/
excludeAfterRemap?: boolean

/**
* Concurrency limit used when processing the coverage results.
* Defaults to `Math.min(20, os.availableParallelism?.() ?? os.cpus().length)`
Expand Down
71 changes: 71 additions & 0 deletions test/coverage-test/test/exclude-after-remap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { expect } from 'vitest'
import { coverageTest, normalizeURL, readCoverageMap, runVitest, test } from '../utils.js'
import * as transpiled from '../fixtures/src/pre-bundle/bundle.js'

test('{ excludeAfterRemap: true } should exclude files that come up after remapping', async () => {
await runVitest({
include: [normalizeURL(import.meta.url)],
coverage: {
include: ['fixtures/src/**'],
exclude: ['fixtures/src/pre-bundle/second.ts'],
excludeAfterRemap: true,
reporter: 'json',
all: false,
},
})

const coverageMap = await readCoverageMap()
const files = coverageMap.files()

expect(files).toMatchInlineSnapshot(`
[
"<process-cwd>/fixtures/src/pre-bundle/first.ts",
]
`)
})

test('{ excludeAfterRemap: false } should not exclude files that come up after remapping', async () => {
await runVitest({
include: [normalizeURL(import.meta.url)],
coverage: {
include: ['fixtures/src/**'],
exclude: ['fixtures/src/pre-bundle/second.ts'],
reporter: 'json',
all: false,
},
})

const coverageMap = await readCoverageMap()
const files = coverageMap.files()

expect(files).toMatchInlineSnapshot(`
[
"<process-cwd>/fixtures/src/pre-bundle/first.ts",
"<process-cwd>/fixtures/src/pre-bundle/second.ts",
]
`)
})

test('{ excludeAfterRemap: true } should exclude uncovered files that come up after remapping', async () => {
await runVitest({
include: ['fixtures/test/math.test.ts'],
coverage: {
include: ['fixtures/src/pre-bundle/**'],
exclude: ['fixtures/src/pre-bundle/second.ts'],
excludeAfterRemap: true,
reporter: 'json',
all: true,
},
})

const coverageMap = await readCoverageMap()
const files = coverageMap.files()

expect(files).contains('<process-cwd>/fixtures/src/pre-bundle/first.ts')
expect(files).not.contains('<process-cwd>/fixtures/src/pre-bundle/second.ts')
})

coverageTest('run bundled sources', () => {
expect(transpiled.first.covered()).toBe('First')
expect(transpiled.second.covered()).toBe('Second')
})