c8 10.0.0 → 10.1.1

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 CHANGED
@@ -43,6 +43,7 @@ Here is a list of common options. Run `c8 --help` for the full list and document
43
43
  | `--per-file` | check thresholds per file | `boolean` | `false` |
44
44
  | `--temp-directory` | directory V8 coverage data is written to and read from | `string` | `process.env.NODE_V8_COVERAGE` |
45
45
  | `--clean` | should temp files be deleted before script execution | `boolean` | `true` |
46
+ | `--experimental-monocart` | see [section below](#using-monocart-coverage-reports-experimental) for more info | `boolean` | `false` |
46
47
 
47
48
  ## Checking for "full" source coverage using `--all`
48
49
 
@@ -119,6 +120,23 @@ The `--100` flag can be set for the `check-coverage` as well:
119
120
  c8 check-coverage --100
120
121
  ```
121
122
 
123
+ ## Using Monocart coverage reports (experimental)
124
+ Monocart is an alternate library for outputting [v8 code coverage](https://v8.dev/blog/javascript-code-coverage) data as Istanbul reports.
125
+
126
+ Monocart also provides reporters based directly on v8's byte-offset-based output. Such as, `console-details` and `v8`. This removes a complex transformation step and may be less bug prone for some environments.
127
+
128
+ **Example usage:**
129
+
130
+ ```sh
131
+ c8 --experimental-monocart --reporter=v8 --reporter=console-details node foo.js
132
+ ```
133
+
134
+ NOTE: Monocart requires additional `monocart-coverage-reports` to be installed:
135
+
136
+ ```sh
137
+ npm i monocart-coverage-reports@2 --save-dev
138
+ ```
139
+
122
140
  ## Ignoring Uncovered Lines, Functions, and Blocks
123
141
 
124
142
  Sometimes you might find yourself wanting to ignore uncovered portions of your
@@ -36,7 +36,8 @@ exports.outputReport = async function (argv) {
36
36
  src: argv.src,
37
37
  skipFull: argv.skipFull,
38
38
  excludeNodeModules: argv.excludeNodeModules,
39
- mergeAsync: argv.mergeAsync
39
+ mergeAsync: argv.mergeAsync,
40
+ monocartArgv: (argv.experimentalMonocart || process.env.EXPERIMENTAL_MONOCART) ? argv : null
40
41
  })
41
42
  await report.run()
42
43
  if (argv.checkCoverage) await checkCoverages(argv, report)
package/lib/parse-args.js CHANGED
@@ -158,6 +158,11 @@ function buildYargs (withCommands = false) {
158
158
  describe: 'supplying --merge-async will merge all v8 coverage reports asynchronously and incrementally. ' +
159
159
  'This is to avoid OOM issues with Node.js runtime.'
160
160
  })
161
+ .option('experimental-monocart', {
162
+ default: false,
163
+ type: 'boolean',
164
+ describe: 'Use Monocart coverage reports'
165
+ })
161
166
  .pkgConf('c8')
162
167
  .demandCommand(1)
163
168
  .check((argv) => {
package/lib/report.js CHANGED
@@ -36,7 +36,8 @@ class Report {
36
36
  allowExternal = false,
37
37
  skipFull,
38
38
  excludeNodeModules,
39
- mergeAsync
39
+ mergeAsync,
40
+ monocartArgv
40
41
  }) {
41
42
  this.reporter = reporter
42
43
  this.reporterOptions = reporterOptions || {}
@@ -60,6 +61,7 @@ class Report {
60
61
  this.src = this._getSrc(src)
61
62
  this.skipFull = skipFull
62
63
  this.mergeAsync = mergeAsync
64
+ this.monocartArgv = monocartArgv
63
65
  }
64
66
 
65
67
  _getSrc (src) {
@@ -73,6 +75,9 @@ class Report {
73
75
  }
74
76
 
75
77
  async run () {
78
+ if (this.monocartArgv) {
79
+ return this.runMonocart()
80
+ }
76
81
  const context = libReport.createContext({
77
82
  dir: this.reportsDirectory,
78
83
  watermarks: this.watermarks,
@@ -89,6 +94,141 @@ class Report {
89
94
  }
90
95
  }
91
96
 
97
+ async importMonocart () {
98
+ return import('monocart-coverage-reports')
99
+ }
100
+
101
+ async getMonocart () {
102
+ let MCR
103
+ try {
104
+ MCR = await this.importMonocart()
105
+ } catch (e) {
106
+ console.error('--experimental-monocart requires the plugin monocart-coverage-reports. Run: "npm i monocart-coverage-reports@2 --save-dev"')
107
+ process.exit(1)
108
+ }
109
+ return MCR
110
+ }
111
+
112
+ async runMonocart () {
113
+ const MCR = await this.getMonocart()
114
+ if (!MCR) {
115
+ return
116
+ }
117
+
118
+ const argv = this.monocartArgv
119
+ const exclude = this.exclude
120
+
121
+ function getEntryFilter () {
122
+ return argv.entryFilter || argv.filter || function (entry) {
123
+ return exclude.shouldInstrument(fileURLToPath(entry.url))
124
+ }
125
+ }
126
+
127
+ function getSourceFilter () {
128
+ return argv.sourceFilter || argv.filter || function (sourcePath) {
129
+ if (argv.excludeAfterRemap) {
130
+ // console.log(sourcePath)
131
+ return exclude.shouldInstrument(sourcePath)
132
+ }
133
+ return true
134
+ }
135
+ }
136
+
137
+ function getReports () {
138
+ const reports = Array.isArray(argv.reporter) ? argv.reporter : [argv.reporter]
139
+ const reporterOptions = argv.reporterOptions || {}
140
+
141
+ return reports.map((reportName) => {
142
+ const reportOptions = {
143
+ ...reporterOptions[reportName]
144
+ }
145
+ if (reportName === 'text') {
146
+ reportOptions.skipEmpty = false
147
+ reportOptions.skipFull = argv.skipFull
148
+ reportOptions.maxCols = process.stdout.columns || 100
149
+ }
150
+ return [reportName, reportOptions]
151
+ })
152
+ }
153
+
154
+ // --all: add empty coverage for all files
155
+ function getAllOptions () {
156
+ if (!argv.all) {
157
+ return
158
+ }
159
+
160
+ const src = argv.src
161
+ const workingDirs = Array.isArray(src) ? src : (typeof src === 'string' ? [src] : [process.cwd()])
162
+ return {
163
+ dir: workingDirs,
164
+ filter: (filePath) => {
165
+ return exclude.shouldInstrument(filePath)
166
+ }
167
+ }
168
+ }
169
+
170
+ function initPct (summary) {
171
+ Object.keys(summary).forEach(k => {
172
+ if (summary[k].pct === '') {
173
+ summary[k].pct = 100
174
+ }
175
+ })
176
+ return summary
177
+ }
178
+
179
+ // adapt coverage options
180
+ const coverageOptions = {
181
+ logging: argv.logging,
182
+ name: argv.name,
183
+
184
+ reports: getReports(),
185
+
186
+ outputDir: argv.reportsDir,
187
+ baseDir: argv.baseDir,
188
+
189
+ entryFilter: getEntryFilter(),
190
+ sourceFilter: getSourceFilter(),
191
+
192
+ inline: argv.inline,
193
+ lcov: argv.lcov,
194
+
195
+ all: getAllOptions(),
196
+
197
+ clean: argv.clean,
198
+
199
+ // use default value for istanbul
200
+ defaultSummarizer: 'pkg',
201
+
202
+ onEnd: (coverageResults) => {
203
+ // for check coverage
204
+ this._allCoverageFiles = {
205
+ files: () => {
206
+ return coverageResults.files.map(it => it.sourcePath)
207
+ },
208
+ fileCoverageFor: (file) => {
209
+ const fileCoverage = coverageResults.files.find(it => it.sourcePath === file)
210
+ return {
211
+ toSummary: () => {
212
+ return initPct(fileCoverage.summary)
213
+ }
214
+ }
215
+ },
216
+ getCoverageSummary: () => {
217
+ return initPct(coverageResults.summary)
218
+ }
219
+ }
220
+ }
221
+ }
222
+ const coverageReport = new MCR.CoverageReport(coverageOptions)
223
+ coverageReport.cleanCache()
224
+
225
+ // read v8 coverage data from tempDirectory
226
+ await coverageReport.addFromDir(argv.tempDirectory)
227
+
228
+ // generate report
229
+ await coverageReport.generate()
230
+ }
231
+
92
232
  async getCoverageMapFromAllCoverageFiles () {
93
233
  // the merge process can be very expensive, and it's often the case that
94
234
  // check-coverage is called immediately after a report. We memoize the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c8",
3
- "version": "10.0.0",
3
+ "version": "10.1.1",
4
4
  "description": "output coverage reports using Node.js' built in coverage",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -51,10 +51,14 @@
51
51
  "chai-jest-snapshot": "^2.0.0",
52
52
  "cross-env": "^7.0.3",
53
53
  "mocha": "^9.2.2",
54
+ "monocart-coverage-reports": "^2.8.3",
54
55
  "standard": "^16.0.4",
55
56
  "ts-node": "^10.7.0",
56
57
  "typescript": "^5.0.0"
57
58
  },
59
+ "c8Requirements": {
60
+ "monocart-coverage-reports": "^2"
61
+ },
58
62
  "engines": {
59
63
  "node": ">=18"
60
64
  },