Skip to content

Commit 04f8185

Browse files
authored
feat(coverage): thresholds.autoUpdate to receive previous threshold as argument (#10495)
1 parent e30dd9c commit 04f8185

4 files changed

Lines changed: 29 additions & 7 deletions

File tree

‎docs/config/coverage.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ Check thresholds per file.
250250
Update all threshold values `lines`, `functions`, `branches` and `statements` to configuration file when current coverage is better than the configured thresholds.
251251
This option helps to maintain thresholds when coverage is improved.
252252

253-
You can also pass a function for formatting the updated threshold values:
253+
You can also pass a function for formatting the updated threshold values. The function receives the new threshold as the first argument and the previous threshold as the second:
254254

255255
<!-- eslint-skip -->
256256
```ts
@@ -260,6 +260,12 @@ You can also pass a function for formatting the updated threshold values:
260260
// Update thresholds without decimals
261261
autoUpdate: (newThreshold) => Math.floor(newThreshold),
262262

263+
// Log the change and update without decimals
264+
autoUpdate: (newThreshold, previousThreshold) => {
265+
console.log(`Updated threshold from ${previousThreshold} to ${newThreshold}`)
266+
return Math.floor(newThreshold)
267+
},
268+
263269
// 95.85 -> 95
264270
functions: 95,
265271
}

‎packages/vitest/src/node/coverage.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ export class BaseCoverageProvider {
596596
)
597597
: [coverageMap.getCoverageSummary()]
598598

599-
const thresholdsToUpdate: [Threshold, number][] = []
599+
const thresholdsToUpdate: [Threshold, number, number][] = []
600600

601601
for (const key of THRESHOLD_KEYS) {
602602
const threshold = thresholds[key] ?? 100
@@ -610,7 +610,7 @@ export class BaseCoverageProvider {
610610
)
611611

612612
if (actual > threshold) {
613-
thresholdsToUpdate.push([key, actual])
613+
thresholdsToUpdate.push([key, actual, threshold])
614614
}
615615
}
616616
else {
@@ -622,7 +622,7 @@ export class BaseCoverageProvider {
622622
if (actual < absoluteThreshold) {
623623
// If everything was covered, set new threshold to 100% (since a threshold of 0 would be considered as 0%)
624624
const updatedThreshold = actual === 0 ? 100 : actual * -1
625-
thresholdsToUpdate.push([key, updatedThreshold])
625+
thresholdsToUpdate.push([key, updatedThreshold, threshold])
626626
}
627627
}
628628
}
@@ -635,8 +635,8 @@ export class BaseCoverageProvider {
635635

636636
const thresholdFormatter = typeof this.options.thresholds?.autoUpdate === 'function' ? this.options.thresholds?.autoUpdate : (value: number) => value
637637

638-
for (const [threshold, newValue] of thresholdsToUpdate) {
639-
const formattedValue = thresholdFormatter(newValue)
638+
for (const [threshold, newValue, previousValue] of thresholdsToUpdate) {
639+
const formattedValue = thresholdFormatter(newValue, previousValue)
640640
if (name === GLOBAL_THRESHOLDS_KEY) {
641641
config.test.coverage.thresholds[threshold] = formattedValue
642642
}

‎packages/vitest/src/node/types/coverage.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ interface Thresholds {
340340
*
341341
* @default false
342342
*/
343-
autoUpdate?: boolean | ((newThreshold: number) => number)
343+
autoUpdate?: boolean | ((newThreshold: number, previousThreshold: number) => number)
344344

345345
/** Thresholds for statements */
346346
statements?: number

‎test/coverage-test/test/threshold-auto-update.unit.test.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,22 @@ test('formats values with custom formatter', async () => {
156156
expect(calls.sort()).toEqual([50, 60, 70, 80])
157157
})
158158

159+
test('passes previous threshold as second argument to custom formatter', async () => {
160+
const config = parseModule(`export default ${initialConfig}`)
161+
162+
const autoUpdate = vi.fn().mockImplementation(value => value)
163+
await updateThresholds(config, { thresholds: { autoUpdate } })
164+
165+
const previousValues = autoUpdate.mock.calls.map(call => [call[0], call[1]])
166+
167+
expect(previousValues.sort((a, b) => a[0] - b[0])).toEqual([
168+
[coveredThresholds.lines, initialThresholds.lines],
169+
[coveredThresholds.branches, initialThresholds.branches],
170+
[coveredThresholds.functions, initialThresholds.functions],
171+
[coveredThresholds.statements, initialThresholds.statements],
172+
].sort((a, b) => a[0] - b[0]))
173+
})
174+
159175
async function updateThresholds(configurationFile: ReturnType<typeof parseModule>, _coverageOptions: Partial<(InstanceType<typeof BaseCoverageProvider>)['options']> = {}) {
160176
const summaryData = { total: 0, covered: 0, skipped: 0 }
161177
const thresholds = [{

0 commit comments

Comments
 (0)