monocart-coverage-reports 2.10.6 → 2.10.8-beta.0

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.
@@ -21,7 +21,6 @@ const {
21
21
  const { getSourceType, initSourceMapSourcesPath } = require('../utils/source-path.js');
22
22
 
23
23
  const { decode } = require('@jridgewell/sourcemap-codec');
24
- const { minimatch } = require('../packages/monocart-coverage-vendor.js');
25
24
 
26
25
  const InfoBranch = require('./info-branch.js');
27
26
  const InfoFunction = require('./info-function.js');
@@ -956,50 +955,10 @@ const getOriginalDecodedMappings = (originalDecodedMap, sourceIndex, locator) =>
956
955
 
957
956
  // ========================================================================================================
958
957
 
959
- const getSourceFilter = (options) => {
960
- let input = options.sourceFilter || options.filter;
961
-
962
- // for function handler
963
- if (typeof input === 'function') {
964
- return input;
965
- }
966
-
967
- // for single minimatch pattern
968
- if (input && typeof input === 'string') {
969
- // string to multiple patterns "{...}"
970
- // mcr npx mocha --sourceFilter {'**/node_modules/**':false,'**/src/*.js':true}
971
- // mcr npx mocha --sourceFilter "{'**/node_modules/**': false, '**/src/*.js': true}"
972
- const obj = Util.strToObj(input);
973
- if (obj) {
974
- input = obj;
975
- } else {
976
- return (sourcePath) => {
977
- return minimatch(sourcePath, input);
978
- };
979
- }
980
- }
981
-
982
- // for patterns
983
- if (input && typeof input === 'object') {
984
- const patterns = Object.keys(input);
985
- return (sourcePath) => {
986
- for (const pattern of patterns) {
987
- if (minimatch(sourcePath, pattern)) {
988
- return input[pattern];
989
- }
990
- }
991
- // false if not matched
992
- };
993
- }
994
-
995
- // default
996
- return () => true;
997
- };
998
-
999
958
  const initOriginalList = (state, originalDecodedMap, options) => {
1000
959
 
1001
960
  // source filter
1002
- const sourceFilter = getSourceFilter(options);
961
+ const sourceFilter = Util.getSourceFilter(options);
1003
962
 
1004
963
  // create original content mappings
1005
964
  const originalStateMap = new Map();
@@ -4,8 +4,10 @@ const Util = require('../utils/util.js');
4
4
 
5
5
  const { pathToFileURL, fileURLToPath } = require('url');
6
6
 
7
+ const { normalizeSourcePath, getSourcePathReplacer } = require('../utils/source-path.js');
8
+
7
9
  // const EC = require('eight-colors');
8
- const { minimatch } = require('../packages/monocart-coverage-vendor.js');
10
+ const { minimatch, convertSourceMap } = require('../packages/monocart-coverage-vendor.js');
9
11
 
10
12
  // ========================================================================================================
11
13
 
@@ -109,16 +111,64 @@ const resolveFileType = (fileType, filePath) => {
109
111
  return 'js';
110
112
  };
111
113
 
112
- const getUntestedCoverageData = (emptyList, options, coverageType) => {
114
+ const saveUntestedFileSource = async (entryFile, options) => {
115
+ const {
116
+ id,
117
+ url,
118
+ source,
119
+ sourceMap
120
+ } = entryFile;
121
+ // console.log('-', entry.sourcePath);
122
+
123
+ const { cachePath } = Util.getCacheFileInfo('source', id, options.cacheDir);
124
+ if (fs.existsSync(cachePath)) {
125
+ return;
126
+ }
127
+
128
+ // save source and sourceMap to separated json file
129
+ const sourceData = {
130
+ id,
131
+ url,
132
+ source,
133
+ sourceMap
134
+ };
135
+
136
+ // remove comments if not debug
137
+ if (!Util.isDebug()) {
138
+ sourceData.source = convertSourceMap.removeComments(source);
139
+ }
140
+
141
+ // console.log('save untested file', id, url);
142
+
143
+ await Util.saveSourceCacheFile(sourceData, options);
144
+
145
+ };
146
+
147
+ const getUntestedCoverageData = async (entryList, options, coverageType) => {
148
+
149
+ // save all empty coverage
150
+ const dataId = Util.uid();
151
+ const results = {
152
+ id: dataId
153
+ };
113
154
 
114
- // NOTE: do not save untested file to raw report
155
+ if (coverageType === 'istanbul') {
156
+ results.type = 'istanbul';
157
+ results.data = {};
158
+ } else {
159
+ results.type = 'v8';
160
+ results.data = [];
161
+ }
115
162
 
116
163
  const emptyCoverageList = [];
117
164
 
118
165
  // save all empty source and sourcemap
119
- for (const entryFile of emptyList) {
166
+ for (const entry of entryList) {
120
167
 
121
- const { type, url } = entryFile;
168
+ // for raw report: source file
169
+ await saveUntestedFileSource(entry, options);
170
+
171
+ const { type, url } = entry;
122
172
 
123
173
  if (coverageType === 'istanbul') {
124
174
 
@@ -133,6 +183,7 @@ const getUntestedCoverageData = (emptyList, options, coverageType) => {
133
183
  b: {}
134
184
  };
135
185
  // object
186
+ results.data[item.path] = item;
136
187
  emptyCoverageList.push(item);
137
188
 
138
189
  } else {
@@ -140,59 +191,99 @@ const getUntestedCoverageData = (emptyList, options, coverageType) => {
140
191
  // ===============================================
141
192
  if (type === 'js') {
142
193
  // empty js
143
- entryFile.functions = entryFile.functions || [{
194
+ entry.functions = entry.functions || [{
144
195
  functionName: '',
145
196
  ranges: [{
146
197
  startOffset: 0,
147
- endOffset: entryFile.source.length,
198
+ endOffset: entry.source.length,
148
199
  count: 0
149
200
  }]
150
201
  }];
151
202
  } else {
152
203
  // empty css
153
- entryFile.ranges = entryFile.ranges || [];
204
+ entry.ranges = entry.ranges || [];
154
205
  }
155
206
 
207
+ const item = {
208
+ ... entry
209
+ };
210
+ delete item.source;
211
+ delete item.sourceMap;
212
+
213
+ // array
214
+ results.data.push(item);
156
215
  // will be parsed to AST and converted to V8 coverage
157
- emptyCoverageList.push(entryFile);
216
+ emptyCoverageList.push(entry);
158
217
 
159
218
  }
160
219
 
161
220
  }
162
221
 
222
+ // for raw report: coverage file
223
+ const { cachePath } = Util.getCacheFileInfo('coverage', dataId, options.cacheDir);
224
+ await Util.writeFile(cachePath, JSON.stringify(results));
225
+
163
226
  return emptyCoverageList;
164
227
  };
165
228
 
166
- const getEmptyCoverages = async (fileList, options, coverageType, fileTransformer) => {
229
+ const getEmptyCoverages = async (testedMap, options, coverageType, fileList, fileTransformer) => {
230
+ const sourceFilter = Util.getSourceFilter(options);
231
+ const sourcePathReplacer = getSourcePathReplacer(options);
232
+ const baseDir = options.baseDir;
167
233
 
168
- const emptyList = [];
234
+ // console.log(fileList);
169
235
 
236
+ const entryList = [];
170
237
  for (const item of fileList) {
171
- const {
172
- filePath, fileType, sourcePath
173
- } = item;
238
+
239
+ const { fileType, filePath } = item;
174
240
  const type = resolveFileType(fileType, filePath);
175
241
  const url = pathToFileURL(filePath).toString();
176
242
  const source = Util.readFileSync(filePath);
177
- const entryFile = {
243
+ const entry = {
178
244
  empty: true,
179
245
  type,
180
246
  url,
181
- sourcePath,
182
- // for empty, css supports both source and text
183
247
  source
184
248
  };
185
249
 
186
- await fileTransformer(entryFile, coverageType);
250
+ // normalize sourcePath here
251
+ let sourcePath = normalizeSourcePath(url, baseDir);
252
+ if (sourcePathReplacer) {
253
+ const newSourcePath = sourcePathReplacer(sourcePath, entry);
254
+ if (typeof newSourcePath === 'string' && newSourcePath) {
255
+ sourcePath = newSourcePath;
256
+ }
257
+ }
258
+
259
+ // console.log(sourcePath);
260
+
261
+ if (testedMap.has(sourcePath)) {
262
+ continue;
263
+ }
187
264
 
265
+ if (!sourceFilter(sourcePath)) {
266
+ continue;
267
+ }
268
+
269
+ entry.sourcePath = sourcePath;
270
+
271
+ await fileTransformer(entry, coverageType);
188
272
  // after transformer
189
- entryFile.id = Util.calculateSha1(entryFile.sourcePath + entryFile.source);
273
+ entry.id = Util.calculateSha1(entry.sourcePath + entry.source);
190
274
 
191
- emptyList.push(entryFile);
275
+ entryList.push(entry);
192
276
  }
193
277
 
278
+
279
+ // console.log('fileList', fileList);
280
+ if (!entryList.length) {
281
+ return;
282
+ }
283
+
284
+
194
285
  // save empty coverage for merging raw reports
195
- return getUntestedCoverageData(emptyList, options, coverageType);
286
+ return getUntestedCoverageData(entryList, options, coverageType);
196
287
  };
197
288
 
198
289
  const getUntestedList = (testedMap, options, coverageType = 'v8') => {
@@ -201,9 +292,11 @@ const getUntestedList = (testedMap, options, coverageType = 'v8') => {
201
292
  if (!allOptions) {
202
293
  return;
203
294
  }
295
+
204
296
  const {
205
297
  dirList, fileFilter, fileTransformer
206
298
  } = allOptions;
299
+
207
300
  const fileList = [];
208
301
  dirList.forEach((dir) => {
209
302
  Util.forEachFile(dir, [], (fileName, fileDir) => {
@@ -211,23 +304,22 @@ const getUntestedList = (testedMap, options, coverageType = 'v8') => {
211
304
  // return file extname for file type
212
305
  const fileType = fileFilter(filePath);
213
306
  if (fileType) {
214
- const sourcePath = Util.relativePath(filePath);
215
- if (!testedMap.has(sourcePath)) {
216
- fileList.push({
217
- filePath,
218
- fileType,
219
- sourcePath
220
- });
221
- }
307
+ fileList.push({
308
+ filePath,
309
+ fileType,
310
+ fileDir,
311
+ fileName
312
+ });
222
313
  }
314
+
223
315
  });
224
316
  });
225
- // console.log('fileList', fileList);
317
+
226
318
  if (!fileList.length) {
227
319
  return;
228
320
  }
229
321
 
230
- return getEmptyCoverages(fileList, options, coverageType, fileTransformer);
322
+ return getEmptyCoverages(testedMap, options, coverageType, fileList, fileTransformer);
231
323
 
232
324
  };
233
325
 
package/lib/index.d.ts CHANGED
@@ -361,8 +361,8 @@ declare namespace MCR {
361
361
  dir: string | string[];
362
362
 
363
363
  /**
364
- * the file filter, return the file type, if true, defaults to css if ".css" otherwise is js
365
- *
364
+ * the file filter is triggered before `sourceFilter`, no need to use it in normal case
365
+ * the filter could return the file type, if true, defaults to css if ".css" otherwise is js
366
366
  * {string} `minimatch` pattern for file path; {object} multiple patterns; {function} A filter function for file path;
367
367
  */
368
368
  filter?: string | {
package/lib/index.js CHANGED
@@ -6,7 +6,7 @@ const EC = require('eight-colors');
6
6
  const defaultOptions = require('./default/options.js');
7
7
  const Util = require('./utils/util.js');
8
8
 
9
- const { initV8ListAndSourcemap, getEntryFilter } = require('./v8/v8.js');
9
+ const { initV8ListAndSourcemap } = require('./v8/v8.js');
10
10
  const {
11
11
  getInputData, readFromDir, generateCoverageReports
12
12
  } = require('./generate.js');
@@ -225,7 +225,7 @@ class CoverageReport {
225
225
 
226
226
  // get entry filter handler
227
227
  getEntryFilter() {
228
- return getEntryFilter(this.options);
228
+ return Util.getEntryFilter(this.options);
229
229
  }
230
230
 
231
231
  // load config file
package/lib/utils/util.js CHANGED
@@ -12,7 +12,9 @@ const request = require('./request.js');
12
12
  const version = require('../../package.json').version;
13
13
  const markdownGrid = require('./markdown.js');
14
14
 
15
- const { findUpSync, supportsColor } = require('../packages/monocart-coverage-vendor.js');
15
+ const {
16
+ findUpSync, supportsColor, minimatch
17
+ } = require('../packages/monocart-coverage-vendor.js');
16
18
 
17
19
  // https://github.com/chalk/supports-color
18
20
  // disabled color if Terminal stdout does not support color
@@ -161,6 +163,115 @@ const Util = {
161
163
  };
162
164
  },
163
165
 
166
+ // eslint-disable-next-line complexity
167
+ getEntryFilter: (options) => {
168
+ // for entry.url
169
+
170
+ if (options.entryFilterHandler) {
171
+ return options.entryFilterHandler;
172
+ }
173
+
174
+ let input = options.entryFilter || options.filter;
175
+
176
+ // for function handler
177
+ if (typeof input === 'function') {
178
+ options.entryFilterHandler = input;
179
+ return input;
180
+ }
181
+
182
+ // for single minimatch pattern
183
+ if (input && typeof input === 'string') {
184
+ // string to multiple patterns "{...}"
185
+ // mcr npx mocha --entryFilter {'**/node_modules/**':false,'**/src/*.js':true}
186
+ // mcr npx mocha --entryFilter "{'**/node_modules/**': false, '**/src/*.js': true}"
187
+ const obj = Util.strToObj(input);
188
+ if (obj) {
189
+ input = obj;
190
+ } else {
191
+ const handler = (entry) => {
192
+ return minimatch(entry.url, input);
193
+ };
194
+ options.entryFilterHandler = handler;
195
+ return handler;
196
+ }
197
+ }
198
+
199
+ // for patterns
200
+ if (input && typeof input === 'object') {
201
+ const patterns = Object.keys(input);
202
+ const handler = (entry) => {
203
+ const url = entry.url;
204
+ for (const pattern of patterns) {
205
+ if (minimatch(url, pattern)) {
206
+ return input[pattern];
207
+ }
208
+ }
209
+ // false if not matched
210
+ };
211
+ options.entryFilterHandler = handler;
212
+ return handler;
213
+ }
214
+
215
+ // default
216
+ const handler = () => true;
217
+ options.entryFilterHandler = handler;
218
+ return handler;
219
+ },
220
+
221
+ // eslint-disable-next-line complexity
222
+ getSourceFilter: (options) => {
223
+ // for sourcePath
224
+
225
+ if (options.sourceFilterHandler) {
226
+ return options.sourceFilterHandler;
227
+ }
228
+
229
+ let input = options.sourceFilter || options.filter;
230
+
231
+ // for function handler
232
+ if (typeof input === 'function') {
233
+ options.sourceFilterHandler = input;
234
+ return input;
235
+ }
236
+
237
+ // for single minimatch pattern
238
+ if (input && typeof input === 'string') {
239
+ // string to multiple patterns "{...}"
240
+ // mcr npx mocha --sourceFilter {'**/node_modules/**':false,'**/src/*.js':true}
241
+ // mcr npx mocha --sourceFilter "{'**/node_modules/**': false, '**/src/*.js': true}"
242
+ const obj = Util.strToObj(input);
243
+ if (obj) {
244
+ input = obj;
245
+ } else {
246
+ const handler = (sourcePath) => {
247
+ return minimatch(sourcePath, input);
248
+ };
249
+ options.sourceFilterHandler = handler;
250
+ return handler;
251
+ }
252
+ }
253
+
254
+ // for patterns
255
+ if (input && typeof input === 'object') {
256
+ const patterns = Object.keys(input);
257
+ const handler = (sourcePath) => {
258
+ for (const pattern of patterns) {
259
+ if (minimatch(sourcePath, pattern)) {
260
+ return input[pattern];
261
+ }
262
+ }
263
+ // false if not matched
264
+ };
265
+ options.sourceFilterHandler = handler;
266
+ return handler;
267
+ }
268
+
269
+ // default
270
+ const handler = () => true;
271
+ options.sourceFilterHandler = handler;
272
+ return handler;
273
+ },
274
+
164
275
  saveSourceCacheFile: async (sourceData, options, fileCache) => {
165
276
  const { cacheName, cachePath } = Util.getCacheFileInfo('source', sourceData.id, options.cacheDir);
166
277
 
package/lib/v8/v8.js CHANGED
@@ -7,7 +7,6 @@ const {
7
7
  resolveAnonymousUrl, normalizeSourcePath, getSourcePathReplacer
8
8
  } = require('../utils/source-path.js');
9
9
  const { collectSourceMaps } = require('../converter/collect-source-maps.js');
10
- const { minimatch } = require('../packages/monocart-coverage-vendor.js');
11
10
 
12
11
  const { v8Report } = require('../reports/v8.js');
13
12
  const { v8JsonReport } = require('../reports/v8-json.js');
@@ -27,53 +26,12 @@ const getWrapperSource = (offset, source) => {
27
26
  return startStr + source;
28
27
  };
29
28
 
30
- const getEntryFilter = (options) => {
31
- let input = options.entryFilter || options.filter;
32
-
33
- // for function handler
34
- if (typeof input === 'function') {
35
- return input;
36
- }
37
-
38
- // for single minimatch pattern
39
- if (input && typeof input === 'string') {
40
- // string to multiple patterns "{...}"
41
- // mcr npx mocha --entryFilter {'**/node_modules/**':false,'**/src/*.js':true}
42
- // mcr npx mocha --entryFilter "{'**/node_modules/**': false, '**/src/*.js': true}"
43
- const obj = Util.strToObj(input);
44
- if (obj) {
45
- input = obj;
46
- } else {
47
- return (entry) => {
48
- return minimatch(entry.url, input);
49
- };
50
- }
51
- }
52
-
53
- // for patterns
54
- if (input && typeof input === 'object') {
55
- const patterns = Object.keys(input);
56
- return (entry) => {
57
- const url = entry.url;
58
- for (const pattern of patterns) {
59
- if (minimatch(url, pattern)) {
60
- return input[pattern];
61
- }
62
- }
63
- // false if not matched
64
- };
65
- }
66
-
67
- // default
68
- return () => true;
69
- };
70
-
71
29
  const initV8ListAndSourcemap = async (mcr, v8list) => {
72
30
 
73
31
  const { options, fileCache } = mcr;
74
32
 
75
33
  // entry filter
76
- const entryFilter = getEntryFilter(options);
34
+ const entryFilter = Util.getEntryFilter(options);
77
35
 
78
36
  const lengthBefore = v8list.length;
79
37
  v8list = v8list.filter(entryFilter);
@@ -367,6 +325,5 @@ const saveV8Report = async (v8list, options, istanbulReportPath) => {
367
325
  module.exports = {
368
326
  initV8ListAndSourcemap,
369
327
  mergeV8Coverage,
370
- saveV8Report,
371
- getEntryFilter
328
+ saveV8Report
372
329
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monocart-coverage-reports",
3
- "version": "2.10.6",
3
+ "version": "2.10.8-beta.0",
4
4
  "description": "A code coverage tool to generate native V8 reports or Istanbul reports.",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -111,4 +111,4 @@
111
111
  "vine-ui": "^3.1.16",
112
112
  "ws": "^8.18.0"
113
113
  }
114
- }
114
+ }