monocart-coverage-reports 2.7.5 → 2.7.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 +394 -358
- package/lib/cli.js +28 -10
- package/lib/client/cdp-client.js +2 -2
- package/lib/client/{cdp-session.js → ws-session.js} +2 -2
- package/lib/converter/converter.js +10 -5
- package/lib/converter/find-original-range.js +24 -3
- package/lib/generate.js +3 -8
- package/lib/index.d.ts +8 -0
- package/lib/index.js +4 -1
- package/lib/index.mjs +2 -0
- package/lib/packages/monocart-coverage-vendor.js +2 -2
- package/lib/utils/request.js +4 -0
- package/lib/utils/util.js +1 -1
- package/package.json +98 -98
package/README.md
CHANGED
|
@@ -9,32 +9,31 @@
|
|
|
9
9
|
> A code coverage tool to generate native [V8](https://v8.dev/blog/javascript-code-coverage) reports or [Istanbul](https://istanbul.js.org/) reports.
|
|
10
10
|
|
|
11
11
|
* [Usage](#usage)
|
|
12
|
-
* [
|
|
12
|
+
* [Options](#options)
|
|
13
13
|
* [Available Reports](#available-reports)
|
|
14
|
-
* [Using `entryFilter` and `sourceFilter` to filter the results for V8 report](#using-entryfilter-and-sourcefilter-to-filter-the-results-for-v8-report)
|
|
15
|
-
* [onEnd Hook](#onend-hook)
|
|
16
|
-
* [Command Line](#command-line)
|
|
17
14
|
* [Compare Reports](#compare-reports)
|
|
18
|
-
* [Compare Workflows](#compare-workflows)
|
|
19
15
|
* [Collecting Istanbul Coverage Data](#collecting-istanbul-coverage-data)
|
|
20
16
|
* [Collecting V8 Coverage Data](#collecting-v8-coverage-data)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* [
|
|
17
|
+
- [Collecting V8 Coverage Data with Playwright](#collecting-v8-coverage-data-with-playwright)
|
|
18
|
+
- [Collecting Raw V8 Coverage Data with Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer)
|
|
19
|
+
- [Node.js V8 Coverage Report for Server Side](#nodejs-v8-coverage-report-for-server-side)
|
|
20
|
+
- [Collecting V8 Coverage Data with `CDPClient` API](#collecting-v8-coverage-data-with-cdpclient-api)
|
|
21
|
+
- [V8 Coverage Data API](#v8-coverage-data-api)
|
|
22
|
+
* [Using `entryFilter` and `sourceFilter` to filter the results for V8 report](#using-entryfilter-and-sourcefilter-to-filter-the-results-for-v8-report)
|
|
27
23
|
* [Resolve `sourcePath` for the Source Files](#resolve-sourcepath-for-the-source-files)
|
|
28
24
|
* [Adding Empty Coverage for Untested Files](#adding-empty-coverage-for-untested-files)
|
|
25
|
+
* [onEnd Hook](#onend-hook)
|
|
29
26
|
* [Ignoring Uncovered Codes](#ignoring-uncovered-codes)
|
|
30
|
-
* [
|
|
31
|
-
* [
|
|
32
|
-
* [
|
|
33
|
-
|
|
34
|
-
- [How Monocart Works](#how-monocart-works)
|
|
35
|
-
* [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
27
|
+
* [Multiprocessing Support](#multiprocessing-support)
|
|
28
|
+
* [Command Line](#command-line)
|
|
29
|
+
* [Config File](#config-file)
|
|
30
|
+
* [Merge Coverage Reports](#merge-coverage-reports)
|
|
36
31
|
* [Common issues](#common-issues)
|
|
37
|
-
|
|
32
|
+
- [Unexpected coverage](#unexpected-coverage)
|
|
33
|
+
- [Unparsable source](#unparsable-source)
|
|
34
|
+
* [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
35
|
+
* [Integration with Any Testing Framework](#integration-with-any-testing-framework)
|
|
36
|
+
* [Integration Examples](#integration-examples)
|
|
38
37
|
- [Playwright](#playwright)
|
|
39
38
|
- [Jest](#jest)
|
|
40
39
|
- [Vitest](#vitest)
|
|
@@ -43,13 +42,18 @@
|
|
|
43
42
|
- [WebdriverIO](#webdriverio)
|
|
44
43
|
- [Storybook Test Runner](#storybook-test-runner)
|
|
45
44
|
- [TestCafe](#testcafe)
|
|
45
|
+
- [Mocha](#mocha)
|
|
46
|
+
- [tsx](#tsx)
|
|
47
|
+
- [ts-node](#ts-node)
|
|
48
|
+
- [AVA](#ava)
|
|
46
49
|
- [Codecov](#codecov)
|
|
47
50
|
- [Coveralls](#coveralls)
|
|
48
51
|
- [Sonar Cloud](#sonar-cloud)
|
|
49
|
-
- [Integration with Any Testing Framework](#integration-with-any-testing-framework)
|
|
50
52
|
* [Thanks](#thanks)
|
|
51
53
|
|
|
52
54
|
## Usage
|
|
55
|
+
> It's recommended to use [Node.js 20+](https://nodejs.org/).
|
|
56
|
+
- [API](#multiprocessing-support)
|
|
53
57
|
```js
|
|
54
58
|
const MCR = require('monocart-coverage-reports');
|
|
55
59
|
const coverageOptions = {
|
|
@@ -57,23 +61,25 @@ const coverageOptions = {
|
|
|
57
61
|
outputDir: './coverage-reports',
|
|
58
62
|
reports: ["v8", "console-details"]
|
|
59
63
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
64
|
+
const mcr = MCR(coverageOptions);
|
|
65
|
+
mcr.cleanCache();
|
|
62
66
|
|
|
63
|
-
await
|
|
64
|
-
await
|
|
67
|
+
await mcr.add(coverageData1);
|
|
68
|
+
await mcr.add(coverageData2);
|
|
65
69
|
|
|
66
|
-
await
|
|
70
|
+
await mcr.generate();
|
|
67
71
|
|
|
68
72
|
// Or
|
|
69
73
|
// const { CoverageReport } = require('monocart-coverage-reports');
|
|
70
|
-
// const
|
|
74
|
+
// const mcr = new CoverageReport(coverageOptions);
|
|
75
|
+
```
|
|
76
|
+
- [CLI](#command-line)
|
|
77
|
+
```sh
|
|
78
|
+
mcr node my-app.js -r v8,console-details
|
|
71
79
|
```
|
|
72
|
-
- [example v8](https://github.com/cenfun/monocart-coverage-reports/blob/main/test/test-v8.js)
|
|
73
|
-
- [example istanbul](https://github.com/cenfun/monocart-coverage-reports/blob/main/test/test-istanbul.js)
|
|
74
80
|
|
|
75
|
-
##
|
|
76
|
-
- [lib/default/options.js](
|
|
81
|
+
## Options
|
|
82
|
+
- Default Options: [lib/default/options.js](./lib/default/options.js)
|
|
77
83
|
- `reports` [Available Reports](#available-reports)
|
|
78
84
|
- `entryFilter` and `sourceFilter` [Using `entryFilter` and `sourceFilter` to filter the results for V8 report](#using-entryfilter-and-sourcefilter-to-filter-the-results-for-v8-report)
|
|
79
85
|
- `sourcePath` [Resolve `sourcePath` for the Source Files](#resolve-sourcepath-for-the-source-files)
|
|
@@ -82,7 +88,8 @@ await coverageReport.generate();
|
|
|
82
88
|
- `logging` [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
83
89
|
- `onEnd` [onEnd Hook](#onend-hook)
|
|
84
90
|
|
|
85
|
-
- Declaration [lib/index.d.ts](
|
|
91
|
+
- Declaration: [lib/index.d.ts](./lib/index.d.ts)
|
|
92
|
+
- [Config file](#config-file)
|
|
86
93
|
|
|
87
94
|
## Available Reports
|
|
88
95
|
|
|
@@ -95,9 +102,7 @@ await coverageReport.generate();
|
|
|
95
102
|
- Coverage for Any Runtime Code
|
|
96
103
|
- CSS Coverage Support
|
|
97
104
|
- Better Support for Sourcemap Conversion
|
|
98
|
-
- Demos:
|
|
99
|
-
- Browser: Build with webpack [V8](https://cenfun.github.io/monocart-coverage-reports/v8) and [Minify](https://cenfun.github.io/monocart-coverage-reports/minify); Build with [Rollup](https://cenfun.github.io/monocart-coverage-reports/rollup) and [Esbuild](https://cenfun.github.io/monocart-coverage-reports/esbuild); Collect with [puppeteer](https://cenfun.github.io/monocart-coverage-reports/puppeteer/); [anonymous](https://cenfun.github.io/monocart-coverage-reports/anonymous/) and [css](https://cenfun.github.io/monocart-coverage-reports/css/)
|
|
100
|
-
- Node.js: Collect with [env](https://cenfun.github.io/monocart-coverage-reports/node-env), and also V8 [API](https://cenfun.github.io/monocart-coverage-reports/node-api), [Inspector](https://cenfun.github.io/monocart-coverage-reports/node-ins) and [CDP](https://cenfun.github.io/monocart-coverage-reports/node-cdp); Web server example: [koa](https://cenfun.github.io/monocart-coverage-reports/node-koa/)
|
|
105
|
+
- Demos: [V8](https://cenfun.github.io/monocart-coverage-reports/v8) and [more](https://cenfun.github.io/monocart-coverage-reports/)
|
|
101
106
|
|
|
102
107
|

|
|
103
108
|
|
|
@@ -112,7 +117,6 @@ await coverageReport.generate();
|
|
|
112
117
|
- [Istanbul html](https://cenfun.github.io/monocart-coverage-reports/istanbul/)
|
|
113
118
|
- [V8 to Istanbul](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/istanbul)
|
|
114
119
|
- `html-spa`
|
|
115
|
-
- [Istanbul html-spa](https://cenfun.github.io/monocart-coverage-reports/istanbul/html-spa/)
|
|
116
120
|
- `json`
|
|
117
121
|
- `json-summary`
|
|
118
122
|
- `lcov`
|
|
@@ -193,148 +197,10 @@ const coverageOptions = {
|
|
|
193
197
|
|
|
194
198
|
]
|
|
195
199
|
}
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Using `entryFilter` and `sourceFilter` to filter the results for V8 report
|
|
201
|
-
When V8 coverage data collected, it actually contains the data of all entry files, for example:
|
|
202
|
-
```
|
|
203
|
-
dist/main.js
|
|
204
|
-
dist/vendor.js
|
|
205
|
-
dist/something-else.js
|
|
206
|
-
```
|
|
207
|
-
We can use `entryFilter` to filter the entry files. For example, we should remove `vendor.js` and `something-else.js` if they are not in our coverage scope.
|
|
208
|
-
```
|
|
209
|
-
dist/main.js
|
|
210
|
-
```
|
|
211
|
-
When inline or linked sourcemap exists to the entry file, the source files will be extracted from the sourcemap for the entry file, and the entry file will be removed if `logging` is not `debug`.
|
|
212
|
-
```
|
|
213
|
-
> src/index.js
|
|
214
|
-
> src/components/app.js
|
|
215
|
-
> node_modules/dependency/dist/dependency.js
|
|
216
|
-
```
|
|
217
|
-
We can use `sourceFilter` to filter the source files. For example, we should remove `dependency.js` if it is not in our coverage scope.
|
|
218
|
-
```
|
|
219
|
-
> src/index.js
|
|
220
|
-
> src/components/app.js
|
|
221
|
-
```
|
|
222
|
-
For example:
|
|
223
|
-
```js
|
|
224
|
-
const coverageOptions = {
|
|
225
|
-
entryFilter: (entry) => entry.url.indexOf("main.js") !== -1,
|
|
226
|
-
sourceFilter: (sourcePath) => sourcePath.search(/src\//) !== -1
|
|
227
|
-
};
|
|
228
|
-
```
|
|
229
|
-
Or using `minimatch` pattern:
|
|
230
|
-
```js
|
|
231
|
-
const coverageOptions = {
|
|
232
|
-
entryFilter: "**/main.js",
|
|
233
|
-
sourceFilter: "**/src/**"
|
|
234
|
-
};
|
|
235
|
-
// supports multiple patterns:
|
|
236
|
-
const coverageOptions = {
|
|
237
|
-
entryFilter: {
|
|
238
|
-
'**/vendor.js': false,
|
|
239
|
-
'**/main.js': true
|
|
240
|
-
},
|
|
241
|
-
sourceFilter: {
|
|
242
|
-
'**/src/**': true
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## onEnd Hook
|
|
248
|
-
For example, checking thresholds:
|
|
249
|
-
```js
|
|
250
|
-
const EC = require('eight-colors');
|
|
251
|
-
const coverageOptions = {
|
|
252
|
-
name: 'My Coverage Report',
|
|
253
|
-
outputDir: './coverage-reports',
|
|
254
|
-
onEnd: (coverageResults) => {
|
|
255
|
-
const thresholds = {
|
|
256
|
-
bytes: 80,
|
|
257
|
-
lines: 60
|
|
258
|
-
};
|
|
259
|
-
console.log('check thresholds ...', thresholds);
|
|
260
|
-
const errors = [];
|
|
261
|
-
const { summary } = coverageResults;
|
|
262
|
-
Object.keys(thresholds).forEach((k) => {
|
|
263
|
-
const pct = summary[k].pct;
|
|
264
|
-
if (pct < thresholds[k]) {
|
|
265
|
-
errors.push(`Coverage threshold for ${k} (${pct} %) not met: ${thresholds[k]} %`);
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
if (errors.length) {
|
|
269
|
-
const errMsg = errors.join('\n');
|
|
270
|
-
console.log(EC.red(errMsg));
|
|
271
|
-
// throw new Error(errMsg);
|
|
272
|
-
// process.exit(1);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
## Command Line
|
|
279
|
-
> The CLI will run the program as a [child process](https://nodejs.org/docs/latest/api/child_process.html) with `NODE_V8_COVERAGE=dir` until it exits gracefully, and generate the coverage report with the coverage data from the `dir`.
|
|
280
|
-
|
|
281
|
-
- Installing globally
|
|
282
|
-
```sh
|
|
283
|
-
npm i monocart-coverage-reports -g
|
|
284
|
-
mcr node ./test/specs/node.test.js -r v8,console-summary --lcov
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
- Locally in your project
|
|
288
|
-
```sh
|
|
289
|
-
npm i monocart-coverage-reports
|
|
290
|
-
npx mcr node ./test/specs/node.test.js -r v8,console-summary --lcov
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
- CLI Options
|
|
294
|
-
```sh
|
|
295
|
-
Usage: mcr [options] <command>
|
|
296
|
-
|
|
297
|
-
CLI to generate coverage reports
|
|
298
|
-
|
|
299
|
-
Arguments:
|
|
300
|
-
command command to execute
|
|
301
|
-
|
|
302
|
-
Options:
|
|
303
|
-
-V, --version output the version number
|
|
304
|
-
-c, --config <path> custom config file path
|
|
305
|
-
--logging <logging> off, error, info, debug
|
|
306
|
-
-n, --name <name> report name for title
|
|
307
|
-
-r, --reports <name[,name]> coverage reports to use
|
|
308
|
-
-o, --outputDir <dir> output dir for reports
|
|
309
|
-
-i, --inputDir <dir> input dir for merging raw files
|
|
310
|
-
--entryFilter <pattern> entry url filter
|
|
311
|
-
--sourceFilter <pattern> source path filter
|
|
312
|
-
--outputFile <path> output file for v8 report
|
|
313
|
-
--inline inline html for v8 report
|
|
314
|
-
--assetsPath <path> assets path if not inline
|
|
315
|
-
--lcov generate lcov.info file
|
|
316
|
-
--import <module> preload module at startup
|
|
317
|
-
--require <module> preload module at startup
|
|
318
|
-
-h, --help display help for command
|
|
200
|
+
const mcr = MCR(coverageOptions);
|
|
201
|
+
mcr.cleanCache();
|
|
319
202
|
```
|
|
320
203
|
|
|
321
|
-
- Loading config file by priority:
|
|
322
|
-
- Custom config file with `-c` or `--config`
|
|
323
|
-
- `mcr.config.js`
|
|
324
|
-
- `mcr.config.cjs`
|
|
325
|
-
- `mcr.config.mjs`
|
|
326
|
-
- `mcr.config.json` - json format
|
|
327
|
-
- `mcr.config.ts` (requires preloading the ts execution module)
|
|
328
|
-
- `.mcrrc.js`
|
|
329
|
-
- `.mcrrc` - json format
|
|
330
|
-
|
|
331
|
-
- Working with `tsx`, see [mcr-tsx](https://github.com/cenfun/mcr-tsx)
|
|
332
|
-
```sh
|
|
333
|
-
npx mcr --import tsx tsx ./src/example.ts
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
- Working with `ts-node`, see [mcr-ts-node](https://github.com/cenfun/mcr-ts-node)
|
|
337
|
-
|
|
338
204
|
## Compare Reports
|
|
339
205
|
| | Istanbul | V8 | V8 to Istanbul |
|
|
340
206
|
| :--------------| :------ | :------ | :---------------------- |
|
|
@@ -349,59 +215,58 @@ Options:
|
|
|
349
215
|
| CSS coverage | ❌ | ✅ | ✅ |
|
|
350
216
|
| Minified code | ❌ | ✅ | ❌ |
|
|
351
217
|
|
|
352
|
-
## Compare Workflows
|
|
353
|
-
- Istanbul Workflows
|
|
354
|
-
- 1, [Collecting Istanbul coverage data](#collecting-istanbul-coverage-data)
|
|
355
|
-
- 2, Adding coverage data and generating coverage report
|
|
356
|
-
|
|
357
|
-
- V8 Workflows
|
|
358
|
-
- 1, [Collecting V8 coverage data](#collecting-v8-coverage-data)
|
|
359
|
-
- 3, Adding coverage data and generating coverage report
|
|
360
|
-
|
|
361
218
|
## Collecting Istanbul Coverage Data
|
|
362
219
|
- Instrumenting source code
|
|
363
220
|
> Before collecting Istanbul coverage data, It requires your source code is instrumented with Istanbul
|
|
364
|
-
- webpack: [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul), example: [webpack.config-istanbul.js](
|
|
221
|
+
- webpack: [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul), example: [webpack.config-istanbul.js](./test/webpack.config-istanbul.js)
|
|
365
222
|
- rollup: [rollup-plugin-istanbul](https://github.com/artberri/rollup-plugin-istanbul)
|
|
366
223
|
- vite: [vite-plugin-istanbul](https://github.com/ifaxity/vite-plugin-istanbul)
|
|
367
224
|
- Browser
|
|
368
|
-
- Collecting coverage data from `window.__coverage__`, example: [test-istanbul.js](
|
|
225
|
+
- Collecting coverage data from `window.__coverage__`, example: [test-istanbul.js](./test/test-istanbul.js)
|
|
369
226
|
- Node.js
|
|
370
227
|
- Collecting coverage data from `global.__coverage__`
|
|
371
228
|
|
|
372
229
|
## Collecting V8 Coverage Data
|
|
373
|
-
-
|
|
374
|
-
- [webpack](https://webpack.js.org/configuration/): `devtool: source-map` and `mode: development`, example [webpack.config-v8.js](
|
|
230
|
+
- Sourcemap for source code: enable `sourcemap` and do not compress/minify:
|
|
231
|
+
- [webpack](https://webpack.js.org/configuration/): `devtool: source-map` and `mode: development`, example [webpack.config-v8.js](./test/webpack.config-v8.js)
|
|
375
232
|
- [rollup](https://rollupjs.org/configuration-options/): `sourcemap: true`
|
|
376
233
|
- [vite](https://vitejs.dev/config/build-options.html): `sourcemap: true` and `minify: false`
|
|
377
234
|
- [esbuild](https://esbuild.github.io/api/): `sourcemap: true` and `minify: false`
|
|
378
|
-
|
|
235
|
+
|
|
379
236
|
- Browser (Chromium Only)
|
|
380
|
-
|
|
381
|
-
- [
|
|
382
|
-
|
|
237
|
+
- [Collecting V8 Coverage Data with Playwright](#collecting-v8-coverage-data-with-playwright)
|
|
238
|
+
- [Collecting Raw V8 Coverage Data with Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer)
|
|
239
|
+
|
|
383
240
|
- Node.js
|
|
384
|
-
-
|
|
241
|
+
- [Node.js V8 Coverage Report for Server Side](#nodejs-v8-coverage-report-for-server-side)
|
|
242
|
+
|
|
385
243
|
- CDP
|
|
386
|
-
-
|
|
244
|
+
- [Collecting V8 Coverage Data with `CDPClient` API](#collecting-v8-coverage-data-with-cdpclient-api)
|
|
387
245
|
|
|
388
|
-
|
|
389
|
-
> Sometimes, the sourcemap file cannot be successfully loaded with the `sourceMappingURL`, you can try to manually read the sourcemap file before the coverage data is added to the report.
|
|
246
|
+
### Collecting V8 Coverage Data with Playwright
|
|
390
247
|
```js
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
})
|
|
248
|
+
await Promise.all([
|
|
249
|
+
page.coverage.startJSCoverage({
|
|
250
|
+
resetOnNavigation: false
|
|
251
|
+
}),
|
|
252
|
+
page.coverage.startCSSCoverage({
|
|
253
|
+
resetOnNavigation: false
|
|
254
|
+
})
|
|
255
|
+
]);
|
|
398
256
|
|
|
399
|
-
await
|
|
257
|
+
await page.goto("your page url");
|
|
258
|
+
|
|
259
|
+
const [jsCoverage, cssCoverage] = await Promise.all([
|
|
260
|
+
page.coverage.stopJSCoverage(),
|
|
261
|
+
page.coverage.stopCSSCoverage()
|
|
262
|
+
]);
|
|
263
|
+
|
|
264
|
+
const coverageData = [... jsCoverage, ... cssCoverage];
|
|
400
265
|
|
|
401
266
|
```
|
|
267
|
+
see [./test/test-v8.js](./test/test-v8.js), and [anonymous](./test/test-anonymous.js), [css](./test/test-css.js)
|
|
402
268
|
|
|
403
|
-
|
|
404
|
-
> Puppeteer does not provide raw v8 coverage data by default. A simple conversion is required, see example: [./test/test-puppeteer.js](./test/test-puppeteer.js)
|
|
269
|
+
### Collecting Raw V8 Coverage Data with Puppeteer
|
|
405
270
|
```js
|
|
406
271
|
await Promise.all([
|
|
407
272
|
page.coverage.startJSCoverage({
|
|
@@ -414,7 +279,7 @@ await Promise.all([
|
|
|
414
279
|
})
|
|
415
280
|
]);
|
|
416
281
|
|
|
417
|
-
await page.goto(url);
|
|
282
|
+
await page.goto("your page url");
|
|
418
283
|
|
|
419
284
|
const [jsCoverage, cssCoverage] = await Promise.all([
|
|
420
285
|
page.coverage.stopJSCoverage(),
|
|
@@ -429,8 +294,9 @@ const coverageData = [... jsCoverage.map((it) => {
|
|
|
429
294
|
};
|
|
430
295
|
}), ... cssCoverage];
|
|
431
296
|
```
|
|
297
|
+
see example: [./test/test-puppeteer.js](./test/test-puppeteer.js)
|
|
432
298
|
|
|
433
|
-
|
|
299
|
+
### Node.js V8 Coverage Report for Server Side
|
|
434
300
|
Possible solutions:
|
|
435
301
|
- [NODE_V8_COVERAGE](https://nodejs.org/docs/latest/api/cli.html#node_v8_coveragedir)=`dir`
|
|
436
302
|
- Sets Node.js env `NODE_V8_COVERAGE`=`dir` before the program running, the coverage data will be saved to the `dir` after the program exits gracefully.
|
|
@@ -463,7 +329,7 @@ Possible solutions:
|
|
|
463
329
|
- [Child Process](https://nodejs.org/docs/latest/api/child_process.html) + NODE_V8_COVERAGE
|
|
464
330
|
- see [Command Line](#command-line)
|
|
465
331
|
|
|
466
|
-
|
|
332
|
+
### Collecting V8 Coverage Data with `CDPClient` API
|
|
467
333
|
- Work with node debugger `--inspect=9229`
|
|
468
334
|
```js
|
|
469
335
|
const MCR = require('monocart-coverage-reports');
|
|
@@ -507,93 +373,97 @@ await page.goto("your page url");
|
|
|
507
373
|
const coverageData = await client.stopCoverage();
|
|
508
374
|
```
|
|
509
375
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
-
|
|
376
|
+
### V8 Coverage Data API
|
|
377
|
+
- [V8 coverage report](https://v8.dev/blog/javascript-code-coverage) - Native support for JavaScript code coverage to V8. (Chromium only)
|
|
378
|
+
- [Playwright Coverage Class](https://playwright.dev/docs/api/class-coverage)
|
|
379
|
+
- [Puppeteer Coverage class](https://pptr.dev/api/puppeteer.coverage)
|
|
380
|
+
- [DevTools Protocol for Coverage](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#method-startPreciseCoverage) see devtools-protocol [ScriptCoverage](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-ScriptCoverage) and [v8-coverage](https://github.com/bcoe/v8-coverage)
|
|
513
381
|
```js
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
//
|
|
519
|
-
|
|
520
|
-
|
|
382
|
+
// Coverage data for a source range.
|
|
383
|
+
export interface CoverageRange {
|
|
384
|
+
// JavaScript script source offset for the range start.
|
|
385
|
+
startOffset: integer;
|
|
386
|
+
// JavaScript script source offset for the range end.
|
|
387
|
+
endOffset: integer;
|
|
388
|
+
// Collected execution count of the source range.
|
|
389
|
+
count: integer;
|
|
390
|
+
}
|
|
521
391
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
392
|
+
// Coverage data for a JavaScript function.
|
|
393
|
+
/**
|
|
394
|
+
* @functionName can be an empty string.
|
|
395
|
+
* @ranges is always non-empty. The first range is called the "root range".
|
|
396
|
+
* @isBlockCoverage indicates if the function has block coverage information.
|
|
397
|
+
If this is false, it usually means that the functions was never called.
|
|
398
|
+
It seems to be equivalent to ranges.length === 1 && ranges[0].count === 0.
|
|
399
|
+
*/
|
|
400
|
+
export interface FunctionCoverage {
|
|
401
|
+
// JavaScript function name.
|
|
402
|
+
functionName: string;
|
|
403
|
+
// Source ranges inside the function with coverage data.
|
|
404
|
+
ranges: CoverageRange[];
|
|
405
|
+
// Whether coverage data for this function has block granularity.
|
|
406
|
+
isBlockCoverage: boolean;
|
|
407
|
+
}
|
|
530
408
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
409
|
+
// Coverage data for a JavaScript script.
|
|
410
|
+
export interface ScriptCoverage {
|
|
411
|
+
// JavaScript script id.
|
|
412
|
+
scriptId: Runtime.ScriptId;
|
|
413
|
+
// JavaScript script name or url.
|
|
414
|
+
url: string;
|
|
415
|
+
// Functions contained in the script that has coverage data.
|
|
416
|
+
functions: FunctionCoverage[];
|
|
417
|
+
}
|
|
539
418
|
|
|
540
|
-
|
|
541
|
-
```js
|
|
542
|
-
// generate coverage reports after the completion of testing
|
|
543
|
-
const MCR = require('monocart-coverage-reports');
|
|
544
|
-
const coverageOptions = require('path-to/same-options.js');
|
|
545
|
-
const coverageReport = MCR(coverageOptions);
|
|
546
|
-
// do not clean cache before generating reports
|
|
547
|
-
await coverageReport.generate();
|
|
419
|
+
export type V8CoverageData = ScriptCoverage[];
|
|
548
420
|
```
|
|
549
421
|
|
|
550
|
-
##
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
422
|
+
## Using `entryFilter` and `sourceFilter` to filter the results for V8 report
|
|
423
|
+
When V8 coverage data collected, it actually contains the data of all entry files, for example:
|
|
424
|
+
```
|
|
425
|
+
dist/main.js
|
|
426
|
+
dist/vendor.js
|
|
427
|
+
dist/something-else.js
|
|
428
|
+
```
|
|
429
|
+
We can use `entryFilter` to filter the entry files. For example, we should remove `vendor.js` and `something-else.js` if they are not in our coverage scope.
|
|
430
|
+
```
|
|
431
|
+
dist/main.js
|
|
432
|
+
```
|
|
433
|
+
When inline or linked sourcemap exists to the entry file, the source files will be extracted from the sourcemap for the entry file, and the entry file will be removed if `logging` is not `debug`.
|
|
434
|
+
```
|
|
435
|
+
> src/index.js
|
|
436
|
+
> src/components/app.js
|
|
437
|
+
> node_modules/dependency/dist/dependency.js
|
|
438
|
+
```
|
|
439
|
+
We can use `sourceFilter` to filter the source files. For example, we should remove `dependency.js` if it is not in our coverage scope.
|
|
440
|
+
```
|
|
441
|
+
> src/index.js
|
|
442
|
+
> src/components/app.js
|
|
443
|
+
```
|
|
444
|
+
For example:
|
|
558
445
|
```js
|
|
559
446
|
const coverageOptions = {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
reports: [
|
|
563
|
-
['raw', {
|
|
564
|
-
// relative path will be "./coverage-reports/unit/raw"
|
|
565
|
-
outputDir: "raw"
|
|
566
|
-
}],
|
|
567
|
-
['v8'],
|
|
568
|
-
['console-summary']
|
|
569
|
-
]
|
|
447
|
+
entryFilter: (entry) => entry.url.indexOf("main.js") !== -1,
|
|
448
|
+
sourceFilter: (sourcePath) => sourcePath.search(/src\//) !== -1
|
|
570
449
|
};
|
|
571
450
|
```
|
|
572
|
-
|
|
451
|
+
Or using `minimatch` pattern:
|
|
573
452
|
```js
|
|
574
|
-
// esm syntax
|
|
575
|
-
import fs from "fs";
|
|
576
|
-
import { CoverageReport } from 'monocart-coverage-reports';
|
|
577
453
|
const coverageOptions = {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
// remove the raw files if it useless
|
|
590
|
-
fs.rmSync('./coverage-reports/unit/raw', {
|
|
591
|
-
recursive: true,
|
|
592
|
-
force: true
|
|
593
|
-
})
|
|
454
|
+
entryFilter: "**/main.js",
|
|
455
|
+
sourceFilter: "**/src/**"
|
|
456
|
+
};
|
|
457
|
+
// supports multiple patterns:
|
|
458
|
+
const coverageOptions = {
|
|
459
|
+
entryFilter: {
|
|
460
|
+
'**/vendor.js': false,
|
|
461
|
+
'**/main.js': true
|
|
462
|
+
},
|
|
463
|
+
sourceFilter: {
|
|
464
|
+
'**/src/**': true
|
|
594
465
|
}
|
|
595
466
|
};
|
|
596
|
-
await new CoverageReport(coverageOptions).generate();
|
|
597
467
|
```
|
|
598
468
|
|
|
599
469
|
## Resolve `sourcePath` for the Source Files
|
|
@@ -660,6 +530,37 @@ const coverageOptions = {
|
|
|
660
530
|
};
|
|
661
531
|
```
|
|
662
532
|
|
|
533
|
+
## onEnd Hook
|
|
534
|
+
For example, checking thresholds:
|
|
535
|
+
```js
|
|
536
|
+
const EC = require('eight-colors');
|
|
537
|
+
const coverageOptions = {
|
|
538
|
+
name: 'My Coverage Report',
|
|
539
|
+
outputDir: './coverage-reports',
|
|
540
|
+
onEnd: (coverageResults) => {
|
|
541
|
+
const thresholds = {
|
|
542
|
+
bytes: 80,
|
|
543
|
+
lines: 60
|
|
544
|
+
};
|
|
545
|
+
console.log('check thresholds ...', thresholds);
|
|
546
|
+
const errors = [];
|
|
547
|
+
const { summary } = coverageResults;
|
|
548
|
+
Object.keys(thresholds).forEach((k) => {
|
|
549
|
+
const pct = summary[k].pct;
|
|
550
|
+
if (pct < thresholds[k]) {
|
|
551
|
+
errors.push(`Coverage threshold for ${k} (${pct} %) not met: ${thresholds[k]} %`);
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
if (errors.length) {
|
|
555
|
+
const errMsg = errors.join('\n');
|
|
556
|
+
console.log(EC.red(errMsg));
|
|
557
|
+
// throw new Error(errMsg);
|
|
558
|
+
// process.exit(1);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
663
564
|
## Ignoring Uncovered Codes
|
|
664
565
|
To ignore codes, use the special comment which starts with `v8 ignore `:
|
|
665
566
|
- Ignoring all until stop
|
|
@@ -682,103 +583,191 @@ if (platform === 'linux') {
|
|
|
682
583
|
}
|
|
683
584
|
```
|
|
684
585
|
|
|
685
|
-
##
|
|
686
|
-
|
|
687
|
-
-
|
|
688
|
-
|
|
689
|
-
|
|
586
|
+
## Multiprocessing Support
|
|
587
|
+
> The data will be added to `[outputDir]/.cache`, After the generation of the report, this data will be removed unless debugging has been enabled or a raw report has been used, see [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
588
|
+
- Main process, before the start of testing
|
|
589
|
+
```js
|
|
590
|
+
const MCR = require('monocart-coverage-reports');
|
|
591
|
+
const coverageOptions = require('path-to/same-options.js');
|
|
592
|
+
const mcr = MCR(coverageOptions);
|
|
593
|
+
// clean previous cache before the start of testing
|
|
594
|
+
// unless the running environment is new and no cache
|
|
595
|
+
mcr.cleanCache();
|
|
596
|
+
```
|
|
690
597
|
|
|
691
|
-
|
|
598
|
+
- Sub process 1, testing stage 1
|
|
692
599
|
```js
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
// Collected execution count of the source range.
|
|
700
|
-
count: integer;
|
|
701
|
-
}
|
|
600
|
+
const MCR = require('monocart-coverage-reports');
|
|
601
|
+
const coverageOptions = require('path-to/same-options.js');
|
|
602
|
+
const mcr = MCR(coverageOptions);
|
|
603
|
+
// do not clean cache in the stage
|
|
604
|
+
await mcr.add(coverageData1);
|
|
605
|
+
```
|
|
702
606
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
export interface FunctionCoverage {
|
|
712
|
-
// JavaScript function name.
|
|
713
|
-
functionName: string;
|
|
714
|
-
// Source ranges inside the function with coverage data.
|
|
715
|
-
ranges: CoverageRange[];
|
|
716
|
-
// Whether coverage data for this function has block granularity.
|
|
717
|
-
isBlockCoverage: boolean;
|
|
718
|
-
}
|
|
607
|
+
- Sub process 2, testing stage 2
|
|
608
|
+
```js
|
|
609
|
+
const MCR = require('monocart-coverage-reports');
|
|
610
|
+
const coverageOptions = require('path-to/same-options.js');
|
|
611
|
+
const mcr = MCR(coverageOptions);
|
|
612
|
+
// do not clean cache in the stage
|
|
613
|
+
await mcr.add(coverageData2);
|
|
614
|
+
```
|
|
719
615
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
616
|
+
- Main process, after the completion of testing
|
|
617
|
+
```js
|
|
618
|
+
// generate coverage reports after the completion of testing
|
|
619
|
+
const MCR = require('monocart-coverage-reports');
|
|
620
|
+
const coverageOptions = require('path-to/same-options.js');
|
|
621
|
+
const mcr = MCR(coverageOptions);
|
|
622
|
+
// do not clean cache before generating reports
|
|
623
|
+
await mcr.generate();
|
|
624
|
+
```
|
|
729
625
|
|
|
730
|
-
|
|
626
|
+
## Command Line
|
|
627
|
+
> The CLI will run the program as a [child process](https://nodejs.org/docs/latest/api/child_process.html) with `NODE_V8_COVERAGE=dir` until it exits gracefully, and generate the coverage report with the coverage data from the `dir`.
|
|
628
|
+
|
|
629
|
+
- Installing globally
|
|
630
|
+
```sh
|
|
631
|
+
npm i monocart-coverage-reports -g
|
|
632
|
+
mcr node ./test/specs/node.test.js -r v8,console-summary --lcov
|
|
731
633
|
```
|
|
732
|
-
see devtools-protocol [ScriptCoverage](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-ScriptCoverage) and [v8-coverage](https://github.com/bcoe/v8-coverage)
|
|
733
634
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
```js
|
|
739
|
-
const a = tf ? 'true' : 'false';
|
|
740
|
-
^ ^ ^
|
|
741
|
-
m1 p m2
|
|
635
|
+
- Locally in your project
|
|
636
|
+
```sh
|
|
637
|
+
npm i monocart-coverage-reports
|
|
638
|
+
npx mcr node ./test/specs/node.test.js -r v8,console-summary --lcov
|
|
742
639
|
```
|
|
743
|
-
> `m1` and `m2` are two consecutive mappings, `p` is the position we looking for. However, we can only get the position of the `m1` or `m2` if we don't fix it to `p`. Especially the generated code is different from the original code, such as the code was minified, compressed or converted, it is difficult to find the exact position.
|
|
744
640
|
|
|
745
|
-
-
|
|
641
|
+
- CLI Options
|
|
642
|
+
```sh
|
|
643
|
+
Usage: mcr [options] [command]
|
|
746
644
|
|
|
747
|
-
|
|
748
|
-
We implemented new converter:
|
|
749
|
-
- 1, Trying to fix the middle position if not found the exact mapping for the position.
|
|
750
|
-
- 2, Finding all functions, statements and branches by parsing the source code [AST](https://github.com/acornjs/acorn). However, there's a small issue, which is the V8 cannot provide effective branch coverage information for `AssignmentPattern`.
|
|
645
|
+
CLI to generate coverage reports
|
|
751
646
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
| AssignmentPattern | 🛇 Not Support |
|
|
755
|
-
| ConditionalExpression | ✔ |
|
|
756
|
-
| IfStatement | ✔ |
|
|
757
|
-
| LogicalExpression | ✔ |
|
|
758
|
-
| SwitchStatement | ✔ |
|
|
647
|
+
Arguments:
|
|
648
|
+
command command to execute
|
|
759
649
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
-
|
|
650
|
+
Options:
|
|
651
|
+
-V, --version output the version number
|
|
652
|
+
-c, --config <path> custom config file path
|
|
653
|
+
-l, --logging <logging> off, error, info, debug
|
|
654
|
+
-n, --name <name> report name for title
|
|
655
|
+
-r, --reports <name[,name]> coverage reports to use
|
|
656
|
+
-o, --outputDir <dir> output dir for reports
|
|
657
|
+
-i, --inputDir <dir> input dir for merging raw files
|
|
658
|
+
--entryFilter <pattern> entry url filter
|
|
659
|
+
--sourceFilter <pattern> source path filter
|
|
660
|
+
--outputFile <path> output file for v8 report
|
|
661
|
+
--inline inline html for v8 report
|
|
662
|
+
--assetsPath <path> assets path if not inline
|
|
663
|
+
--lcov generate lcov.info file
|
|
664
|
+
--import <module> preload module at startup
|
|
665
|
+
--require <module> preload module at startup
|
|
666
|
+
-h, --help display help for command
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
- Use `--` to separate sub CLI args
|
|
670
|
+
```sh
|
|
671
|
+
mcr -c mcr.config.js -- sub-cli -c sub-cli.config.js
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
## Config File
|
|
675
|
+
Loading config file by priority:
|
|
676
|
+
- Custom config file:
|
|
677
|
+
- CLI: `mcr --config <my-config-file-path>`
|
|
678
|
+
- API: `await mcr.loadConfig("my-config-file-path")`
|
|
679
|
+
- `mcr.config.js`
|
|
680
|
+
- `mcr.config.cjs`
|
|
681
|
+
- `mcr.config.mjs`
|
|
682
|
+
- `mcr.config.json` - json format
|
|
683
|
+
- `mcr.config.ts` (requires preloading the ts execution module)
|
|
684
|
+
- `.mcrrc.js`
|
|
685
|
+
- `.mcrrc` - json format
|
|
686
|
+
|
|
687
|
+
## Merge Coverage Reports
|
|
688
|
+
The following usage scenarios may require merging coverage reports:
|
|
689
|
+
- When the code is executed in different environments, like Node.js Server Side and browser Client Side (Next.js for instance). Each environment may generate its own coverage report. Merging them can give a more comprehensive view of the test coverage. see example [nextjs-with-playwright](https://github.com/cenfun/nextjs-with-playwright) for automatic report merging.
|
|
690
|
+
- When the code is subjected to different kinds of testing. For example, unit tests with Jest might cover certain parts of the code, while end-to-end tests with Playwright might cover other parts. Merging these different coverage reports can provide a holistic view of what code has been tested.
|
|
691
|
+
- When tests are run on different machines or different shards, each might produce its own coverage report. Merging these can give a complete picture of the test coverage across all machines or shards.
|
|
692
|
+
|
|
693
|
+
If the reports cannot be merged automatically, then here is how to manually merge the reports.
|
|
694
|
+
First, using the `raw` report to export the original coverage data to the specified directory.
|
|
763
695
|
```js
|
|
764
696
|
const coverageOptions = {
|
|
765
|
-
|
|
697
|
+
name: 'My Unit Test Coverage Report',
|
|
698
|
+
outputDir: "./coverage-reports/unit",
|
|
766
699
|
reports: [
|
|
700
|
+
['raw', {
|
|
701
|
+
// relative path will be "./coverage-reports/unit/raw"
|
|
702
|
+
outputDir: "raw"
|
|
703
|
+
}],
|
|
767
704
|
['v8'],
|
|
768
705
|
['console-summary']
|
|
769
706
|
]
|
|
770
707
|
};
|
|
771
708
|
```
|
|
772
|
-
|
|
773
|
-
|
|
709
|
+
Then, after all the tests are completed, generate a merged report with option `inputDir`:
|
|
710
|
+
```js
|
|
711
|
+
const fs = require('fs');
|
|
712
|
+
const { CoverageReport } = require('monocart-coverage-reports');
|
|
713
|
+
const inputDir = [
|
|
714
|
+
'./coverage-reports/unit/raw',
|
|
715
|
+
'./coverage-reports/e2e/raw'
|
|
716
|
+
];
|
|
717
|
+
const coverageOptions = {
|
|
718
|
+
name: 'My Merged Coverage Report',
|
|
719
|
+
inputDir,
|
|
720
|
+
outputDir: './coverage-reports/merged',
|
|
774
721
|
|
|
775
|
-
|
|
722
|
+
// filter for both unit and e2e
|
|
723
|
+
entryFilter: {
|
|
724
|
+
'**/node_modules/**': false,
|
|
725
|
+
'**/*': true
|
|
726
|
+
},
|
|
727
|
+
sourceFilter: {
|
|
728
|
+
'**/node_modules/**': false,
|
|
729
|
+
'**/src/**': true
|
|
730
|
+
},
|
|
731
|
+
|
|
732
|
+
sourcePath: (filePath, info) => {
|
|
733
|
+
// Unify the file path for the same files
|
|
734
|
+
return filePath;
|
|
735
|
+
},
|
|
776
736
|
|
|
777
|
-
|
|
737
|
+
reports: [
|
|
738
|
+
['v8'],
|
|
739
|
+
['console-details']
|
|
740
|
+
],
|
|
741
|
+
|
|
742
|
+
onEnd: () => {
|
|
743
|
+
// remove the raw files if it useless
|
|
744
|
+
inputDir.forEach((p) => {
|
|
745
|
+
fs.rmSync(p, {
|
|
746
|
+
recursive: true,
|
|
747
|
+
force: true
|
|
748
|
+
});
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
await new CoverageReport(coverageOptions).generate();
|
|
753
|
+
```
|
|
778
754
|
|
|
779
755
|
## Common issues
|
|
780
|
-
|
|
756
|
+
### Unexpected coverage
|
|
757
|
+
In most cases, it happens when the coverage of the generated code is converted to the coverage of the original code through a sourcemap. In other words, it's an issue with the sourcemap. Most of the time, we can solve this by setting `minify` to `false` in the build tools configuration. Let's take a look at an example:
|
|
758
|
+
```js
|
|
759
|
+
const a = tf ? 'true' : 'false';
|
|
760
|
+
^ ^ ^
|
|
761
|
+
m1 p m2
|
|
762
|
+
```
|
|
763
|
+
`m1` and `m2` are two consecutive mappings, `p` is the position we looking for. However, we can only get the position of the `m1` or `m2` if we don't fix it to `p`. Especially the generated code is different from the original code, such as the code was minified, compressed or converted, it is difficult to find the exact position. You can try [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap)
|
|
781
764
|
|
|
765
|
+
How `MCR` Works:
|
|
766
|
+
- 1, Trying to fix the middle position if not found the exact mapping for the position. However, for non-JS code, such as Vue template, JSX, etc., it might be hard to find a perfect solution.
|
|
767
|
+
- 2, Finding all functions, statements and branches by parsing the source code [AST](https://github.com/acornjs/acorn). However, there's a small issue, which is the V8 cannot provide effective branch coverage information for `AssignmentPattern`.
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
### Unparsable source
|
|
782
771
|
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.
|
|
783
772
|
```js
|
|
784
773
|
import * as fs from "fs";
|
|
@@ -798,7 +787,35 @@ const coverageOptions = {
|
|
|
798
787
|
}
|
|
799
788
|
```
|
|
800
789
|
|
|
801
|
-
##
|
|
790
|
+
## Debug for Coverage and Sourcemap
|
|
791
|
+
> Sometimes, the coverage is not what we expect. The next step is to figure out why, and we can easily find out the answer step by step through debugging.
|
|
792
|
+
- Start debugging for v8 report with option `logging: 'debug'`
|
|
793
|
+
```js
|
|
794
|
+
const coverageOptions = {
|
|
795
|
+
logging: 'debug',
|
|
796
|
+
reports: [
|
|
797
|
+
['v8'],
|
|
798
|
+
['console-summary']
|
|
799
|
+
]
|
|
800
|
+
};
|
|
801
|
+
```
|
|
802
|
+
When `logging` is `debug`, the raw report data will be preserved in `[outputDir]/.cache` or `[outputDir]/raw` if `raw` report is used. And the dist file will be preserved in the V8 list, and by opening the browser's devtool, it makes data verification visualization effortless.
|
|
803
|
+

|
|
804
|
+
|
|
805
|
+
- Check sourcemap with [Source Map Visualization](https://evanw.github.io/source-map-visualization/)
|
|
806
|
+
|
|
807
|
+

|
|
808
|
+
|
|
809
|
+
## Integration with Any Testing Framework
|
|
810
|
+
- API
|
|
811
|
+
- Collecting coverage data when any stage of the test is completed, and adding the coverage data to the coverage reporter. `await mcr.add(coverageData)`
|
|
812
|
+
- Generating the coverage reports after the completion of all tests. `await mcr.generate()`
|
|
813
|
+
- see [Multiprocessing Support](#multiprocessing-support)
|
|
814
|
+
- CLI
|
|
815
|
+
- Wrapping with any CLI. `mcr your-cli --your-arguments`
|
|
816
|
+
- see [Command line](#command-line)
|
|
817
|
+
|
|
818
|
+
## Integration Examples
|
|
802
819
|
|
|
803
820
|
### [Playwright](https://github.com/microsoft/playwright)
|
|
804
821
|
- [monocart-reporter](https://github.com/cenfun/monocart-reporter) - A Playwright custom reporter, supports generating [Code Coverage Report](https://github.com/cenfun/monocart-reporter?#code-coverage-report)
|
|
@@ -833,6 +850,29 @@ const coverageOptions = {
|
|
|
833
850
|
### [TestCafe](https://github.com/DevExpress/testcafe)
|
|
834
851
|
- [testcafe-reporter-coverage](https://github.com/cenfun/testcafe-reporter-coverage) - A TestCafe custom reporter for coverage reports
|
|
835
852
|
|
|
853
|
+
### [Mocha](https://github.com/mochajs/mocha)
|
|
854
|
+
```sh
|
|
855
|
+
mcr mocha ./test/**/*.js
|
|
856
|
+
```
|
|
857
|
+
```sh
|
|
858
|
+
mcr --import tsx mocha ./test/**/*.ts
|
|
859
|
+
```
|
|
860
|
+
- see [mcr-tsx](https://github.com/cenfun/mcr-tsx)
|
|
861
|
+
|
|
862
|
+
### [tsx](https://github.com/privatenumber/tsx)
|
|
863
|
+
```sh
|
|
864
|
+
mcr --import tsx tsx ./src/example.ts
|
|
865
|
+
```
|
|
866
|
+
- see [mcr-tsx](https://github.com/cenfun/mcr-tsx)
|
|
867
|
+
|
|
868
|
+
### [ts-node](https://github.com/TypeStrong/ts-node)
|
|
869
|
+
- see [mcr-ts-node](https://github.com/cenfun/mcr-ts-node)
|
|
870
|
+
|
|
871
|
+
### [AVA](https://github.com/avajs/ava)
|
|
872
|
+
```sh
|
|
873
|
+
mcr ava
|
|
874
|
+
```
|
|
875
|
+
|
|
836
876
|
### [Codecov](https://codecov.com/)
|
|
837
877
|
[](https://codecov.io/gh/cenfun/monocart-coverage-reports)
|
|
838
878
|
- Supports native `codecov` built-in report ([specification](https://docs.codecov.com/docs/codecov-custom-coverage-format))
|
|
@@ -886,10 +926,6 @@ const coverageOptions = {
|
|
|
886
926
|
-Dsonar.tests=test
|
|
887
927
|
-Dsonar.exclusions=dist/*,packages/*
|
|
888
928
|
```
|
|
889
|
-
### Integration with Any Testing Framework
|
|
890
|
-
- Collecting coverage data when any stage of the test is completed, and adding the coverage data to the coverage reporter.
|
|
891
|
-
- Generating the coverage reports after the completion of all tests.
|
|
892
|
-
- see [Multiprocessing Support](#multiprocessing-support)
|
|
893
929
|
|
|
894
930
|
### VSCode Extension
|
|
895
931
|
- [Coverage Gutters](https://github.com/ryanluker/vscode-coverage-gutters) - Display test coverage generated by lcov or xml in VSCode editor.
|