monocart-coverage-reports 2.5.5 → 2.5.6
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 +22 -5
- package/lib/cli.js +94 -15
- package/lib/converter/collect-source-maps.js +10 -7
- package/lib/converter/converter.js +19 -5
- package/lib/index.d.ts +23 -8
- package/lib/packages/monocart-coverage-vendor.js +46 -44
- package/lib/v8/v8.js +26 -6
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -125,7 +125,7 @@ console.log(coverageResults.summary);
|
|
|
125
125
|
}
|
|
126
126
|
```
|
|
127
127
|
- istanbul custom reporter
|
|
128
|
-
> example: [./test/custom-istanbul-reporter.js](./test/custom-istanbul-reporter.js), see [istanbul built-in reporters' implementation](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib) for reference
|
|
128
|
+
> example: [./test/custom-istanbul-reporter.js](./test/custom-istanbul-reporter.js), see [istanbul built-in reporters' implementation](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib) for reference.
|
|
129
129
|
- v8 custom reporter
|
|
130
130
|
> example: [./test/custom-v8-reporter.js](./test/custom-v8-reporter.js)
|
|
131
131
|
|
|
@@ -183,13 +183,20 @@ We can use `sourceFilter` to filter the source files. For example, we should rem
|
|
|
183
183
|
> src/index.js
|
|
184
184
|
> src/components/app.js
|
|
185
185
|
```
|
|
186
|
-
|
|
186
|
+
For example:
|
|
187
187
|
```js
|
|
188
188
|
const coverageOptions = {
|
|
189
189
|
entryFilter: (entry) => entry.url.indexOf("main.js") !== -1,
|
|
190
190
|
sourceFilter: (sourcePath) => sourcePath.search(/src\//) !== -1
|
|
191
191
|
};
|
|
192
192
|
```
|
|
193
|
+
Or `minimatch` pattern:
|
|
194
|
+
```js
|
|
195
|
+
const coverageOptions = {
|
|
196
|
+
entryFilter: "**/main.js",
|
|
197
|
+
sourceFilter: "**/src/**"
|
|
198
|
+
};
|
|
199
|
+
```
|
|
193
200
|
|
|
194
201
|
## onEnd Hook
|
|
195
202
|
For example, checking thresholds:
|
|
@@ -245,19 +252,29 @@ Arguments:
|
|
|
245
252
|
|
|
246
253
|
Options:
|
|
247
254
|
-V, --version output the version number
|
|
248
|
-
-c, --config <path> config path
|
|
255
|
+
-c, --config <path> custom config path
|
|
249
256
|
-o, --outputDir <dir> output dir for reports
|
|
250
257
|
-r, --reports <name[,name]> coverage reports to use
|
|
251
258
|
-n, --name <name> report name for title
|
|
259
|
+
-i, --inputDir <dir> input dir for merging raw files
|
|
260
|
+
--entryFilter <pattern> entry url filter
|
|
261
|
+
--sourceFilter <pattern> source path filter
|
|
252
262
|
--outputFile <path> output file for v8 report
|
|
253
263
|
--inline inline html for v8 report
|
|
254
264
|
--assetsPath <path> assets path if not inline
|
|
255
265
|
--lcov generate lcov.info file
|
|
266
|
+
--logging <logging> off, error, info, debug
|
|
256
267
|
-h, --help display help for command
|
|
257
268
|
```
|
|
258
|
-
-
|
|
269
|
+
- Supports loading default configuration file
|
|
270
|
+
- `.mcrrc`
|
|
271
|
+
- `mcr.config.json`
|
|
272
|
+
- `mcr.config.mjs`
|
|
273
|
+
- `mcr.config.cjs`
|
|
274
|
+
- `mcr.config.js`
|
|
275
|
+
- Specify custom configuration file
|
|
259
276
|
```sh
|
|
260
|
-
mcr "node ./test
|
|
277
|
+
mcr "node ./test.js" -c path-to/my-custom-config.js
|
|
261
278
|
```
|
|
262
279
|
|
|
263
280
|
## Compare Reports
|
package/lib/cli.js
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const EC = require('eight-colors');
|
|
6
|
-
const { fileURLToPath } = require('url');
|
|
7
|
-
|
|
6
|
+
const { fileURLToPath, pathToFileURL } = require('url');
|
|
8
7
|
const {
|
|
9
8
|
foregroundChild,
|
|
10
9
|
program
|
|
@@ -13,21 +12,76 @@ const {
|
|
|
13
12
|
const MCR = require('./index.js');
|
|
14
13
|
const Util = require('./utils/util.js');
|
|
15
14
|
const defaultOptions = require('./default/options.js');
|
|
15
|
+
const { resolveSourceMap } = require('./converter/collect-source-maps.js');
|
|
16
|
+
|
|
16
17
|
const version = require('../package.json').version;
|
|
17
18
|
|
|
18
19
|
const cleanDir = (dir) => {
|
|
19
20
|
Util.rmSync(dir);
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
const
|
|
23
|
+
const resolveConfigPath = (customConfigPath) => {
|
|
24
|
+
|
|
25
|
+
const configList = [
|
|
26
|
+
'.mcrrc',
|
|
27
|
+
'mcr.config.json',
|
|
28
|
+
'mcr.config.mjs',
|
|
29
|
+
'mcr.config.cjs',
|
|
30
|
+
'mcr.config.js'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
if (customConfigPath) {
|
|
34
|
+
configList.push(customConfigPath);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const existsList = configList.filter((p) => fs.existsSync(p));
|
|
38
|
+
if (!existsList.length) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// last one
|
|
43
|
+
const configPath = existsList.pop();
|
|
44
|
+
Util.logInfo(`Config: ${EC.cyan(configPath)}`);
|
|
45
|
+
|
|
46
|
+
return configPath;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const resolveConfigOptions = async (configPath) => {
|
|
50
|
+
|
|
51
|
+
// json format
|
|
52
|
+
const ext = path.extname(configPath);
|
|
53
|
+
if (ext === '.json' || configPath.slice(-2) === 'rc') {
|
|
54
|
+
return JSON.parse(Util.readFileSync(configPath));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let configOptions;
|
|
58
|
+
let err;
|
|
59
|
+
try {
|
|
60
|
+
configOptions = await import(pathToFileURL(configPath));
|
|
61
|
+
} catch (ee) {
|
|
62
|
+
err = ee;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!configOptions) {
|
|
66
|
+
Util.logError(err.message);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
configOptions = configOptions.default || configOptions;
|
|
71
|
+
|
|
72
|
+
return configOptions;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const initOptions = async (cliOptions) => {
|
|
76
|
+
|
|
77
|
+
const configPath = resolveConfigPath(cliOptions.config);
|
|
25
78
|
if (configPath) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
79
|
+
const configOptions = await resolveConfigOptions(configPath);
|
|
80
|
+
if (configOptions) {
|
|
81
|
+
cliOptions = {
|
|
82
|
+
... configOptions,
|
|
83
|
+
... cliOptions
|
|
84
|
+
};
|
|
31
85
|
}
|
|
32
86
|
}
|
|
33
87
|
|
|
@@ -46,9 +100,9 @@ const initOptions = (cliOptions) => {
|
|
|
46
100
|
|
|
47
101
|
const executeCommand = async (command, cliOptions) => {
|
|
48
102
|
|
|
49
|
-
const options = initOptions(cliOptions);
|
|
103
|
+
const options = await initOptions(cliOptions);
|
|
50
104
|
|
|
51
|
-
|
|
105
|
+
Util.logInfo(`Execute: ${EC.cyan(command)}`);
|
|
52
106
|
// console.log(options);
|
|
53
107
|
|
|
54
108
|
const nodeV8CoverageDir = path.resolve(options.outputDir, '.v8-coverage');
|
|
@@ -82,6 +136,9 @@ const executeCommand = async (command, cliOptions) => {
|
|
|
82
136
|
const json = JSON.parse(content);
|
|
83
137
|
let coverageList = json.result;
|
|
84
138
|
|
|
139
|
+
// for node sourcemap
|
|
140
|
+
const sourceMapCache = json['source-map-cache'] || {};
|
|
141
|
+
|
|
85
142
|
// filter node internal files
|
|
86
143
|
coverageList = coverageList.filter((entry) => entry.url && entry.url.startsWith('file:'));
|
|
87
144
|
|
|
@@ -90,11 +147,28 @@ const executeCommand = async (command, cliOptions) => {
|
|
|
90
147
|
}
|
|
91
148
|
// attached source content
|
|
92
149
|
coverageList.forEach((entry) => {
|
|
150
|
+
// source content
|
|
93
151
|
const filePath = fileURLToPath(entry.url);
|
|
94
152
|
if (fs.existsSync(filePath)) {
|
|
95
153
|
entry.source = fs.readFileSync(filePath).toString('utf8');
|
|
96
|
-
}
|
|
97
|
-
|
|
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
|
+
}
|
|
98
172
|
}
|
|
99
173
|
});
|
|
100
174
|
|
|
@@ -118,18 +192,23 @@ program
|
|
|
118
192
|
.description('CLI to generate coverage reports')
|
|
119
193
|
.version(version)
|
|
120
194
|
.argument('<command>', 'command to execute')
|
|
121
|
-
.option('-c, --config <path>', 'config path
|
|
195
|
+
.option('-c, --config <path>', 'custom config path')
|
|
122
196
|
.option('-o, --outputDir <dir>', 'output dir for reports')
|
|
123
197
|
.option('-r, --reports <name[,name]>', 'coverage reports to use')
|
|
124
198
|
.option('-n, --name <name>', 'report name for title')
|
|
125
199
|
.option('-i, --inputDir <dir>', 'input dir for merging raw files')
|
|
126
200
|
|
|
201
|
+
.option('--entryFilter <pattern>', 'entry url filter')
|
|
202
|
+
.option('--sourceFilter <pattern>', 'source path filter')
|
|
203
|
+
|
|
127
204
|
.option('--outputFile <path>', 'output file for v8 report')
|
|
128
205
|
.option('--inline', 'inline html for v8 report')
|
|
129
206
|
.option('--assetsPath <path>', 'assets path if not inline')
|
|
130
207
|
|
|
131
208
|
.option('--lcov', 'generate lcov.info file')
|
|
132
209
|
|
|
210
|
+
.option('--logging <logging>', 'off, error, info, debug')
|
|
211
|
+
|
|
133
212
|
.action((command, cliOptions) => {
|
|
134
213
|
executeCommand(command, cliOptions);
|
|
135
214
|
});
|
|
@@ -67,14 +67,14 @@ const getSourceMapUrl = (content, url) => {
|
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
const resolveSourcesContent =
|
|
70
|
+
const resolveSourcesContent = (sources, url) => {
|
|
71
71
|
const list = [];
|
|
72
72
|
for (const file of sources) {
|
|
73
73
|
const sourceUrl = Util.resolveUrl(file, url);
|
|
74
74
|
if (sourceUrl) {
|
|
75
75
|
const sourcePath = sourceUrl.toString();
|
|
76
76
|
if (sourcePath.startsWith('file:')) {
|
|
77
|
-
const content =
|
|
77
|
+
const content = Util.readFileSync(path.resolve(fileURLToPath(sourcePath)));
|
|
78
78
|
list.push(content);
|
|
79
79
|
continue;
|
|
80
80
|
}
|
|
@@ -86,7 +86,7 @@ const resolveSourcesContent = async (sources, url) => {
|
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
const resolveSourceMap =
|
|
89
|
+
const resolveSourceMap = (data, url) => {
|
|
90
90
|
if (!data) {
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
@@ -104,7 +104,7 @@ const resolveSourceMap = async (data, url) => {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
// load sources content by sources
|
|
107
|
-
const contents =
|
|
107
|
+
const contents = resolveSourcesContent(sources, url);
|
|
108
108
|
if (contents) {
|
|
109
109
|
data.sourcesContent = contents;
|
|
110
110
|
return data;
|
|
@@ -164,7 +164,7 @@ const collectSourceMaps = async (v8list, options) => {
|
|
|
164
164
|
// from inline sync
|
|
165
165
|
const smc = convertSourceMap.fromSource(source);
|
|
166
166
|
if (smc) {
|
|
167
|
-
sourceData.sourceMap =
|
|
167
|
+
sourceData.sourceMap = resolveSourceMap(smc.sourcemap, url);
|
|
168
168
|
smList.push({
|
|
169
169
|
url,
|
|
170
170
|
inline: true
|
|
@@ -195,7 +195,7 @@ const collectSourceMaps = async (v8list, options) => {
|
|
|
195
195
|
const { url } = sourceData;
|
|
196
196
|
const data = await loadSourceMap(sourceMapUrl);
|
|
197
197
|
if (data) {
|
|
198
|
-
sourceData.sourceMap =
|
|
198
|
+
sourceData.sourceMap = resolveSourceMap(data, url);
|
|
199
199
|
smList.push({
|
|
200
200
|
url,
|
|
201
201
|
sourceMapUrl
|
|
@@ -208,4 +208,7 @@ const collectSourceMaps = async (v8list, options) => {
|
|
|
208
208
|
|
|
209
209
|
};
|
|
210
210
|
|
|
211
|
-
module.exports =
|
|
211
|
+
module.exports = {
|
|
212
|
+
collectSourceMaps,
|
|
213
|
+
resolveSourceMap
|
|
214
|
+
};
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
sortRanges, dedupeCountRanges, mergeRangesWith
|
|
16
16
|
} = require('../utils/dedupe.js');
|
|
17
17
|
const { getSourceType, initSourceMapSourcePath } = require('../utils/source-path.js');
|
|
18
|
-
const { decode } = require('../packages/monocart-coverage-vendor.js');
|
|
18
|
+
const { decode, minimatch } = require('../packages/monocart-coverage-vendor.js');
|
|
19
19
|
|
|
20
20
|
const InfoBranch = require('./info-branch.js');
|
|
21
21
|
const InfoFunction = require('./info-function.js');
|
|
@@ -838,13 +838,25 @@ const getOriginalDecodedMappings = (originalDecodedMap, sourceIndex, locator) =>
|
|
|
838
838
|
|
|
839
839
|
// ========================================================================================================
|
|
840
840
|
|
|
841
|
+
const getSourceFilter = (options) => {
|
|
842
|
+
const sourceFilter = options.sourceFilter;
|
|
843
|
+
if (typeof sourceFilter === 'function') {
|
|
844
|
+
return sourceFilter;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
if (sourceFilter && typeof sourceFilter === 'string') {
|
|
848
|
+
return (sourcePath) => {
|
|
849
|
+
return minimatch(sourcePath, sourceFilter);
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
return () => true;
|
|
854
|
+
};
|
|
855
|
+
|
|
841
856
|
const initOriginalList = (state, originalDecodedMap, options) => {
|
|
842
857
|
|
|
843
858
|
// source filter
|
|
844
|
-
|
|
845
|
-
if (typeof sourceFilter !== 'function') {
|
|
846
|
-
sourceFilter = () => true;
|
|
847
|
-
}
|
|
859
|
+
const sourceFilter = getSourceFilter(options);
|
|
848
860
|
|
|
849
861
|
// create original content mappings
|
|
850
862
|
const originalStateMap = new Map();
|
|
@@ -855,8 +867,10 @@ const initOriginalList = (state, originalDecodedMap, options) => {
|
|
|
855
867
|
|
|
856
868
|
// filter
|
|
857
869
|
if (!sourceFilter(sourcePath)) {
|
|
870
|
+
// console.log('-', sourcePath);
|
|
858
871
|
return;
|
|
859
872
|
}
|
|
873
|
+
// console.log(sourcePath);
|
|
860
874
|
|
|
861
875
|
// console.log(`add source: ${k}`);
|
|
862
876
|
const sourceContent = sourcesContent[sourceIndex];
|
package/lib/index.d.ts
CHANGED
|
@@ -198,9 +198,14 @@ declare namespace MCR {
|
|
|
198
198
|
/** {string|string[]} input raw dir(s) */
|
|
199
199
|
inputDir?: string | string[];
|
|
200
200
|
|
|
201
|
-
/**
|
|
202
|
-
|
|
203
|
-
|
|
201
|
+
/**
|
|
202
|
+
*
|
|
203
|
+
* {string} 'v8', 'v8,console-details'
|
|
204
|
+
*
|
|
205
|
+
* {array} ['v8'], ['v8', ['console-details', { skipPercent: 80 }]]
|
|
206
|
+
*
|
|
207
|
+
* By default, `v8` for V8 data, `html` for Istanbul data
|
|
208
|
+
*/
|
|
204
209
|
reports?: string | ReportDescription[];
|
|
205
210
|
|
|
206
211
|
/** {string} Report name. Defaults to "Coverage Report". */
|
|
@@ -213,11 +218,21 @@ declare namespace MCR {
|
|
|
213
218
|
/** (V8 only) {string} Assets path if not inline. Defaults to "./assets" */
|
|
214
219
|
assetsPath?: string;
|
|
215
220
|
|
|
216
|
-
/** (V8 only)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
/** (V8 only)
|
|
222
|
+
*
|
|
223
|
+
* {string} `minimatch` pattern for entry url; multiple patterns: "{pattern1,pattern2}";
|
|
224
|
+
*
|
|
225
|
+
* {function} A filter function for each entry file in the V8 list.
|
|
226
|
+
* */
|
|
227
|
+
entryFilter?: string | ((entry: V8CoverageEntry) => boolean);
|
|
228
|
+
|
|
229
|
+
/** (V8 only)
|
|
230
|
+
*
|
|
231
|
+
* {string} `minimatch` pattern for source path; multiple patterns: "{pattern1,pattern2}";
|
|
232
|
+
*
|
|
233
|
+
* {function} A filter function for each source path when the source is unpacked from the source map.
|
|
234
|
+
* */
|
|
235
|
+
sourceFilter?: string | ((sourcePath: string) => boolean);
|
|
221
236
|
|
|
222
237
|
/** (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop */
|
|
223
238
|
v8Ignore?: boolean;
|