monocart-coverage-reports 2.5.7 → 2.5.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 +69 -42
- package/lib/converter/ast.js +18 -3
- package/lib/converter/converter.js +22 -5
- package/lib/default/options.js +7 -0
- package/lib/generate.js +200 -1
- package/lib/index.d.ts +26 -4
- package/lib/index.js +9 -6
- package/lib/packages/monocart-coverage-v8.js +1 -1
- package/lib/utils/util.js +2 -10
- package/lib/v8/v8-summary.js +8 -0
- package/lib/v8/v8.js +23 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
- [Playwright](#playwright)
|
|
38
38
|
- [Jest](#jest)
|
|
39
39
|
- [Vitest](#vitest)
|
|
40
|
+
- [CodeceptJS](#codeceptjs)
|
|
41
|
+
- [WebdriverIO](#webdriverio)
|
|
40
42
|
- [Codecov](#codecov)
|
|
41
43
|
- [Coveralls](#coveralls)
|
|
42
44
|
- [Sonar Cloud](#sonar-cloud)
|
|
@@ -190,12 +192,22 @@ const coverageOptions = {
|
|
|
190
192
|
sourceFilter: (sourcePath) => sourcePath.search(/src\//) !== -1
|
|
191
193
|
};
|
|
192
194
|
```
|
|
193
|
-
Or `minimatch` pattern:
|
|
195
|
+
Or using `minimatch` pattern:
|
|
194
196
|
```js
|
|
195
197
|
const coverageOptions = {
|
|
196
198
|
entryFilter: "**/main.js",
|
|
197
199
|
sourceFilter: "**/src/**"
|
|
198
200
|
};
|
|
201
|
+
// supports multiple patterns:
|
|
202
|
+
const coverageOptions = {
|
|
203
|
+
entryFilter: {
|
|
204
|
+
'**/vendor.js': false,
|
|
205
|
+
'**/main.js': true
|
|
206
|
+
},
|
|
207
|
+
sourceFilter: {
|
|
208
|
+
'**/src/**': true
|
|
209
|
+
}
|
|
210
|
+
};
|
|
199
211
|
```
|
|
200
212
|
|
|
201
213
|
## onEnd Hook
|
|
@@ -343,21 +355,31 @@ await MCR(coverageOptions).add(jsCoverage);
|
|
|
343
355
|
## Collecting Raw V8 Coverage Data with Puppeteer
|
|
344
356
|
> 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)
|
|
345
357
|
```js
|
|
346
|
-
await
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
358
|
+
await Promise.all([
|
|
359
|
+
page.coverage.startJSCoverage({
|
|
360
|
+
resetOnNavigation: false,
|
|
361
|
+
// provide raw v8 coverage data
|
|
362
|
+
includeRawScriptCoverage: true
|
|
363
|
+
}),
|
|
364
|
+
page.coverage.startCSSCoverage({
|
|
365
|
+
resetOnNavigation: false
|
|
366
|
+
})
|
|
367
|
+
]);
|
|
350
368
|
|
|
351
369
|
await page.goto(url);
|
|
352
370
|
|
|
353
|
-
const jsCoverage = await
|
|
354
|
-
|
|
355
|
-
|
|
371
|
+
const [jsCoverage, cssCoverage] = await Promise.all([
|
|
372
|
+
page.coverage.stopJSCoverage(),
|
|
373
|
+
page.coverage.stopCSSCoverage()
|
|
374
|
+
]);
|
|
375
|
+
|
|
376
|
+
// to raw V8 script coverage
|
|
377
|
+
const coverageData = [... jsCoverage.map((it) => {
|
|
356
378
|
return {
|
|
357
379
|
source: it.text,
|
|
358
380
|
... it.rawScriptCoverage
|
|
359
381
|
};
|
|
360
|
-
}
|
|
382
|
+
}), ... cssCoverage];
|
|
361
383
|
```
|
|
362
384
|
|
|
363
385
|
## Node.js V8 Coverage Report for Server Side
|
|
@@ -503,42 +525,41 @@ const coverageOptions = {
|
|
|
503
525
|
```
|
|
504
526
|
|
|
505
527
|
## Adding Empty Coverage for Untested Files
|
|
506
|
-
By default the untested files will not be included in the coverage report, we can
|
|
528
|
+
By default the untested files will not be included in the coverage report, we can add empty coverage data for all files with option `all`, the untested files will show 0% coverage.
|
|
507
529
|
```js
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
const coverageData = [];
|
|
515
|
-
const fileList = fs.readdirSync(dir);
|
|
516
|
-
for (const filename of fileList) {
|
|
517
|
-
const filePath = path.resolve(dir, filename);
|
|
518
|
-
const source = fs.readFileSync(filePath).toString('utf-8');
|
|
519
|
-
const sourcePath = path.relative(process.cwd(), filePath);
|
|
520
|
-
const url = pathToFileURL(sourcePath).toString();
|
|
521
|
-
const extname = path.extname(filename);
|
|
522
|
-
if (['.css'].includes(extname)) {
|
|
523
|
-
coverageData.push({
|
|
524
|
-
empty: true,
|
|
525
|
-
type: 'css',
|
|
526
|
-
url,
|
|
527
|
-
text: source
|
|
528
|
-
});
|
|
529
|
-
} else {
|
|
530
|
-
coverageData.push({
|
|
531
|
-
empty: true,
|
|
532
|
-
type: 'js',
|
|
533
|
-
url,
|
|
534
|
-
source
|
|
535
|
-
});
|
|
530
|
+
const coverageOptions = {
|
|
531
|
+
all: {
|
|
532
|
+
dir: ['./src'],
|
|
533
|
+
filter: (filePath) => {
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
536
|
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
|
|
537
|
+
};
|
|
538
|
+
```
|
|
539
|
+
The filter also supports `minimatch` pattern:
|
|
540
|
+
```js
|
|
541
|
+
const coverageOptions = {
|
|
542
|
+
all: {
|
|
543
|
+
dir: ['./src'],
|
|
544
|
+
filter: '**/*.js'
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
// or multiple patterns
|
|
548
|
+
const coverageOptions = {
|
|
549
|
+
all: {
|
|
550
|
+
dir: ['./src'],
|
|
551
|
+
filter: {
|
|
552
|
+
// exclude files
|
|
553
|
+
'**/ignored-*.js': false,
|
|
554
|
+
'**/*.html': false,
|
|
555
|
+
'**/*.ts': false,
|
|
556
|
+
// empty css coverage
|
|
557
|
+
'**/*.scss': "css",
|
|
558
|
+
'**/*': true
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
};
|
|
540
562
|
```
|
|
541
|
-
see example: [./test/cli-options.js](./test/cli-options.js)
|
|
542
563
|
|
|
543
564
|
## Ignoring Uncovered Codes
|
|
544
565
|
To ignore codes, use the special comment which starts with `v8 ignore `:
|
|
@@ -675,6 +696,12 @@ When `logging` is `debug`, the raw report data will be preserved in `[outputDir]
|
|
|
675
696
|
### [Vitest](https://github.com/vitest-dev/vitest)
|
|
676
697
|
- [vitest-monocart-coverage](https://github.com/cenfun/vitest-monocart-coverage) - A Vitest custom provider module for coverage reports
|
|
677
698
|
|
|
699
|
+
### [CodeceptJS](https://github.com/codeceptjs/CodeceptJS)
|
|
700
|
+
- [codeceptjs-monocart-coverage](https://github.com/cenfun/codeceptjs-monocart-coverage) - A CodeceptJS plugin for coverage reports
|
|
701
|
+
|
|
702
|
+
### [WebdriverIO](https://github.com/webdriverio/webdriverio)
|
|
703
|
+
- [wdio-monocart-service](https://github.com/cenfun/wdio-monocart-service) - A WebdriverIO service for coverage reports
|
|
704
|
+
|
|
678
705
|
### [Codecov](https://codecov.com/)
|
|
679
706
|
[](https://codecov.io/gh/cenfun/monocart-coverage-reports)
|
|
680
707
|
- Supports native `codecov` built-in report ([specification](https://docs.codecov.com/docs/codecov-custom-coverage-format))
|
package/lib/converter/ast.js
CHANGED
|
@@ -167,19 +167,34 @@ const getJsAstInfo = (item, coverageList) => {
|
|
|
167
167
|
allowHashBang: true
|
|
168
168
|
};
|
|
169
169
|
|
|
170
|
+
let err;
|
|
170
171
|
let ast;
|
|
171
172
|
try {
|
|
172
173
|
ast = acorn.parse(source, options);
|
|
173
174
|
} catch (e) {
|
|
175
|
+
err = e;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (err) {
|
|
174
179
|
|
|
175
|
-
// empty = untested file
|
|
176
|
-
|
|
177
|
-
|
|
180
|
+
// empty = untested file
|
|
181
|
+
// could be .ts, .vue and so on, that can not be parsed normally
|
|
182
|
+
if (empty) {
|
|
183
|
+
return {
|
|
184
|
+
functions: [],
|
|
185
|
+
branches: [],
|
|
186
|
+
statements: []
|
|
187
|
+
};
|
|
178
188
|
}
|
|
189
|
+
|
|
190
|
+
// runtime code should be parsed successful
|
|
191
|
+
Util.logInfo(`failed to parse source file: ${item.sourcePath} ${err.message}`);
|
|
192
|
+
|
|
179
193
|
// https://github.com/acornjs/acorn/tree/master/acorn-loose
|
|
180
194
|
// It is recommended to always try a parse with the regular acorn parser first,
|
|
181
195
|
// and only fall back to this parser when that one finds syntax errors.
|
|
182
196
|
ast = acornLoose.parse(source, options);
|
|
197
|
+
|
|
183
198
|
}
|
|
184
199
|
|
|
185
200
|
const coverageInfo = getCoverageInfo(coverageList);
|
|
@@ -841,17 +841,34 @@ const getOriginalDecodedMappings = (originalDecodedMap, sourceIndex, locator) =>
|
|
|
841
841
|
// ========================================================================================================
|
|
842
842
|
|
|
843
843
|
const getSourceFilter = (options) => {
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
|
|
844
|
+
const input = options.sourceFilter;
|
|
845
|
+
|
|
846
|
+
// for function handler
|
|
847
|
+
if (typeof input === 'function') {
|
|
848
|
+
return input;
|
|
847
849
|
}
|
|
848
850
|
|
|
849
|
-
|
|
851
|
+
// for single minimatch pattern
|
|
852
|
+
if (input && typeof input === 'string') {
|
|
850
853
|
return (sourcePath) => {
|
|
851
|
-
return minimatch(sourcePath,
|
|
854
|
+
return minimatch(sourcePath, input);
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// for patterns
|
|
859
|
+
if (input && typeof input === 'object') {
|
|
860
|
+
const patterns = Object.keys(input);
|
|
861
|
+
return (sourcePath) => {
|
|
862
|
+
for (const pattern of patterns) {
|
|
863
|
+
if (minimatch(sourcePath, pattern)) {
|
|
864
|
+
return input[pattern];
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
// false if not matched
|
|
852
868
|
};
|
|
853
869
|
}
|
|
854
870
|
|
|
871
|
+
// default
|
|
855
872
|
return () => true;
|
|
856
873
|
};
|
|
857
874
|
|
package/lib/default/options.js
CHANGED
|
@@ -46,6 +46,13 @@ module.exports = {
|
|
|
46
46
|
// sourceFilter: (sourcePath) => sourcePath.search(/src\/.+/) !== -1,
|
|
47
47
|
sourceFilter: null,
|
|
48
48
|
|
|
49
|
+
// options for adding empty coverage for all files
|
|
50
|
+
// all: {
|
|
51
|
+
// dir: ['src'],
|
|
52
|
+
// filter: (sourcePath) => true
|
|
53
|
+
// },
|
|
54
|
+
all: null,
|
|
55
|
+
|
|
49
56
|
// (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop
|
|
50
57
|
v8Ignore: true,
|
|
51
58
|
|
package/lib/generate.js
CHANGED
|
@@ -11,6 +11,9 @@ const { mergeV8Coverage, saveV8Report } = require('./v8/v8.js');
|
|
|
11
11
|
|
|
12
12
|
const { convertV8List } = require('./converter/converter.js');
|
|
13
13
|
|
|
14
|
+
const { minimatch } = require('./packages/monocart-coverage-vendor.js');
|
|
15
|
+
const { pathToFileURL } = require('url');
|
|
16
|
+
|
|
14
17
|
// ========================================================================================================
|
|
15
18
|
|
|
16
19
|
// maybe v8 or to istanbul reports
|
|
@@ -288,8 +291,175 @@ const generateCoverageReports = async (dataList, sourceCache, options) => {
|
|
|
288
291
|
|
|
289
292
|
// ========================================================================================================
|
|
290
293
|
|
|
294
|
+
const resolveAllDirList = (input) => {
|
|
295
|
+
const dirs = Util.toList(input, ',');
|
|
296
|
+
if (!dirs.length) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const dirList = dirs.filter((it) => fs.existsSync(it));
|
|
300
|
+
if (!dirList.length) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
return dirList;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const resolveAllFilter = (input) => {
|
|
307
|
+
// for function handler
|
|
308
|
+
if (typeof input === 'function') {
|
|
309
|
+
return input;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// for single minimatch pattern
|
|
313
|
+
if (input && typeof input === 'string') {
|
|
314
|
+
return (filePath) => {
|
|
315
|
+
return minimatch(filePath, input);
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// for patterns
|
|
320
|
+
if (input && typeof input === 'object') {
|
|
321
|
+
const patterns = Object.keys(input);
|
|
322
|
+
return (filePath) => {
|
|
323
|
+
for (const pattern of patterns) {
|
|
324
|
+
if (minimatch(filePath, pattern)) {
|
|
325
|
+
return input[pattern];
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// false if not matched
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// default
|
|
333
|
+
return () => true;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const resolveAllDataType = (type, dataList) => {
|
|
337
|
+
if (!type && dataList.length) {
|
|
338
|
+
const firstData = dataList[0];
|
|
339
|
+
type = firstData.type;
|
|
340
|
+
}
|
|
341
|
+
const types = {
|
|
342
|
+
v8: 'v8',
|
|
343
|
+
istanbul: 'istanbul'
|
|
344
|
+
};
|
|
345
|
+
return types[type] || types.v8;
|
|
346
|
+
};
|
|
291
347
|
|
|
292
|
-
const
|
|
348
|
+
const resolveAllOptions = (input, dataList) => {
|
|
349
|
+
if (!input) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
let type;
|
|
354
|
+
let dir;
|
|
355
|
+
let filter;
|
|
356
|
+
if (typeof input === 'string' || Array.isArray(input)) {
|
|
357
|
+
dir = input;
|
|
358
|
+
filter = () => true;
|
|
359
|
+
} else {
|
|
360
|
+
type = input.type;
|
|
361
|
+
dir = input.dir;
|
|
362
|
+
filter = input.filter;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const dirList = resolveAllDirList(dir);
|
|
366
|
+
if (!dirList) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const dataType = resolveAllDataType(type, dataList);
|
|
371
|
+
const fileFilter = resolveAllFilter(filter);
|
|
372
|
+
|
|
373
|
+
return {
|
|
374
|
+
dirList,
|
|
375
|
+
dataType,
|
|
376
|
+
fileFilter
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
const resolveFileType = (fileType, filePath) => {
|
|
381
|
+
if (fileType === 'js' || fileType === 'css') {
|
|
382
|
+
return fileType;
|
|
383
|
+
}
|
|
384
|
+
const extname = path.extname(filePath);
|
|
385
|
+
if (['.css', '.scss', '.sass', '.less'].includes(extname)) {
|
|
386
|
+
return 'css';
|
|
387
|
+
}
|
|
388
|
+
return 'js';
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
const getV8EmptyData = (fileList) => {
|
|
392
|
+
const v8DataList = [];
|
|
393
|
+
fileList.forEach((item) => {
|
|
394
|
+
const { filePath, fileType } = item;
|
|
395
|
+
const type = resolveFileType(fileType, filePath);
|
|
396
|
+
const url = pathToFileURL(filePath).toString();
|
|
397
|
+
const source = Util.readFileSync(filePath);
|
|
398
|
+
const entryFile = {
|
|
399
|
+
empty: true,
|
|
400
|
+
type,
|
|
401
|
+
url,
|
|
402
|
+
// for empty, css supports both source and text
|
|
403
|
+
source
|
|
404
|
+
};
|
|
405
|
+
v8DataList.push(entryFile);
|
|
406
|
+
});
|
|
407
|
+
return v8DataList;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
const getIstanbulEmptyData = (fileList) => {
|
|
411
|
+
const istanbulData = {};
|
|
412
|
+
fileList.forEach((item) => {
|
|
413
|
+
const { filePath } = item;
|
|
414
|
+
istanbulData[filePath] = {
|
|
415
|
+
path: filePath,
|
|
416
|
+
statementMap: {},
|
|
417
|
+
fnMap: {},
|
|
418
|
+
branchMap: {},
|
|
419
|
+
s: {},
|
|
420
|
+
f: {},
|
|
421
|
+
b: {}
|
|
422
|
+
};
|
|
423
|
+
});
|
|
424
|
+
return istanbulData;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const getEmptyData = (all, dataList) => {
|
|
428
|
+
const allOptions = resolveAllOptions(all, dataList);
|
|
429
|
+
// console.log('allOptions', all, allOptions);
|
|
430
|
+
if (!allOptions) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const {
|
|
434
|
+
dirList, dataType, fileFilter
|
|
435
|
+
} = allOptions;
|
|
436
|
+
const fileList = [];
|
|
437
|
+
dirList.forEach((dir) => {
|
|
438
|
+
Util.forEachFile(dir, [], (fileName, fileDir) => {
|
|
439
|
+
const filePath = path.resolve(fileDir, fileName);
|
|
440
|
+
const fileType = fileFilter(filePath);
|
|
441
|
+
if (fileType) {
|
|
442
|
+
fileList.push({
|
|
443
|
+
filePath,
|
|
444
|
+
fileType
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
// console.log('fileList', fileList);
|
|
450
|
+
if (!fileList.length) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (dataType === 'v8') {
|
|
454
|
+
return getV8EmptyData(fileList);
|
|
455
|
+
}
|
|
456
|
+
return getIstanbulEmptyData(fileList);
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
// ========================================================================================================
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
const getInputData = async (inputList, all, cacheDir, addHandler) => {
|
|
293
463
|
const dataList = [];
|
|
294
464
|
const sourceCache = new Map();
|
|
295
465
|
|
|
@@ -321,6 +491,35 @@ const getInputData = async (inputList) => {
|
|
|
321
491
|
}
|
|
322
492
|
}
|
|
323
493
|
}
|
|
494
|
+
|
|
495
|
+
// add empty coverage for all files
|
|
496
|
+
// dataList for data type, before `add` we don't which one is tested, because using hash id
|
|
497
|
+
const emptyData = getEmptyData(all, dataList);
|
|
498
|
+
if (emptyData) {
|
|
499
|
+
const coverageResults = await addHandler(emptyData);
|
|
500
|
+
// after `add`
|
|
501
|
+
if (coverageResults) {
|
|
502
|
+
dataList.push(coverageResults);
|
|
503
|
+
if (coverageResults.type === 'v8') {
|
|
504
|
+
// sourceCache
|
|
505
|
+
coverageResults.data.forEach((entry) => {
|
|
506
|
+
const { id } = entry;
|
|
507
|
+
if (sourceCache.has(id)) {
|
|
508
|
+
// console.log('+', entry.sourcePath);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
// console.log('-', entry.sourcePath);
|
|
512
|
+
const sourcePath = Util.resolveCacheSourcePath(cacheDir, id);
|
|
513
|
+
const content = Util.readFileSync(sourcePath);
|
|
514
|
+
if (content) {
|
|
515
|
+
const json = JSON.parse(content);
|
|
516
|
+
sourceCache.set(json.id, json);
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
324
523
|
return {
|
|
325
524
|
dataList,
|
|
326
525
|
sourceCache
|
package/lib/index.d.ts
CHANGED
|
@@ -220,19 +220,41 @@ declare namespace MCR {
|
|
|
220
220
|
|
|
221
221
|
/** (V8 only)
|
|
222
222
|
*
|
|
223
|
-
* {string} `minimatch` pattern for entry url; multiple patterns
|
|
223
|
+
* {string} `minimatch` pattern for entry url; {object} multiple patterns;
|
|
224
224
|
*
|
|
225
225
|
* {function} A filter function for each entry file in the V8 list.
|
|
226
226
|
* */
|
|
227
|
-
entryFilter?: string |
|
|
227
|
+
entryFilter?: string | {
|
|
228
|
+
[pattern: string]: boolean;
|
|
229
|
+
} | ((entry: V8CoverageEntry) => boolean);
|
|
228
230
|
|
|
229
231
|
/** (V8 only)
|
|
230
232
|
*
|
|
231
|
-
* {string} `minimatch` pattern for source path; multiple patterns
|
|
233
|
+
* {string} `minimatch` pattern for source path; {object} multiple patterns;
|
|
232
234
|
*
|
|
233
235
|
* {function} A filter function for each source path when the source is unpacked from the source map.
|
|
234
236
|
* */
|
|
235
|
-
sourceFilter?: string |
|
|
237
|
+
sourceFilter?: string | {
|
|
238
|
+
[pattern: string]: boolean;
|
|
239
|
+
} | ((sourcePath: string) => boolean);
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* options for adding empty coverage for all files
|
|
243
|
+
*/
|
|
244
|
+
all?: string | string[] | {
|
|
245
|
+
/** the dir(s) of all files */
|
|
246
|
+
dir: string | string[];
|
|
247
|
+
/** the coverage data type, v8 or istanbul */
|
|
248
|
+
type?: "v8" | "istanbul";
|
|
249
|
+
/**
|
|
250
|
+
* the file filter, return the file type, if true, defaults to css if ".css" otherwise is js
|
|
251
|
+
*
|
|
252
|
+
* {string} `minimatch` pattern for file path; {object} multiple patterns; {function} A filter function for file path;
|
|
253
|
+
*/
|
|
254
|
+
filter?: string | {
|
|
255
|
+
[pattern: string]: "js" | "css" | boolean;
|
|
256
|
+
} | ((filePath: string) => "js" | "css" | boolean)
|
|
257
|
+
};
|
|
236
258
|
|
|
237
259
|
/** (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop */
|
|
238
260
|
v8Ignore?: boolean;
|
package/lib/index.js
CHANGED
|
@@ -83,7 +83,10 @@ class CoverageReport {
|
|
|
83
83
|
|
|
84
84
|
this.initOptions();
|
|
85
85
|
|
|
86
|
-
const {
|
|
86
|
+
const {
|
|
87
|
+
all, inputDir, cacheDir
|
|
88
|
+
} = this.options;
|
|
89
|
+
|
|
87
90
|
const inputDirs = Util.toList(inputDir, ',');
|
|
88
91
|
if (this.hasCache()) {
|
|
89
92
|
inputDirs.push(cacheDir);
|
|
@@ -92,16 +95,16 @@ class CoverageReport {
|
|
|
92
95
|
const inputList = inputDirs.filter((dir) => {
|
|
93
96
|
const hasDir = fs.existsSync(dir);
|
|
94
97
|
if (!hasDir) {
|
|
95
|
-
|
|
98
|
+
// could be empty
|
|
99
|
+
Util.logInfo(`Not found coverage data dir: ${Util.relativePath(dir)}`);
|
|
96
100
|
}
|
|
97
101
|
return hasDir;
|
|
98
102
|
});
|
|
99
103
|
|
|
100
|
-
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
104
|
+
const { dataList, sourceCache } = await getInputData(inputList, all, cacheDir, (emptyData) => {
|
|
105
|
+
return this.add(emptyData);
|
|
106
|
+
});
|
|
103
107
|
|
|
104
|
-
const { dataList, sourceCache } = await getInputData(inputList);
|
|
105
108
|
if (!dataList.length) {
|
|
106
109
|
const dirs = inputList.map((dir) => Util.relativePath(dir));
|
|
107
110
|
Util.logError(`Not found coverage data in dir(s): ${dirs.join(', ')}`);
|