monocart-coverage-reports 2.6.3 → 2.6.5
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 +36 -16
- package/lib/cli.js +27 -97
- package/lib/converter/ast.js +3 -1
- package/lib/converter/find-original-range.js +49 -27
- package/lib/default/options.js +28 -24
- package/lib/generate.js +5 -2
- package/lib/index.d.ts +71 -40
- package/lib/index.js +86 -11
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
- [Using `v8-to-istanbul`](#using-v8-to-istanbul)
|
|
34
34
|
- [How Monocart Works](#how-monocart-works)
|
|
35
35
|
* [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
36
|
+
* [Common issues](#common-issues)
|
|
36
37
|
* [Integration](#integration)
|
|
37
38
|
- [Playwright](#playwright)
|
|
38
39
|
- [Jest](#jest)
|
|
@@ -282,10 +283,11 @@ Arguments:
|
|
|
282
283
|
|
|
283
284
|
Options:
|
|
284
285
|
-V, --version output the version number
|
|
285
|
-
-c, --config <path> custom config path
|
|
286
|
-
|
|
287
|
-
-r, --reports <name[,name]> coverage reports to use
|
|
286
|
+
-c, --config <path> custom config file path
|
|
287
|
+
--logging <logging> off, error, info, debug
|
|
288
288
|
-n, --name <name> report name for title
|
|
289
|
+
-r, --reports <name[,name]> coverage reports to use
|
|
290
|
+
-o, --outputDir <dir> output dir for reports
|
|
289
291
|
-i, --inputDir <dir> input dir for merging raw files
|
|
290
292
|
--entryFilter <pattern> entry url filter
|
|
291
293
|
--sourceFilter <pattern> source path filter
|
|
@@ -293,24 +295,20 @@ Options:
|
|
|
293
295
|
--inline inline html for v8 report
|
|
294
296
|
--assetsPath <path> assets path if not inline
|
|
295
297
|
--lcov generate lcov.info file
|
|
296
|
-
--logging <logging> off, error, info, debug
|
|
297
298
|
-h, --help display help for command
|
|
298
299
|
```
|
|
299
300
|
|
|
300
|
-
- Loading
|
|
301
|
-
-
|
|
302
|
-
- `mcr.config.json`
|
|
303
|
-
- `mcr.config.mjs`
|
|
304
|
-
- `mcr.config.cjs`
|
|
301
|
+
- Loading config file by priority:
|
|
302
|
+
- custom config file with `-c` or `--config`
|
|
305
303
|
- `mcr.config.js`
|
|
306
|
-
- `mcr.config.
|
|
307
|
-
|
|
308
|
-
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
304
|
+
- `mcr.config.cjs`
|
|
305
|
+
- `mcr.config.mjs`
|
|
306
|
+
- `mcr.config.json` - json format
|
|
307
|
+
- `.mcrrc.js`
|
|
308
|
+
- `.mcrrc` - json format
|
|
309
|
+
- `mcr.config.ts` - it requires `NODE_OPTIONS="--loader ts-node/esm"`
|
|
312
310
|
|
|
313
|
-
-
|
|
311
|
+
- Working with `ts-node`, see [mcr-ts-node](https://github.com/cenfun/mcr-ts-node)
|
|
314
312
|
|
|
315
313
|
## Compare Reports
|
|
316
314
|
| | Istanbul | V8 | V8 to Istanbul |
|
|
@@ -707,6 +705,28 @@ When `logging` is `debug`, the raw report data will be preserved in `[outputDir]
|
|
|
707
705
|
|
|
708
706
|

|
|
709
707
|
|
|
708
|
+
## Common issues
|
|
709
|
+
- `Unparsable source`
|
|
710
|
+
|
|
711
|
+
It happens during the parsing of the source code into AST, if the source code is not in the standard ECMAScript. For example `ts`, `jsx` and so on. There is a option to fix it, which is to manually compile the source code for these files.
|
|
712
|
+
```js
|
|
713
|
+
import * as fs from "fs";
|
|
714
|
+
import * as path from "path";
|
|
715
|
+
import { fileURLToPath } from "url";
|
|
716
|
+
import * as TsNode from 'ts-node';
|
|
717
|
+
const coverageOptions = {
|
|
718
|
+
onEntry: async (entry) => {
|
|
719
|
+
const filePath = fileURLToPath(entry.url)
|
|
720
|
+
const originalSource = fs.readFileSync(filePath).toString("utf-8");
|
|
721
|
+
const fileName = path.basename(filePath);
|
|
722
|
+
const tn = TsNode.create({});
|
|
723
|
+
const source = tn.compile(originalSource, fileName);
|
|
724
|
+
entry.fake = false;
|
|
725
|
+
entry.source = source;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
```
|
|
729
|
+
|
|
710
730
|
## Integration
|
|
711
731
|
|
|
712
732
|
### [Playwright](https://github.com/microsoft/playwright)
|
package/lib/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const EC = require('eight-colors');
|
|
6
|
-
const { fileURLToPath
|
|
6
|
+
const { fileURLToPath } = require('url');
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
9
|
foregroundChild,
|
|
@@ -12,86 +12,10 @@ const {
|
|
|
12
12
|
|
|
13
13
|
const MCR = require('./index.js');
|
|
14
14
|
const Util = require('./utils/util.js');
|
|
15
|
-
const defaultOptions = require('./default/options.js');
|
|
16
15
|
const { resolveSourceMap } = require('./converter/collect-source-maps.js');
|
|
17
16
|
|
|
18
17
|
const version = require('../package.json').version;
|
|
19
18
|
|
|
20
|
-
const resolveConfigPath = (customConfigPath) => {
|
|
21
|
-
|
|
22
|
-
const configList = [
|
|
23
|
-
'.mcrrc',
|
|
24
|
-
'mcr.config.json',
|
|
25
|
-
'mcr.config.mjs',
|
|
26
|
-
'mcr.config.cjs',
|
|
27
|
-
'mcr.config.js',
|
|
28
|
-
'mcr.config.ts'
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
if (customConfigPath) {
|
|
32
|
-
configList.push(customConfigPath);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const existsList = configList.filter((p) => fs.existsSync(p));
|
|
36
|
-
if (!existsList.length) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// last one
|
|
41
|
-
const configPath = existsList.pop();
|
|
42
|
-
Util.logInfo(`Config: ${EC.cyan(configPath)}`);
|
|
43
|
-
|
|
44
|
-
return configPath;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const resolveConfigOptions = async (configPath) => {
|
|
48
|
-
|
|
49
|
-
// json format
|
|
50
|
-
const ext = path.extname(configPath);
|
|
51
|
-
if (ext === '.json' || configPath.slice(-2) === 'rc') {
|
|
52
|
-
return JSON.parse(Util.readFileSync(configPath));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let configOptions;
|
|
56
|
-
let err;
|
|
57
|
-
try {
|
|
58
|
-
configOptions = await import(pathToFileURL(configPath));
|
|
59
|
-
} catch (ee) {
|
|
60
|
-
err = ee;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (err || !configOptions) {
|
|
64
|
-
Util.logError(`ERROR: failed to import "${configPath}": ${err && err.message} `);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
configOptions = configOptions.default || configOptions;
|
|
69
|
-
|
|
70
|
-
return configOptions;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const initOptions = async (cliOptions) => {
|
|
74
|
-
|
|
75
|
-
const configPath = resolveConfigPath(cliOptions.config);
|
|
76
|
-
if (configPath) {
|
|
77
|
-
const configOptions = await resolveConfigOptions(configPath);
|
|
78
|
-
if (configOptions) {
|
|
79
|
-
cliOptions = {
|
|
80
|
-
... configOptions,
|
|
81
|
-
... cliOptions
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// report options
|
|
87
|
-
const options = {
|
|
88
|
-
... defaultOptions,
|
|
89
|
-
... cliOptions
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
return options;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
19
|
const resolveEntrySource = (entry, sourceMapCache = {}) => {
|
|
96
20
|
let source;
|
|
97
21
|
const filePath = fileURLToPath(entry.url);
|
|
@@ -100,7 +24,7 @@ const resolveEntrySource = (entry, sourceMapCache = {}) => {
|
|
|
100
24
|
source = fs.readFileSync(filePath).toString('utf8');
|
|
101
25
|
}
|
|
102
26
|
|
|
103
|
-
// not for typescript
|
|
27
|
+
// not for typescript, but it could be jsx even it is `.js`
|
|
104
28
|
if (source && !['.ts', '.tsx'].includes(extname)) {
|
|
105
29
|
entry.source = source;
|
|
106
30
|
return;
|
|
@@ -111,7 +35,6 @@ const resolveEntrySource = (entry, sourceMapCache = {}) => {
|
|
|
111
35
|
|
|
112
36
|
// for fake source file (can not parse to AST)
|
|
113
37
|
if (lineLengths) {
|
|
114
|
-
// get runtime code with ts-node
|
|
115
38
|
let fakeSource = '';
|
|
116
39
|
sourcemapData.lineLengths.forEach((length) => {
|
|
117
40
|
fakeSource += `${''.padEnd(length, '*')}\n`;
|
|
@@ -188,25 +111,25 @@ const addCoverageData = async (coverageReport, nodeV8CoverageDir) => {
|
|
|
188
111
|
|
|
189
112
|
const executeCommand = async (command, cliOptions) => {
|
|
190
113
|
|
|
191
|
-
const options = await initOptions(cliOptions);
|
|
192
|
-
|
|
193
114
|
Util.logInfo(`Execute: ${EC.cyan(command)}`);
|
|
115
|
+
|
|
194
116
|
// console.log(options);
|
|
117
|
+
const coverageReport = MCR(cliOptions);
|
|
118
|
+
await coverageReport.loadConfig(cliOptions.config);
|
|
119
|
+
coverageReport.cleanCache();
|
|
195
120
|
|
|
196
|
-
const
|
|
197
|
-
process.env.NODE_V8_COVERAGE = nodeV8CoverageDir;
|
|
121
|
+
const coverageOptions = coverageReport.options;
|
|
198
122
|
|
|
123
|
+
// dir for node v8 coverage
|
|
124
|
+
const nodeV8CoverageDir = Util.relativePath(path.resolve(coverageOptions.outputDir, '.v8-coverage'));
|
|
125
|
+
process.env.NODE_V8_COVERAGE = nodeV8CoverageDir;
|
|
199
126
|
// clean v8 cache before running
|
|
200
127
|
Util.rmSync(nodeV8CoverageDir);
|
|
201
|
-
|
|
202
|
-
// console.log('nodeV8CoverageDir', nodeV8CoverageDir);
|
|
203
|
-
|
|
204
|
-
const coverageReport = MCR(options);
|
|
205
|
-
coverageReport.cleanCache();
|
|
128
|
+
// Util.logInfo(`V8 coverage dir: ${EC.cyan(nodeV8CoverageDir)}`);
|
|
206
129
|
|
|
207
130
|
// =========================================
|
|
208
131
|
// onStart hook
|
|
209
|
-
const onStart =
|
|
132
|
+
const onStart = coverageOptions.onStart;
|
|
210
133
|
if (typeof onStart === 'function') {
|
|
211
134
|
await onStart(coverageReport);
|
|
212
135
|
}
|
|
@@ -214,17 +137,19 @@ const executeCommand = async (command, cliOptions) => {
|
|
|
214
137
|
|
|
215
138
|
const subprocess = foregroundChild(command, {
|
|
216
139
|
shell: true
|
|
217
|
-
}, async () => {
|
|
140
|
+
}, async (code, signal) => {
|
|
141
|
+
|
|
142
|
+
// generate coverage even it is failed. code != 0
|
|
218
143
|
|
|
219
144
|
if (!fs.existsSync(nodeV8CoverageDir)) {
|
|
220
|
-
EC.logRed(`Not found coverage
|
|
145
|
+
EC.logRed(`Not found V8 coverage dir: ${Util.relativePath(nodeV8CoverageDir)}`);
|
|
221
146
|
return 1;
|
|
222
147
|
}
|
|
223
148
|
|
|
224
149
|
// =========================================
|
|
225
150
|
// onReady hook before adding coverage data.
|
|
226
151
|
// Sometimes, the child process has not yet finished writing the coverage data, and it needs to wait here.
|
|
227
|
-
const onReady =
|
|
152
|
+
const onReady = coverageOptions.onReady;
|
|
228
153
|
if (typeof onReady === 'function') {
|
|
229
154
|
await onReady(coverageReport, nodeV8CoverageDir, subprocess);
|
|
230
155
|
}
|
|
@@ -243,16 +168,23 @@ const executeCommand = async (command, cliOptions) => {
|
|
|
243
168
|
|
|
244
169
|
};
|
|
245
170
|
|
|
171
|
+
process.on('uncaughtException', function(err) {
|
|
172
|
+
Util.logError(`ERROR: ${err.message || err}`);
|
|
173
|
+
});
|
|
174
|
+
|
|
246
175
|
program
|
|
247
176
|
.name('mcr')
|
|
248
177
|
.description('CLI to generate coverage reports')
|
|
249
178
|
.version(version)
|
|
250
179
|
.argument('<command>', 'command to execute')
|
|
251
180
|
.allowUnknownOption()
|
|
252
|
-
.option('-c, --config <path>', 'custom config path')
|
|
253
|
-
.option('
|
|
254
|
-
|
|
181
|
+
.option('-c, --config <path>', 'custom config file path')
|
|
182
|
+
.option('--logging <logging>', 'off, error, info, debug')
|
|
183
|
+
|
|
255
184
|
.option('-n, --name <name>', 'report name for title')
|
|
185
|
+
.option('-r, --reports <name[,name]>', 'coverage reports to use')
|
|
186
|
+
|
|
187
|
+
.option('-o, --outputDir <dir>', 'output dir for reports')
|
|
256
188
|
.option('-i, --inputDir <dir>', 'input dir for merging raw files')
|
|
257
189
|
|
|
258
190
|
.option('--entryFilter <pattern>', 'entry url filter')
|
|
@@ -264,8 +196,6 @@ program
|
|
|
264
196
|
|
|
265
197
|
.option('--lcov', 'generate lcov.info file')
|
|
266
198
|
|
|
267
|
-
.option('--logging <logging>', 'off, error, info, debug')
|
|
268
|
-
|
|
269
199
|
.action((_command, cliOptions) => {
|
|
270
200
|
const command = program.args.join(' ');
|
|
271
201
|
executeCommand(command, cliOptions);
|
package/lib/converter/ast.js
CHANGED
|
@@ -188,7 +188,9 @@ const getJsAstInfo = (item, coverageList) => {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
// runtime code should be parsed successful
|
|
191
|
-
Util.logInfo(`
|
|
191
|
+
Util.logInfo(`Unparsable source: ${item.sourcePath} ${err.message}`);
|
|
192
|
+
|
|
193
|
+
// it could be jsx even it is `.js`
|
|
192
194
|
|
|
193
195
|
// https://github.com/acornjs/acorn/tree/master/acorn-loose
|
|
194
196
|
// It is recommended to always try a parse with the regular acorn parser first,
|
|
@@ -97,6 +97,7 @@ const getBlockEndPosition = (originalLineText) => {
|
|
|
97
97
|
// generatedPos: 17,
|
|
98
98
|
// originalText: ' }}</slot>'
|
|
99
99
|
|
|
100
|
+
// end marks
|
|
100
101
|
const list = ['>', '}', ')'];
|
|
101
102
|
for (const s of list) {
|
|
102
103
|
const endBlockIndex = originalLineText.lastIndexOf(s);
|
|
@@ -116,7 +117,11 @@ const getBlockEndPosition = (originalLineText) => {
|
|
|
116
117
|
|
|
117
118
|
};
|
|
118
119
|
|
|
119
|
-
const getComparedPosition = (
|
|
120
|
+
const getComparedPosition = (info, direction) => {
|
|
121
|
+
|
|
122
|
+
let gt = info.generatedText;
|
|
123
|
+
const gp = info.generatedPos;
|
|
124
|
+
let ot = info.originalText;
|
|
120
125
|
|
|
121
126
|
// before trim
|
|
122
127
|
const oLen = ot.length;
|
|
@@ -175,45 +180,54 @@ const getComparedPosition = (gt, gp, ot, direction) => {
|
|
|
175
180
|
|
|
176
181
|
// ============================
|
|
177
182
|
// right matched
|
|
183
|
+
// only for original first line text
|
|
178
184
|
|
|
185
|
+
const olt = info.originalLineText;
|
|
179
186
|
const right = gt.slice(gp);
|
|
180
|
-
if (
|
|
187
|
+
if (olt.endsWith(right)) {
|
|
181
188
|
return {
|
|
182
|
-
pos:
|
|
189
|
+
pos: olt.length - right.length
|
|
183
190
|
};
|
|
184
191
|
}
|
|
185
192
|
|
|
186
193
|
};
|
|
187
194
|
|
|
195
|
+
const initOriginalLineText = (info) => {
|
|
196
|
+
const originalText = info.originalText;
|
|
197
|
+
// never cross line, using first line of original text
|
|
198
|
+
// trim end remove \r\n and \n
|
|
199
|
+
const originalLines = originalText.split(/\n/);
|
|
200
|
+
if (originalLines.length === 1) {
|
|
201
|
+
// already single line
|
|
202
|
+
info.originalLineText = originalText.trimEnd();
|
|
203
|
+
info.originalSingle = true;
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// multiple liens
|
|
207
|
+
info.originalLineText = originalLines[0].trimEnd();
|
|
208
|
+
};
|
|
209
|
+
|
|
188
210
|
const getSimilarPosition = (info, direction) => {
|
|
189
211
|
|
|
190
|
-
|
|
191
|
-
generatedText, generatedPos, originalText
|
|
192
|
-
} = info;
|
|
212
|
+
initOriginalLineText(info);
|
|
193
213
|
|
|
194
|
-
const textPos = getComparedPosition(
|
|
214
|
+
const textPos = getComparedPosition(info, direction);
|
|
195
215
|
if (textPos) {
|
|
196
216
|
return textPos;
|
|
197
217
|
}
|
|
198
218
|
|
|
199
|
-
|
|
200
|
-
// trim end remove \r\n and \n
|
|
201
|
-
const originalLines = originalText.split(/\n/);
|
|
202
|
-
if (originalLines.length === 1) {
|
|
203
|
-
// already single line
|
|
204
|
-
info.originalLineText = originalText;
|
|
219
|
+
if (info.originalSingle) {
|
|
205
220
|
return;
|
|
206
221
|
}
|
|
207
222
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
223
|
+
// multiple lines
|
|
224
|
+
const { generatedPos, originalLineText } = info;
|
|
211
225
|
// generatedPos not in first line
|
|
212
226
|
if (generatedPos > originalLineText.length) {
|
|
213
227
|
return;
|
|
214
228
|
}
|
|
215
229
|
|
|
216
|
-
const linePos = getComparedPosition(
|
|
230
|
+
const linePos = getComparedPosition(info, direction);
|
|
217
231
|
if (linePos) {
|
|
218
232
|
return linePos;
|
|
219
233
|
}
|
|
@@ -236,6 +250,7 @@ const getFixedPosition = (info, direction) => {
|
|
|
236
250
|
return similarPos.pos;
|
|
237
251
|
}
|
|
238
252
|
|
|
253
|
+
|
|
239
254
|
// generatedText: never cross lines
|
|
240
255
|
// originalText: could be multiple lines
|
|
241
256
|
// originalLineText: single line originalText
|
|
@@ -266,7 +281,7 @@ const getOriginalEndOffset = (m, rangeInfo) => {
|
|
|
266
281
|
return m.originalEndOffset;
|
|
267
282
|
};
|
|
268
283
|
|
|
269
|
-
const getOriginalText = (m1, m2, rangeInfo
|
|
284
|
+
const getOriginalText = (m1, m2, rangeInfo) => {
|
|
270
285
|
const originalLocator = rangeInfo.originalState.locator;
|
|
271
286
|
|
|
272
287
|
const o1 = m1.originalOffset;
|
|
@@ -383,15 +398,17 @@ const getFixedOriginalStart = (start, mappings, state, rangeInfo) => {
|
|
|
383
398
|
}
|
|
384
399
|
|
|
385
400
|
const direction = 'start';
|
|
386
|
-
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo
|
|
401
|
+
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo);
|
|
387
402
|
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, start);
|
|
388
403
|
|
|
389
|
-
const
|
|
404
|
+
const info = {
|
|
390
405
|
generatedText,
|
|
391
406
|
generatedPos,
|
|
392
407
|
originalText,
|
|
393
408
|
originalState
|
|
394
|
-
}
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
const originalPos = getFixedPosition(info, direction);
|
|
395
412
|
|
|
396
413
|
// if (start === 2660) {
|
|
397
414
|
// console.log('=====================================================');
|
|
@@ -437,7 +454,8 @@ const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
|
437
454
|
const gt = state.locator.source[end];
|
|
438
455
|
const oi = m2.originalOffset - 1;
|
|
439
456
|
const ot = originalState.locator.source[oi];
|
|
440
|
-
|
|
457
|
+
// it could be ; but it quite far away
|
|
458
|
+
if (gt === ot && [';', ','].includes(gt)) {
|
|
441
459
|
return {
|
|
442
460
|
originalEnd: oi
|
|
443
461
|
};
|
|
@@ -456,24 +474,28 @@ const getFixedOriginalEnd = (end, mappings, state, rangeInfo) => {
|
|
|
456
474
|
}
|
|
457
475
|
|
|
458
476
|
const direction = 'end';
|
|
459
|
-
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo
|
|
477
|
+
const { originalText, originalOffset } = getOriginalText(m1, m2, rangeInfo);
|
|
460
478
|
const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, end);
|
|
461
479
|
|
|
462
|
-
const
|
|
480
|
+
const info = {
|
|
481
|
+
offset: end,
|
|
463
482
|
generatedText,
|
|
464
483
|
generatedPos,
|
|
465
484
|
originalText,
|
|
466
485
|
originalState
|
|
467
|
-
}
|
|
486
|
+
};
|
|
468
487
|
|
|
469
|
-
|
|
488
|
+
const originalPos = getFixedPosition(info, direction);
|
|
489
|
+
|
|
490
|
+
// if (end === 1304578) {
|
|
470
491
|
// console.log('=====================================================');
|
|
471
492
|
// console.log('fixed end', originalState.sourcePath);
|
|
472
493
|
// console.log({
|
|
473
494
|
// generatedText,
|
|
474
495
|
// generatedPos,
|
|
475
496
|
// originalText,
|
|
476
|
-
// originalPos
|
|
497
|
+
// originalPos,
|
|
498
|
+
// originalLineText: info.originalLineText
|
|
477
499
|
// });
|
|
478
500
|
// }
|
|
479
501
|
|
package/lib/default/options.js
CHANGED
|
@@ -3,11 +3,8 @@ module.exports = {
|
|
|
3
3
|
// {string} logging levels: off, error, info, debug
|
|
4
4
|
logging: 'info',
|
|
5
5
|
|
|
6
|
-
// {string}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// {string|string[]} input raw dir(s)
|
|
10
|
-
inputDir: null,
|
|
6
|
+
// {string} Report name. Defaults to "Coverage Report".
|
|
7
|
+
name: 'Coverage Report',
|
|
11
8
|
|
|
12
9
|
// {string} v8 or html for istanbul by default
|
|
13
10
|
// {array} multiple reports with options
|
|
@@ -21,17 +18,11 @@ module.exports = {
|
|
|
21
18
|
// ],
|
|
22
19
|
reports: '',
|
|
23
20
|
|
|
24
|
-
// {string}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// (V8 only) {string} Output [sub dir/]filename. Defaults to "index.html"
|
|
28
|
-
outputFile: 'index.html',
|
|
29
|
-
|
|
30
|
-
// (V8 only) {boolean} Inline all scripts to the single HTML file. Defaults to false.
|
|
31
|
-
inline: false,
|
|
21
|
+
// {string} output dir
|
|
22
|
+
outputDir: './coverage-reports',
|
|
32
23
|
|
|
33
|
-
//
|
|
34
|
-
|
|
24
|
+
// {string|string[]} input raw dir(s)
|
|
25
|
+
inputDir: null,
|
|
35
26
|
|
|
36
27
|
// (V8 only) {function} A filter function to execute for each element in the V8 list.
|
|
37
28
|
// entryFilter: (entry) => {
|
|
@@ -46,6 +37,24 @@ module.exports = {
|
|
|
46
37
|
// sourceFilter: (sourcePath) => sourcePath.search(/src\/.+/) !== -1,
|
|
47
38
|
sourceFilter: null,
|
|
48
39
|
|
|
40
|
+
// {function} Source path handler.
|
|
41
|
+
// sourcePath: (filePath) => `wwwroot/${filePath}`,
|
|
42
|
+
sourcePath: null,
|
|
43
|
+
|
|
44
|
+
// (V8 only) {string} Output [sub dir/]filename. Defaults to "index.html"
|
|
45
|
+
outputFile: 'index.html',
|
|
46
|
+
|
|
47
|
+
// (V8 only) {boolean} Inline all scripts to the single HTML file. Defaults to false.
|
|
48
|
+
inline: false,
|
|
49
|
+
|
|
50
|
+
// (V8 only) {string} Assets path if not inline. Defaults to "./assets"
|
|
51
|
+
assetsPath: './assets',
|
|
52
|
+
|
|
53
|
+
// (Istanbul only) defaultSummarizer, sourceFinder
|
|
54
|
+
|
|
55
|
+
// {boolean} Generate lcov.info file, same as lcovonly report. Defaults to false.
|
|
56
|
+
lcov: false,
|
|
57
|
+
|
|
49
58
|
// options for adding empty coverage for all files
|
|
50
59
|
// all: {
|
|
51
60
|
// dir: ['src'],
|
|
@@ -56,15 +65,6 @@ module.exports = {
|
|
|
56
65
|
// (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop
|
|
57
66
|
v8Ignore: true,
|
|
58
67
|
|
|
59
|
-
// (Istanbul only) defaultSummarizer, sourceFinder
|
|
60
|
-
|
|
61
|
-
// {boolean} Generate lcov.info file, same as lcovonly report. Defaults to false.
|
|
62
|
-
lcov: false,
|
|
63
|
-
|
|
64
|
-
// {function} Source path handler.
|
|
65
|
-
// sourcePath: (filePath) => `wwwroot/${filePath}`,
|
|
66
|
-
sourcePath: null,
|
|
67
|
-
|
|
68
68
|
// {string|function} Specify the report path, especially when there are multiple reports. Defaults to outputDir/index.html.
|
|
69
69
|
reportPath: null,
|
|
70
70
|
|
|
@@ -78,6 +78,10 @@ module.exports = {
|
|
|
78
78
|
// {boolean} Indicates whether to clean previous cache in output dir before generating report. Defaults to false.
|
|
79
79
|
cleanCache: false,
|
|
80
80
|
|
|
81
|
+
// {function} onEntry hook
|
|
82
|
+
// onEntry: async (entry) => {}
|
|
83
|
+
onEntry: null,
|
|
84
|
+
|
|
81
85
|
// {function} onEnd hook
|
|
82
86
|
// onEnd: async (reportData) => {}
|
|
83
87
|
onEnd: null
|
package/lib/generate.js
CHANGED
|
@@ -288,12 +288,15 @@ const handleConsoleDetailsReport = (reportData, reportOptions, options) => {
|
|
|
288
288
|
} = reportData;
|
|
289
289
|
|
|
290
290
|
if (name) {
|
|
291
|
-
EC.
|
|
291
|
+
Util.logInfo(EC.cyan(name));
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
const metrics = Util.getMetrics(cdOptions.metrics, type);
|
|
295
295
|
const rows = getDetailsRows(files, metrics, cdOptions);
|
|
296
296
|
const summaryRow = getRowData('Summary', summary, metrics);
|
|
297
|
+
if (summaryRow.nameStatus) {
|
|
298
|
+
summaryRow.name = Util.getColorStrByStatus(summaryRow.name, summaryRow.nameStatus);
|
|
299
|
+
}
|
|
297
300
|
// no rows if skipped all by skipPercent
|
|
298
301
|
if (rows.length) {
|
|
299
302
|
rows.push({
|
|
@@ -339,7 +342,7 @@ const handleConsoleSummaryReport = (reportData, reportOptions, options) => {
|
|
|
339
342
|
} = reportData;
|
|
340
343
|
|
|
341
344
|
if (name) {
|
|
342
|
-
EC.
|
|
345
|
+
Util.logInfo(EC.cyan(name));
|
|
343
346
|
}
|
|
344
347
|
|
|
345
348
|
const metrics = Util.getMetrics(csOptions.metrics, type);
|