Skip to content

Commit

Permalink
feat(coverage): glob based coverage thresholds
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio committed Nov 5, 2023
1 parent 7f50229 commit e96b8a3
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 126 deletions.
77 changes: 44 additions & 33 deletions packages/coverage-istanbul/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co
provider: 'istanbul',
reportsDirectory: resolve(ctx.config.root, config.reportsDirectory || coverageConfigDefaults.reportsDirectory),
reporter: this.resolveReporters(config.reporter || coverageConfigDefaults.reporter),
lines: config['100'] ? 100 : config.lines,
functions: config['100'] ? 100 : config.functions,
branches: config['100'] ? 100 : config.branches,
statements: config['100'] ? 100 : config.statements,
}

this.instrumenter = createInstrumenter({
Expand Down Expand Up @@ -170,35 +166,8 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co
}).execute(context)
}

if (this.options.branches
|| this.options.functions
|| this.options.lines
|| this.options.statements) {
this.checkThresholds({
coverageMap,
thresholds: {
branches: this.options.branches,
functions: this.options.functions,
lines: this.options.lines,
statements: this.options.statements,
},
perFile: this.options.perFile,
})
}

if (this.options.thresholdAutoUpdate && allTestsRun) {
this.updateThresholds({
coverageMap,
thresholds: {
branches: this.options.branches,
functions: this.options.functions,
lines: this.options.lines,
statements: this.options.statements,
},
perFile: this.options.perFile,
configurationFile: this.ctx.server.config.configFile,
})
}
if (this.options.thresholds)
await this.handleThresholds({ coverageMap, allTestsRun, thresholds: this.options.thresholds })
}

async getCoverageMapForUncoveredFiles(coveredFiles: string[]) {
Expand Down Expand Up @@ -234,6 +203,48 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co

return coverageMap.data
}

async handleThresholds(options: { coverageMap: CoverageMap; allTestsRun?: boolean; thresholds: NonNullable<Options['thresholds']> }) {
const resolvedThresholds = this.resolveThresholds({
coverageMap: options.coverageMap,
thresholds: options.thresholds,
createCoverageMap: () => libCoverage.createCoverageMap({}),
})

for (const { thresholds, coverageMap, name } of resolvedThresholds) {
if (thresholds.branches
|| thresholds.functions
|| thresholds.lines
|| thresholds.statements) {
this.checkThresholds({
name,
coverageMap,
perFile: this.options.thresholds?.perFile,
thresholds: {
branches: thresholds.branches,
functions: thresholds.functions,
lines: thresholds.lines,
statements: thresholds.statements,
},
})
}

if (this.options.thresholds?.autoUpdate && options.allTestsRun) {
this.updateThresholds({
name,
coverageMap,
perFile: this.options.thresholds?.perFile,
thresholds: {
branches: thresholds?.branches,
functions: thresholds?.functions,
lines: thresholds?.lines,
statements: thresholds?.statements,
},
configurationFile: this.ctx.server.config.configFile,
})
}
}
}
}

async function mergeAndTransformCoverage(coverages: CoverageMapData[]) {
Expand Down
77 changes: 44 additions & 33 deletions packages/coverage-v8/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
provider: 'v8',
reporter: this.resolveReporters(config.reporter || coverageConfigDefaults.reporter),
reportsDirectory: resolve(ctx.config.root, config.reportsDirectory || coverageConfigDefaults.reportsDirectory),
lines: config['100'] ? 100 : config.lines,
functions: config['100'] ? 100 : config.functions,
branches: config['100'] ? 100 : config.branches,
statements: config['100'] ? 100 : config.statements,
}

this.testExclude = new _TestExclude({
Expand Down Expand Up @@ -156,35 +152,8 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
}).execute(context)
}

if (this.options.branches
|| this.options.functions
|| this.options.lines
|| this.options.statements) {
this.checkThresholds({
coverageMap,
thresholds: {
branches: this.options.branches,
functions: this.options.functions,
lines: this.options.lines,
statements: this.options.statements,
},
perFile: this.options.perFile,
})
}

