monocart-coverage-reports 2.0.5 → 2.0.7

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
@@ -6,12 +6,9 @@
6
6
 
7
7
  > Code coverage tool to generate native [V8](https://v8.dev/blog/javascript-code-coverage) reports or [Istanbul](https://istanbul.js.org/) reports.
8
8
 
9
- * [Preview Reports](#preview-reports)
10
9
  * [Usage](#usage)
11
10
  * [Default Options](#default-options)
12
- * [Multiple Reports](#multiple-reports)
13
- - [V8 reports](#v8-reports)
14
- - [Istanbul reports](#istanbul-reports)
11
+ * [Available Reports](#available-reports)
15
12
  * [Multiprocessing Support](#multiprocessing-support)
16
13
  * [Compare Reports](#compare-reports)
17
14
  * [Compare Workflows](#compare-workflows)
@@ -26,14 +23,6 @@
26
23
  * [Istanbul Introduction](#istanbul-introduction)
27
24
  * [Thanks](#thanks)
28
25
 
29
- ## Preview Reports
30
- - [V8](https://cenfun.github.io/monocart-coverage-reports/v8) - Example for browser, build with webpack, and also [Rollup](https://cenfun.github.io/monocart-coverage-reports/v8-rollup) and [Esbuild](https://cenfun.github.io/monocart-coverage-reports/v8-esbuild)
31
- - [V8 Node](https://cenfun.github.io/monocart-coverage-reports/v8-node-env) - Example for Node.js using 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)
32
- - [V8 Minify](https://cenfun.github.io/monocart-coverage-reports/v8-minify)
33
- - [V8 to Istanbul](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/istanbul)
34
- - [Istanbul](https://cenfun.github.io/monocart-coverage-reports/istanbul/)
35
- - [Integration with Monocart Reporter](https://cenfun.github.io/monocart-reporter/) - Playwright test report
36
-
37
26
  ## Usage
38
27
  ```js
39
28
  const CoverageReport = require('monocart-coverage-reports');
@@ -53,30 +42,46 @@ console.log(coverageResults.summary);
53
42
  ## Default Options
54
43
  - [lib/default/options.js](https://github.com/cenfun/monocart-coverage-reports/blob/main/lib/default/options.js)
55
44
 
56
- ## Multiple Reports
57
- ### V8 reports
58
- - v8 (html)
59
- - v8-json
60
- ### [Istanbul reports](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib)
61
- - clover
62
- - cobertura
63
- - html
64
- - html-spa
65
- - json
66
- - json-summary
67
- - lcov
68
- - lcovonly
69
- - none
70
- - teamcity
71
- - text
72
- - text-lcov
73
- - text-summary
45
+ ## Available Reports
46
+ - `v8` (V8 data only)
47
+ - [V8 html](https://cenfun.github.io/monocart-coverage-reports/v8) - Example for browser, build with webpack, and also [Rollup](https://cenfun.github.io/monocart-coverage-reports/v8-rollup) and [Esbuild](https://cenfun.github.io/monocart-coverage-reports/v8-esbuild)
48
+ - [V8 Node](https://cenfun.github.io/monocart-coverage-reports/v8-node-env) - Example for Node.js using 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)
49
+ - [V8 Minify](https://cenfun.github.io/monocart-coverage-reports/v8-minify)
50
+
51
+ ![](test/v8.gif)
52
+
53
+ - `v8-json` (V8 data only)
54
+ - [V8 coverage-report.json](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json)
55
+ - `console-summary` shows coverage summary in console
56
+
57
+ ![](test/console-summary.png)
58
+
59
+ > Following are [istanbul reports](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib)
60
+ - `clover`
61
+ - `cobertura`
62
+ - `html`
63
+ - [Istanbul html](https://cenfun.github.io/monocart-coverage-reports/istanbul/)
64
+ - [V8 to Istanbul](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/istanbul)
65
+ - `html-spa`
66
+ - [Istanbul html-spa](https://cenfun.github.io/monocart-coverage-reports/istanbul/html-spa/)
67
+ - `json`
68
+ - `json-summary`
69
+ - `lcov`
70
+ - `lcovonly`
71
+ - [V8 lcov.info](https://cenfun.github.io/monocart-coverage-reports/v8/lcov.info)
72
+ - [Istanbul lcov.info](https://cenfun.github.io/monocart-coverage-reports/istanbul/lcov.info)
73
+ - `none`
74
+ - `teamcity`
75
+ - `text`
76
+ - `text-lcov`
77
+ - `text-summary`
74
78
 
75
79
  ```js
76
80
  const CoverageReport = require('monocart-coverage-reports');
77
81
  const options = {
78
82
  outputDir: './coverage-reports',
79
83
  reports: [
84
+ ['console-summary'],
80
85
  ['v8'],
81
86
  ['html', {
82
87
  subdir: 'istanbul'
@@ -90,6 +95,11 @@ const options = {
90
95
  const coverageReport = new CoverageReport(options);
91
96
  ```
92
97
 
98
+ ## Integration
99
+ - [monocart-reporter](https://cenfun.github.io/monocart-reporter/) - Test reporter for [Playwright](https://github.com/microsoft/playwright)
100
+ - [vitest-monocart-coverage](https://github.com/cenfun/vitest-monocart-coverage) - Integration with [Vitest](https://github.com/vitest-dev/vitest) coverage
101
+
102
+
93
103
  ## Multiprocessing Support
94
104
  The data will be added to `[outputDir]/.cache`, and the cache will be removed after reports generated.
95
105
  - sub process 1
@@ -184,38 +184,9 @@ const collectFileCoverage = (item, coverageInfo, state) => {
184
184
 
185
185
  // ========================================================================================================
186
186
 
187
- // https://github.com/demurgos/v8-coverage
188
- /**
189
- * @ranges is always non-empty. The first range is called the "root range".
190
- * @isBlockCoverage indicates if the function has block coverage information
191
- * @false means that there is a single range and its count is the number of times the function was called.
192
- * @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
193
- * It detects skipped or repeated statements. The root range counts the number of function calls.
194
- *
195
- * @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
196
- */
197
- // if you have a line of code that says `var x= 10; console.log(x);` that's one line and 2 statements.
198
-
199
- const addJsLineCoverage = (state, range) => {
200
-
201
- const { locator, coverageInfo } = state;
202
-
203
- const { data, lineMap } = coverageInfo;
204
-
205
- const {
206
- startOffset, endOffset, count
207
- } = range;
208
-
209
- // add bytes range
210
- data.bytes.push({
211
- // index,
212
- start: startOffset,
213
- end: endOffset,
214
- count
215
- });
216
-
217
- const sLoc = locator.offsetToLocation(startOffset);
218
- const eLoc = locator.offsetToLocation(endOffset);
187
+ const updateLineCoverage = (start, end, count, lineMap, locator) => {
188
+ const sLoc = locator.offsetToLocation(start);
189
+ const eLoc = locator.offsetToLocation(end);
219
190
 
220
191
  // update lines coverage
221
192
  const lines = Util.getRangeLines(sLoc, eLoc);
@@ -251,6 +222,39 @@ const addJsLineCoverage = (state, range) => {
251
222
  // console.log('===========================================', state.sourcePath);
252
223
  // console.log(coverageInfo.lines);
253
224
  // }
225
+ };
226
+
227
+ // https://github.com/demurgos/v8-coverage
228
+ /**
229
+ * @ranges is always non-empty. The first range is called the "root range".
230
+ * @isBlockCoverage indicates if the function has block coverage information
231
+ * @false means that there is a single range and its count is the number of times the function was called.
232
+ * @true means that the ranges form a tree of blocks representing how many times each statement or expression inside was executed.
233
+ * It detects skipped or repeated statements. The root range counts the number of function calls.
234
+ *
235
+ * @functionName can be an empty string. This is common for the FunctionCov representing the whole module.
236
+ */
237
+ // if you have a line of code that says `var x= 10; console.log(x);` that's one line and 2 statements.
238
+
239
+ const addJsLineCoverage = (state, range) => {
240
+
241
+ const { locator, coverageInfo } = state;
242
+
243
+ const { data, lineMap } = coverageInfo;
244
+
245
+ const {
246
+ startOffset, endOffset, count
247
+ } = range;
248
+
249
+ // add bytes range
250
+ data.bytes.push({
251
+ // index,
252
+ start: startOffset,
253
+ end: endOffset,
254
+ count
255
+ });
256
+
257
+ updateLineCoverage(startOffset, endOffset, count, lineMap, locator);
254
258
 
255
259
  };
256
260
 
@@ -264,28 +268,11 @@ const addCssLineCoverage = (state, range) => {
264
268
  start, end, count
265
269
  } = range;
266
270
 
267
- if (count > 0) {
268
- const sLoc = locator.offsetToLocation(start);
269
- const eLoc = locator.offsetToLocation(end);
270
-
271
- // covered css lines
272
- const lines = Util.getRangeLines(sLoc, eLoc);
273
- lines.forEach((it) => {
274
- if (!it.entire) {
275
- return;
276
- }
277
- const line = lineMap.get(it.line);
278
- if (line) {
279
- // default is uncovered
280
- // count always 1, covered is certain
281
- line.covered = true;
282
- }
283
- });
284
- }
285
-
286
271
  // add bytes range
287
272
  data.bytes.push(range);
288
273
 
274
+ updateLineCoverage(start, end, count, lineMap, locator);
275
+
289
276
  };
290
277
 
291
278
  // ========================================================================================================
@@ -406,9 +393,7 @@ const handleBranchesCoverage = (state) => {
406
393
 
407
394
  const handleLinesCoverage = (state) => {
408
395
 
409
- const {
410
- js, locator, coverageInfo
411
- } = state;
396
+ const { locator, coverageInfo } = state;
412
397
 
413
398
  const lines = coverageInfo.lines;
414
399
  const lineMap = coverageInfo.lineMap;
@@ -417,10 +402,6 @@ const handleLinesCoverage = (state) => {
417
402
  let blankCount = 0;
418
403
  let commentCount = 0;
419
404
 
420
- // js: 1 (functions include all uncovered)
421
- // css: 0 (ranges include all covered)
422
- const baseLineCount = js ? 1 : 0;
423
-
424
405
  locator.lines.forEach((it) => {
425
406
  // exclude blank and comment
426
407
  if (it.blank) {
@@ -433,7 +414,8 @@ const handleLinesCoverage = (state) => {
433
414
  }
434
415
  // line 1-base
435
416
  const line = it.line + 1;
436
- const lineInfo = new InfoLine(line, it.length, baseLineCount);
417
+ // default count to 1, both js and css
418
+ const lineInfo = new InfoLine(line, it.length, 1);
437
419
  lineMap.set(line, lineInfo);
438
420
  lines.push(lineInfo);
439
421
  });
package/lib/generate.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
-
3
+ const CG = require('console-grid');
4
+ const EC = require('eight-colors');
4
5
  const Util = require('./utils/util.js');
5
6
  const {
6
7
  initIstanbulData, mergeIstanbulCoverage, saveIstanbulReports
@@ -72,6 +73,9 @@ const getReportGroup = (reports, lcov, dataType) => {
72
73
  'v8',
73
74
  'v8-json',
74
75
 
76
+ // both
77
+ 'console-summary',
78
+
75
79
  // istanbul
76
80
  'clover',
77
81
  'cobertura',
@@ -95,6 +99,7 @@ const getReportGroup = (reports, lcov, dataType) => {
95
99
  return;
96
100
  }
97
101
 
102
+ // v8
98
103
  if (k.startsWith('v8')) {
99
104
  // v8
100
105
  if (!reportGroup.v8) {
@@ -104,6 +109,12 @@ const getReportGroup = (reports, lcov, dataType) => {
104
109
  return;
105
110
  }
106
111
 
112
+ // both
113
+ if (k === 'console-summary') {
114
+ reportGroup[k] = reportMap[k];
115
+ return;
116
+ }
117
+
107
118
  // istanbul
108
119
  if (!reportGroup.istanbul) {
109
120
  reportGroup.istanbul = {};
@@ -114,6 +125,8 @@ const getReportGroup = (reports, lcov, dataType) => {
114
125
  return reportGroup;
115
126
  };
116
127
 
128
+ // ========================================================================================================
129
+
117
130
 
118
131
  const generateCoverageReports = async (dataList, options) => {
119
132
 
@@ -144,6 +157,8 @@ const generateCoverageReports = async (dataList, options) => {
144
157
 
145
158
  };
146
159
 
160
+ // ========================================================================================================
161
+
147
162
 
148
163
  const getCoverageDataList = async (cacheDir) => {
149
164
  const files = fs.readdirSync(cacheDir).filter((f) => f.startsWith('coverage-'));
@@ -164,8 +179,114 @@ const getCoverageDataList = async (cacheDir) => {
164
179
  }
165
180
  };
166
181
 
182
+ // ========================================================================================================
183
+
184
+ const capitalizeFirstLetter = (string) => {
185
+ return string.charAt(0).toUpperCase() + string.slice(1);
186
+ };
187
+
188
+ const pFormatter = (v, row, column) => {
189
+ if (typeof v === 'number') {
190
+ const p = Util.PSF(v, 100, 2);
191
+ if (row.status === 'low') {
192
+ return EC.red(p);
193
+ }
194
+ if (row.status === 'medium') {
195
+ return EC.yellow(p);
196
+ }
197
+ if (row.status === 'high') {
198
+ return EC.green(p);
199
+ }
200
+ }
201
+ return v;
202
+ };
203
+
204
+ const nFormatter = (v) => {
205
+ if (typeof v === 'number') {
206
+ return Util.NF(v);
207
+ }
208
+ return v;
209
+ };
210
+
211
+ const showConsoleSummary = (coverageResults, options) => {
212
+
213
+ const reportGroup = options.reportGroup;
214
+ const consoleOptions = reportGroup['console-summary'];
215
+ if (!consoleOptions) {
216
+ return;
217
+ }
218
+
219
+ const { metrics } = consoleOptions;
220
+
221
+ const {
222
+ summary, name, type
223
+ } = coverageResults;
224
+ if (name) {
225
+ EC.logCyan(name);
226
+ }
227
+
228
+ const allMetrics = {
229
+ v8: ['bytes', 'functions', 'branches', 'lines'],
230
+ istanbul: ['statements', 'functions', 'branches', 'lines']
231
+ };
232
+
233
+ let list = allMetrics[type];
234
+ if (Util.isList(metrics)) {
235
+ const newList = list.filter((k) => metrics.includes(k));
236
+ if (newList.length) {
237
+ list = newList;
238
+ }
239
+ }
240
+
241
+ const rows = list.map((k) => {
242
+ return {
243
+ ... summary[k],
244
+ name: capitalizeFirstLetter(k)
245
+ };
246
+ });
247
+
248
+ const columns = [{
249
+ id: 'name',
250
+ name: 'Name'
251
+ }, {
252
+ id: 'pct',
253
+ name: 'Coverage %',
254
+ align: 'right',
255
+ formatter: pFormatter
256
+ }, {
257
+ id: 'covered',
258
+ name: 'Covered',
259
+ align: 'right',
260
+ formatter: nFormatter
261
+ }, {
262
+ id: 'uncovered',
263
+ name: 'Uncovered',
264
+ align: 'right',
265
+ formatter: nFormatter
266
+ }, {
267
+ id: 'total',
268
+ name: 'Total',
269
+ align: 'right',
270
+ formatter: nFormatter
271
+ }];
272
+
273
+ if (type === 'istanbul') {
274
+ columns.splice(4, 0, {
275
+ id: 'skipped',
276
+ name: 'Skipped',
277
+ align: 'right',
278
+ formatter: nFormatter
279
+ });
280
+ }
281
+
282
+ CG({
283
+ columns,
284
+ rows
285
+ });
286
+ };
167
287
 
168
288
  module.exports = {
169
289
  getCoverageDataList,
170
- generateCoverageReports
290
+ generateCoverageReports,
291
+ showConsoleSummary
171
292
  };
package/lib/index.d.ts CHANGED
@@ -23,11 +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
  }] |
32
+ ['console-summary'] | ['console-summary', {
33
+ metrics?: Array<"bytes" | "functions" | "branches" | "lines" | "statements">
34
+ }] |
31
35
  ['clover'] | ['clover', {
32
36
  file?: string
33
37
  }] |
package/lib/index.js CHANGED
@@ -4,7 +4,9 @@ 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 { getCoverageDataList, generateCoverageReports } = require('./generate.js');
7
+ const {
8
+ getCoverageDataList, generateCoverageReports, showConsoleSummary
9
+ } = require('./generate.js');
8
10
 
9
11
  class CoverageReport {
10
12
 
@@ -107,6 +109,8 @@ class CoverageReport {
107
109
  Util.rmSync(cacheDir);
108
110
  }
109
111
 
112
+ showConsoleSummary(coverageResults, this.options);
113
+
110
114
  const onEnd = this.options.onEnd;
111
115
  if (typeof onEnd === 'function') {
112
116
  await onEnd(coverageResults);
@@ -37,6 +37,19 @@ class IstanbulSummary extends ReportBase {
37
37
  }
38
38
 
39
39
  getReport() {
40
+
41
+ // remove branchesTrue
42
+ delete this.summary.branchesTrue;
43
+
44
+ // add uncovered
45
+ Object.keys(this.summary).forEach((id) => {
46
+ const item = this.summary[id];
47
+ // NOTE: skipped
48
+ item.uncovered = item.total - item.covered - item.skipped;
49
+ });
50
+
51
+ // console.log(this.summary);
52
+
40
53
  return {
41
54
  summary: this.summary,
42
55
  files: this.files