monocart-coverage-reports 2.2.1 → 2.2.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
@@ -64,6 +64,8 @@ console.log(coverageResults.summary);
64
64
 
65
65
  - `v8-json` (V8 data only)
66
66
  - [V8 coverage-report.json](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json)
67
+ - `codecov` (V8 data only)
68
+ - coverage data for [Codecov](https://docs.codecov.com/docs/codecov-custom-coverage-format), see [example](https://app.codecov.io/github/cenfun/monocart-coverage-reports)
67
69
  - `console-summary` shows coverage summary in console
68
70
 
69
71
  ![](test/console-summary.png)
package/lib/cli.js CHANGED
@@ -38,7 +38,7 @@ const initOptions = (cliOptions) => {
38
38
 
39
39
  // init reports to list with `,`
40
40
  const reports = cliOptions.reports;
41
- if (reports) {
41
+ if (reports && typeof reports === 'string') {
42
42
  cliOptions.reports = reports.split(',');
43
43
  }
44
44
 
@@ -313,9 +313,21 @@ const collectFileCoverage = (item, state, coverageData, options) => {
313
313
  b: {}
314
314
  };
315
315
 
316
+ // for codecov https://docs.codecov.com/docs/codecov-custom-coverage-format
317
+ data.lines = {};
318
+
316
319
  lines.filter((it) => !it.ignored).forEach((line, index) => {
317
320
  istanbulCoverage.statementMap[`${index}`] = line.generate();
318
321
  istanbulCoverage.s[`${index}`] = line.count;
322
+
323
+ let count = 0;
324
+ if (line.covered) {
325
+ count = line.count;
326
+ } else if (!line.covered && line.count > 0) {
327
+ count = '1/2';
328
+ }
329
+ // 1-base
330
+ data.lines[`${line.line}`] = count;
319
331
  });
320
332
 
321
333
  functions.filter((it) => !it.ignored).forEach((fn, index) => {
@@ -987,6 +999,7 @@ const convertV8List = async (v8list, options) => {
987
999
  if (sourceList.length) {
988
1000
  sourceList.forEach((item) => {
989
1001
 
1002
+ // second time filter for empty source
990
1003
  // exists same id, mark previous item as dedupe
991
1004
  const prevItem = v8list.find((it) => it.id === item.id);
992
1005
  if (prevItem) {
package/lib/generate.js CHANGED
@@ -67,59 +67,50 @@ const getReportGroup = (reports, lcov, dataType) => {
67
67
  reportMap[defaultReport] = {};
68
68
  }
69
69
 
70
- const allSupportedReports = [
70
+ const allSupportedReports = {
71
71
 
72
72
  // v8
73
- 'v8',
74
- 'v8-json',
73
+ 'v8': 'v8',
74
+ 'v8-json': 'v8',
75
+ 'codecov': 'v8',
75
76
 
76
77
  // both
77
- 'console-summary',
78
+ 'console-summary': 'both',
78
79
 
79
80
  // istanbul
80
- 'clover',
81
- 'cobertura',
82
- 'html',
83
- 'html-spa',
84
- 'json',
85
- 'json-summary',
86
- 'lcov',
87
- 'lcovonly',
88
- 'none',
89
- 'teamcity',
90
- 'text',
91
- 'text-lcov',
92
- 'text-summary'
93
- ];
81
+ 'clover': 'istanbul',
82
+ 'cobertura': 'istanbul',
83
+ 'html': 'istanbul',
84
+ 'html-spa': 'istanbul',
85
+ 'json': 'istanbul',
86
+ 'json-summary': 'istanbul',
87
+ 'lcov': 'istanbul',
88
+ 'lcovonly': 'istanbul',
89
+ 'none': 'istanbul',
90
+ 'teamcity': 'istanbul',
91
+ 'text': 'istanbul',
92
+ 'text-lcov': 'istanbul',
93
+ 'text-summary': 'istanbul'
94
+ };
94
95
 
95
96
  // group v8 and istanbul
96
97
  const reportGroup = {};
97
98
  Object.keys(reportMap).forEach((k) => {
98
- if (!allSupportedReports.includes(k)) {
99
- return;
100
- }
101
99
 
102
- // v8
103
- if (k.startsWith('v8')) {
104
- // v8
105
- if (!reportGroup.v8) {
106
- reportGroup.v8 = {};
107
- }
108
- reportGroup.v8[k] = reportMap[k];
100
+ const groupName = allSupportedReports[k];
101
+ if (!groupName) {
102
+ Util.logError(`Unsupported report: ${k}`);
109
103
  return;
110
104
  }
111
105
 
112
- // both
113
- if (k === 'console-summary') {
114
- reportGroup[k] = reportMap[k];
115
- return;
106
+ let group = reportGroup[groupName];
107
+ if (!group) {
108
+ group = {};
109
+ reportGroup[groupName] = group;
116
110
  }
117
111
 
118
- // istanbul
119
- if (!reportGroup.istanbul) {
120
- reportGroup.istanbul = {};
121
- }
122
- reportGroup.istanbul[k] = reportMap[k];
112
+ group[k] = reportMap[k];
113
+
123
114
  });
124
115
 
125
116
  return reportGroup;
@@ -156,8 +147,12 @@ const nFormatter = (v) => {
156
147
 
157
148
  const showConsoleSummary = (coverageResults, options) => {
158
149
 
159
- const reportGroup = options.reportGroup;
160
- const consoleOptions = reportGroup['console-summary'];
150
+ const bothGroup = options.reportGroup.both;
151
+ if (!bothGroup) {
152
+ return;
153
+ }
154
+
155
+ const consoleOptions = bothGroup['console-summary'];
161
156
  if (!consoleOptions) {
162
157
  return;
163
158
  }
package/lib/index.d.ts CHANGED
@@ -34,6 +34,9 @@ declare namespace MCR {
34
34
  ['v8-json'] | ["v8-json", {
35
35
  outputFile?: string;
36
36
  }] |
37
+ ['codecov'] | ["codecov", {
38
+ outputFile?: string;
39
+ }] |
37
40
  ['console-summary'] | ['console-summary', {
38
41
  metrics?: Array<"bytes" | "functions" | "branches" | "lines" | "statements">;
39
42
  }] |
@@ -87,9 +87,9 @@ const saveIstanbulReports = (coverageData, fileSources, options) => {
87
87
  // create a context for report generation
88
88
  const context = istanbulLibReport.createContext(contextOptions);
89
89
 
90
- const istanbulMap = options.reportGroup.istanbul;
91
- Object.keys(istanbulMap).forEach((reportName) => {
92
- const report = istanbulReports.create(reportName, istanbulMap[reportName]);
90
+ const istanbulGroup = options.reportGroup.istanbul;
91
+ Object.keys(istanbulGroup).forEach((reportName) => {
92
+ const report = istanbulReports.create(reportName, istanbulGroup[reportName]);
93
93
  report.execute(context);
94
94
  });
95
95
 
package/lib/v8/v8.js CHANGED
@@ -21,9 +21,18 @@ const initV8ListAndSourcemap = async (v8list, options) => {
21
21
 
22
22
  v8list = v8list.filter((item) => {
23
23
  if (typeof item.source === 'string' && item.functions) {
24
+ item.type = 'js';
24
25
  return true;
25
26
  }
26
27
  if (typeof item.text === 'string' && item.ranges) {
28
+ item.type = 'css';
29
+ return true;
30
+ }
31
+ // allow empty coverage
32
+ if (item.empty) {
33
+ if (!['js', 'css'].includes(item.type)) {
34
+ item.type = 'js';
35
+ }
27
36
  return true;
28
37
  }
29
38
  // 404 css, text will be empty
@@ -39,22 +48,30 @@ const initV8ListAndSourcemap = async (v8list, options) => {
39
48
  // init id, sourcePath
40
49
  v8list = v8list.map((item, i) => {
41
50
 
51
+ const type = item.type;
52
+
42
53
  const data = {
43
- url: item.url
54
+ url: item.url,
55
+ type
44
56
  };
45
57
 
46
- if (item.functions) {
47
- data.type = 'js';
58
+ if (type === 'js') {
48
59
  data.functions = item.functions;
49
60
  data.source = item.source;
50
61
  // could be existed
51
62
  data.sourceMap = item.sourceMap;
52
- } else if (item.ranges) {
53
- data.type = 'css';
63
+ } else {
64
+ // css
54
65
  data.ranges = item.ranges;
55
66
  data.source = item.text;
56
67
  }
57
68
 
69
+
70
+ // no functions and ranges
71
+ if (item.empty) {
72
+ data.empty = true;
73
+ }
74
+
58
75
  const idList = [];
59
76
  // could be existed
60
77
  const distFile = item.distFile;
@@ -122,17 +139,17 @@ const mergeJsFunctions = (itemList) => {
122
139
 
123
140
  const mergeV8Coverage = async (dataList, options) => {
124
141
 
125
- let list = [];
142
+ let allList = [];
126
143
  dataList.forEach((d) => {
127
- list = list.concat(d.data);
144
+ allList = allList.concat(d.data);
128
145
  });
129
146
 
130
- // console.log('before merge', list.map((it) => it.url));
147
+ const coverageList = allList.filter((it) => !it.empty);
131
148
 
132
149
  // connect all functions and ranges
133
150
  const itemMap = {};
134
151
  const mergeMap = {};
135
- list.forEach((item) => {
152
+ coverageList.forEach((item) => {
136
153
  const { id } = item;
137
154
  const prev = itemMap[id];
138
155
  if (prev) {
@@ -158,11 +175,17 @@ const mergeV8Coverage = async (dataList, options) => {
158
175
  }
159
176
  }
160
177
 
161
- list = Object.values(itemMap);
178
+ // first time filter for empty, (not for sources)
179
+ const emptyList = allList.filter((it) => it.empty).filter((it) => !itemMap[it.id]);
180
+
181
+ // empty list + merged list
182
+ const mergedList = emptyList.concat(Object.values(itemMap));
162
183
 
163
184
  // try to load coverage and source by id
164
- for (const item of list) {
165
- const { id } = item;
185
+ for (const item of mergedList) {
186
+ const {
187
+ id, type, empty
188
+ } = item;
166
189
  const sourcePath = Util.resolveCacheSourcePath(options.cacheDir, id);
167
190
  const content = await Util.readFile(sourcePath);
168
191
  if (content) {
@@ -173,24 +196,63 @@ const mergeV8Coverage = async (dataList, options) => {
173
196
  Util.logError(`failed to read source: ${item.url}`);
174
197
  item.source = '';
175
198
  }
199
+
200
+ // add empty coverage after merged
201
+ if (empty) {
202
+ if (type === 'js') {
203
+ item.functions = [{
204
+ functionName: '',
205
+ ranges: [{
206
+ startOffset: 0,
207
+ endOffset: item.source.length,
208
+ count: 0
209
+ }]
210
+ }];
211
+ } else {
212
+ // empty css
213
+ item.ranges = [];
214
+ }
215
+ }
216
+
176
217
  }
177
218
 
178
- return list;
219
+ return mergedList;
179
220
  };
180
221
 
181
222
  // ============================================================
182
223
 
224
+ const saveCodecovReport = async (reportData, options, codecovOptions) => {
225
+ const mergedOptions = {
226
+ outputFile: 'codecov.json',
227
+ ... codecovOptions
228
+ };
229
+
230
+ // console.log(mergedOptions);
231
+ const jsonPath = path.resolve(options.outputDir, mergedOptions.outputFile);
232
+
233
+ // https://docs.codecov.com/docs/codecov-custom-coverage-format
234
+ const coverage = {};
235
+ reportData.files.forEach((item) => {
236
+ const { sourcePath, data } = item;
237
+ coverage[sourcePath] = data.lines;
238
+ });
239
+ const codecovData = {
240
+ coverage
241
+ };
242
+
243
+ await Util.writeFile(jsonPath, JSON.stringify(codecovData));
244
+ return Util.relativePath(jsonPath);
245
+ };
246
+
183
247
  const saveV8JsonReport = async (reportData, options, v8JsonOptions) => {
184
- const v8MergedOptions = {
248
+ const mergedOptions = {
185
249
  outputFile: 'coverage-report.json',
186
250
  ... v8JsonOptions
187
251
  };
188
252
 
189
- // console.log(v8MergedOptions);
190
- const jsonPath = path.resolve(options.outputDir, v8MergedOptions.outputFile);
191
- // console.log(reportPath);
253
+ // console.log(mergedOptions);
254
+ const jsonPath = path.resolve(options.outputDir, mergedOptions.outputFile);
192
255
  await Util.writeFile(jsonPath, JSON.stringify(reportData));
193
-
194
256
  return Util.relativePath(jsonPath);
195
257
  };
196
258
 
@@ -255,10 +317,10 @@ const saveV8Report = async (v8list, options) => {
255
317
  let outputPath;
256
318
 
257
319
  // v8 reports
258
- const v8Map = options.reportGroup.v8;
320
+ const v8Group = options.reportGroup.v8;
259
321
 
260
322
  // v8 html
261
- const v8Options = v8Map.v8;
323
+ const v8Options = v8Group.v8;
262
324
  if (v8Options) {
263
325
 
264
326
  // V8 only options, merged with root options
@@ -276,12 +338,25 @@ const saveV8Report = async (v8list, options) => {
276
338
  outputPath = await saveV8HtmlReport(reportData, options, v8HtmlOptions);
277
339
  }
278
340
 
279
- // v8 json
280
- const v8JsonOptions = v8Map['v8-json'];
341
+ // v8 json (after html for metrics data)
342
+ const v8JsonOptions = v8Group['v8-json'];
281
343
  if (v8JsonOptions) {
282
- outputPath = await saveV8JsonReport(reportData, options, v8JsonOptions);
344
+ const jsonPath = await saveV8JsonReport(reportData, options, v8JsonOptions);
345
+ if (!outputPath) {
346
+ outputPath = jsonPath;
347
+ }
348
+ }
349
+
350
+ // codecov
351
+ const codecovOptions = v8Group.codecov;
352
+ if (codecovOptions) {
353
+ const jsonPath = await saveCodecovReport(reportData, options, codecovOptions);
354
+ if (!outputPath) {
355
+ outputPath = jsonPath;
356
+ }
283
357
  }
284
358
 
359
+ // outputPath last one is html
285
360
  const reportPath = Util.resolveReportPath(options, () => {
286
361
  return outputPath;
287
362
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monocart-coverage-reports",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "Monocart coverage reports",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -28,7 +28,7 @@
28
28
  "test-node-cdp": "node --inspect=9229 ./test/test-node-cdp.js",
29
29
  "test-node-koa": "node ./test/test-node-koa.js",
30
30
  "test-browser": "node ./test/test.js",
31
- "test-cli": "npx mcr \"node ./test/test-node-env.js\" -o docs/cli -r v8,console-summary --lcov -c test/cli-options.js",
31
+ "test-cli": "npx mcr \"node ./test/test-node-env.js\" -o docs/cli -c test/cli-options.js",
32
32
  "test": "npm run test-browser && npm run test-node && npm run test-cli && npm run build-docs",
33
33
  "dev": "sf d v8",
34
34
  "open": "node ./scripts/open.js",