monocart-coverage-reports 2.6.2 → 2.6.4

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/index.d.ts CHANGED
@@ -2,16 +2,35 @@ declare namespace MCR {
2
2
 
3
3
  export interface V8CoverageEntry {
4
4
  url: string;
5
+
6
+ /** entry type */
7
+ type?: "js" | "css";
8
+
5
9
  /** css only */
6
10
  text?: string;
7
11
  /** css only */
8
12
  ranges?: any[];
9
- /** js only */
10
- scriptId?: string;
13
+
11
14
  /** js only */
12
15
  source?: string;
13
16
  /** js only */
17
+ scriptId?: string;
18
+ /** js only */
14
19
  functions?: any[];
20
+
21
+ /** js only */
22
+ sourceMap?: any;
23
+ /** js only */
24
+ scriptOffset?: number;
25
+ /** js only */
26
+ distFile?: string;
27
+
28
+ /** empty coverage */
29
+ empty?: boolean;
30
+ /** fake source */
31
+ fake?: boolean;
32
+
33
+ [key: string]: any;
15
34
  }
16
35
 
17
36
  export type Watermarks = [number, number] | {
@@ -166,10 +185,10 @@ declare namespace MCR {
166
185
  js?: boolean;
167
186
  /** V8 only */
168
187
  data?: {
169
- bytes: CoverageRange[];
170
- statements: CoverageRange[];
171
- branches: CoverageRange[];
172
- functions: CoverageRange[];
188
+ bytes?: CoverageRange[];
189
+ statements?: CoverageRange[];
190
+ branches?: CoverageRange[];
191
+ functions?: CoverageRange[];
173
192
  ignores?: IgnoredRange[];
174
193
  /** codecov json format */
175
194
  lines: {
@@ -192,11 +211,8 @@ declare namespace MCR {
192
211
  /** {string} logging levels: off, error, info, debug */
193
212
  logging?: string;
194
213
 
195
- /** {string} output dir */
196
- outputDir?: string;
197
-
198
- /** {string|string[]} input raw dir(s) */
199
- inputDir?: string | string[];
214
+ /** {string} Report name. Defaults to "Coverage Report". */
215
+ name?: string;
200
216
 
201
217
  /**
202
218
  *
@@ -205,25 +221,21 @@ declare namespace MCR {
205
221
  * {array} ['v8'], ['v8', ['console-details', { skipPercent: 80 }]]
206
222
  *
207
223
  * By default, `v8` for V8 data, `html` for Istanbul data
208
- */
209
- reports?: string | ReportDescription[];
224
+ */
225
+ reports?: string | string[] | ReportDescription[];
210
226
 
211
- /** {string} Report name. Defaults to "Coverage Report". */
212
- name?: string;
227
+ /** {string} output dir */
228
+ outputDir?: string;
213
229
 
214
- /** (V8 only) {string} Output [sub dir/]filename. Defaults to "index.html" */
215
- outputFile?: string;
216
- /** (V8 only) {boolean} Inline all scripts to the single HTML file. Defaults to false. */
217
- inline?: boolean;
218
- /** (V8 only) {string} Assets path if not inline. Defaults to "./assets" */
219
- assetsPath?: string;
230
+ /** {string|string[]} input raw dir(s) */
231
+ inputDir?: string | string[];
220
232
 
221
233
  /** (V8 only)
222
234
  *
223
235
  * {string} `minimatch` pattern for entry url; {object} multiple patterns;
224
236
  *
225
237
  * {function} A filter function for each entry file in the V8 list.
226
- * */
238
+ */
227
239
  entryFilter?: string | {
228
240
  [pattern: string]: boolean;
229
241
  } | ((entry: V8CoverageEntry) => boolean);
@@ -233,11 +245,33 @@ declare namespace MCR {
233
245
  * {string} `minimatch` pattern for source path; {object} multiple patterns;
234
246
  *
235
247
  * {function} A filter function for each source path when the source is unpacked from the source map.
236
- * */
248
+ */
237
249
  sourceFilter?: string | {
238
250
  [pattern: string]: boolean;
239
251
  } | ((sourcePath: string) => boolean);
240
252
 
253
+ /**
254
+ * {function} Source path handler.
255
+ *
256
+ * {object} Replace key with value.
257
+ * */
258
+ sourcePath?: ((filePath: string) => string) | {
259
+ [key: string]: string;
260
+ };
261
+
262
+
263
+ /** (V8 only) {string} Output [sub dir/]filename. Defaults to "index.html" */
264
+ outputFile?: string;
265
+ /** (V8 only) {boolean} Inline all scripts to the single HTML file. Defaults to false. */
266
+ inline?: boolean;
267
+ /** (V8 only) {string} Assets path if not inline. Defaults to "./assets" */
268
+ assetsPath?: string;
269
+
270
+ /** (Istanbul only) defaultSummarizer, sourceFinder */
271
+
272
+ /** {boolean} Generate lcov.info file, same as lcovonly report. Defaults to false. */
273
+ lcov?: boolean;
274
+
241
275
  /**
242
276
  * options for adding empty coverage for all files
243
277
  */
@@ -259,20 +293,6 @@ declare namespace MCR {
259
293
  /** (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop */
260
294
  v8Ignore?: boolean;
261
295
 
262
- /** (Istanbul only) defaultSummarizer, sourceFinder */
263
-
264
- /** {boolean} Generate lcov.info file, same as lcovonly report. Defaults to false. */
265
- lcov?: boolean;
266
-
267
- /**
268
- * {function} Source path handler.
269
- *
270
- * {object} Replace key with value.
271
- * */
272
- sourcePath?: ((filePath: string) => string) | {
273
- [key: string]: string;
274
- };
275
-
276
296
  /** {string|function} Specify the report path, especially when there are multiple reports. Defaults to outputDir/index.html. */
277
297
  reportPath?: string | (() => string);
278
298
 
@@ -280,30 +300,51 @@ declare namespace MCR {
280
300
  * {object} { bytes:[50,80], statements:[50,80], branches:[50,80], functions:[50,80], lines:[50,80] } */
281
301
  watermarks?: Watermarks;
282
302
 
283
- /** {boolean} Indicates whether to clean previous files in output dir before generating report. Defaults to true. */
303
+ /**
304
+ * {boolean} Indicates whether to clean previous reports in output dir before generating new reports. Defaults to true.
305
+ *
306
+ * If true, the API `clean()` will execute automatically.
307
+ * */
284
308
  clean?: boolean;
285
309
 
286
310
  /**
287
- * {boolean} Indicates whether to clean previous cache in output dir before generating report. Defaults to false.
311
+ * {boolean} Indicates whether to clean previous cache in output dir on start. Defaults to false.
288
312
  *
289
313
  * If true, the API `cleanCache()` will execute automatically.
290
314
  */
291
315
  cleanCache?: boolean;
292
316
 
317
+ /** (V8 only) {function} onEntry hook */
318
+ onEntry?: (entry: V8CoverageEntry) => Promise<void>;
319
+
293
320
  /** {function} onEnd hook */
294
321
  onEnd?: (coverageResults: CoverageResults) => Promise<void>;
322
+
295
323
  }
296
324
 
297
325
  export interface McrCliOptions extends CoverageReportOptions {
298
- /** {function} onStart hook */
326
+
327
+ /** (CLI only) {function} onStart hook */
299
328
  onStart?: (coverageReport: CoverageReport) => Promise<void>;
329
+
330
+ /** (CLI only) {function} onReady hook before adding coverage data.
331
+ *
332
+ * Sometimes, the child process has not yet finished writing the coverage data, and it needs to wait here.
333
+ */
334
+ onReady?: (coverageReport: CoverageReport, nodeV8CoverageDir: string, subprocess: any) => Promise<void>;
335
+
300
336
  }
301
337
 
302
338
  export class CoverageReport {
303
339
 
340
+ /**
341
+ * @param options coverage report options
342
+ */
304
343
  constructor(options?: CoverageReportOptions);
305
344
 
306
- /** add coverage data: {array} V8 format, {object} Istanbul format */
345
+ /** add coverage data
346
+ *
347
+ * @param coverageData {array} V8 format, {object} Istanbul format */
307
348
  add: (coverageData: any[] | any) => Promise<AddedResults>;
308
349
 
309
350
  /** generate report */
@@ -314,6 +355,27 @@ declare namespace MCR {
314
355
 
315
356
  /** clean previous cache, return `false` if no cache */
316
357
  cleanCache: () => boolean;
358
+
359
+ /** clean previous reports except cache dir and v8 coverage dir */
360
+ clean: () => void;
361
+
362
+ /** get entry filter handler, it can be used to filter the coverage data list before adding it. */
363
+ getEntryFilter: () => ((entry: V8CoverageEntry) => boolean);
364
+
365
+ /** load config file.
366
+ *
367
+ * @param configFile custom config file path
368
+ *
369
+ * Supports loading default config file if no custom config specified:
370
+ 'mcr.config.js',
371
+ 'mcr.config.cjs',
372
+ 'mcr.config.mjs',
373
+ 'mcr.config.json',
374
+ '.mcrrc.js',
375
+ '.mcrrc',
376
+ 'mcr.config.ts'
377
+ */
378
+ loadConfig: (configFile?: string) => Promise<void>;
317
379
  }
318
380
 
319
381
  export interface CoverageSnapshot {
package/lib/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const { pathToFileURL } = require('url');
4
+ const EC = require('eight-colors');
5
+
3
6
  const defaultOptions = require('./default/options.js');
4
7
  const Util = require('./utils/util.js');
5
8
 
@@ -7,26 +10,46 @@ const { initV8ListAndSourcemap, getEntryFilter } = require('./v8/v8.js');
7
10
  const { getInputData, generateCoverageReports } = require('./generate.js');
8
11
  const { getSnapshot, diffSnapshot } = require('./utils/snapshot.js');
9
12
 
13
+ const resolveConfigOptions = async (configPath) => {
14
+ // json format
15
+ const ext = path.extname(configPath);
16
+ if (ext === '.json' || configPath.slice(-2) === 'rc') {
17
+ return JSON.parse(Util.readFileSync(configPath));
18
+ }
19
+
20
+ let configOptions;
21
+ let err;
22
+ try {
23
+ configOptions = await import(pathToFileURL(configPath));
24
+ } catch (ee) {
25
+ err = ee;
26
+ }
27
+
28
+ if (err || !configOptions) {
29
+ Util.logError(`ERROR: failed to load config "${configPath}": ${err && err.message} `);
30
+ return;
31
+ }
32
+
33
+ configOptions = configOptions.default || configOptions;
34
+
35
+ return configOptions;
36
+ };
37
+
10
38
  class CoverageReport {
11
39
 
12
40
  constructor(options = {}) {
13
41
  this.cacheDirName = '.cache';
42
+ this.constructorOptions = options;
14
43
  this.options = {
15
44
  ... defaultOptions,
16
45
  ... options
17
46
  };
18
-
19
47
  this.initOptions();
20
- // If true, the API `cleanCache()` will execute automatically.
21
- if (this.options.cleanCache) {
22
- this.cleanCache();
23
- }
24
-
25
48
  }
26
49
 
27
- initOptions() {
50
+ initOptions(force) {
28
51
 
29
- if (this.fixedOptions) {
52
+ if (this.fixedOptions && !force) {
30
53
  return;
31
54
  }
32
55
 
@@ -43,6 +66,11 @@ class CoverageReport {
43
66
  const cacheDir = path.resolve(outputDir, this.cacheDirName);
44
67
  this.options.cacheDir = cacheDir;
45
68
 
69
+ // If true, the API `cleanCache()` will execute automatically.
70
+ if (this.options.cleanCache) {
71
+ this.cleanCache();
72
+ }
73
+
46
74
  this.fixedOptions = true;
47
75
  }
48
76
 
@@ -125,12 +153,7 @@ class CoverageReport {
125
153
  if (fs.existsSync(outputDir)) {
126
154
  // if assets dir is out of output dir will be ignore
127
155
  if (this.options.clean) {
128
- fs.readdirSync(outputDir).forEach((itemName) => {
129
- if (itemName === this.cacheDirName) {
130
- return;
131
- }
132
- Util.rmSync(path.resolve(outputDir, itemName));
133
- });
156
+ this.clean();
134
157
  }
135
158
  } else {
136
159
  fs.mkdirSync(outputDir, {
@@ -160,7 +183,7 @@ class CoverageReport {
160
183
  return fs.existsSync(this.options.cacheDir);
161
184
  }
162
185
 
163
- // cache clean
186
+ // cache clean dir
164
187
  cleanCache() {
165
188
  // clean previous artifacts
166
189
  if (this.hasCache()) {
@@ -170,10 +193,75 @@ class CoverageReport {
170
193
  return false;
171
194
  }
172
195
 
196
+ // clean previous reports except cache dir and v8 coverage dir
197
+ clean() {
198
+ const outputDir = this.options.outputDir;
199
+ let v8DirName;
200
+ const nodeV8CoverageDir = process.env.NODE_V8_COVERAGE;
201
+ if (nodeV8CoverageDir) {
202
+ v8DirName = path.relative(outputDir, nodeV8CoverageDir);
203
+ }
204
+ fs.readdirSync(outputDir).forEach((itemName) => {
205
+ if (itemName === this.cacheDirName) {
206
+ return;
207
+ }
208
+ if (itemName === v8DirName) {
209
+ return;
210
+ }
211
+ Util.rmSync(path.resolve(outputDir, itemName));
212
+ });
213
+ }
214
+
215
+ // get entry filter handler
173
216
  getEntryFilter() {
174
217
  return getEntryFilter(this.options);
175
218
  }
176
219
 
220
+ // load config file
221
+ async loadConfig(customConfigFile) {
222
+
223
+ // order by priority
224
+ const configList = customConfigFile ? [customConfigFile] : [
225
+ 'mcr.config.js',
226
+ 'mcr.config.cjs',
227
+ 'mcr.config.mjs',
228
+ 'mcr.config.json',
229
+ '.mcrrc.js',
230
+ '.mcrrc',
231
+ 'mcr.config.ts'
232
+ ];
233
+
234
+ const existsList = configList.filter((p) => p && fs.existsSync(p));
235
+ if (!existsList.length) {
236
+ if (customConfigFile) {
237
+ Util.logError(`The config file does not exist: ${customConfigFile}`);
238
+ }
239
+ // no config
240
+ return;
241
+ }
242
+
243
+ // first one, high priority
244
+ const configPath = existsList[0];
245
+ const configOptions = await resolveConfigOptions(configPath);
246
+ if (!configOptions) {
247
+ // failed to load config options
248
+ if (customConfigFile) {
249
+ Util.logError(`Failed to load config file: ${customConfigFile}`);
250
+ }
251
+ return;
252
+ }
253
+
254
+ Util.logInfo(`Loaded config: ${EC.cyan(configPath)}`);
255
+ // init options again
256
+ this.options = {
257
+ ... defaultOptions,
258
+ ... configOptions,
259
+ ... this.constructorOptions
260
+ };
261
+ this.initOptions(true);
262
+
263
+ }
264
+
177
265
  }
178
266
 
179
267
  /** create coverage report */