c8 7.12.0 → 7.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/index.d.ts +4 -1
- package/lib/commands/report.js +2 -1
- package/lib/parse-args.js +6 -0
- package/lib/report.js +113 -33
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# c8 - native V8 code-coverage
|
|
2
2
|
|
|
3
|
-
](https://github.com/bcoe/c8/actions/workflows/ci.yaml)
|
|
4
4
|

|
|
5
5
|
[](https://www.conventionalcommits.org/)
|
|
6
6
|
|
|
@@ -40,6 +40,7 @@ Here is a list of common options. Run `c8 --help` for the full list and document
|
|
|
40
40
|
| `-e`, `--extension` | only files matching these extensions will show coverage | `string \| Array<string>` | [list](https://github.com/istanbuljs/schema/blob/master/default-extension.js) |
|
|
41
41
|
| `--skip-full` | do not show files with 100% statement, branch, and function coverage | `boolean` | `false` |
|
|
42
42
|
| `--check-coverage` | check whether coverage is within thresholds provided | `boolean` | `false` |
|
|
43
|
+
| `--per-file` | check thresholds per file | `boolean` | `false` |
|
|
43
44
|
| `--temp-directory` | directory V8 coverage data is written to and read from | `string` | `process.env.NODE_V8_COVERAGE` |
|
|
44
45
|
| `--clean` | should temp files be deleted before script execution | `boolean` | `true` |
|
|
45
46
|
|
package/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare class Report {
|
|
|
8
8
|
include?: string | string[],
|
|
9
9
|
reporter: string[],
|
|
10
10
|
reportsDirectory?: string,
|
|
11
|
+
reporterOptions?: Record<string, Record<string, unknown>>
|
|
11
12
|
tempDirectory?: string,
|
|
12
13
|
watermarks?: Partial<{
|
|
13
14
|
statements: Watermark;
|
|
@@ -20,7 +21,9 @@ export declare class Report {
|
|
|
20
21
|
resolve?: string,
|
|
21
22
|
all?: boolean,
|
|
22
23
|
src?: Array<string>,
|
|
23
|
-
allowExternal?: boolean
|
|
24
|
+
allowExternal?: boolean,
|
|
25
|
+
skipFull?: boolean,
|
|
26
|
+
excludeNodeModules?: boolean
|
|
24
27
|
})
|
|
25
28
|
run(): Promise<void>;
|
|
26
29
|
}
|
package/lib/commands/report.js
CHANGED
|
@@ -34,7 +34,8 @@ exports.outputReport = async function (argv) {
|
|
|
34
34
|
allowExternal: argv.allowExternal,
|
|
35
35
|
src: argv.src,
|
|
36
36
|
skipFull: argv.skipFull,
|
|
37
|
-
excludeNodeModules: argv.excludeNodeModules
|
|
37
|
+
excludeNodeModules: argv.excludeNodeModules,
|
|
38
|
+
mergeAsync: argv.mergeAsync
|
|
38
39
|
})
|
|
39
40
|
await report.run()
|
|
40
41
|
if (argv.checkCoverage) await checkCoverages(argv, report)
|
package/lib/parse-args.js
CHANGED
|
@@ -152,6 +152,12 @@ function buildYargs (withCommands = false) {
|
|
|
152
152
|
describe: 'supplying --allowExternal will cause c8 to allow files from outside of your cwd. This applies both to ' +
|
|
153
153
|
'files discovered in coverage temp files and also src files discovered if using the --all flag.'
|
|
154
154
|
})
|
|
155
|
+
.options('merge-async', {
|
|
156
|
+
default: false,
|
|
157
|
+
type: 'boolean',
|
|
158
|
+
describe: 'supplying --merge-async will merge all v8 coverage reports asynchronously and incrementally. ' +
|
|
159
|
+
'This is to avoid OOM issues with Node.js runtime.'
|
|
160
|
+
})
|
|
155
161
|
.pkgConf('c8')
|
|
156
162
|
.demandCommand(1)
|
|
157
163
|
.check((argv) => {
|
package/lib/report.js
CHANGED
|
@@ -2,6 +2,12 @@ const Exclude = require('test-exclude')
|
|
|
2
2
|
const libCoverage = require('istanbul-lib-coverage')
|
|
3
3
|
const libReport = require('istanbul-lib-report')
|
|
4
4
|
const reports = require('istanbul-reports')
|
|
5
|
+
let readFile
|
|
6
|
+
try {
|
|
7
|
+
;({ readFile } = require('fs/promises'))
|
|
8
|
+
} catch (err) {
|
|
9
|
+
;({ readFile } = require('fs').promises)
|
|
10
|
+
}
|
|
5
11
|
const { readdirSync, readFileSync, statSync } = require('fs')
|
|
6
12
|
const { isAbsolute, resolve, extname } = require('path')
|
|
7
13
|
const { pathToFileURL, fileURLToPath } = require('url')
|
|
@@ -19,6 +25,7 @@ class Report {
|
|
|
19
25
|
excludeAfterRemap,
|
|
20
26
|
include,
|
|
21
27
|
reporter,
|
|
28
|
+
reporterOptions,
|
|
22
29
|
reportsDirectory,
|
|
23
30
|
tempDirectory,
|
|
24
31
|
watermarks,
|
|
@@ -29,9 +36,11 @@ class Report {
|
|
|
29
36
|
src,
|
|
30
37
|
allowExternal = false,
|
|
31
38
|
skipFull,
|
|
32
|
-
excludeNodeModules
|
|
39
|
+
excludeNodeModules,
|
|
40
|
+
mergeAsync
|
|
33
41
|
}) {
|
|
34
42
|
this.reporter = reporter
|
|
43
|
+
this.reporterOptions = reporterOptions || {}
|
|
35
44
|
this.reportsDirectory = reportsDirectory
|
|
36
45
|
this.tempDirectory = tempDirectory
|
|
37
46
|
this.watermarks = watermarks
|
|
@@ -51,6 +60,7 @@ class Report {
|
|
|
51
60
|
this.all = all
|
|
52
61
|
this.src = this._getSrc(src)
|
|
53
62
|
this.skipFull = skipFull
|
|
63
|
+
this.mergeAsync = mergeAsync
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
_getSrc (src) {
|
|
@@ -74,7 +84,8 @@ class Report {
|
|
|
74
84
|
reports.create(_reporter, {
|
|
75
85
|
skipEmpty: false,
|
|
76
86
|
skipFull: this.skipFull,
|
|
77
|
-
maxCols: process.stdout.columns || 100
|
|
87
|
+
maxCols: process.stdout.columns || 100,
|
|
88
|
+
...this.reporterOptions[_reporter]
|
|
78
89
|
}).execute(context)
|
|
79
90
|
}
|
|
80
91
|
}
|
|
@@ -87,7 +98,13 @@ class Report {
|
|
|
87
98
|
if (this._allCoverageFiles) return this._allCoverageFiles
|
|
88
99
|
|
|
89
100
|
const map = libCoverage.createCoverageMap()
|
|
90
|
-
|
|
101
|
+
let v8ProcessCov
|
|
102
|
+
|
|
103
|
+
if (this.mergeAsync) {
|
|
104
|
+
v8ProcessCov = await this._getMergedProcessCovAsync()
|
|
105
|
+
} else {
|
|
106
|
+
v8ProcessCov = this._getMergedProcessCov()
|
|
107
|
+
}
|
|
91
108
|
const resultCountPerPath = new Map()
|
|
92
109
|
const possibleCjsEsmBridges = new Map()
|
|
93
110
|
|
|
@@ -185,43 +202,106 @@ class Report {
|
|
|
185
202
|
}
|
|
186
203
|
|
|
187
204
|
if (this.all) {
|
|
188
|
-
const emptyReports =
|
|
205
|
+
const emptyReports = this._includeUncoveredFiles(fileIndex)
|
|
189
206
|
v8ProcessCovs.unshift({
|
|
190
207
|
result: emptyReports
|
|
191
208
|
})
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return mergeProcessCovs(v8ProcessCovs)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Returns the merged V8 process coverage.
|
|
216
|
+
*
|
|
217
|
+
* It asynchronously and incrementally reads and merges individual process coverages
|
|
218
|
+
* generated by Node. This can be used via the `--merge-async` CLI arg. It's intended
|
|
219
|
+
* to be used across a large multi-process test run.
|
|
220
|
+
*
|
|
221
|
+
* @return {ProcessCov} Merged V8 process coverage.
|
|
222
|
+
* @private
|
|
223
|
+
*/
|
|
224
|
+
async _getMergedProcessCovAsync () {
|
|
225
|
+
const { mergeProcessCovs } = require('@bcoe/v8-coverage')
|
|
226
|
+
const fileIndex = new Set() // Set<string>
|
|
227
|
+
let mergedCov = null
|
|
228
|
+
for (const file of readdirSync(this.tempDirectory)) {
|
|
229
|
+
try {
|
|
230
|
+
const rawFile = await readFile(
|
|
231
|
+
resolve(this.tempDirectory, file),
|
|
232
|
+
'utf8'
|
|
233
|
+
)
|
|
234
|
+
let report = JSON.parse(rawFile)
|
|
235
|
+
|
|
236
|
+
if (this._isCoverageObject(report)) {
|
|
237
|
+
if (report['source-map-cache']) {
|
|
238
|
+
Object.assign(this.sourceMapCache, this._normalizeSourceMapCache(report['source-map-cache']))
|
|
219
239
|
}
|
|
220
|
-
|
|
240
|
+
report = this._normalizeProcessCov(report, fileIndex)
|
|
241
|
+
if (mergedCov) {
|
|
242
|
+
mergedCov = mergeProcessCovs([mergedCov, report])
|
|
243
|
+
} else {
|
|
244
|
+
mergedCov = mergeProcessCovs([report])
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
} catch (err) {
|
|
248
|
+
debuglog(`${err.stack}`)
|
|
221
249
|
}
|
|
222
250
|
}
|
|
223
251
|
|
|
224
|
-
|
|
252
|
+
if (this.all) {
|
|
253
|
+
const emptyReports = this._includeUncoveredFiles(fileIndex)
|
|
254
|
+
const emptyReport = {
|
|
255
|
+
result: emptyReports
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
mergedCov = mergeProcessCovs([emptyReport, mergedCov])
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return mergedCov
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Adds empty coverage reports to account for uncovered/untested code.
|
|
266
|
+
* This is only done when the `--all` flag is present.
|
|
267
|
+
*
|
|
268
|
+
* @param {Set} fileIndex list of files that have coverage
|
|
269
|
+
* @returns {Array} list of empty coverage reports
|
|
270
|
+
*/
|
|
271
|
+
_includeUncoveredFiles (fileIndex) {
|
|
272
|
+
const emptyReports = []
|
|
273
|
+
const workingDirs = this.src
|
|
274
|
+
const { extension } = this.exclude
|
|
275
|
+
for (const workingDir of workingDirs) {
|
|
276
|
+
this.exclude.globSync(workingDir).forEach((f) => {
|
|
277
|
+
const fullPath = resolve(workingDir, f)
|
|
278
|
+
if (!fileIndex.has(fullPath)) {
|
|
279
|
+
const ext = extname(fullPath)
|
|
280
|
+
if (extension.includes(ext)) {
|
|
281
|
+
const stat = statSync(fullPath)
|
|
282
|
+
const sourceMap = getSourceMapFromFile(fullPath)
|
|
283
|
+
if (sourceMap) {
|
|
284
|
+
this.sourceMapCache[pathToFileURL(fullPath)] = { data: sourceMap }
|
|
285
|
+
}
|
|
286
|
+
emptyReports.push({
|
|
287
|
+
scriptId: 0,
|
|
288
|
+
url: resolve(fullPath),
|
|
289
|
+
functions: [{
|
|
290
|
+
functionName: '(empty-report)',
|
|
291
|
+
ranges: [{
|
|
292
|
+
startOffset: 0,
|
|
293
|
+
endOffset: stat.size,
|
|
294
|
+
count: 0
|
|
295
|
+
}],
|
|
296
|
+
isBlockCoverage: true
|
|
297
|
+
}]
|
|
298
|
+
})
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return emptyReports
|
|
225
305
|
}
|
|
226
306
|
|
|
227
307
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c8",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.14.0",
|
|
4
4
|
"description": "output coverage reports using Node.js' built in coverage",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"yargs-parser": "^20.2.9"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@types/node": "^
|
|
50
|
+
"@types/node": "^18.0.0",
|
|
51
51
|
"chai": "^4.3.6",
|
|
52
52
|
"chai-jest-snapshot": "^2.0.0",
|
|
53
53
|
"cross-env": "^7.0.3",
|