monocart-reporter 1.7.12 → 2.0.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.
Files changed (42) hide show
  1. package/README.md +10 -26
  2. package/lib/generate-data.js +7 -19
  3. package/lib/generate-report.js +13 -6
  4. package/lib/index.d.ts +5 -46
  5. package/lib/index.js +1 -4
  6. package/lib/index.mjs +0 -1
  7. package/lib/packages/monocart-common.js +1 -0
  8. package/lib/packages/monocart-network.js +1 -0
  9. package/lib/packages/monocart-reporter.js +1 -0
  10. package/lib/packages/monocart-vendor.js +22 -0
  11. package/lib/platform/share.js +0 -5
  12. package/lib/plugins/audit/audit.js +2 -2
  13. package/lib/plugins/coverage/coverage.js +63 -249
  14. package/lib/plugins/network/network.js +17 -13
  15. package/lib/plugins/state/client.js +1 -1
  16. package/lib/plugins/state/state.js +1 -1
  17. package/lib/utils/parse-source.js +1 -1
  18. package/lib/utils/util.js +25 -38
  19. package/lib/visitor.js +6 -26
  20. package/package.json +10 -8
  21. package/lib/plugins/coverage/converter/collect-source-maps.js +0 -194
  22. package/lib/plugins/coverage/converter/converter.js +0 -565
  23. package/lib/plugins/coverage/converter/dedupe.js +0 -110
  24. package/lib/plugins/coverage/converter/find-original-range.js +0 -581
  25. package/lib/plugins/coverage/converter/info-branch.js +0 -30
  26. package/lib/plugins/coverage/converter/info-function.js +0 -29
  27. package/lib/plugins/coverage/converter/info-line.js +0 -20
  28. package/lib/plugins/coverage/converter/position-mapping.js +0 -183
  29. package/lib/plugins/coverage/converter/source-path.js +0 -140
  30. package/lib/plugins/coverage/istanbul/istanbul-summary.js +0 -49
  31. package/lib/plugins/coverage/istanbul/istanbul.js +0 -133
  32. package/lib/plugins/coverage/v8/v8-summary.js +0 -80
  33. package/lib/plugins/coverage/v8/v8.js +0 -260
  34. package/lib/runtime/monocart-code-viewer.js +0 -1
  35. package/lib/runtime/monocart-common.js +0 -1
  36. package/lib/runtime/monocart-coverage.js +0 -14
  37. package/lib/runtime/monocart-formatter.js +0 -1
  38. package/lib/runtime/monocart-network.js +0 -1
  39. package/lib/runtime/monocart-reporter.js +0 -1
  40. package/lib/runtime/monocart-v8.js +0 -1
  41. package/lib/runtime/monocart-vendor.js +0 -22
  42. package/lib/utils/decode-mappings.js +0 -49
@@ -19,11 +19,6 @@ const Util = {
19
19
  name: 'network',
20
20
  contentType: 'text/html',
21
21
  reportFile: 'network-report.json'
22
- },
23
- // artifact will be removed finally
24
- artifact: {
25
- name: 'artifact',
26
- contentType: 'application/json'
27
22
  }
28
23
  },
29
24
 
@@ -73,7 +73,7 @@ const attachAuditReport = async (runnerResult, testInfo, options = {}) => {
73
73
  }
74
74
 
