monocart-coverage-reports 2.4.3 → 2.5.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 +66 -26
- package/lib/converter/ast-visitor.js +40 -20
- package/lib/converter/ast.js +1 -1
- package/lib/converter/converter.js +3 -2
- package/lib/converter/find-original-range.js +67 -26
- package/lib/generate.js +13 -33
- package/lib/index.d.ts +5 -0
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/packages/monocart-coverage-vendor.js +1 -1
- package/lib/platform/share.js +18 -59
- package/lib/utils/util.js +13 -0
- package/lib/v8/v8.js +214 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
* [Node.js V8 Coverage Report for Server Side](#nodejs-v8-coverage-report-for-server-side)
|
|
25
25
|
* [Multiprocessing Support](#multiprocessing-support)
|
|
26
26
|
* [Merge Coverage Reports](#merge-coverage-reports)
|
|
27
|
+
* [Resolve `sourcePath` for the Source Files](#resolve-sourcepath-for-the-source-files)
|
|
28
|
+
* [Adding Empty Coverage for Untested Files](#adding-empty-coverage-for-untested-files)
|
|
27
29
|
* [Ignoring Uncovered Codes](#ignoring-uncovered-codes)
|
|
28
30
|
* [Chromium Coverage API](#chromium-coverage-api)
|
|
29
31
|
* [V8 Coverage Data Format](#v8-coverage-data-format)
|
|
@@ -54,26 +56,22 @@ console.log(coverageResults.summary);
|
|
|
54
56
|
- [lib/default/options.js](https://github.com/cenfun/monocart-coverage-reports/blob/main/lib/default/options.js)
|
|
55
57
|
|
|
56
58
|
## Available Reports
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- Collect with [puppeteer](https://cenfun.github.io/monocart-coverage-reports/puppeteer/)
|
|
62
|
-
- [anonymous](https://cenfun.github.io/monocart-coverage-reports/anonymous/) and [css](https://cenfun.github.io/monocart-coverage-reports/css/)
|
|
63
|
-
- Test in Node.js
|
|
64
|
-
- Collect with [env](https://cenfun.github.io/monocart-coverage-reports/v8-node-env), and also V8 [API](https://cenfun.github.io/monocart-coverage-reports/v8-node-api), [Inspector](https://cenfun.github.io/monocart-coverage-reports/v8-node-ins) and [CDP](https://cenfun.github.io/monocart-coverage-reports/v8-node-cdp)
|
|
65
|
-
- Web server example: [koa](https://cenfun.github.io/monocart-coverage-reports/v8-node-koa/)
|
|
59
|
+
> V8 build-in reports (V8 data only):
|
|
60
|
+
- `v8`
|
|
61
|
+
- Browser: Build with webpack [V8](https://cenfun.github.io/monocart-coverage-reports/v8) and [V8 Minify](https://cenfun.github.io/monocart-coverage-reports/v8-minify); Build with [Rollup](https://cenfun.github.io/monocart-coverage-reports/v8-rollup) and [Esbuild](https://cenfun.github.io/monocart-coverage-reports/v8-esbuild); Collect with [puppeteer](https://cenfun.github.io/monocart-coverage-reports/puppeteer/); [anonymous](https://cenfun.github.io/monocart-coverage-reports/anonymous/) and [css](https://cenfun.github.io/monocart-coverage-reports/css/)
|
|
62
|
+
- Node.js: Collect with [env](https://cenfun.github.io/monocart-coverage-reports/v8-node-env), and also V8 [API](https://cenfun.github.io/monocart-coverage-reports/v8-node-api), [Inspector](https://cenfun.github.io/monocart-coverage-reports/v8-node-ins) and [CDP](https://cenfun.github.io/monocart-coverage-reports/v8-node-cdp); Web server example: [koa](https://cenfun.github.io/monocart-coverage-reports/v8-node-koa/)
|
|
66
63
|
|
|
67
64
|

|
|
68
65
|
|
|
69
|
-
- `v8-json`
|
|
66
|
+
- `v8-json`
|
|
70
67
|
- [V8 coverage-report.json](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json)
|
|
71
|
-
- `codecov`
|
|
68
|
+
- `codecov`
|
|
72
69
|
- coverage data for [Codecov](https://docs.codecov.com/docs/codecov-custom-coverage-format), see [example](https://app.codecov.io/github/cenfun/monocart-coverage-reports)
|
|
73
|
-
|
|
74
|
-

|
|
70
|
+
- `console-details` Show file coverage and uncovered lines in the console. Like `text`, but for V8.
|
|
75
71
|
|
|
76
|
-
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+
> Istanbul build-in reports (both V8 and istanbul data):
|
|
77
75
|
- `clover`
|
|
78
76
|
- `cobertura`
|
|
79
77
|
- `html`
|
|
@@ -93,8 +91,11 @@ console.log(coverageResults.summary);
|
|
|
93
91
|
- `text-lcov`
|
|
94
92
|
- `text-summary`
|
|
95
93
|
|
|
96
|
-
> Other reports
|
|
97
|
-
- `console-summary` shows coverage summary in console
|
|
94
|
+
> Other reports:
|
|
95
|
+
- `console-summary` shows coverage summary in the console
|
|
96
|
+
|
|
97
|
+

|
|
98
|
+
|
|
98
99
|
- `raw` only keep all original data, which can be used for other reports input with `inputDir`
|
|
99
100
|
- see [Merge Coverage Reports](#merge-coverage-reports)
|
|
100
101
|
|
|
@@ -258,16 +259,14 @@ mcr "node ./test/test-node-env.js" -c test/cli-options.js
|
|
|
258
259
|
| Coverage data | [Istanbul](https://github.com/gotwarlost/istanbul/blob/master/coverage.json.md) (Object) | [V8](#v8-coverage-data-format) (Array) | [V8](#v8-coverage-data-format) (Array) |
|
|
259
260
|
| Output | [Istanbul reports](#available-reports) | [V8 reports](#available-reports) | [Istanbul reports](#available-reports) |
|
|
260
261
|
| - Bytes | ❌ | ✅ | ❌ |
|
|
261
|
-
| - Statements | ✅ |
|
|
262
|
-
| - Branches | ✅ |
|
|
262
|
+
| - Statements | ✅ | ✅ | ✅ |
|
|
263
|
+
| - Branches | ✅ | ✅ | ✅ |
|
|
263
264
|
| - Functions | ✅ | ✅ | ✅ |
|
|
264
265
|
| - Lines | ✅ | ✅ | ✅ |
|
|
265
266
|
| - Execution counts | ✅ | ✅ | ✅ |
|
|
266
267
|
| CSS coverage | ❌ | ✅ | ✅ |
|
|
267
268
|
| Minified code | ❌ | ✅ | ❌ |
|
|
268
269
|
|
|
269
|
-
❔ - Partial or conditional support
|
|
270
|
-
|
|
271
270
|
## Compare Workflows
|
|
272
271
|
- Istanbul Workflows
|
|
273
272
|
- 1, [Collecting Istanbul coverage data](#collecting-istanbul-coverage-data)
|
|
@@ -451,7 +450,10 @@ const coverageOptions = {
|
|
|
451
450
|
};
|
|
452
451
|
await new CoverageReport(coverageOptions).generate();
|
|
453
452
|
```
|
|
454
|
-
|
|
453
|
+
|
|
454
|
+
## Resolve `sourcePath` for the Source Files
|
|
455
|
+
If the source file comes from the sourcemap, then its path is a virtual path. Using the `sourcePath` option to resolve a custom path.
|
|
456
|
+
For example, we have tested multiple dist files, which contain some common files. We hope to merge the coverage of the same files, so we need to unify the `sourcePath` in order to be able to merge the coverage data.
|
|
455
457
|
```js
|
|
456
458
|
const coverageOptions = {
|
|
457
459
|
sourcePath: (filePath) => {
|
|
@@ -468,6 +470,44 @@ const coverageOptions = {
|
|
|
468
470
|
```
|
|
469
471
|
see example: [./test/test-merge.js](./test/test-merge.js)
|
|
470
472
|
|
|
473
|
+
## Adding Empty Coverage for Untested Files
|
|
474
|
+
By default the untested files will not be included in the coverage report, we can first add empty coverage data for all files, so the files with coverage data will be merged, and untested files will retain 0% coverage.
|
|
475
|
+
```js
|
|
476
|
+
const fs = require('fs');
|
|
477
|
+
const path = require('path');
|
|
478
|
+
const { pathToFileURL } = require('url');
|
|
479
|
+
const MCR = require('monocart-coverage-reports');
|
|
480
|
+
|
|
481
|
+
const dir = "./src";
|
|
482
|
+
const coverageData = [];
|
|
483
|
+
const fileList = fs.readdirSync(dir);
|
|
484
|
+
for (const filename of fileList) {
|
|
485
|
+
const filePath = path.resolve(dir, filename);
|
|
486
|
+
const source = fs.readFileSync(filePath).toString('utf-8');
|
|
487
|
+
const sourcePath = path.relative(process.cwd(), filePath);
|
|
488
|
+
const url = pathToFileURL(sourcePath).toString();
|
|
489
|
+
const extname = path.extname(filename);
|
|
490
|
+
if (['.css'].includes(extname)) {
|
|
491
|
+
coverageData.push({
|
|
492
|
+
empty: true,
|
|
493
|
+
type: 'css',
|
|
494
|
+
url,
|
|
495
|
+
text: source
|
|
496
|
+
});
|
|
497
|
+
} else {
|
|
498
|
+
coverageData.push({
|
|
499
|
+
empty: true,
|
|
500
|
+
type: 'js',
|
|
501
|
+
url,
|
|
502
|
+
source
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const options = require('path-to/same-options.js');
|
|
507
|
+
await MCR(options).add(coverageData);
|
|
508
|
+
```
|
|
509
|
+
see example: [./test/cli-options.js](./test/cli-options.js)
|
|
510
|
+
|
|
471
511
|
## Ignoring Uncovered Codes
|
|
472
512
|
To ignore codes, use the special comment which starts with `v8 ignore `:
|
|
473
513
|
- Ignoring all until stop
|
|
@@ -575,15 +615,15 @@ see source code [v8-to-istanbul.js](https://github.com/istanbuljs/v8-to-istanbul
|
|
|
575
615
|
### How Monocart Works
|
|
576
616
|
We implemented new converter instead of v8-to-istanbul:
|
|
577
617
|
- 1, Trying to fix the middle position if not found the exact mapping for the position.
|
|
578
|
-
- 2, Finding all functions and branches by parsing the source code [AST](https://github.com/acornjs/acorn), however the V8 cannot provide effective branch coverage information
|
|
618
|
+
- 2, Finding all functions, statements and branches by parsing the source code [AST](https://github.com/acornjs/acorn), however the V8 cannot provide effective branch coverage information for `AssignmentPattern`.
|
|
579
619
|
|
|
580
620
|
| AST | V8 |
|
|
581
621
|
| :---------------------| :------------- |
|
|
582
622
|
| AssignmentPattern | 🛇 Not Support |
|
|
583
|
-
| ConditionalExpression | ✔
|
|
584
|
-
| IfStatement | ✔
|
|
585
|
-
| LogicalExpression | ✔
|
|
586
|
-
| SwitchStatement | ✔
|
|
623
|
+
| ConditionalExpression | ✔ |
|
|
624
|
+
| IfStatement | ✔ |
|
|
625
|
+
| LogicalExpression | ✔ |
|
|
626
|
+
| SwitchStatement | ✔ |
|
|
587
627
|
|
|
588
628
|
## Debug for Coverage and Sourcemap
|
|
589
629
|
> Sometimes, the coverage is not what we expect. The next step is to figure out why, and we can easily find out the answer step by step through debugging.
|
|
@@ -117,18 +117,21 @@ const createBranchGroup = (type, node, parents, branchMap) => {
|
|
|
117
117
|
group.operator = node.operator;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
// could be same start
|
|
121
|
+
const branchKey = `${start}_${end}`;
|
|
122
|
+
|
|
123
|
+
branchMap.set(branchKey, group);
|
|
121
124
|
return group;
|
|
122
125
|
};
|
|
123
126
|
|
|
124
127
|
const addBranch = (group, node, locationMap) => {
|
|
125
128
|
const { start, end } = node;
|
|
126
129
|
|
|
127
|
-
const
|
|
130
|
+
const branchKey = `${group.start}_${group.end}`;
|
|
128
131
|
|
|
129
132
|
const branchInfo = {
|
|
130
133
|
// for get previous group for LogicalExpression
|
|
131
|
-
|
|
134
|
+
branchKey,
|
|
132
135
|
start,
|
|
133
136
|
end,
|
|
134
137
|
// branch count default to 0
|
|
@@ -203,23 +206,16 @@ const IfStatement = (group, parentCount) => {
|
|
|
203
206
|
|
|
204
207
|
// const b = tf2 || tf1 || a;
|
|
205
208
|
const LogicalExpression = (group, parentCount) => {
|
|
206
|
-
const { noBlockList, blockCount } = updateBlockLocations(group.locations);
|
|
207
|
-
if (!noBlockList.length) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
209
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
// from left to right
|
|
211
|
+
group.locations.forEach((item, i) => {
|
|
212
|
+
if (item.block) {
|
|
213
|
+
item.count = item.block.count;
|
|
214
|
+
} else {
|
|
214
215
|
item.count = parentCount;
|
|
215
|
-
}
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const count = parentCount - blockCount;
|
|
220
|
-
noBlockList.forEach((item) => {
|
|
221
|
-
item.count = count;
|
|
216
|
+
}
|
|
222
217
|
});
|
|
218
|
+
|
|
223
219
|
};
|
|
224
220
|
|
|
225
221
|
const SwitchStatement = (group, parentCount) => {
|
|
@@ -408,7 +404,7 @@ const collectNodes = (ast) => {
|
|
|
408
404
|
// =============================================================
|
|
409
405
|
// id: { type: 'Identifier', name: '__webpack_modules__' },
|
|
410
406
|
const name = node.id && node.id.name;
|
|
411
|
-
if (name === '__webpack_modules__' && node.init) {
|
|
407
|
+
if (name === '__webpack_modules__' && node.init && node.init.properties) {
|
|
412
408
|
// mark all as wrap function
|
|
413
409
|
node.init.properties.forEach((it) => {
|
|
414
410
|
it.value._wrapKey = it.key && it.key.value;
|
|
@@ -501,12 +497,15 @@ const collectNodes = (ast) => {
|
|
|
501
497
|
const { left, right } = node;
|
|
502
498
|
// console.log(left.start, right.start);
|
|
503
499
|
|
|
500
|
+
// could be same branch start
|
|
501
|
+
// const da = arguments.length > 1 && typeof arguments[1] !== 'undefined' ? arguments[1] : true;
|
|
502
|
+
|
|
504
503
|
let group;
|
|
505
504
|
// link to same branch start if LogicalExpression
|
|
506
505
|
const prevLocation = locationMap.get(node.start);
|
|
507
506
|
if (prevLocation) {
|
|
508
507
|
// console.log('link branch ==================', type);
|
|
509
|
-
group = branchMap.get(prevLocation.
|
|
508
|
+
group = branchMap.get(prevLocation.branchKey);
|
|
510
509
|
} else {
|
|
511
510
|
group = createBranchGroup('LogicalExpression', node, parents, branchMap);
|
|
512
511
|
addBranch(group, left, locationMap);
|
|
@@ -574,6 +573,26 @@ const getRootFunctionState = (ast, coverageInfo) => {
|
|
|
574
573
|
return rootState;
|
|
575
574
|
};
|
|
576
575
|
|
|
576
|
+
const findFunctionRange = (item, coverageInfo) => {
|
|
577
|
+
|
|
578
|
+
const { node, reverseParents } = item;
|
|
579
|
+
const { start, end } = node;
|
|
580
|
+
|
|
581
|
+
// try function start/end
|
|
582
|
+
const functionRange = getFunctionRange(start, end, coverageInfo);
|
|
583
|
+
if (functionRange) {
|
|
584
|
+
return functionRange;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// try if class MethodDefinition
|
|
588
|
+
// 0 is function self
|
|
589
|
+
const parent = reverseParents[1];
|
|
590
|
+
if (parent && parent.type === 'MethodDefinition') {
|
|
591
|
+
return getFunctionRange(parent.start, parent.end, coverageInfo);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
};
|
|
595
|
+
|
|
577
596
|
const collectAstInfo = (ast, coverageInfo) => {
|
|
578
597
|
|
|
579
598
|
const {
|
|
@@ -611,7 +630,8 @@ const collectAstInfo = (ast, coverageInfo) => {
|
|
|
611
630
|
isFunction: true,
|
|
612
631
|
count: functionItem.count
|
|
613
632
|
};
|
|
614
|
-
|
|
633
|
+
|
|
634
|
+
const functionRange = findFunctionRange(item, coverageInfo);
|
|
615
635
|
if (functionRange) {
|
|
616
636
|
if (isWrap) {
|
|
617
637
|
functionRange.wrap = true;
|
package/lib/converter/ast.js
CHANGED
|
@@ -159,8 +159,8 @@ const getJsAstInfo = (item, coverageList) => {
|
|
|
159
159
|
// most time for node.js file
|
|
160
160
|
allowReturnOutsideFunction: true,
|
|
161
161
|
allowImportExportEverywhere: true,
|
|
162
|
-
allowSuperOutsideMethod: true,
|
|
163
162
|
allowAwaitOutsideFunction: true,
|
|
163
|
+
allowSuperOutsideMethod: true,
|
|
164
164
|
// first line: #!/usr/bin/env node
|
|
165
165
|
allowHashBang: true
|
|
166
166
|
};
|
|
@@ -579,11 +579,12 @@ const handleOriginalBranchesCoverage = (state, originalStateMap) => {
|
|
|
579
579
|
return newLoc;
|
|
580
580
|
}
|
|
581
581
|
|
|
582
|
+
// before new range
|
|
583
|
+
newLoc.generatedStart = newLoc.start;
|
|
584
|
+
newLoc.generatedEnd = newLoc.end;
|
|
582
585
|
// mapping to new range
|
|
583
586
|
newLoc.start = locResult.start;
|
|
584
587
|
newLoc.end = locResult.end;
|
|
585
|
-
newLoc.generatedStart = newLoc.start;
|
|
586
|
-
newLoc.generatedEnd = newLoc.end;
|
|
587
588
|
|
|
588
589
|
return newLoc;
|
|
589
590
|
});
|
|
@@ -371,8 +371,9 @@ const getGeneratedText = (m1, m2, state, offset) => {
|
|
|
371
371
|
// ========================================================================================================
|
|
372
372
|
|
|
373
373
|
const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
|
|
374
|
-
|
|
374
|
+
|
|
375
375
|
const [m1, m2] = mappings;
|
|
376
|
+
const { originalState, crossStart } = rangeInfo;
|
|
376
377
|
|
|
377
378
|
// cross file from start of line
|
|
378
379
|
if (crossStart) {
|
|
@@ -410,18 +411,8 @@ const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
|
|
|
410
411
|
|
|
411
412
|
const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
412
413
|
|
|
413
|
-
const { decodedMappings } = state;
|
|
414
|
-
|
|
415
|
-
// end is exclusive, try previous one if exact match
|
|
416
|
-
const prevMapping = findMapping(decodedMappings, end - 1);
|
|
417
|
-
if (prevMapping && !Array.isArray(prevMapping)) {
|
|
418
|
-
return {
|
|
419
|
-
originalEnd: prevMapping.originalOffset + 1
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
const { originalState, crossEnd } = rangeInfo;
|
|
424
414
|
const [m1, m2] = mappings;
|
|
415
|
+
const { originalState, crossEnd } = rangeInfo;
|
|
425
416
|
|
|
426
417
|
// cross file until e1 line end (not file end)
|
|
427
418
|
if (crossEnd) {
|
|
@@ -431,6 +422,39 @@ const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
|
431
422
|
};
|
|
432
423
|
}
|
|
433
424
|
|
|
425
|
+
// end is exclusive
|
|
426
|
+
// quick check previous one if exact match
|
|
427
|
+
// most of case is matching "}"
|
|
428
|
+
if (m1.generatedOffset === end - 1) {
|
|
429
|
+
return {
|
|
430
|
+
originalEnd: m1.originalOffset + 1
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// quick check next one if exact match
|
|
435
|
+
// most of case is same string
|
|
436
|
+
if (m2.generatedOffset === end + 1) {
|
|
437
|
+
const gt = state.locator.source[end];
|
|
438
|
+
const oi = m2.originalOffset - 1;
|
|
439
|
+
const ot = originalState.locator.source[oi];
|
|
440
|
+
if (gt === ot) {
|
|
441
|
+
return {
|
|
442
|
+
originalEnd: oi
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Not applicable
|
|
447
|
+
// console.log('==================================');
|
|
448
|
+
// console.log({
|
|
449
|
+
// gp: state.sourcePath,
|
|
450
|
+
// g: end,
|
|
451
|
+
// gt,
|
|
452
|
+
// op: originalState.sourcePath,
|
|
453
|
+
// o: oi,
|
|
454
|
+
// ot
|
|
455
|
+
// });
|
|
456
|
+
}
|
|
457
|
+
|
|
434
458
|
const direction = 'end';
|
|
435
459
|
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo, direction);
|
|
436
460
|
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, end);
|
|
@@ -621,23 +645,13 @@ const getOriginalState = (startMappings, endMappings, originalMap) => {
|
|
|
621
645
|
};
|
|
622
646
|
};
|
|
623
647
|
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
const createMappingError = (errors) => {
|
|
648
|
+
const getMappingInfo = (decodedMappings, start, end) => {
|
|
649
|
+
// possible no length
|
|
650
|
+
if (decodedMappings.length < 2) {
|
|
629
651
|
return {
|
|
630
652
|
error: true,
|
|
631
|
-
|
|
632
|
-
end,
|
|
633
|
-
sourcePath,
|
|
634
|
-
errors
|
|
653
|
+
errors: ['invalid decoded mappings (length < 2)']
|
|
635
654
|
};
|
|
636
|
-
};
|
|
637
|
-
|
|
638
|
-
// possible no length
|
|
639
|
-
if (decodedMappings.length < 2) {
|
|
640
|
-
return createMappingError(['not found decoded mappings']);
|
|
641
655
|
}
|
|
642
656
|
|
|
643
657
|
// start: inclusive
|
|
@@ -660,6 +674,33 @@ const findOriginalRange = (start, end, state, originalMap) => {
|
|
|
660
674
|
};
|
|
661
675
|
}
|
|
662
676
|
|
|
677
|
+
return {
|
|
678
|
+
startMappings,
|
|
679
|
+
endMappings
|
|
680
|
+
};
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
const findOriginalRange = (start, end, state, originalMap) => {
|
|
684
|
+
|
|
685
|
+
const { sourcePath, decodedMappings } = state;
|
|
686
|
+
|
|
687
|
+
const createMappingError = (errors) => {
|
|
688
|
+
return {
|
|
689
|
+
error: true,
|
|
690
|
+
start,
|
|
691
|
+
end,
|
|
692
|
+
sourcePath,
|
|
693
|
+
errors
|
|
694
|
+
};
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
const mappingInfo = getMappingInfo(decodedMappings, start, end);
|
|
698
|
+
if (mappingInfo.error) {
|
|
699
|
+
return createMappingError(mappingInfo.errors);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const { startMappings, endMappings } = mappingInfo;
|
|
703
|
+
|
|
663
704
|
const rangeInfo = getOriginalState(startMappings, endMappings, originalMap);
|
|
664
705
|
if (rangeInfo.error) {
|
|
665
706
|
return createMappingError(rangeInfo.errors);
|
package/lib/generate.js
CHANGED
|
@@ -72,6 +72,7 @@ const getReportGroup = (reports, lcov, dataType) => {
|
|
|
72
72
|
'v8': 'v8',
|
|
73
73
|
'v8-json': 'v8',
|
|
74
74
|
'codecov': 'v8',
|
|
75
|
+
'console-details': 'v8',
|
|
75
76
|
|
|
76
77
|
// istanbul
|
|
77
78
|
'clover': 'istanbul',
|
|
@@ -126,22 +127,9 @@ const getReportGroup = (reports, lcov, dataType) => {
|
|
|
126
127
|
|
|
127
128
|
// ========================================================================================================
|
|
128
129
|
|
|
129
|
-
const capitalizeFirstLetter = (string) => {
|
|
130
|
-
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
130
|
const pFormatter = (v, row, column) => {
|
|
134
131
|
if (typeof v === 'number') {
|
|
135
|
-
|
|
136
|
-
if (row.status === 'low') {
|
|
137
|
-
return EC.red(p);
|
|
138
|
-
}
|
|
139
|
-
if (row.status === 'medium') {
|
|
140
|
-
return EC.yellow(p);
|
|
141
|
-
}
|
|
142
|
-
if (row.status === 'high') {
|
|
143
|
-
return EC.green(p);
|
|
144
|
-
}
|
|
132
|
+
return Util.getColorStrByStatus(Util.PSF(v, 100, 2), row.status);
|
|
145
133
|
}
|
|
146
134
|
return v;
|
|
147
135
|
};
|
|
@@ -153,9 +141,12 @@ const nFormatter = (v) => {
|
|
|
153
141
|
return v;
|
|
154
142
|
};
|
|
155
143
|
|
|
156
|
-
const
|
|
144
|
+
const handleConsoleSummaryReport = (reportData, reportOptions, options) => {
|
|
157
145
|
|
|
158
|
-
const
|
|
146
|
+
const csOptions = {
|
|
147
|
+
metrics: [],
|
|
148
|
+
... reportOptions
|
|
149
|
+
};
|
|
159
150
|
|
|
160
151
|
const {
|
|
161
152
|
summary, name, type
|
|
@@ -165,23 +156,12 @@ const showConsoleSummary = (reportData, reportOptions, options) => {
|
|
|
165
156
|
EC.logCyan(name);
|
|
166
157
|
}
|
|
167
158
|
|
|
168
|
-
const
|
|
169
|
-
v8: ['bytes', 'statements', 'branches', 'functions', 'lines'],
|
|
170
|
-
istanbul: ['statements', 'branches', 'functions', 'lines']
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
let list = allMetrics[type];
|
|
174
|
-
if (Util.isList(metrics)) {
|
|
175
|
-
const newList = list.filter((k) => metrics.includes(k));
|
|
176
|
-
if (newList.length) {
|
|
177
|
-
list = newList;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
159
|
+
const metrics = Util.getMetrics(type, csOptions.metrics);
|
|
180
160
|
|
|
181
|
-
const rows =
|
|
161
|
+
const rows = metrics.map((k) => {
|
|
182
162
|
return {
|
|
183
163
|
... summary[k],
|
|
184
|
-
name: capitalizeFirstLetter(k)
|
|
164
|
+
name: Util.capitalizeFirstLetter(k)
|
|
185
165
|
};
|
|
186
166
|
});
|
|
187
167
|
|
|
@@ -216,7 +196,7 @@ const showConsoleSummary = (reportData, reportOptions, options) => {
|
|
|
216
196
|
});
|
|
217
197
|
};
|
|
218
198
|
|
|
219
|
-
const
|
|
199
|
+
const handleRawReport = (reportData, reportOptions, options) => {
|
|
220
200
|
const rawOptions = {
|
|
221
201
|
outputDir: 'raw',
|
|
222
202
|
... reportOptions
|
|
@@ -285,8 +265,8 @@ const generateCoverageReports = async (dataList, sourceCache, options) => {
|
|
|
285
265
|
// console.log(Object.keys(coverageResults));
|
|
286
266
|
|
|
287
267
|
const buildInBothReports = {
|
|
288
|
-
'console-summary':
|
|
289
|
-
'raw':
|
|
268
|
+
'console-summary': handleConsoleSummaryReport,
|
|
269
|
+
'raw': handleRawReport
|
|
290
270
|
};
|
|
291
271
|
|
|
292
272
|
const bothGroup = options.reportGroup.both;
|
package/lib/index.d.ts
CHANGED
|
@@ -36,6 +36,11 @@ declare namespace MCR {
|
|
|
36
36
|
['codecov'] | ["codecov", {
|
|
37
37
|
outputFile?: string;
|
|
38
38
|
}] |
|
|
39
|
+
['console-details'] | ['console-details', {
|
|
40
|
+
maxCols?: number;
|
|
41
|
+
skipPercent?: number;
|
|
42
|
+
metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">;
|
|
43
|
+
}] |
|
|
39
44
|
['clover'] | ['clover', {
|
|
40
45
|
file?: string;
|
|
41
46
|
}] |
|