[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

feat(coverage): add `allowExternal` option (#3894)

Co-authored-by: Ari Perkkiö <ari.perkkio@gmail.com>

authored by

Stefan Vojvodic
Ari Perkkiö
and committed by
GitHub
(Aug 21, 2023, 6:34 PM +0200) c03faa22 5704b341

+134 -2
+9
docs/config/index.md
··· 985 985 986 986 Generate coverage report even when tests fail. 987 987 988 + #### coverage.allowExternal 989 + 990 + - **Type:** `boolean` 991 + - **Default:** `false` 992 + - **Available for providers:** `'v8' | 'istanbul'` 993 + - **CLI:** `--coverage.allowExternal`, `--coverage.allowExternal=false` 994 + 995 + Collect coverage of files outside the [project `root`](https://vitest.dev/config/#root). 996 + 988 997 #### coverage.skipFull 989 998 990 999 - **Type:** `boolean`
+2 -1
test/coverage-test/package.json
··· 2 2 "name": "@vitest/test-coverage", 3 3 "private": true, 4 4 "scripts": { 5 - "test": "pnpm test:v8 && pnpm test:istanbul && pnpm test:custom && pnpm test:browser && pnpm test:types", 5 + "test": "pnpm test:v8 && pnpm test:istanbul && pnpm test:custom && pnpm test:browser && pnpm test:options && pnpm test:types", 6 6 "test:v8": "node ./testing.mjs --provider v8", 7 7 "test:custom": "node ./testing.mjs --provider custom", 8 8 "test:istanbul": "node ./testing.mjs --provider istanbul", 9 9 "test:browser": "node ./testing.mjs --browser --provider istanbul", 10 + "test:options": "node ./testing-options.mjs", 10 11 "test:types": "vitest typecheck --run --reporter verbose" 11 12 }, 12 13 "devDependencies": {
+69
test/coverage-test/testing-options.mjs
··· 1 + import { startVitest } from 'vitest/node' 2 + 3 + /** @type {Record<string, Partial<import('vitest/config').UserConfig['test']>>[]} */ 4 + const testCases = [ 5 + { 6 + testConfig: { 7 + name: 'allowExternal: true', 8 + include: ['option-tests/allow-external.test.ts'], 9 + coverage: { 10 + allowExternal: true, 11 + include: ['**/src/**', '**/test-utils/fixtures/**'], 12 + reporter: 'html', 13 + }, 14 + }, 15 + assertionConfig: { 16 + include: ['coverage-report-tests/allow-external.test.ts'], 17 + env: { VITE_COVERAGE_ALLOW_EXTERNAL: true }, 18 + }, 19 + }, 20 + { 21 + testConfig: { 22 + name: 'allowExternal: false', 23 + include: ['option-tests/allow-external.test.ts'], 24 + coverage: { 25 + allowExternal: false, 26 + include: ['**/src/**', '**/test-utils/fixtures/**'], 27 + reporter: 'html', 28 + }, 29 + }, 30 + assertionConfig: { 31 + include: ['coverage-report-tests/allow-external.test.ts'], 32 + }, 33 + }, 34 + ] 35 + 36 + for (const provider of ['v8', 'istanbul']) { 37 + for (const { testConfig, assertionConfig } of testCases) { 38 + // Run test case 39 + await startVitest('test', ['option-tests/'], { 40 + config: false, 41 + watch: false, 42 + ...testConfig, 43 + name: `${provider} - ${testConfig.name}`, 44 + coverage: { 45 + enabled: true, 46 + clean: true, 47 + provider, 48 + ...testConfig.coverage, 49 + }, 50 + }) 51 + 52 + checkExit() 53 + 54 + // Check generated coverage report 55 + await startVitest('test', ['coverage-report-tests'], { 56 + config: false, 57 + watch: false, 58 + ...assertionConfig, 59 + name: `${provider} - assert ${testConfig.name}`, 60 + }) 61 + 62 + checkExit() 63 + } 64 + } 65 + 66 + function checkExit() { 67 + if (process.exitCode) 68 + process.exit(process.exitCode) 69 + }
+2
packages/coverage-istanbul/src/provider.ts
··· 23 23 exclude?: string | string[] 24 24 extension?: string | string[] 25 25 excludeNodeModules?: boolean 26 + relativePath?: boolean 26 27 }): { 27 28 shouldInstrument(filePath: string): boolean 28 29 glob(cwd: string): Promise<string[]> ··· 79 80 exclude: [...defaultExclude, ...defaultInclude, ...this.options.exclude], 80 81 excludeNodeModules: true, 81 82 extension: this.options.extension, 83 + relativePath: !this.options.allowExternal, 82 84 }) 83 85 } 84 86
+2
packages/coverage-v8/src/provider.ts
··· 30 30 exclude?: string | string[] 31 31 extension?: string | string[] 32 32 excludeNodeModules?: boolean 33 + relativePath?: boolean 33 34 }): { 34 35 shouldInstrument(filePath: string): boolean 35 36 glob(cwd: string): Promise<string[]> ··· 79 80 exclude: [...defaultExclude, ...defaultInclude, ...this.options.exclude], 80 81 excludeNodeModules: true, 81 82 extension: this.options.extension, 83 + relativePath: !this.options.allowExternal, 82 84 }) 83 85 } 84 86
+1
packages/vitest/src/defaults.ts
··· 39 39 reportOnFailure: false, 40 40 reporter: [['text', {}], ['html', {}], ['clover', {}], ['json', {}]], 41 41 extension: ['.js', '.cjs', '.mjs', '.ts', '.mts', '.cts', '.tsx', '.jsx', '.vue', '.svelte'], 42 + allowExternal: false, 42 43 } 43 44 44 45 export const fakeTimersDefaults = {
+20
test/coverage-test/coverage-report-tests/allow-external.test.ts
··· 1 + import fs from 'node:fs' 2 + import { expect, test } from 'vitest' 3 + 4 + const allowExternal = import.meta.env.VITE_COVERAGE_ALLOW_EXTERNAL 5 + 6 + test.skipIf(!allowExternal)('{ allowExternal: true } includes files outside project root', async () => { 7 + expect(fs.existsSync('./coverage/test-utils/fixtures/math.ts.html')).toBe(true) 8 + 9 + // Files inside project root should always be included 10 + expect(fs.existsSync('./coverage/coverage-test/src/utils.ts.html')).toBe(true) 11 + }) 12 + 13 + test.skipIf(allowExternal)('{ allowExternal: false } excludes files outside project root', async () => { 14 + expect(fs.existsSync('./coverage/test-utils/fixtures/math.ts.html')).toBe(false) 15 + expect(fs.existsSync('./test-utils/fixtures/math.ts.html')).toBe(false) 16 + expect(fs.existsSync('./fixtures/math.ts.html')).toBe(false) 17 + 18 + // Files inside project root should always be included 19 + expect(fs.existsSync('./coverage/utils.ts.html')).toBe(true) 20 + })
+12
test/coverage-test/option-tests/allow-external.test.ts
··· 1 + import { expect, test } from 'vitest' 2 + 3 + import { multiply } from '../src/utils' 4 + import * as ExternalMath from '../../test-utils/fixtures/math' 5 + 6 + test('calling files outside project root', () => { 7 + expect(ExternalMath.sum(2, 3)).toBe(5) 8 + }) 9 + 10 + test('multiply - add some files to report', () => { 11 + expect(multiply(2, 3)).toBe(6) 12 + })
+1
test/coverage-test/test/configuration-options.test-d.ts
··· 103 103 reporter: [['html', {}], ['json', { file: 'string' }]], 104 104 reportsDirectory: 'string', 105 105 reportOnFailure: true, 106 + allowExternal: true, 106 107 } 107 108 }, 108 109 clean(_: boolean) {},
+7
test/test-utils/fixtures/math.ts
··· 1 + export function sum(a: number, b: number) { 2 + return a + b 3 + } 4 + 5 + export function multiply(a: number, b: number) { 6 + return a * b 7 + }
+1 -1
packages/vitest/src/node/config.ts
··· 279 279 ?? resolve(resolved.root, file), 280 280 ), 281 281 ) 282 - resolved.coverage.exclude.push(...resolved.setupFiles.map(file => relative(resolved.root, file))) 282 + resolved.coverage.exclude.push(...resolved.setupFiles.map(file => `${resolved.coverage.allowExternal ? '**/' : ''}${relative(resolved.root, file)}`)) 283 283 284 284 resolved.forceRerunTriggers = [ 285 285 ...resolved.forceRerunTriggers,
+8
packages/vitest/src/types/coverage.ts
··· 78 78 | 'exclude' 79 79 | 'extension' 80 80 | 'reportOnFailure' 81 + | 'allowExternal' 81 82 82 83 export type ResolvedCoverageOptions<T extends Provider = Provider> = 83 84 & CoverageOptions<T> ··· 216 217 * @default false 217 218 */ 218 219 reportOnFailure?: boolean 220 + 221 + /** 222 + * Collect coverage of files outside the project `root`. 223 + * 224 + * @default false 225 + */ 226 + allowExternal?: boolean 219 227 } 220 228 221 229 export interface CoverageIstanbulOptions extends BaseCoverageOptions {