@@ -53,15 +53,31 @@ interface TestExclude {
53
53
54
54
type Options = ResolvedCoverageOptions < 'v8' >
55
55
type TransformResults = Map < string , FetchResult >
56
- type Filename = string
57
56
type RawCoverage = Profiler . TakePreciseCoverageReturnType
58
- type CoverageFilesByTransformMode = Record <
59
- AfterSuiteRunMeta [ 'transformMode' ] ,
60
- Filename [ ]
57
+
58
+ /**
59
+ * Holds info about raw coverage results that are stored on file system:
60
+ *
61
+ * ```json
62
+ * "project-a": {
63
+ * "web": {
64
+ * "tests/math.test.ts": "coverage-1.json",
65
+ * "tests/utils.test.ts": "coverage-2.json",
66
+ * // ^^^^^^^^^^^^^^^ Raw coverage on file system
67
+ * },
68
+ * "ssr": { ... },
69
+ * "browser": { ... },
70
+ * },
71
+ * "project-b": ...
72
+ * ```
73
+ */
74
+ type CoverageFiles = Map <
75
+ NonNullable < AfterSuiteRunMeta [ 'projectName' ] > | typeof DEFAULT_PROJECT ,
76
+ Record <
77
+ AfterSuiteRunMeta [ 'transformMode' ] ,
78
+ { [ TestFilenames : string ] : string }
79
+ >
61
80
>
62
- type ProjectName =
63
- | NonNullable < AfterSuiteRunMeta [ 'projectName' ] >
64
- | typeof DEFAULT_PROJECT
65
81
66
82
type Entries < T > = [ keyof T , T [ keyof T ] ] [ ]
67
83
@@ -86,7 +102,7 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
86
102
options ! : Options
87
103
testExclude ! : InstanceType < TestExclude >
88
104
89
- coverageFiles : Map < ProjectName , CoverageFilesByTransformMode > = new Map ( )
105
+ coverageFiles : CoverageFiles = new Map ( )
90
106
coverageFilesDirectory ! : string
91
107
pendingPromises : Promise < void > [ ] = [ ]
92
108
@@ -181,23 +197,26 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
181
197
* Note that adding new entries here and requiring on those without
182
198
* backwards compatibility is a breaking change.
183
199
*/
184
- onAfterSuiteRun ( { coverage, transformMode, projectName } : AfterSuiteRunMeta ) : void {
200
+ onAfterSuiteRun ( { coverage, transformMode, projectName, testFiles } : AfterSuiteRunMeta ) : void {
185
201
if ( transformMode !== 'web' && transformMode !== 'ssr' && transformMode !== 'browser' ) {
186
202
throw new Error ( `Invalid transform mode: ${ transformMode } ` )
187
203
}
188
204
189
205
let entry = this . coverageFiles . get ( projectName || DEFAULT_PROJECT )
190
206
191
207
if ( ! entry ) {
192
- entry = { web : [ ] , ssr : [ ] , browser : [ ] }
208
+ entry = { web : { } , ssr : { } , browser : { } }
193
209
this . coverageFiles . set ( projectName || DEFAULT_PROJECT , entry )
194
210
}
195
211
212
+ const testFilenames = testFiles . join ( )
196
213
const filename = resolve (
197
214
this . coverageFilesDirectory ,
198
215
`coverage-${ uniqueId ++ } .json` ,
199
216
)
200
- entry [ transformMode ] . push ( filename )
217
+
218
+ // If there's a result from previous run, overwrite it
219
+ entry [ transformMode ] [ testFilenames ] = filename
201
220
202
221
const promise = fs . writeFile ( filename , JSON . stringify ( coverage ) , 'utf-8' )
203
222
this . pendingPromises . push ( promise )
@@ -212,9 +231,10 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
212
231
this . pendingPromises = [ ]
213
232
214
233
for ( const [ projectName , coveragePerProject ] of this . coverageFiles . entries ( ) ) {
215
- for ( const [ transformMode , filenames ] of Object . entries ( coveragePerProject ) as Entries < CoverageFilesByTransformMode > ) {
234
+ for ( const [ transformMode , coverageByTestfiles ] of Object . entries ( coveragePerProject ) as Entries < typeof coveragePerProject > ) {
216
235
let merged : RawCoverage = { result : [ ] }
217
236
237
+ const filenames = Object . values ( coverageByTestfiles )
218
238
const project = this . ctx . projects . find ( p => p . getName ( ) === projectName ) || this . ctx . getCoreWorkspaceProject ( )
219
239
220
240
for ( const chunk of this . toSlices ( filenames , this . options . processingConcurrency ) ) {
@@ -245,7 +265,9 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
245
265
}
246
266
}
247
267
248
- if ( this . options . all && allTestsRun ) {
268
+ // Include untested files when all tests were run (not a single file re-run)
269
+ // or if previous results are preserved by "cleanOnRerun: false"
270
+ if ( this . options . all && ( allTestsRun || ! this . options . cleanOnRerun ) ) {
249
271
const coveredFiles = coverageMap . files ( )
250
272
const untestedCoverage = await this . getUntestedFiles ( coveredFiles )
251
273
@@ -519,7 +541,7 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
519
541
private async convertCoverage (
520
542
coverage : RawCoverage ,
521
543
project : WorkspaceProject = this . ctx . getCoreWorkspaceProject ( ) ,
522
- transformMode ?: keyof CoverageFilesByTransformMode ,
544
+ transformMode ?: AfterSuiteRunMeta [ 'transformMode' ] ,
523
545
) : Promise < CoverageMap > {
524
546
let fetchCache = project . vitenode . fetchCache
525
547
0 commit comments