if (this.options.thresholdAutoUpdate && allTestsRun) {
this.updateThresholds({
coverageMap,
thresholds: {
branches: this.options.branches,
functions: this.options.functions,
lines: this.options.lines,
statements: this.options.statements,
},
perFile: this.options.perFile,
configurationFile: this.ctx.server.config.configFile,
})
}
if (this.options.thresholds)
await this.handleThresholds({ coverageMap, allTestsRun, thresholds: this.options.thresholds })
}

private async getUntestedFiles(testedFiles: string[]): Promise<Profiler.ScriptCoverage[]> {
Expand Down Expand Up @@ -278,6 +247,48 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
const sourceMapStore = libSourceMaps.createSourceMapStore()
return sourceMapStore.transformCoverage(mergedCoverage)
}

async handleThresholds(options: { coverageMap: CoverageMap; allTestsRun?: boolean; thresholds: NonNullable<Options['thresholds']> }) {
const resolvedThresholds = this.resolveThresholds({
coverageMap: options.coverageMap,
thresholds: options.thresholds,
createCoverageMap: () => libCoverage.createCoverageMap({}),
})

for (const { thresholds, coverageMap, name } of resolvedThresholds) {
if (thresholds.branches
|| thresholds.functions
|| thresholds.lines
|| thresholds.statements) {
this.checkThresholds({
name,
coverageMap,
perFile: options.thresholds.perFile,
thresholds: {
branches: thresholds.branches,
functions: thresholds.functions,
lines: thresholds.lines,
statements: thresholds.statements,
},
})
}

if (this.options.thresholds?.autoUpdate && options.allTestsRun) {
this.updateThresholds({
name,
coverageMap,
perFile: options.thresholds.perFile,
thresholds: {
branches: thresholds?.branches,
functions: thresholds?.functions,
lines: thresholds?.lines,
statements: thresholds?.statements,
},
configurationFile: this.ctx.server.config.configFile,
})
}
}
}
}

function mergeCoverageMaps(...coverageMaps: (CoverageMap | CoverageMapData)[]) {
Expand Down
94 changes: 51 additions & 43 deletions packages/vitest/src/types/coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,40 +157,62 @@ export interface BaseCoverageOptions {
skipFull?: boolean

/**
* Check thresholds per file.
* See `lines`, `functions`, `branches` and `statements` for the actual thresholds.
* Threshold for statements, lines, branches and functions
*
* @default false
*/
perFile?: boolean

/**
* Threshold for lines
* Default value is `undefined` for each property.
*
* @default undefined
*/
lines?: number

/**
* Threshold for functions
* @example
*
* @default undefined
*/
functions?: number

/**
* Threshold for branches
* ```ts
* {
* // Thresholds for all files
* functions: 95,
* branches: 70,
*
* @default undefined
* // Thresholds for utilities
* 'src/utils/**.ts': {
* lines: 100,
* statements: 95,
* }
* }
* ```
*/
branches?: number

/**
* Threshold for statements
*
* @default undefined
*/
statements?: number
thresholds?: {
/** Set global thresholds to `100` */
100?: boolean

/** Check thresholds per file. */
perFile?: boolean

/**
* Update threshold values automatically when current coverage is higher than earlier thresholds
*
* @default false
*/
autoUpdate?: boolean

statements?: number
functions?: number
branches?: number
lines?: number

/**
* Thresholds for files matching the glob pattern
*
* @example
*
* ```ts
* {
* 'src/utils/**.ts': {
* statements: 80,
* functions: 95,
* branches: 100,
* lines: 50,
* }
* ```
*/
[glob: string]: unknown
}

/**
* Watermarks for statements, lines, branches and functions.
Expand All @@ -204,13 +226,6 @@ export interface BaseCoverageOptions {
lines?: [number, number]
}

/**
* Update threshold values automatically when current coverage is higher than earlier thresholds
*
* @default false
*/
thresholdAutoUpdate?: boolean

/**
* Generate coverage report even when tests fail.
*
Expand All @@ -224,13 +239,6 @@ export interface BaseCoverageOptions {
* @default false
*/
allowExternal?: boolean

/**
* Shortcut for `{ lines: 100, functions: 100, branches: 100, statements: 100 }`
*
* @default false
*/
100?: boolean
}

export interface CoverageIstanbulOptions extends BaseCoverageOptions {
Expand Down
Loading

0 comments on commit e96b8a3

Please sign in to comment.