monocart-coverage-reports 2.10.4 → 2.10.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/lib/generate.js CHANGED
@@ -1,9 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { pathToFileURL, fileURLToPath } = require('url');
4
-
5
- const EC = require('eight-colors');
6
- const { minimatch } = require('./packages/monocart-coverage-vendor.js');
3
+ const { fileURLToPath } = require('url');
7
4
 
8
5
  const Util = require('./utils/util.js');
9
6
  const { convertV8List } = require('./converter/converter.js');
@@ -178,7 +175,7 @@ const getCoverageResults = async (dataList, sourceCache, options) => {
178
175
  // console.log('after merge', v8list.map((it) => it.url));
179
176
 
180
177
  const t2 = Date.now();
181
- const results = convertV8List(v8list, options);
178
+ const results = await convertV8List(v8list, options);
182
179
  Util.logTime('┌ [generate] converted coverage data', t2);
183
180
 
184
181
  const {
@@ -189,7 +186,7 @@ const getCoverageResults = async (dataList, sourceCache, options) => {
189
186
 
190
187
  // istanbul data
191
188
  const t3 = Date.now();
192
- const istanbulData = mergeIstanbulCoverage(dataList);
189
+ const istanbulData = await mergeIstanbulCoverage(dataList, options);
193
190
  const { coverageData, fileSources } = initIstanbulData(istanbulData, options);
194
191
  Util.logTime('┌ [generate] prepared istanbul coverage data', t3);
195
192
  const results = await saveIstanbulReports(coverageData, fileSources, options);
@@ -219,187 +216,6 @@ const generateCoverageReports = async (dataList, sourceCache, options) => {
219
216
  return coverageResults;
220
217
  };
221
218
 
222
- // ========================================================================================================
223
-
224
- const resolveAllDirList = (input) => {
225
- const dirs = Util.toList(input, ',');
226
- if (!dirs.length) {
227
- return;
228
- }
229
- const dirList = dirs.filter((it) => fs.existsSync(it));
230
- if (!dirList.length) {
231
- return;
232
- }
233
- return dirList;
234
- };
235
-
236
- const resolveAllFilter = (input) => {
237
- // for function handler
238
- if (typeof input === 'function') {
239
- return input;
240
- }
241
-
242
- // for single minimatch pattern
243
- if (input && typeof input === 'string') {
244
- // string to multiple patterns "{...}"
245
- const obj = Util.strToObj(input);
246
- if (obj) {
247
- input = obj;
248
- } else {
249
- return (filePath) => {
250
- return minimatch(filePath, input);
251
- };
252
- }
253
- }
254
-
255
- // for patterns
256
- if (input && typeof input === 'object') {
257
- const patterns = Object.keys(input);
258
- return (filePath) => {
259
- for (const pattern of patterns) {
260
- if (minimatch(filePath, pattern)) {
261
- return input[pattern];
262
- }
263
- }
264
- // false if not matched
265
- };
266
- }
267
-
268
- // default
269
- return () => true;
270
- };
271
-
272
- const resolveAllDataType = (type, dataList) => {
273
- if (!type && dataList.length) {
274
- const firstData = dataList[0];
275
- type = firstData.type;
276
- }
277
- const types = {
278
- v8: 'v8',
279
- istanbul: 'istanbul'
280
- };
281
- return types[type] || types.v8;
282
- };
283
-
284
- const resolveAllOptions = (input, dataList) => {
285
- if (!input) {
286
- return;
287
- }
288
-
289
- let type;
290
- let dir;
291
- let filter;
292
-
293
- if (typeof input === 'string') {
294
- const obj = Util.strToObj(input);
295
- if (obj) {
296
- type = obj.type;
297
- dir = obj.dir;
298
- filter = obj.filter;
299
- } else {
300
- dir = input;
301
- }
302
- } else if (Array.isArray(input)) {
303
- dir = input;
304
- } else {
305
- type = input.type;
306
- dir = input.dir;
307
- filter = input.filter;
308
- }
309
-
310
- const dirList = resolveAllDirList(dir);
311
- if (!dirList) {
312
- return;
313
- }
314
-
315
- const dataType = resolveAllDataType(type, dataList);
316
- const fileFilter = resolveAllFilter(filter);
317
-
318
- return {
319
- dirList,
320
- dataType,
321
- fileFilter
322
- };
323
- };
324
-
325
- const resolveFileType = (fileType, filePath) => {
326
- if (fileType === 'js' || fileType === 'css') {
327
- return fileType;
328
- }
329
- const extname = path.extname(filePath);
330
- if (['.css', '.scss', '.sass', '.less'].includes(extname)) {
331
- return 'css';
332
- }
333
- return 'js';
334
- };
335
-
336
- const getV8EmptyData = (fileList) => {
337
- const v8DataList = [];
338
- fileList.forEach((item) => {
339
- const { filePath, fileType } = item;
340
- const type = resolveFileType(fileType, filePath);
341
- const url = pathToFileURL(filePath).toString();
342
- const source = Util.readFileSync(filePath);
343
- const entryFile = {
344
- empty: true,
345
- type,
346
- url,
347
- // for empty, css supports both source and text
348
- source
349
- };
350
- v8DataList.push(entryFile);
351
- });
352
- return v8DataList;
353
- };
354
-
355
- const getIstanbulEmptyData = (fileList) => {
356
- const istanbulData = {};
357
- fileList.forEach((item) => {
358
- const { filePath } = item;
359
- istanbulData[filePath] = {
360
- path: filePath,
361
- statementMap: {},
362
- fnMap: {},
363
- branchMap: {},
364
- s: {},
365
- f: {},
366
- b: {}
367
- };
368
- });
369
- return istanbulData;
370
- };
371
-
372
- const getEmptyData = (all, dataList) => {
373
- const allOptions = resolveAllOptions(all, dataList);
374
- // console.log('allOptions', all, allOptions);
375
- if (!allOptions) {
376
- return;
377
- }
378
- const {
379
- dirList, dataType, fileFilter
380
- } = allOptions;
381
- const fileList = [];
382
- dirList.forEach((dir) => {
383
- Util.forEachFile(dir, [], (fileName, fileDir) => {
384
- const filePath = path.resolve(fileDir, fileName);
385
- const fileType = fileFilter(filePath);
386
- if (fileType) {
387
- fileList.push({
388
- filePath,
389
- fileType
390
- });
391
- }
392
- });
393
- });
394
- // console.log('fileList', fileList);
395
- if (!fileList.length) {
396
- return;
397
- }
398
- if (dataType === 'v8') {
399
- return getV8EmptyData(fileList);
400
- }
401
- return getIstanbulEmptyData(fileList);
402
- };
403
219
 
404
220
  // ========================================================================================================
405
221
 
@@ -448,55 +264,6 @@ const addJsonData = async (mcr, dataList, sourceCache, dir, filename) => {
448
264
  }
449
265
  };
450
266
 
451
- const addEmptyData = async (mcr, dataList, sourceCache) => {
452
-
453
- const { all, cacheDir } = mcr.options;
454
- // add empty coverage for all files
455
- // dataList for data type, before `add` we don't which one is tested, because using hash id
456
- const emptyData = getEmptyData(all, dataList);
457
- if (!emptyData) {
458
- return;
459
- }
460
-
461
- let files = 0;
462
- if (Util.isList(emptyData)) {
463
- files = emptyData.length;
464
- } else {
465
- files = Object.keys(emptyData).length;
466
- }
467
-
468
- Util.logDebug(`added all files with empty coverage: ${EC.yellow(files)}`);
469
- const coverageResults = await mcr.add(emptyData);
470
- // after `add`
471
- if (!coverageResults) {
472
- return;
473
- }
474
-
475
- dataList.push(coverageResults);
476
-
477
- if (coverageResults.type === 'v8') {
478
- // sourceCache
479
- coverageResults.data.forEach((entry) => {
480
- const { id } = entry;
481
- if (sourceCache.has(id)) {
482
- // console.log('+', entry.sourcePath);
483
- return;
484
- }
485
- // console.log('-', entry.sourcePath);
486
- const { cacheName, cachePath } = Util.getCacheFileInfo('source', id, cacheDir);
487
- if (mcr.fileCache.has(cacheName)) {
488
- const json = mcr.fileCache.get(cacheName);
489
- sourceCache.set(json.id, json);
490
- } else {
491
- const content = Util.readFileSync(cachePath);
492
- if (content) {
493
- const json = JSON.parse(content);
494
- sourceCache.set(json.id, json);
495
- }
496
- }
497
- });
498
- }
499
- };
500
267
 
501
268
  const getInputData = async (mcr) => {
502
269
 
@@ -520,8 +287,6 @@ const getInputData = async (mcr) => {
520
287
  }
521
288
  }
522
289
 
523
- await addEmptyData(mcr, dataList, sourceCache);
524
-
525
290
  if (!dataList.length) {
526
291
  const dirs = inputList.map((dir) => Util.relativePath(dir));
527
292
  Util.logError(`Not found coverage data in dir(s): ${dirs.join(', ')}`);
package/lib/index.d.ts CHANGED
@@ -359,8 +359,7 @@ declare namespace MCR {
359
359
  all?: string | string[] | {
360
360
  /** the dir(s) of all files */
361
361
  dir: string | string[];
362
- /** the coverage data type, v8 or istanbul */
363
- type?: "v8" | "istanbul";
362
+
364
363
  /**
365
364
  * the file filter, return the file type, if true, defaults to css if ".css" otherwise is js
366
365
  *
@@ -369,6 +368,14 @@ declare namespace MCR {
369
368
  filter?: string | {
370
369
  [pattern: string]: "js" | "css" | boolean;
371
370
  } | ((filePath: string) => "js" | "css" | boolean);
371
+
372
+ /**
373
+ * the file transformer for source and sourceMap
374
+ * some of untested files like .ts/.jsx/.vue can not be parsed to AST directly by acorn
375
+ * so this is the function which can transform the original source to generated source and sourceMap
376
+ */
377
+ transformer?: (entry: any) => Promise<void>;
378
+
372
379
  };
373
380
 
374
381
  /** (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop */
@@ -8,6 +8,7 @@ const Util = require('../utils/util.js');
8
8
  const IstanbulSummary = require('./istanbul-summary.js');
9
9
 
10
10
  const { initIstanbulSourcePath } = require('../utils/source-path.js');
11
+ const { getUntestedList } = require('../converter/untested.js');
11
12
 
12
13
  const findHtmlPath = (outputDir) => {
13
14
  const defaultHtml = path.resolve(outputDir, 'index.html');
@@ -121,18 +122,42 @@ const saveIstanbulReports = (coverageData, fileSources, options) => {
121
122
  return coverageResults;
122
123
  };
123
124
 
124
- const mergeIstanbulCoverage = (dataList) => {
125
+ const addUntestedFiles = async (istanbulData, options) => {
126
+ const testedMap = new Map();
127
+ Object.keys(istanbulData).forEach((filePath) => {
128
+ const sourcePath = Util.relativePath(filePath);
129
+ testedMap.set(sourcePath, true);
130
+ });
131
+
132
+ // untested files
133
+ const untestedList = await getUntestedList(testedMap, options, 'istanbul');
134
+ if (!untestedList) {
135
+ return;
136
+ }
137
+
138
+ // console.log('istanbul untestedList', untestedList);
139
+ untestedList.forEach((item) => {
140
+ if (!istanbulData[item.path]) {
141
+ istanbulData[item.path] = item;
142
+ }
143
+ });
144
+
145
+ };
146
+
147
+ const mergeIstanbulCoverage = async (dataList, options) => {
125
148
  const istanbulCoverageList = dataList.map((it) => it.data);
126
149
  const coverageMap = istanbulLibCoverage.createCoverageMap();
127
150
  istanbulCoverageList.forEach((coverage) => {
128
151
  coverageMap.merge(coverage);
129
152
  });
130
153
  const istanbulData = coverageMap.toJSON();
154
+
155
+ await addUntestedFiles(istanbulData, options);
156
+
131
157
  return istanbulData;
132
158
  };
133
159
 
134
160
  const initIstanbulData = (istanbulData, options) => {
135
-
136
161
  const fileSources = options.fileSources || {};
137
162
  const coverageData = initIstanbulSourcePath(istanbulData, fileSources, options);
138
163