monocart-coverage-reports 2.6.0 → 2.6.2

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
@@ -39,6 +39,7 @@
39
39
  - [Vitest](#vitest)
40
40
  - [CodeceptJS](#codeceptjs)
41
41
  - [WebdriverIO](#webdriverio)
42
+ - [Storybook Test Runner](#storybook-test-runner)
42
43
  - [Codecov](#codecov)
43
44
  - [Coveralls](#coveralls)
44
45
  - [Sonar Cloud](#sonar-cloud)
@@ -257,15 +258,15 @@ const coverageOptions = {
257
258
 
258
259
  ## `mcr` CLI
259
260
  > The CLI will run the program as a [child process](https://nodejs.org/docs/latest/api/child_process.html) with `NODE_V8_COVERAGE=dir` until it exits gracefully, and generate the coverage report with the coverage data from the `dir`.
260
- - Global mode
261
+ - Installing globally
261
262
  ```sh
262
263
  npm i monocart-coverage-reports -g
263
- mcr "node ./test/test-node-env.js" -r v8,console-summary --lcov
264
+ mcr node ./test/test-node-env.js -r v8,console-summary --lcov
264
265
  ```
265
- - Current working directory mode
266
+ - Locally in your project
266
267
  ```sh
267
268
  npm i monocart-coverage-reports
268
- npx mcr "node ./test/test-node-env.js" -r v8,console-summary --lcov
269
+ npx mcr node ./test/test-node-env.js -r v8,console-summary --lcov
269
270
  ```
270
271
  - CLI Options
271
272
  ```sh
@@ -292,15 +293,15 @@ Options:
292
293
  --logging <logging> off, error, info, debug
293
294
  -h, --help display help for command
294
295
  ```
295
- - Supports loading default configuration file
296
+ - Loading default configuration file
296
297
  - `.mcrrc`
297
298
  - `mcr.config.json`
298
299
  - `mcr.config.mjs`
299
300
  - `mcr.config.cjs`
300
301
  - `mcr.config.js`
301
- - Specify custom configuration file
302
+ - Or loading custom configuration file with `-c` or `--config`
302
303
  ```sh
303
- mcr "node ./test.js" -c path-to/my-custom-config.js
304
+ mcr node ./test.js -c path-to/my-custom-config.js
304
305
  ```
305
306
 
306
307
  ## Compare Reports
@@ -723,6 +724,9 @@ When `logging` is `debug`, the raw report data will be preserved in `[outputDir]
723
724
  ### [WebdriverIO](https://github.com/webdriverio/webdriverio)
724
725
  - [wdio-monocart-service](https://github.com/cenfun/wdio-monocart-service) - A WebdriverIO service for coverage reports
725
726
 
727
+ ### [Storybook Test Runner](https://github.com/storybookjs/test-runner)
728
+ - [storybook-monocart-coverage](https://github.com/cenfun/storybook-monocart-coverage) - Storybook V8 Coverage Example
729
+
726
730
  ### [Codecov](https://codecov.com/)
727
731
  [![codecov](https://codecov.io/gh/cenfun/monocart-coverage-reports/graph/badge.svg?token=H0LW7UKYU3)](https://codecov.io/gh/cenfun/monocart-coverage-reports)
728
732
  - Supports native `codecov` built-in report ([specification](https://docs.codecov.com/docs/codecov-custom-coverage-format))
package/lib/cli.js CHANGED
@@ -4,6 +4,7 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const EC = require('eight-colors');
6
6
  const { fileURLToPath, pathToFileURL } = require('url');
7
+
7
8
  const {
8
9
  foregroundChild,
9
10
  program
@@ -98,6 +99,71 @@ const initOptions = async (cliOptions) => {
98
99
  return options;
99
100
  };
100
101
 
102
+ const resolveEntrySource = (entry, sourceMapCache = {}) => {
103
+ let source;
104
+ const filePath = fileURLToPath(entry.url);
105
+ const extname = path.extname(filePath);
106
+ if (fs.existsSync(filePath)) {
107
+ source = fs.readFileSync(filePath).toString('utf8');
108
+ }
109
+
110
+ // not for typescript
111
+ if (source && !['.ts', '.tsx'].includes(extname)) {
112
+ entry.source = source;
113
+ return;
114
+ }
115
+
116
+ const sourcemapData = sourceMapCache[entry.url];
117
+ const lineLengths = sourcemapData && sourcemapData.lineLengths;
118
+
119
+ // for fake source file (can not parse to AST)
120
+ if (lineLengths) {
121
+ // get runtime code with ts-node
122
+ let fakeSource = '';
123
+ sourcemapData.lineLengths.forEach((length) => {
124
+ fakeSource += `${''.padEnd(length, '*')}\n`;
125
+ });
126
+ entry.fake = true;
127
+ entry.source = fakeSource;
128
+ }
129
+
130
+ // Note: no runtime code in source map cache
131
+ // This is a problem for typescript
132
+
133
+ };
134
+
135
+ const resolveEntrySourceMap = (entry, sourceMapCache = {}) => {
136
+ // sourcemap data
137
+ const sourcemapData = sourceMapCache[entry.url];
138
+ if (sourcemapData) {
139
+ if (sourcemapData.data) {
140
+ entry.sourceMap = resolveSourceMap(sourcemapData.data, entry.url);
141
+ }
142
+ }
143
+ };
144
+
145
+ const collectCoverageData = (coverageList, entryFilterHandler, sourceMapCache = {}) => {
146
+
147
+ if (!Util.isList(coverageList)) {
148
+ return;
149
+ }
150
+
151
+ // filter node internal files
152
+ coverageList = coverageList.filter((entry) => entry.url && entry.url.startsWith('file:'));
153
+ coverageList = coverageList.filter(entryFilterHandler);
154
+
155
+ if (!Util.isList(coverageList)) {
156
+ return;
157
+ }
158
+
159
+ for (const entry of coverageList) {
160
+ resolveEntrySource(entry, sourceMapCache);
161
+ resolveEntrySourceMap(entry, sourceMapCache);
162
+ }
163
+
164
+ return coverageList;
165
+ };
166
+
101
167
  const executeCommand = async (command, cliOptions) => {
102
168
 
103
169
  const options = await initOptions(cliOptions);
@@ -130,49 +196,18 @@ const executeCommand = async (command, cliOptions) => {
130
196
  return 1;
131
197
  }
132
198
 
199
+ const entryFilterHandler = coverageReport.getEntryFilter();
200
+
133
201
  const files = fs.readdirSync(nodeV8CoverageDir);
134
202
  for (const filename of files) {
135
203
  const content = fs.readFileSync(path.resolve(nodeV8CoverageDir, filename)).toString('utf-8');
136
204
  const json = JSON.parse(content);
137
- let coverageList = json.result;
138
-
139
- // for node sourcemap
140
- const sourceMapCache = json['source-map-cache'] || {};
141
-
142
- // filter node internal files
143
- coverageList = coverageList.filter((entry) => entry.url && entry.url.startsWith('file:'));
144
-
145
- if (!coverageList.length) {
146
- continue;
205
+ const coverageList = json.result;
206
+ const sourceMapCache = json['source-map-cache'];
207
+ const coverageData = await collectCoverageData(coverageList, entryFilterHandler, sourceMapCache);
208
+ if (coverageData) {
209
+ await coverageReport.add(coverageData);
147
210
  }
148
- // attached source content
149
- coverageList.forEach((entry) => {
150
- // source content
151
- const filePath = fileURLToPath(entry.url);
152
- if (fs.existsSync(filePath)) {
153
- entry.source = fs.readFileSync(filePath).toString('utf8');
154
- }
155
-
156
- // sourcemap data
157
- const sourcemapData = sourceMapCache[entry.url];
158
- if (sourcemapData) {
159
- if (sourcemapData.data) {
160
- entry.sourceMap = resolveSourceMap(sourcemapData.data, entry.url);
161
- }
162
- // sourcemapData.lineLengths just for fake source file (can not parse to AST)
163
- if (!entry.source && sourcemapData.lineLengths) {
164
- // get runtime code with ts-node
165
- let source = '';
166
- sourcemapData.lineLengths.forEach((length) => {
167
- source += `${''.padEnd(length, '*')}\n`;
168
- });
169
- entry.fake = true;
170
- entry.source = source;
171
- }
172
- }
173
- });
174
-
175
- await coverageReport.add(coverageList);
176
211
  }
177
212
 
178
213
  await coverageReport.generate();
@@ -192,6 +227,7 @@ program
192
227
  .description('CLI to generate coverage reports')
193
228
  .version(version)
194
229
  .argument('<command>', 'command to execute')
230
+ .allowUnknownOption()
195
231
  .option('-c, --config <path>', 'custom config path')
196
232
  .option('-o, --outputDir <dir>', 'output dir for reports')
197
233
  .option('-r, --reports <name[,name]>', 'coverage reports to use')
@@ -209,7 +245,8 @@ program
209
245
 
210
246
  .option('--logging <logging>', 'off, error, info, debug')
211
247
 
212
- .action((command, cliOptions) => {
248
+ .action((_command, cliOptions) => {
249
+ const command = program.args.join(' ');
213
250
  executeCommand(command, cliOptions);
214
251
  });
215
252
 
@@ -135,8 +135,8 @@ const collectSourceMaps = async (v8list, options) => {
135
135
 
136
136
  // save source and sourceMap to separated json file
137
137
  const sourceData = {
138
- url,
139
138
  id,
139
+ url,
140
140
  source,
141
141
  sourceMap
142
142
  };
package/lib/generate.js CHANGED
@@ -21,21 +21,22 @@ const { getGroupedRows } = require('./utils/snapshot.js');
21
21
  // maybe v8 or to istanbul reports
22
22
  const generateV8ListReports = async (v8list, coverageData, fileSources, options) => {
23
23
 
24
- let report;
25
-
26
- const { v8, istanbul } = options.reportGroup;
27
-
28
- // generate istanbul reports first
29
- if (istanbul) {
30
- report = await saveIstanbulReports(coverageData, fileSources, options);
24
+ let istanbulCoverageResults;
25
+ // v8 to istanbul reports
26
+ if (options.reportGroup.istanbul) {
27
+ istanbulCoverageResults = await saveIstanbulReports(coverageData, fileSources, options);
31
28
  }
32
29
 
33
- // generate v8 report
34
- if (v8) {
35
- report = await saveV8Report(v8list, options);
30
+ // v8 reports and v8 coverage results
31
+ // could be no v8 or v8-json, but requires v8 coverage results
32
+ const v8CoverageResults = await saveV8Report(v8list, options);
33
+
34
+ // fix reportPath
35
+ if (!v8CoverageResults.reportPath && istanbulCoverageResults) {
36
+ v8CoverageResults.reportPath = istanbulCoverageResults.reportPath;
36
37
  }
37
38
 
38
- return report;
39
+ return v8CoverageResults;
39
40
  };
40
41
 
41
42
  // ========================================================================================================
package/lib/index.js CHANGED
@@ -3,7 +3,7 @@ const path = require('path');
3
3
  const defaultOptions = require('./default/options.js');
4
4
  const Util = require('./utils/util.js');
5
5
 
6
- const { initV8ListAndSourcemap } = require('./v8/v8.js');
6
+ const { initV8ListAndSourcemap, getEntryFilter } = require('./v8/v8.js');
7
7
  const { getInputData, generateCoverageReports } = require('./generate.js');
8
8
  const { getSnapshot, diffSnapshot } = require('./utils/snapshot.js');
9
9
 
@@ -63,12 +63,12 @@ class CoverageReport {
63
63
  const dataPath = path.resolve(this.options.cacheDir, dataName);
64
64
 
65
65
  const results = {
66
- id: dataId,
67
- path: dataPath
66
+ id: dataId
68
67
  };
69
68
 
70
69
  if (Array.isArray(data)) {
71
70
  results.type = 'v8';
71
+ // could be empty list after entryFilter
72
72
  results.data = await initV8ListAndSourcemap(data, this.options);
73
73
  } else {
74
74
  results.type = 'istanbul';
@@ -170,6 +170,10 @@ class CoverageReport {
170
170
  return false;
171
171
  }
172
172
 
173
+ getEntryFilter() {
174
+ return getEntryFilter(this.options);
175
+ }
176
+
173
177
  }
174
178
 
175
179
  /** create coverage report */
package/lib/v8/v8.js CHANGED
@@ -356,7 +356,7 @@ const saveV8Report = async (v8list, options) => {
356
356
  files: v8list
357
357
  };
358
358
 
359
- // v8 reports
359
+ // v8 only reports
360
360
  const buildInV8Reports = {
361
361
  'v8': handleV8HtmlReport,
362
362
  'v8-json': handleV8JsonReport
@@ -364,14 +364,17 @@ const saveV8Report = async (v8list, options) => {
364
364
 
365
365
  const outputs = {};
366
366
  const v8Group = options.reportGroup.v8;
367
- const v8Reports = Object.keys(v8Group);
368
- for (const reportName of v8Reports) {
369
- const reportOptions = v8Group[reportName];
370
- const buildInHandler = buildInV8Reports[reportName];
371
- if (buildInHandler) {
372
- outputs[reportName] = await buildInHandler(reportData, reportOptions, options);
373
- } else {
374
- outputs[reportName] = await Util.runCustomReporter(reportName, reportData, reportOptions, options);
367
+ // could be no v8 only reports, but have `both` data reports
368
+ if (v8Group) {
369
+ const v8Reports = Object.keys(v8Group);
370
+ for (const reportName of v8Reports) {
371
+ const reportOptions = v8Group[reportName];
372
+ const buildInHandler = buildInV8Reports[reportName];
373
+ if (buildInHandler) {
374
+ outputs[reportName] = await buildInHandler(reportData, reportOptions, options);
375
+ } else {
376
+ outputs[reportName] = await Util.runCustomReporter(reportName, reportData, reportOptions, options);
377
+ }
375
378
  }
376
379
  }
377
380
 
@@ -395,5 +398,6 @@ const saveV8Report = async (v8list, options) => {
395
398
  module.exports = {
396
399
  initV8ListAndSourcemap,
397
400
  mergeV8Coverage,
398
- saveV8Report
401
+ saveV8Report,
402
+ getEntryFilter
399
403
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monocart-coverage-reports",
3
- "version": "2.6.0",
3
+ "version": "2.6.2",
4
4
  "description": "Monocart coverage reports",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -34,11 +34,11 @@
34
34
  "test-browser": "node ./test/test-browser.js && npm run test-istanbul && npm run test-v8 && npm run test-puppeteer && npm run test-anonymous && npm run test-css",
35
35
  "test-anonymous": "node ./test/test-anonymous.js",
36
36
  "test-css": "node ./test/test-css.js",
37
- "test-cli": "npx mcr \"node ./test/test-node-env.js\" -o docs/cli -c test/cli-options.js",
37
+ "test-cli": "npx mcr node ./test/test-node-env.js -o docs/cli -c test/cli-options.js",
38
38
  "test-merge": "node ./test/test-merge.js",
39
39
  "test-merge-istanbul": "node ./test/test-merge-istanbul.js",
40
40
  "test-all": "npm run test-browser && npm run test-node && npm run test-cli && npm run test-merge && npm run build-docs",
41
- "test": "npx mcr \"npm run test-all\" -c test/mcr-options.js",
41
+ "test": "npx mcr npm run test-all -c test/mcr-options.js",
42
42
  "test:snap": "cross-env TEST_SNAPSHOT=true npm run test",
43
43
  "dev": "sf d v8",
44
44
  "open": "node ./scripts/open.js",