75
75
  options = {
76
- title: `Lighthouse Report - ${testInfo.title}`,
76
+ name: `Lighthouse Report - ${testInfo.title}`,
77
77
  outputDir: Util.resolveOutputDir(testInfo, options),
78
78
  outputName: `audit-${Util.resolveTestIdWithRetry(testInfo)}`,
79
79
  ... options
@@ -89,7 +89,7 @@ const attachAuditReport = async (runnerResult, testInfo, options = {}) => {
89
89
 
90
90
  // `.lhr` is the Lighthouse Result as a JS object
91
91
  const report = {
92
- title: options.title,
92
+ name: options.name,
93
93
  ... getSummaryReport(runnerResult.lhr)
94
94
  };
95
95
 
@@ -1,302 +1,116 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
-
3
+ const CoverageReport = require('monocart-coverage-reports');
4
4
  const Util = require('../../utils/util.js');
5
- const {
6
- initIstanbulData, mergeIstanbulCoverage, saveIstanbulReport
7
- } = require('./istanbul/istanbul.js');
8
- const {
9
- initV8ListAndSourcemap, mergeV8Coverage, saveV8Report
10
- } = require('./v8/v8.js');
11
-
12
- const { convertV8List } = require('./converter/converter.js');
13
-
14
- const artifactsDirName = '.artifacts';
15
-
16
- const defaultOptions = {
17
-
18
- // Defaults to test title
19
- // title
20
- // outputDir
21
- // outputName
22
-
23
- // (Boolean) Whether to convert to Istanbul report from V8 list. Defaults to `html-spa` report | (String) or using `html` report
24
- toIstanbul: false,
25
5
 
26
- // (Function) A filter function to execute for each element in the V8 list.
27
- entryFilter: null,
6
+ const attachCoverageReport = async (data, testInfo, options = {}) => {
28
7
 
29
- // (Function) A filter function to execute for each element in the sources which unpacked from the source map.
30
- sourceFilter: null,
8
+ const reporterOptions = Util.resolveReporterOptions(testInfo);
31
9
 
32
- // Istanbul Only
10
+ const outputDir = Util.resolveOutputDir(testInfo, options);
11
+ const folderName = `coverage-${Util.resolveTestIdWithRetry(testInfo)}`;
33
12
 
34
- // source path handler
35
- sourcePath: null,
36
-
37
- // (usually not used) source finder for Istanbul HTML report
38
- sourceFinder: null,
39
-
40
- // (Boolean) Whether to create `lcov.info`
41
- lcov: false,
42
-
43
- // (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report)
44
- // watermarks: {},
45
- // (Array) V8 watermarks, Defaults to `[50, 80]`
46
- // watermarks: [50, 80],
47
-
48
- // (Boolean) Whether inline all scripts to the single HTML file. V8 only.
49
- inline: false
50
-
51
- };
52
-
53
- // ========================================================================================================
54
-
55
- const generateV8ListReport = async (v8list, coverageData, fileSources, options) => {
56
- const { toIstanbul, lcov } = options;
57
- const istanbulReport = toIstanbul || lcov;
58
- const v8Report = !toIstanbul;
59
-
60
- let report;
61
- if (istanbulReport) {
62
- report = await saveIstanbulReport(coverageData, fileSources, options);
63
- }
64
- if (v8Report) {
65
- report = await saveV8Report(v8list, options);
13
+ // support multiple calls
14
+ let outputName = folderName;
15
+ let htmlDir = path.resolve(outputDir, outputName);
16
+ let i = 0;
17
+ while (fs.existsSync(htmlDir)) {
18
+ i += 1;
19
+ outputName = `${folderName}-${i}`;
20
+ htmlDir = path.resolve(outputDir, outputName);
66
21
  }
67
22
 
68
- return report;
69
- };
70
-
71
- // ========================================================================================================
23
+ const coverageOptions = {
24
+ logging: reporterOptions.logging,
25
+ outputDir: htmlDir,
26
+ name: `Coverage Report - ${testInfo.title}`,
27
+ assetsPath: '../assets',
28
+ ... options
29
+ };
72
30
 
73
- const saveReportAttachment = (testInfo, report, htmlDir) => {
31
+ const coverageReport = new CoverageReport(coverageOptions);
32
+ await coverageReport.add(data);
33
+ const coverageResults = await coverageReport.generate();
74
34
 
35
+ // save report json
75
36
  const definition = Util.attachments.coverage;
76
- // save report
77
37
  const reportPath = path.resolve(htmlDir, definition.reportFile);
78
- Util.writeJSONSync(reportPath, report);
38
+ Util.writeJSONSync(reportPath, coverageResults);
79
39
 
40
+ // save attachments html link
80
41
  testInfo.attachments.push({
81
42
  name: definition.name,
82
43
  contentType: definition.contentType,
83
- path: path.resolve(htmlDir, 'index.html')
44
+ path: coverageResults.reportPath
84
45
  });
85
- };
86
-
87
- // ========================================================================================================
88
-
89
- const generateIstanbulReport = (istanbulData, testInfo, options) => {
90
46
 
91
- const { coverageData, fileSources } = initIstanbulData(istanbulData, options);
92
- const report = saveIstanbulReport(coverageData, fileSources, options);
93
-
94
- saveReportAttachment(testInfo, report, options.htmlDir);
95
-
96
- return report;
47
+ return coverageResults;
97
48
  };
98
49
 
99
-
100
50
  // ========================================================================================================
101
51
 
102
- const generateV8Coverage = async (v8list, testInfo, options) => {
103
-
104
- // init v8list and unpack sourcemap
105
- const inlineSourceMap = true;
106
- v8list = await initV8ListAndSourcemap(v8list, options, inlineSourceMap);
107
-
108
- const { coverageData, fileSources } = await convertV8List(v8list, options);
109
-
110
- const report = await generateV8ListReport(v8list, coverageData, fileSources, options);
52
+ const getGlobalCoverageOptions = async (reporterOptions) => {
111
53
 
112
- saveReportAttachment(testInfo, report, options.htmlDir);
54
+ const reporterOutputFile = await Util.resolveOutputFile(reporterOptions.outputFile);
55
+ const outputDir = path.dirname(reporterOutputFile);
56
+ const htmlDir = path.resolve(outputDir, 'coverage');
113
57
 
114
- return report;
115
- };
116
-
117
- const attachCoverageReport = (data, testInfo, options = {}) => {
118
-
119
- const logging = Util.resolveLogging(testInfo, options);
120
- Util.initLoggingLevel(logging, 'coverage-attach');
121
-
122
- if (!data) {
123
- Util.logError(`invalid coverage data: ${testInfo.title}`);
124
- return;
125
- }
126
-
127
- options = {
128
- ... defaultOptions,
129
- // default title
130
- title: `Coverage Report - ${testInfo.title}`,
131
- outputDir: Util.resolveOutputDir(testInfo, options),
132
- outputName: `coverage-${Util.resolveTestIdWithRetry(testInfo)}`,
133
- ... options
58
+ const coverageOptions = {
59
+ logging: reporterOptions.logging,
60
+ outputDir: htmlDir,
61
+ name: `Coverage Report - ${reporterOptions.name}`,
62
+ assetsPath: '../assets',
63
+ // merge all global coverage options
64
+ ... reporterOptions.coverage
134
65
  };
135
66
 
136
- // support multiple calls
137
- let htmlDir = path.resolve(options.outputDir, options.outputName);
138
- let i = 1;
139
- while (fs.existsSync(htmlDir)) {
140
- const outputName = `${options.outputName}-${i}`;
141
- htmlDir = path.resolve(options.outputDir, outputName);
142
- i += 1;
143
- }
144
-
145
- Util.initDir(htmlDir);
146
- options.htmlDir = htmlDir;
147
-
148
- const dataType = Array.isArray(data) ? 'v8' : 'istanbul';
149
- // console.log('data type', dataType);
150
-
151
- if (dataType === 'v8') {
152
- return generateV8Coverage(data, testInfo, options);
153
- }
154
-
155
- return generateIstanbulReport(data, testInfo, options);
67
+ return coverageOptions;
156
68
  };
157
69
 
158
- // ========================================================================================================
159
-
160
70
  // add coverage report to global, v8list only
161
- const addCoverageReport = async (data, testInfo, options = {}) => {
162
-
163
- const logging = Util.resolveLogging(testInfo, options);
164
- Util.initLoggingLevel(logging, 'coverage-add');
165
-
166
- if (!data) {
167
- Util.logError(`invalid coverage data: ${testInfo.title}`);
168
- return;
169
- }
170
-
171
- // global outputDir
172
- const outputDir = await Util.resolveGlobalOutputDir(testInfo, options);
173
-
174
- const coverageOptions = Util.resolveCoverageOptions(testInfo, options);
175
-
176
- options = {
177
- ... defaultOptions,
178
- // use reporter dir as output dir, NOT test output dir
179
- outputDir,
180
- outputName: 'coverage',
181
- ... coverageOptions
182
- };
183
-
184
- const reportDir = path.resolve(options.outputDir, options.outputName);
185
- // do NOT empty dir, there are previous artifacts generated
186
-
187
- // artifactsDir for temp artifact files
188
- const artifactsDir = path.resolve(reportDir, artifactsDirName);
189
- options.artifactsDir = artifactsDir;
190
-
191
- const filename = `coverage-${Util.resolveTestIdWithRetry(testInfo)}.json`;
192
- const jsonPath = path.resolve(artifactsDir, filename);
193
-
194
- const report = {
195
- title: testInfo.title
196
- };
197
-
198
- if (Array.isArray(data)) {
199
- // init v8list and unpack sourcemap
200
- const inlineSourceMap = false;
201
- report.data = await initV8ListAndSourcemap(data, options, inlineSourceMap);
202
- } else {
203
- // istanbul
204
- report.data = data;
205
- }
71
+ const addCoverageReport = async (data, testInfo) => {
206
72
 
207
- const artifactContent = JSON.stringify({
208
- type: 'coverage',
209
- data: report
210
- });
211
-
212
- await Util.writeFile(jsonPath, artifactContent);
73
+ const reporterOptions = Util.resolveReporterOptions(testInfo);
74
+ const coverageOptions = await getGlobalCoverageOptions(reporterOptions);
213
75
 
214
- const definition = Util.attachments.artifact;
215
- testInfo.attachments.push({
216
- name: definition.name,
217
- contentType: definition.contentType,
218
- path: jsonPath
219
- });
76
+ const coverageReport = new CoverageReport(coverageOptions);
77
+ const results = await coverageReport.add(data);
220
78
 
221
- return report;
79
+ return results;
222
80
  };
223
81
 
224
- // ========================================================================================================
225
-
226
- const getGlobalCoverageData = async (dataList, options) => {
82
+ const generateGlobalCoverageReport = async (reporterOptions) => {
227
83
 
228
- // get first and check v8list or istanbul data
229
- const firstData = dataList[0].data;
230
- const dataType = Array.isArray(firstData) ? 'v8' : 'istanbul';
231
- // console.log('data type', dataType);
84
+ const coverageOptions = await getGlobalCoverageOptions(reporterOptions);
232
85
 
233
- // v8list
234
- if (dataType === 'v8') {
235
- // merge v8list first
236
- const v8list = await mergeV8Coverage(dataList, options);
237
- // console.log('after merge', v8list.map((it) => it.url));
238
-
239
- const { coverageData, fileSources } = await convertV8List(v8list, options);
240
- return generateV8ListReport(v8list, coverageData, fileSources, options);
86
+ const coverageReport = new CoverageReport(coverageOptions);
241
87
 
88
+ // check if has cache
89
+ if (!coverageReport.hasCache()) {
90
+ return;
242
91
  }
243
92
 
244
- // istanbul data
245
- const istanbulData = mergeIstanbulCoverage(dataList, options);
246
- const { coverageData, fileSources } = initIstanbulData(istanbulData, options);
247
- return saveIstanbulReport(coverageData, fileSources, options);
248
-
249
- };
250
-
251
- // global coverage report, run different process with addCoverageReport
252
- const addGlobalCoverageReport = async (dataList, coverageOptions) => {
253
-
254
- Util.logInfo('generating global coverage report ...');
255
-
256
- const options = {
257
- ... defaultOptions,
258
- ... coverageOptions
259
- };
260
-
261
- const reportDir = path.resolve(options.outputDir, options.outputName);
262
-
263
- // empty dir except artifacts dir
264
- if (fs.existsSync(reportDir)) {
265
- fs.readdirSync(reportDir).forEach((itemName) => {
266
- if (itemName === artifactsDirName) {
267
- return;
268
- }
269
- Util.rmSync(path.resolve(reportDir, itemName));
270
- });
93
+ const coverageResults = await coverageReport.generate();
94
+ if (!coverageResults) {
95
+ return;
271
96
  }
272
97
 
273
- options.htmlDir = reportDir;
98
+ // coverageResults: type, reportPath, name, watermarks, summary, files
274
99
 
275
- // artifactsDir for temp artifact files
276
- const artifactsDir = path.resolve(reportDir, artifactsDirName);
277
- options.artifactsDir = artifactsDir;
100
+ // showing list props: global, name, path, title
278
101
 
279
- const report = await getGlobalCoverageData(dataList, options);
280
- // console.log(report);
281
-
282
- // =============================================================
283
- // remove artifacts dir after report generated
284
- if (Util.loggingType !== 'debug') {
285
- Util.rmSync(artifactsDir);
286
- }
287
- // =============================================================
102
+ // console.log('global coverage report', report);
288
103
 
289
104
  return {
290
105
  global: true,
291
- name: 'coverage',
292
- path: report.htmlPath,
293
- summary: report.summary,
294
- title: options.title
106
+ type: 'coverage',
107
+ name: coverageResults.name,
108
+ path: coverageResults.reportPath
295
109
  };
296
110
  };
297
111
 
298
112
  module.exports = {
299
113
  addCoverageReport,
300
- addGlobalCoverageReport,
301
- attachCoverageReport
114
+ attachCoverageReport,
115
+ generateGlobalCoverageReport
302
116
  };
@@ -96,21 +96,25 @@ const getNetworkSummary = (log) => {
96
96
 
97
97
  const saveNetworkHtmlReport = async (reportData, _options) => {
98
98
 
99
- const {
100
- htmlDir, outputDir, inline
101
- } = _options;
99
+ const { htmlDir, inline } = _options;
100
+
101
+ // deps
102
+ const jsFiles = ['monocart-code-viewer', 'monocart-formatter', 'turbogrid'].map((it) => {
103
+ return path.resolve(`node_modules/${it}/dist/${it}.js`);
104
+ });
105
+
106
+ jsFiles.push(path.resolve(__dirname, '../../packages/monocart-common.js'));
107
+ jsFiles.push(path.resolve(__dirname, '../../packages/monocart-network.js'));
102
108
 
103
109
  const options = {
104
110
  inline,
105
111
  reportData,
106
- jsFiles: ['monocart-code-viewer.js', 'monocart-formatter.js', 'monocart-common.js', 'monocart-network.js'],
107
- htmlDir,
112
+ jsFiles,
113
+ assetsPath: '../assets',
114
+ outputDir: htmlDir,
108
115
  htmlFile: 'index.html',
109
116
 
110
- outputDir,
111
- reportDataFile: 'network-data.js',
112
- assetsName: 'assets',
113
- assetsRelative: '../'
117
+ reportDataFile: 'network-data.js'
114
118
  };
115
119
 
116
120
  const htmlPath = await Util.saveHtmlReport(options);
@@ -131,7 +135,7 @@ const attachNetworkReport = async (har, testInfo, options = {}) => {
131
135
 
132
136
  options = {
133
137
  // default title
134
- title: `Network Report - ${testInfo.title}`,
138
+ name: `Network Report - ${testInfo.title}`,
135
139
  outputDir: Util.resolveOutputDir(testInfo, options),
136
140
  outputName: `network-${Util.resolveTestIdWithRetry(testInfo)}`,
137
141
  inline: false,
@@ -150,7 +154,7 @@ const attachNetworkReport = async (har, testInfo, options = {}) => {
150
154
 
151
155
  // save har
152
156
  const reportData = {
153
- title: options.title,
157
+ name: options.name,
154
158
  summary,
155
159
  ... harData
156
160
  };
@@ -158,14 +162,14 @@ const attachNetworkReport = async (har, testInfo, options = {}) => {
158
162
  const htmlPath = await saveNetworkHtmlReport(reportData, options);
159
163
 
160
164
  const report = {
161
- title: options.title,
165
+ name: options.name,
162
166
  ... harData.log,
163
167
  htmlPath,
164
168
  summary
165
169
  };
166
170
  delete report.entries;
167
171
 
168
- // save report
172
+ // save report json
169
173
  const definition = Util.attachments.network;
170
174
  const reportPath = path.resolve(htmlDir, definition.reportFile);
171
175
  Util.writeJSONSync(reportPath, report);
@@ -1,4 +1,4 @@
1
- const { WebSocket } = require('../../runtime/monocart-vendor.js');
1
+ const { WebSocket } = require('../../packages/monocart-vendor.js');
2
2
  const Util = require('../../utils/util.js');
3
3
 
4
4
  const getServerUrl = (options = {}) => {
@@ -1,5 +1,5 @@
1
1
  const EC = require('eight-colors');
2
- const { WebSocketServer } = require('../../runtime/monocart-vendor.js');
2
+ const { WebSocketServer } = require('../../packages/monocart-vendor.js');
3
3
  const Util = require('../../utils/util.js');
4
4
  const { getServerUrl, Client } = require('./client.js');
5
5
 
@@ -1,5 +1,5 @@
1
1
  const Util = require('./util.js');
2
- const { parse } = require('../runtime/monocart-vendor.js');
2
+ const { parse } = require('../packages/monocart-vendor.js');
3
3
 
4
4
  const parseSource = (data) => {
5
5
  const {
package/lib/utils/util.js CHANGED
@@ -8,6 +8,8 @@ const CG = require('console-grid');
8
8
  const Share = require('../platform/share.js');
9
9
  const { deflateSync } = require('lz-utils');
10
10
 
11
+ const defaultOptions = require('../default/options.js');
12
+
11
13
  const assetsName = 'assets';
12
14
 
13
15
  const Util = {
@@ -79,24 +81,16 @@ const Util = {
79
81
  return path.resolve(testInfo.outputDir, '../');
80
82
  },
81
83
 
82
- resolveGlobalOutputDir: async (testInfo, options) => {
83
- if (options && options.outputDir) {
84
- return options.outputDir;
85
- }
86
- const reporterOptions = Util.resolveReporterOptions(testInfo);
87
- const outputFile = await Util.resolveOutputFile(reporterOptions.outputFile);
88
- const outputDir = path.dirname(outputFile);
89
- return outputDir;
90
- },
91
-
92
84
  resolveOutputFile: async (outputFile) => {
85
+ // function to string first
93
86
  if (typeof outputFile === 'function') {
94
87
  outputFile = await outputFile();
95
88
  }
96
- if (typeof outputFile === 'string' && outputFile) {
97
- return outputFile;
89
+ // then check string
90
+ if (!outputFile || typeof outputFile !== 'string') {
91
+ outputFile = defaultOptions.outputFile;
98
92
  }
99
- return './test-results/report.html';
93
+ return path.resolve(outputFile);
100
94
  },
101
95
 
102
96
  resolveLogging: (testInfo, options) => {
@@ -107,14 +101,6 @@ const Util = {
107
101
  return reporterOptions.logging;
108
102
  },
109
103
 
110
- resolveCoverageOptions: (testInfo, options) => {
111
- const reporterOptions = Util.resolveReporterOptions(testInfo);
112
- return {
113
- ... reporterOptions.coverage,
114
- ... options
115
- };
116
- },
117
-
118
104
  resolveReporterOptions: (testInfo) => {
119
105
  if (!testInfo) {
120
106
  return {};
@@ -171,12 +157,11 @@ const Util = {
171
157
  inline,
172
158
  reportData,
173
159
  jsFiles,
174
- htmlDir,
160
+ assetsPath,
161
+ outputDir,
175
162
  htmlFile,
176
163
 
177
- outputDir,
178
- reportDataFile,
179
- assetsRelative
164
+ reportDataFile
180
165
  } = options;
181
166
 
182
167
  // report data
@@ -186,10 +171,9 @@ const Util = {
186
171
  // js libs
187
172
  const jsList = [];
188
173
  for (const jsFile of jsFiles) {
189
- const jsPath = path.resolve(__dirname, `../runtime/${jsFile}`);
190
- const jsStr = await Util.readFile(jsPath);
174
+ const jsStr = await Util.readFile(jsFile);
191
175
  jsList.push({
192
- file: jsFile,
176
+ filename: path.basename(jsFile),
193
177
  str: jsStr
194
178
  });
195
179
  }
@@ -206,10 +190,13 @@ const Util = {
206
190
  ].join(EOL);
207
191
  } else {
208
192
 
209
- await Util.writeFile(path.resolve(htmlDir, reportDataFile), reportDataStr);
193
+ await Util.writeFile(path.resolve(outputDir, reportDataFile), reportDataStr);
194
+
195
+ const assetsDir = path.resolve(outputDir, assetsPath);
196
+ const relAssetsDir = Util.relativePath(assetsDir, outputDir);
210
197
 
211
198
  for (const item of jsList) {
212
- const filePath = path.resolve(outputDir, assetsName, item.file);
199
+ const filePath = path.resolve(assetsDir, item.filename);
213
200
  if (!fs.existsSync(filePath)) {
214
201
  await Util.writeFile(filePath, item.str);
215
202
  }
@@ -217,12 +204,12 @@ const Util = {
217
204
 
218
205
  htmlStr = [
219
206
  `<script src="${reportDataFile}"></script>`,
220
- ... jsList.map((it) => `<script src="${assetsRelative}${assetsName}/${it.file}"></script>`)
207
+ ... jsList.map((it) => `<script src="${relAssetsDir}/${it.filename}"></script>`)
221
208
  ].join(EOL);
222
209
  }
223
210
 
224
211
  // html
225
- const htmlPath = path.resolve(htmlDir, htmlFile);
212
+ const htmlPath = path.resolve(outputDir, htmlFile);
226
213
  const template = Util.getTemplate(path.resolve(__dirname, '../default/template.html'));
227
214
  const html = Util.replace(template, {
228
215
  title: reportData.title,
@@ -319,7 +306,7 @@ const Util = {
319
306
  readFile: async (filePath) => {
320
307
  if (fs.existsSync(filePath)) {
321
308
  const buf = await readFile(filePath).catch((e) => {
322
- console.log(e);
309
+ Util.logError(`read file: ${filePath} ${e.message || e}`);
323
310
  });
324
311
  if (Buffer.isBuffer(buf)) {
325
312
  return buf.toString('utf8');
@@ -350,7 +337,7 @@ const Util = {
350
337
  }
351
338
  }
352
339
  await writeFile(filePath, content).catch((e) => {
353
- console.log(e);
340
+ Util.logError(`write file: ${filePath} ${e.message || e}`);
354
341
  });
355
342
  },
356
343
 
@@ -433,14 +420,14 @@ const Util = {
433
420
  if (Util.loggingLevel < Util.loggingLevels.error) {
434
421
  return;
435
422
  }
436
- EC.logRed(`[MCR] ${message}`);
423
+ EC.logRed(`[MR] ${message}`);
437
424
  },
438
425
 
439
426
  logInfo: (message) => {
440
427
  if (Util.loggingLevel < Util.loggingLevels.info) {
441
428
  return;
442
429
  }
443
- console.log(`[MCR] ${message}`);
430
+ console.log(`[MR] ${message}`);
444
431
  },
445
432
 
446
433
  // grid is info level
@@ -455,7 +442,7 @@ const Util = {
455
442
  if (Util.loggingLevel < Util.loggingLevels.debug) {
456
443
  return;
457
444
  }
458
- console.log(`[MCR] ${message}`);
445
+ console.log(`[MR] ${message}`);
459
446
  },
460
447
 
461
448
  // time is debug level
@@ -465,7 +452,7 @@ const Util = {
465
452
  }
466
453
  const duration = Date.now() - time_start;
467
454
  const durationH = Util.TSF(duration);
468
- const ls = [`[MCR] ${message}`, ' ('];
455
+ const ls = [`[MR] ${message}`, ' ('];
469
456
  if (duration <= 100) {
470
457
  ls.push(EC.green(durationH));
471
458
  } else if (duration < 500) {