Skip to content

Commit 4b41131

Browse files
authored
fix(coverage): thresholds.autoUpdate to work with arrow function configuration files (#4959)
1 parent 3e6668e commit 4b41131

File tree

8 files changed

+109
-46
lines changed

8 files changed

+109
-46
lines changed

packages/coverage-istanbul/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"istanbul-lib-report": "^3.0.1",
5252
"istanbul-lib-source-maps": "^4.0.1",
5353
"istanbul-reports": "^3.1.6",
54-
"magicast": "^0.3.2",
54+
"magicast": "^0.3.3",
5555
"picocolors": "^1.0.0",
5656
"test-exclude": "^6.0.0"
5757
},

packages/coverage-istanbul/src/provider.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { AfterSuiteRunMeta, CoverageIstanbulOptions, CoverageProvider, Repo
44
import { coverageConfigDefaults, defaultExclude, defaultInclude } from 'vitest/config'
55
import { BaseCoverageProvider } from 'vitest/coverage'
66
import c from 'picocolors'
7+
import type { ProxifiedModule } from 'magicast'
78
import { parseModule } from 'magicast'
89
import createDebug from 'debug'
910
import libReport from 'istanbul-lib-report'
@@ -238,9 +239,7 @@ export class IstanbulCoverageProvider extends BaseCoverageProvider implements Co
238239
perFile: this.options.thresholds.perFile,
239240
configurationFile: {
240241
write: () => writeFileSync(configFilePath, configModule.generate().code, 'utf-8'),
241-
read: () => configModule.exports.default.$type === 'function-call'
242-
? configModule.exports.default.$args[0]
243-
: configModule.exports.default,
242+
read: () => resolveConfig(configModule),
244243
},
245244
})
246245
}
@@ -360,3 +359,29 @@ function toSlices<T>(array: T[], size: number): T[][] {
360359
return chunks
361360
}, [])
362361
}
362+
363+
function resolveConfig(configModule: ProxifiedModule<any>) {
364+
const mod = configModule.exports.default
365+
366+
try {
367+
// Check for "export default { test: {...} }"
368+
if (mod.$type === 'object')
369+
return mod
370+
371+
if (mod.$type === 'function-call') {
372+
// "export default defineConfig({ test: {...} })"
373+
if (mod.$args[0].$type === 'object')
374+
return mod.$args[0]
375+
376+
// "export default defineConfig(() => ({ test: {...} }))"
377+
if (mod.$args[0].$type === 'arrow-function-expression' && mod.$args[0].$body.$type === 'object')
378+
return mod.$args[0].$body
379+
}
380+
}
381+
catch (error) {
382+
// Reduce magicast's verbose errors to readable ones
383+
throw new Error(error instanceof Error ? error.message : String(error))
384+
}
385+
386+
throw new Error('Failed to update coverage thresholds. Configuration file is too complex.')
387+
}

packages/coverage-v8/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"istanbul-lib-source-maps": "^4.0.1",
5454
"istanbul-reports": "^3.1.6",
5555
"magic-string": "^0.30.5",
56-
"magicast": "^0.3.2",
56+
"magicast": "^0.3.3",
5757
"picocolors": "^1.0.0",
5858
"std-env": "^3.5.0",
5959
"test-exclude": "^6.0.0",

packages/coverage-v8/src/provider.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { CoverageMap } from 'istanbul-lib-coverage'
99
import libCoverage from 'istanbul-lib-coverage'
1010
import libSourceMaps from 'istanbul-lib-source-maps'
1111
import MagicString from 'magic-string'
12+
import type { ProxifiedModule } from 'magicast'
1213
import { parseModule } from 'magicast'
1314
import remapping from '@ampproject/remapping'
1415
import { normalize, resolve } from 'pathe'
@@ -230,9 +231,7 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
230231
perFile: this.options.thresholds.perFile,
231232
configurationFile: {
232233
write: () => writeFileSync(configFilePath, configModule.generate().code, 'utf-8'),
233-
read: () => configModule.exports.default.$type === 'function-call'
234-
? configModule.exports.default.$args[0]
235-
: configModule.exports.default,
234+
read: () => resolveConfig(configModule),
236235
},
237236
})
238237
}
@@ -432,3 +431,29 @@ function toSlices<T>(array: T[], size: number): T[][] {
432431
return chunks
433432
}, [])
434433
}
434+
435+
function resolveConfig(configModule: ProxifiedModule<any>) {
436+
const mod = configModule.exports.default
437+
438+
try {
439+
// Check for "export default { test: {...} }"
440+
if (mod.$type === 'object')
441+
return mod
442+
443+
if (mod.$type === 'function-call') {
444+
// "export default defineConfig({ test: {...} })"
445+
if (mod.$args[0].$type === 'object')
446+
return mod.$args[0]
447+
448+
// "export default defineConfig(() => ({ test: {...} }))"
449+
if (mod.$args[0].$type === 'arrow-function-expression' && mod.$args[0].$body.$type === 'object')
450+
return mod.$args[0].$body
451+
}
452+
}
453+
catch (error) {
454+
// Reduce magicast's verbose errors to readable ones
455+
throw new Error(error instanceof Error ? error.message : String(error))
456+
}
457+
458+
throw new Error('Failed to update coverage thresholds. Configuration file is too complex.')
459+
}

0 commit comments

Comments
 (0)