monocart-coverage-reports 2.0.6 → 2.0.8
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 +45 -22
- package/lib/converter/ast.js +2 -3
- package/lib/converter/branches.js +1 -37
- package/lib/converter/converter.js +398 -394
- package/lib/converter/find-in-ranges.js +39 -0
- package/lib/converter/ignore.js +130 -0
- package/lib/default/options.js +3 -0
- package/lib/generate.js +75 -67
- package/lib/index.d.ts +8 -2
- package/lib/index.js +1 -5
- package/lib/istanbul/istanbul-summary.js +1 -2
- package/lib/istanbul/istanbul.js +2 -2
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/packages/monocart-coverage-vendor.js +28 -28
- package/lib/utils/dedupe.js +0 -5
- package/lib/v8/v8-summary.js +85 -34
- package/lib/v8/v8.js +27 -83
- package/package.json +1 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const Util = require('../utils/util.js');
|
|
2
|
+
|
|
3
|
+
const quickFindRange = (position, ranges) => {
|
|
4
|
+
let start = 0;
|
|
5
|
+
let end = ranges.length - 1;
|
|
6
|
+
while (end - start > 1) {
|
|
7
|
+
const i = Math.floor((start + end) * 0.5);
|
|
8
|
+
const item = ranges[i];
|
|
9
|
+
if (position < item.startOffset) {
|
|
10
|
+
end = i;
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (position > item.endOffset) {
|
|
14
|
+
start = i;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
return ranges[i];
|
|
18
|
+
}
|
|
19
|
+
// last two items, less is start
|
|
20
|
+
const endItem = ranges[end];
|
|
21
|
+
if (position < endItem.startOffset) {
|
|
22
|
+
return ranges[start];
|
|
23
|
+
}
|
|
24
|
+
return ranges[end];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
const findInRanges = (start, end, ranges) => {
|
|
29
|
+
if (!Util.isList(ranges)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const range = quickFindRange(start, ranges);
|
|
33
|
+
if (start >= range.startOffset && end <= range.endOffset) {
|
|
34
|
+
return range;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
module.exports = findInRanges;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const Util = require('../utils/util.js');
|
|
2
|
+
|
|
3
|
+
const getNextN = (content, currentLine, item, locator) => {
|
|
4
|
+
|
|
5
|
+
// v8 ignore next N
|
|
6
|
+
if (content) {
|
|
7
|
+
const n = parseInt(content);
|
|
8
|
+
if (n && n > 0) {
|
|
9
|
+
return n;
|
|
10
|
+
}
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// block comment not end of line, same line
|
|
15
|
+
if (item.block) {
|
|
16
|
+
// has code between comment and line end
|
|
17
|
+
const text = locator.getSlice(item.end, currentLine.end).trim();
|
|
18
|
+
if (text) {
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// v8 ignore next
|
|
24
|
+
return 1;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const addNextIgnore = (list, content, item, locator) => {
|
|
28
|
+
|
|
29
|
+
const { lineParser } = locator;
|
|
30
|
+
|
|
31
|
+
// findLine 0-base
|
|
32
|
+
const currentLine = lineParser.findLine(item.end);
|
|
33
|
+
const n = getNextN(content, currentLine, item, locator);
|
|
34
|
+
|
|
35
|
+
// console.log('current line', currentLine.line, 'lines', lines);
|
|
36
|
+
|
|
37
|
+
// getLine 1-base
|
|
38
|
+
const line = currentLine.line + 1;
|
|
39
|
+
const endLine = locator.getLine(line + n);
|
|
40
|
+
const endOffset = endLine ? endLine.end : locator.source.length;
|
|
41
|
+
|
|
42
|
+
const nextItem = {
|
|
43
|
+
type: 'next',
|
|
44
|
+
n,
|
|
45
|
+
startOffset: item.end,
|
|
46
|
+
endOffset
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
list.push(nextItem);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const getIgnoredRanges = (locator, options) => {
|
|
53
|
+
if (!options.v8Ignore) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { lineParser } = locator;
|
|
58
|
+
|
|
59
|
+
const comments = lineParser.comments;
|
|
60
|
+
if (!Util.isList(comments)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const list = [];
|
|
65
|
+
let ignoreStart = null;
|
|
66
|
+
|
|
67
|
+
comments.forEach((item) => {
|
|
68
|
+
const {
|
|
69
|
+
block, start, end, text
|
|
70
|
+
} = item;
|
|
71
|
+
let content = block ? text.slice(2, -2) : text.slice(2);
|
|
72
|
+
content = content.trim();
|
|
73
|
+
|
|
74
|
+
const v8IgnoreKey = 'v8 ignore';
|
|
75
|
+
if (!content.startsWith(v8IgnoreKey)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
content = content.slice(v8IgnoreKey.length).trim();
|
|
80
|
+
|
|
81
|
+
if (ignoreStart) {
|
|
82
|
+
// v8 ignore stop
|
|
83
|
+
if (content === 'stop') {
|
|
84
|
+
ignoreStart.endOffset = start;
|
|
85
|
+
ignoreStart = null;
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// v8 ignore start
|
|
91
|
+
if (content === 'start') {
|
|
92
|
+
// add first for sort by start
|
|
93
|
+
ignoreStart = {
|
|
94
|
+
type: 'start',
|
|
95
|
+
startOffset: end,
|
|
96
|
+
endOffset: end
|
|
97
|
+
};
|
|
98
|
+
list.push(ignoreStart);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// v8 ignore next N
|
|
103
|
+
const nextKey = 'next';
|
|
104
|
+
if (content.startsWith(nextKey)) {
|
|
105
|
+
content = content.slice(nextKey.length).trim();
|
|
106
|
+
addNextIgnore(list, content, item, locator);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// ignore not stop
|
|
112
|
+
if (ignoreStart) {
|
|
113
|
+
ignoreStart.endOffset = locator.source.length;
|
|
114
|
+
ignoreStart = null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!list.length) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// console.log('=============================================');
|
|
122
|
+
// console.log(list);
|
|
123
|
+
|
|
124
|
+
return list;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
getIgnoredRanges
|
|
130
|
+
};
|
package/lib/default/options.js
CHANGED
|
@@ -43,6 +43,9 @@ module.exports = {
|
|
|
43
43
|
// sourceFilter: (sourcePath) => sourcePath.search(/src\/.+/) !== -1,
|
|
44
44
|
sourceFilter: null,
|
|
45
45
|
|
|
46
|
+
// [V8 only](Boolean) Enable/Disable ignoring uncovered codes with the special comments: /* v8 ignore next/next N/start/stop */
|
|
47
|
+
v8Ignore: true,
|
|
48
|
+
|
|
46
49
|
// [Istanbul only] defaultSummarizer, sourceFinder
|
|
47
50
|
|
|
48
51
|
// (Boolean) Generate lcov.info file, same as lcovonly report. Defaults to false.
|
package/lib/generate.js
CHANGED
|
@@ -127,60 +127,6 @@ const getReportGroup = (reports, lcov, dataType) => {
|
|
|
127
127
|
|
|
128
128
|
// ========================================================================================================
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
const generateCoverageReports = async (dataList, options) => {
|
|
132
|
-
|
|
133
|
-
// get first and check v8list or istanbul data
|
|
134
|
-
const firstData = dataList[0];
|
|
135
|
-
const dataType = firstData.type;
|
|
136
|
-
// console.log('data type', dataType);
|
|
137
|
-
|
|
138
|
-
// init reports
|
|
139
|
-
options.reportGroup = getReportGroup(options.reports, options.lcov, dataType);
|
|
140
|
-
// console.log('reportGroup', options.reportGroup);
|
|
141
|
-
|
|
142
|
-
// v8list
|
|
143
|
-
if (dataType === 'v8') {
|
|
144
|
-
// merge v8list first
|
|
145
|
-
const v8list = await mergeV8Coverage(dataList, options);
|
|
146
|
-
// console.log('after merge', v8list.map((it) => it.url));
|
|
147
|
-
|
|
148
|
-
const { coverageData, fileSources } = await convertV8List(v8list, options);
|
|
149
|
-
return generateV8ListReports(v8list, coverageData, fileSources, options);
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// istanbul data
|
|
154
|
-
const istanbulData = mergeIstanbulCoverage(dataList, options);
|
|
155
|
-
const { coverageData, fileSources } = initIstanbulData(istanbulData, options);
|
|
156
|
-
return saveIstanbulReports(coverageData, fileSources, options);
|
|
157
|
-
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
// ========================================================================================================
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const getCoverageDataList = async (cacheDir) => {
|
|
164
|
-
const files = fs.readdirSync(cacheDir).filter((f) => f.startsWith('coverage-'));
|
|
165
|
-
if (!files.length) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const dataList = [];
|
|
170
|
-
for (const item of files) {
|
|
171
|
-
const content = await Util.readFile(path.resolve(cacheDir, item));
|
|
172
|
-
if (content) {
|
|
173
|
-
dataList.push(JSON.parse(content));
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (dataList.length) {
|
|
178
|
-
return dataList;
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
// ========================================================================================================
|
|
183
|
-
|
|
184
130
|
const capitalizeFirstLetter = (string) => {
|
|
185
131
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
186
132
|
};
|
|
@@ -216,6 +162,8 @@ const showConsoleSummary = (coverageResults, options) => {
|
|
|
216
162
|
return;
|
|
217
163
|
}
|
|
218
164
|
|
|
165
|
+
const { metrics } = consoleOptions;
|
|
166
|
+
|
|
219
167
|
const {
|
|
220
168
|
summary, name, type
|
|
221
169
|
} = coverageResults;
|
|
@@ -223,12 +171,19 @@ const showConsoleSummary = (coverageResults, options) => {
|
|
|
223
171
|
EC.logCyan(name);
|
|
224
172
|
}
|
|
225
173
|
|
|
226
|
-
const
|
|
174
|
+
const allMetrics = {
|
|
227
175
|
v8: ['bytes', 'functions', 'branches', 'lines'],
|
|
228
176
|
istanbul: ['statements', 'functions', 'branches', 'lines']
|
|
229
177
|
};
|
|
230
178
|
|
|
231
|
-
|
|
179
|
+
let list = allMetrics[type];
|
|
180
|
+
if (Util.isList(metrics)) {
|
|
181
|
+
const newList = list.filter((k) => metrics.includes(k));
|
|
182
|
+
if (newList.length) {
|
|
183
|
+
list = newList;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
232
187
|
const rows = list.map((k) => {
|
|
233
188
|
return {
|
|
234
189
|
... summary[k],
|
|
@@ -261,23 +216,76 @@ const showConsoleSummary = (coverageResults, options) => {
|
|
|
261
216
|
formatter: nFormatter
|
|
262
217
|
}];
|
|
263
218
|
|
|
264
|
-
if (type === 'istanbul') {
|
|
265
|
-
columns.splice(4, 0, {
|
|
266
|
-
id: 'skipped',
|
|
267
|
-
name: 'Skipped',
|
|
268
|
-
align: 'right',
|
|
269
|
-
formatter: nFormatter
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
|
|
273
219
|
CG({
|
|
274
220
|
columns,
|
|
275
221
|
rows
|
|
276
222
|
});
|
|
277
223
|
};
|
|
278
224
|
|
|
225
|
+
|
|
226
|
+
// ========================================================================================================
|
|
227
|
+
|
|
228
|
+
const getCoverageResults = async (dataList, options) => {
|
|
229
|
+
// get first and check v8list or istanbul data
|
|
230
|
+
const firstData = dataList[0];
|
|
231
|
+
const dataType = firstData.type;
|
|
232
|
+
// console.log('data type', dataType);
|
|
233
|
+
|
|
234
|
+
// init reports
|
|
235
|
+
options.reportGroup = getReportGroup(options.reports, options.lcov, dataType);
|
|
236
|
+
// console.log('reportGroup', options.reportGroup);
|
|
237
|
+
|
|
238
|
+
// v8list
|
|
239
|
+
if (dataType === 'v8') {
|
|
240
|
+
// merge v8list first
|
|
241
|
+
const v8list = await mergeV8Coverage(dataList, options);
|
|
242
|
+
// console.log('after merge', v8list.map((it) => it.url));
|
|
243
|
+
|
|
244
|
+
const { coverageData, fileSources } = await convertV8List(v8list, options);
|
|
245
|
+
return generateV8ListReports(v8list, coverageData, fileSources, options);
|
|
246
|
+
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// istanbul data
|
|
250
|
+
const istanbulData = mergeIstanbulCoverage(dataList, options);
|
|
251
|
+
const { coverageData, fileSources } = initIstanbulData(istanbulData, options);
|
|
252
|
+
return saveIstanbulReports(coverageData, fileSources, options);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const generateCoverageReports = async (dataList, options) => {
|
|
256
|
+
const coverageResults = await getCoverageResults(dataList, options);
|
|
257
|
+
|
|
258
|
+
// [ 'type', 'reportPath', 'name', 'watermarks', 'summary', 'files' ]
|
|
259
|
+
// console.log(Object.keys(coverageResults));
|
|
260
|
+
|
|
261
|
+
showConsoleSummary(coverageResults, options);
|
|
262
|
+
|
|
263
|
+
return coverageResults;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// ========================================================================================================
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
const getCoverageDataList = async (cacheDir) => {
|
|
270
|
+
const files = fs.readdirSync(cacheDir).filter((f) => f.startsWith('coverage-'));
|
|
271
|
+
if (!files.length) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const dataList = [];
|
|
276
|
+
for (const item of files) {
|
|
277
|
+
const content = await Util.readFile(path.resolve(cacheDir, item));
|
|
278
|
+
if (content) {
|
|
279
|
+
dataList.push(JSON.parse(content));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (dataList.length) {
|
|
284
|
+
return dataList;
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
279
288
|
module.exports = {
|
|
280
289
|
getCoverageDataList,
|
|
281
|
-
generateCoverageReports
|
|
282
|
-
showConsoleSummary
|
|
290
|
+
generateCoverageReports
|
|
283
291
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -23,12 +23,15 @@ export type ReportDescription =
|
|
|
23
23
|
['v8'] | ["v8", {
|
|
24
24
|
outputFile?: string,
|
|
25
25
|
inline?: boolean,
|
|
26
|
-
assetsPath?: string
|
|
26
|
+
assetsPath?: string,
|
|
27
|
+
metrics?: Array<"bytes" | "functions" | "branches" | "lines">
|
|
27
28
|
}] |
|
|
28
29
|
['v8-json'] | ["v8-json", {
|
|
29
30
|
outputFile?: string
|
|
30
31
|
}] |
|
|
31
|
-
['console-summary'] |
|
|
32
|
+
['console-summary'] | ['console-summary', {
|
|
33
|
+
metrics?: Array<"bytes" | "functions" | "branches" | "lines" | "statements">
|
|
34
|
+
}] |
|
|
32
35
|
['clover'] | ['clover', {
|
|
33
36
|
file?: string
|
|
34
37
|
}] |
|
|
@@ -120,6 +123,9 @@ export type CoverageReportOptions = {
|
|
|
120
123
|
// [V8 only](Function) A filter function to execute for each element in the sources which unpacked from the source map.
|
|
121
124
|
sourceFilter?: (sourcePath: string) => boolean,
|
|
122
125
|
|
|
126
|
+
// [V8 only](Boolean) Enable/Disable ignoring uncovered codes with the special comments: /* v8 ignore next/next N/start/stop */
|
|
127
|
+
v8Ignore?: boolean,
|
|
128
|
+
|
|
123
129
|
// [Istanbul only] defaultSummarizer, sourceFinder
|
|
124
130
|
|
|
125
131
|
// (Boolean) Generate lcov.info file, same as lcovonly report. Defaults to false.
|
package/lib/index.js
CHANGED
|
@@ -4,9 +4,7 @@ const defaultOptions = require('./default/options.js');
|
|
|
4
4
|
const Util = require('./utils/util.js');
|
|
5
5
|
|
|
6
6
|
const { initV8ListAndSourcemap } = require('./v8/v8.js');
|
|
7
|
-
const {
|
|
8
|
-
getCoverageDataList, generateCoverageReports, showConsoleSummary
|
|
9
|
-
} = require('./generate.js');
|
|
7
|
+
const { getCoverageDataList, generateCoverageReports } = require('./generate.js');
|
|
10
8
|
|
|
11
9
|
class CoverageReport {
|
|
12
10
|
|
|
@@ -109,8 +107,6 @@ class CoverageReport {
|
|
|
109
107
|
Util.rmSync(cacheDir);
|
|
110
108
|
}
|
|
111
109
|
|
|
112
|
-
showConsoleSummary(coverageResults, this.options);
|
|
113
|
-
|
|
114
110
|
const onEnd = this.options.onEnd;
|
|
115
111
|
if (typeof onEnd === 'function') {
|
|
116
112
|
await onEnd(coverageResults);
|
|
@@ -44,8 +44,7 @@ class IstanbulSummary extends ReportBase {
|
|
|
44
44
|
// add uncovered
|
|
45
45
|
Object.keys(this.summary).forEach((id) => {
|
|
46
46
|
const item = this.summary[id];
|
|
47
|
-
|
|
48
|
-
item.uncovered = item.total - item.covered - item.skipped;
|
|
47
|
+
item.uncovered = item.total - item.covered;
|
|
49
48
|
});
|
|
50
49
|
|
|
51
50
|
// console.log(this.summary);
|
package/lib/istanbul/istanbul.js
CHANGED
|
@@ -103,7 +103,7 @@ const saveIstanbulReports = (coverageData, fileSources, options) => {
|
|
|
103
103
|
return Util.relativePath(htmlPath);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
const
|
|
106
|
+
const coverageResults = {
|
|
107
107
|
type: 'istanbul',
|
|
108
108
|
reportPath,
|
|
109
109
|
name: options.name,
|
|
@@ -112,7 +112,7 @@ const saveIstanbulReports = (coverageData, fileSources, options) => {
|
|
|
112
112
|
... coverageReport.getReport()
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
return
|
|
115
|
+
return coverageResults;
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
const mergeIstanbulCoverage = (dataList, options) => {
|