monocart-reporter 2.8.4 → 2.9.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.
- package/README.md +7 -0
- package/lib/default/options.js +6 -0
- package/lib/generate-report.js +101 -28
- package/lib/index.d.ts +8 -0
- package/lib/index.js +3 -2
- package/lib/merge-data.js +117 -69
- package/lib/packages/monocart-reporter-assets.js +1 -1
- package/lib/packages/monocart-reporter-vendor.js +25 -25
- package/lib/plugins/audit/audit.js +1 -1
- package/lib/plugins/coverage/coverage.js +10 -7
- package/lib/plugins/network/network.js +1 -1
- package/lib/utils/util.js +60 -7
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|

|
|
60
60
|
|
|
61
61
|

|
|
62
|
+
(For Github actions, we can enforce color with env: `FORCE_COLOR: true`)
|
|
62
63
|
|
|
63
64
|
## Install
|
|
64
65
|
```sh
|
|
@@ -1064,6 +1065,12 @@ The default config files (In order of priority)
|
|
|
1064
1065
|
- mr.config.json
|
|
1065
1066
|
- mr.config.ts
|
|
1066
1067
|
|
|
1068
|
+
Preload for TypeScript config file:
|
|
1069
|
+
- It requires node 18.19.0+
|
|
1070
|
+
- Installing tsx: `npm i -D tsx`
|
|
1071
|
+
- Using the `--import tsx` flag
|
|
1072
|
+
- see [comment](https://github.com/cenfun/monocart-reporter/issues/145#issuecomment-2365460013)
|
|
1073
|
+
|
|
1067
1074
|
|
|
1068
1075
|
## onEnd Hook
|
|
1069
1076
|
The `onEnd` function will be executed after report generated. Arguments:
|
package/lib/default/options.js
CHANGED
|
@@ -8,6 +8,9 @@ module.exports = () => ({
|
|
|
8
8
|
// the output html file path (relative process.cwd)
|
|
9
9
|
outputFile: './monocart-report/index.html',
|
|
10
10
|
|
|
11
|
+
json: true,
|
|
12
|
+
zip: false,
|
|
13
|
+
|
|
11
14
|
// whether to copy attachments to the reporter output dir, defaults to true
|
|
12
15
|
// it is useful when there are multiple html reports being output.
|
|
13
16
|
copyAttachments: true,
|
|
@@ -22,6 +25,9 @@ module.exports = () => ({
|
|
|
22
25
|
// timezone offset in minutes, GMT+0800 = -480
|
|
23
26
|
timezoneOffset: 0,
|
|
24
27
|
|
|
28
|
+
// normal or exclude-idle
|
|
29
|
+
durationStrategy: null,
|
|
30
|
+
|
|
25
31
|
// global coverage settings for addCoverageReport API
|
|
26
32
|
coverage: null,
|
|
27
33
|
// coverage: {
|
package/lib/generate-report.js
CHANGED
|
@@ -1,26 +1,92 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
1
2
|
const path = require('path');
|
|
2
3
|
const EC = require('eight-colors');
|
|
3
4
|
const nodemailer = require('nodemailer');
|
|
4
5
|
const Util = require('./utils/util.js');
|
|
5
6
|
const emailPlugin = require('./plugins/email.js');
|
|
6
7
|
const Assets = require('./assets.js');
|
|
7
|
-
|
|
8
|
+
const { ZipFile } = require('./packages/monocart-reporter-vendor.js');
|
|
8
9
|
// ===========================================================================
|
|
9
10
|
|
|
10
|
-
const generateJson = (outputDir,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const generateJson = (outputDir, filename, reportData, options) => {
|
|
12
|
+
if (!options.json) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const jsonPath = path.resolve(outputDir, `${filename}.json`);
|
|
13
17
|
Util.writeJSONSync(jsonPath, reportData);
|
|
14
|
-
jsonPath = Util.relativePath(jsonPath);
|
|
15
|
-
|
|
18
|
+
reportData.jsonPath = Util.relativePath(jsonPath);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const forEachFile = (dir, callback) => {
|
|
22
|
+
if (!fs.existsSync(dir)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const dirs = [];
|
|
26
|
+
fs.readdirSync(dir, {
|
|
27
|
+
withFileTypes: true
|
|
28
|
+
}).forEach((it) => {
|
|
29
|
+
|
|
30
|
+
if (it.isFile()) {
|
|
31
|
+
callback(it.name, dir);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (it.isDirectory()) {
|
|
36
|
+
dirs.push(path.resolve(dir, it.name));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
for (const subDir of dirs) {
|
|
41
|
+
forEachFile(subDir, callback);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const generateZip = (outputDir, filename, reportData, options) => {
|
|
47
|
+
|
|
48
|
+
if (!options.zip) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const zipPath = path.resolve(outputDir, `${filename}.zip`);
|
|
53
|
+
const reportFiles = [];
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
const zipFile = new ZipFile();
|
|
56
|
+
zipFile.outputStream.pipe(fs.createWriteStream(zipPath)).on('close', function() {
|
|
57
|
+
|
|
58
|
+
// remove files after zip
|
|
59
|
+
reportData.reportFiles = reportFiles;
|
|
60
|
+
reportData.zipPath = Util.relativePath(zipPath);
|
|
61
|
+
|
|
62
|
+
resolve();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
forEachFile(outputDir, (name, dir) => {
|
|
66
|
+
const absPath = path.resolve(dir, name);
|
|
67
|
+
const relPath = Util.relativePath(absPath, outputDir);
|
|
68
|
+
reportFiles.push(relPath);
|
|
69
|
+
// console.log(relPath);
|
|
70
|
+
zipFile.addFile(absPath, relPath);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
zipFile.end();
|
|
74
|
+
});
|
|
16
75
|
};
|
|
17
76
|
|
|
18
|
-
const generateHtml = async (outputDir,
|
|
77
|
+
const generateHtml = async (outputDir, filename, reportData, options) => {
|
|
78
|
+
|
|
79
|
+
// generate html
|
|
80
|
+
let inline = true;
|
|
81
|
+
if (typeof options.inline === 'boolean') {
|
|
82
|
+
inline = options.inline;
|
|
83
|
+
}
|
|
19
84
|
|
|
20
85
|
// deps
|
|
21
86
|
const jsFiles = ['monocart-reporter-app'];
|
|
87
|
+
const htmlFile = `${filename}.html`;
|
|
22
88
|
|
|
23
|
-
const
|
|
89
|
+
const htmlPath = await Assets.saveHtmlReport({
|
|
24
90
|
inline,
|
|
25
91
|
reportData,
|
|
26
92
|
jsFiles,
|
|
@@ -29,11 +95,10 @@ const generateHtml = async (outputDir, htmlFile, reportData, inline) => {
|
|
|
29
95
|
htmlFile,
|
|
30
96
|
|
|
31
97
|
reportDataFile: 'report-data.js'
|
|
32
|
-
};
|
|
98
|
+
});
|
|
33
99
|
|
|
34
|
-
|
|
100
|
+
reportData.htmlPath = htmlPath;
|
|
35
101
|
|
|
36
|
-
return htmlPath;
|
|
37
102
|
};
|
|
38
103
|
|
|
39
104
|
const showTestResults = (reportData) => {
|
|
@@ -221,30 +286,38 @@ const generateReport = async (reportData, options, rawData) => {
|
|
|
221
286
|
await onDataHandler(reportData, options, rawData);
|
|
222
287
|
|
|
223
288
|
// console.log(reportData);
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
// generate json
|
|
227
|
-
const jsonPath = await generateJson(outputDir, htmlFile, reportData);
|
|
228
|
-
|
|
229
|
-
// generate html
|
|
230
|
-
let inline = true;
|
|
231
|
-
if (typeof options.inline === 'boolean') {
|
|
232
|
-
inline = options.inline;
|
|
233
|
-
}
|
|
234
|
-
const htmlPath = await generateHtml(outputDir, htmlFile, reportData, inline);
|
|
289
|
+
const filename = path.basename(outputFile, '.html');
|
|
235
290
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
jsonPath
|
|
240
|
-
});
|
|
291
|
+
await generateHtml(outputDir, filename, reportData, options);
|
|
292
|
+
await generateJson(outputDir, filename, reportData, options);
|
|
293
|
+
await generateZip(outputDir, filename, reportData, options);
|
|
241
294
|
|
|
242
295
|
await onEndHandler(reportData, options);
|
|
243
296
|
|
|
244
297
|
// after onEnd for summary changes
|
|
245
298
|
showTestResults(reportData);
|
|
246
299
|
|
|
247
|
-
|
|
300
|
+
// clean .cache for merge
|
|
301
|
+
if (options.cacheDir) {
|
|
302
|
+
Util.rmSync(options.cacheDir);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const {
|
|
306
|
+
htmlPath, jsonPath, zipPath
|
|
307
|
+
} = reportData;
|
|
308
|
+
|
|
309
|
+
const assets = [];
|
|
310
|
+
if (jsonPath) {
|
|
311
|
+
assets.push(`json: ${EC.cyan(jsonPath)}`);
|
|
312
|
+
}
|
|
313
|
+
if (zipPath) {
|
|
314
|
+
assets.push(`zip: ${EC.cyan(zipPath)}`);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (assets.length) {
|
|
318
|
+
Util.logInfo(assets.join(' '));
|
|
319
|
+
}
|
|
320
|
+
|
|
248
321
|
Util.logInfo(`view report: ${EC.cyan(`npx monocart show-report ${htmlPath}`)}`);
|
|
249
322
|
|
|
250
323
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -54,6 +54,11 @@ export type MonocartReporterOptions = {
|
|
|
54
54
|
/** the output file path (relative process.cwd) */
|
|
55
55
|
outputFile?: string;
|
|
56
56
|
|
|
57
|
+
/** output json file for data only */
|
|
58
|
+
json?: boolean;
|
|
59
|
+
/** output zip file for all report files */
|
|
60
|
+
zip?: boolean;
|
|
61
|
+
|
|
57
62
|
/**
|
|
58
63
|
* whether to copy attachments to the reporter output dir, defaults to true
|
|
59
64
|
* it is useful when there are multiple html reports being output
|
|
@@ -73,6 +78,9 @@ export type MonocartReporterOptions = {
|
|
|
73
78
|
/** timezone offset in minutes, For example: GMT+0800 = -480 */
|
|
74
79
|
timezoneOffset?: number;
|
|
75
80
|
|
|
81
|
+
/** normal or exclude-idle */
|
|
82
|
+
durationStrategy?: 'normal' | 'exclude-idle',
|
|
83
|
+
|
|
76
84
|
/** global coverage options: https://github.com/cenfun/monocart-reporter?#code-coverage-report
|
|
77
85
|
* ```js
|
|
78
86
|
* coverage: {
|
package/lib/index.js
CHANGED
|
@@ -55,6 +55,7 @@ class MonocartReporter {
|
|
|
55
55
|
this.tickTime = this.options.tickTime || 1000;
|
|
56
56
|
this.tickStart();
|
|
57
57
|
|
|
58
|
+
this.trends = [];
|
|
58
59
|
// read trends from json before clean dir
|
|
59
60
|
getTrends(this.options.trend).then((trends) => {
|
|
60
61
|
// console.log('=========================== ', 'trends', trends.length);
|
|
@@ -65,12 +66,12 @@ class MonocartReporter {
|
|
|
65
66
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
init() {
|
|
69
70
|
|
|
70
71
|
this.options.cwd = Util.formatPath(process.cwd());
|
|
71
72
|
|
|
72
73
|
// init outputDir
|
|
73
|
-
const outputFile =
|
|
74
|
+
const outputFile = Util.resolveOutputFile(this.options.outputFile);
|
|
74
75
|
this.options.outputFile = outputFile;
|
|
75
76
|
|
|
76
77
|
const outputDir = path.dirname(outputFile);
|
package/lib/merge-data.js
CHANGED
|
@@ -5,6 +5,7 @@ const generateReport = require('./generate-report.js');
|
|
|
5
5
|
const getDefaultOptions = require('./default/options.js');
|
|
6
6
|
const { calculateSummary, getTrends } = require('./common.js');
|
|
7
7
|
const { mergeGlobalCoverageReport } = require('./plugins/coverage/coverage.js');
|
|
8
|
+
const { StreamZip } = require('./packages/monocart-reporter-vendor.js');
|
|
8
9
|
|
|
9
10
|
const checkReportData = (item) => {
|
|
10
11
|
if (item && typeof item === 'object') {
|
|
@@ -14,7 +15,71 @@ const checkReportData = (item) => {
|
|
|
14
15
|
}
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
const
|
|
18
|
+
const unzipDataFile = async (item, num, options) => {
|
|
19
|
+
|
|
20
|
+
if (!options.cacheDir) {
|
|
21
|
+
options.cacheDir = path.resolve(options.outputDir, '.cache');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const unzipDir = path.resolve(options.cacheDir, `extracted-${num}`);
|
|
25
|
+
|
|
26
|
+
fs.mkdirSync(unzipDir, {
|
|
27
|
+
recursive: true
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const zip = new StreamZip({
|
|
31
|
+
file: item
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await zip.extract(null, unzipDir);
|
|
35
|
+
|
|
36
|
+
// Do not forget to close the file once you're done
|
|
37
|
+
await zip.close();
|
|
38
|
+
|
|
39
|
+
const filename = path.basename(item, '.zip');
|
|
40
|
+
return path.resolve(unzipDir, `${filename}.json`);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const getReportData = async (item, num, options) => {
|
|
44
|
+
if (typeof item === 'string') {
|
|
45
|
+
|
|
46
|
+
// json or zip path
|
|
47
|
+
const extname = path.extname(item);
|
|
48
|
+
if (extname === '.zip') {
|
|
49
|
+
item = await unzipDataFile(item, num, options);
|
|
50
|
+
// console.log(item);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// json path
|
|
54
|
+
const data = Util.readJSONSync(item);
|
|
55
|
+
if (!data) {
|
|
56
|
+
Util.logError(`failed to read report data file: ${item}`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// for finding attachments
|
|
61
|
+
const jsonDir = Util.relativePath(path.dirname(item));
|
|
62
|
+
|
|
63
|
+
Util.logInfo(`report data loaded: ${item}`);
|
|
64
|
+
return {
|
|
65
|
+
jsonDir,
|
|
66
|
+
data
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!checkReportData(item)) {
|
|
71
|
+
Util.logError(`unmatched report data format: ${item}`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// json
|
|
76
|
+
return {
|
|
77
|
+
jsonDir: item.outputDir,
|
|
78
|
+
data: item
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const initDataList = async (reportDataList, options) => {
|
|
18
83
|
if (!Util.isList(reportDataList)) {
|
|
19
84
|
Util.logError(`invalid report data list: ${reportDataList}`);
|
|
20
85
|
return;
|
|
@@ -23,31 +88,17 @@ const initDataList = (reportDataList) => {
|
|
|
23
88
|
let hasError = false;
|
|
24
89
|
const list = [];
|
|
25
90
|
|
|
91
|
+
let num = 1;
|
|
26
92
|
for (const item of reportDataList) {
|
|
27
|
-
if (typeof item === 'string') {
|
|
28
|
-
const data = Util.readJSONSync(item);
|
|
29
|
-
if (!data) {
|
|
30
|
-
hasError = true;
|
|
31
|
-
Util.logError(`failed to read report data file: ${item}`);
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// for finding attachments
|
|
36
|
-
data.jsonDir = Util.relativePath(path.dirname(item));
|
|
37
93
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
94
|
+
const data = await getReportData(item, num, options);
|
|
95
|
+
if (!data) {
|
|
96
|
+
hasError = true;
|
|
97
|
+
break;
|
|
41
98
|
}
|
|
99
|
+
num += 1;
|
|
42
100
|
|
|
43
|
-
|
|
44
|
-
Util.logError(`unmatched report data format: ${item}`);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
item.jsonDir = item.outputDir;
|
|
49
|
-
|
|
50
|
-
list.push(item);
|
|
101
|
+
list.push(data);
|
|
51
102
|
}
|
|
52
103
|
|
|
53
104
|
if (hasError) {
|
|
@@ -82,12 +133,10 @@ const copyTarget = (targetPath, fromDir, toDir) => {
|
|
|
82
133
|
}
|
|
83
134
|
};
|
|
84
135
|
|
|
85
|
-
const attachmentsHandler = (
|
|
136
|
+
const attachmentsHandler = (data, jsonDir, outputDir, attachmentPathHandler) => {
|
|
86
137
|
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
const extras = Util.getAttachmentPathExtras(item);
|
|
90
|
-
Util.forEach(item.rows, (row) => {
|
|
138
|
+
const extras = Util.getAttachmentPathExtras(data);
|
|
139
|
+
Util.forEach(data.rows, (row) => {
|
|
91
140
|
if (row.type !== 'case' || !row.attachments) {
|
|
92
141
|
return;
|
|
93
142
|
}
|
|
@@ -195,62 +244,51 @@ const mergeArtifacts = async (artifactsList, options) => {
|
|
|
195
244
|
|
|
196
245
|
const mergeDataList = async (dataList, options) => {
|
|
197
246
|
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
const outputFile = await Util.resolveOutputFile(options.outputFile);
|
|
201
|
-
// init outputDir
|
|
202
|
-
const outputDir = path.dirname(outputFile);
|
|
203
|
-
// clean
|
|
204
|
-
if (fs.existsSync(outputDir)) {
|
|
205
|
-
fs.rmSync(outputDir, {
|
|
206
|
-
recursive: true,
|
|
207
|
-
force: true,
|
|
208
|
-
maxRetries: 10
|
|
209
|
-
});
|
|
210
|
-
}
|
|
247
|
+
const { outputFile, outputDir } = options;
|
|
211
248
|
|
|
212
|
-
|
|
213
|
-
recursive: true
|
|
214
|
-
});
|
|
215
|
-
// for attachment path handler
|
|
216
|
-
options.outputDir = outputDir;
|
|
249
|
+
const trends = await getTrends(options.trend);
|
|
217
250
|
|
|
218
251
|
const attachmentPathHandler = typeof options.attachmentPath === 'function' ? options.attachmentPath : null;
|
|
219
252
|
|
|
220
|
-
const
|
|
221
|
-
const
|
|
253
|
+
const startDates = [];
|
|
254
|
+
const dateRanges = [];
|
|
222
255
|
const metadata = {};
|
|
223
256
|
const system = [];
|
|
224
257
|
const rows = [];
|
|
225
258
|
const artifactsList = [];
|
|
226
259
|
|
|
227
|
-
for (const
|
|
260
|
+
for (const dataItem of dataList) {
|
|
228
261
|
|
|
229
|
-
|
|
262
|
+
const { data, jsonDir } = dataItem;
|
|
230
263
|
|
|
231
|
-
|
|
232
|
-
|
|
264
|
+
attachmentsHandler(data, jsonDir, outputDir, attachmentPathHandler);
|
|
265
|
+
|
|
266
|
+
startDates.push(data.date);
|
|
267
|
+
dateRanges.push({
|
|
268
|
+
start: data.date,
|
|
269
|
+
end: data.date + data.duration
|
|
270
|
+
});
|
|
233
271
|
|
|
234
272
|
// merge metadata (may collect from diff shard)
|
|
235
|
-
Object.assign(metadata,
|
|
273
|
+
Object.assign(metadata, data.metadata);
|
|
236
274
|
|
|
237
275
|
// merge system
|
|
238
|
-
system.push(
|
|
276
|
+
system.push(data.system);
|
|
239
277
|
|
|
240
278
|
// merge rows
|
|
241
279
|
rows.push({
|
|
242
280
|
// add shard level suite
|
|
243
|
-
title:
|
|
281
|
+
title: data.system.hostname,
|
|
244
282
|
type: 'suite',
|
|
245
283
|
suiteType: 'shard',
|
|
246
|
-
caseNum:
|
|
247
|
-
subs:
|
|
284
|
+
caseNum: data.summary.tests.value,
|
|
285
|
+
subs: data.rows
|
|
248
286
|
});
|
|
249
287
|
|
|
250
|
-
if (
|
|
288
|
+
if (data.artifacts) {
|
|
251
289
|
artifactsList.push({
|
|
252
|
-
jsonDir
|
|
253
|
-
artifacts:
|
|
290
|
+
jsonDir,
|
|
291
|
+
artifacts: data.artifacts
|
|
254
292
|
});
|
|
255
293
|
}
|
|
256
294
|
|
|
@@ -260,7 +298,7 @@ const mergeDataList = async (dataList, options) => {
|
|
|
260
298
|
|
|
261
299
|
// base on first one, do not change dataList (need for onData)
|
|
262
300
|
const mergedData = {
|
|
263
|
-
... dataList[0]
|
|
301
|
+
... dataList[0].data
|
|
264
302
|
};
|
|
265
303
|
|
|
266
304
|
// merge new options
|
|
@@ -272,11 +310,10 @@ const mergeDataList = async (dataList, options) => {
|
|
|
272
310
|
|
|
273
311
|
const reportName = options.name || mergedData.name;
|
|
274
312
|
|
|
275
|
-
const date = Math.min.apply(null,
|
|
313
|
+
const date = Math.min.apply(null, startDates);
|
|
276
314
|
const dateH = new Date(date).toLocaleString();
|
|
277
315
|
|
|
278
|
-
const
|
|
279
|
-
const duration = endDate - date;
|
|
316
|
+
const duration = Util.getDuration(dateRanges, options.durationStrategy);
|
|
280
317
|
const durationH = Util.TF(duration);
|
|
281
318
|
|
|
282
319
|
Object.assign(mergedData, {
|
|
@@ -315,19 +352,30 @@ module.exports = async (reportDataList, userOptions = {}) => {
|
|
|
315
352
|
|
|
316
353
|
Util.logInfo('merging report data ...');
|
|
317
354
|
|
|
318
|
-
const dataList = await initDataList(reportDataList);
|
|
319
|
-
if (!dataList) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
355
|
const options = {
|
|
324
356
|
... getDefaultOptions(),
|
|
325
357
|
... userOptions
|
|
326
358
|
};
|
|
327
359
|
|
|
360
|
+
// init options
|
|
361
|
+
const outputFile = Util.resolveOutputFile(options.outputFile);
|
|
362
|
+
options.outputFile = outputFile;
|
|
363
|
+
// init outputDir
|
|
364
|
+
const outputDir = path.dirname(outputFile);
|
|
365
|
+
// clean
|
|
366
|
+
Util.initDir(outputDir);
|
|
367
|
+
// for attachment path handler
|
|
368
|
+
options.outputDir = outputDir;
|
|
369
|
+
|
|
370
|
+
const dataList = await initDataList(reportDataList, options);
|
|
371
|
+
if (!dataList) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
328
375
|
const reportData = await mergeDataList(dataList, options);
|
|
329
376
|
// console.log(reportData.artifacts);
|
|
330
377
|
|
|
331
|
-
|
|
378
|
+
const rawData = dataList.map((it) => it.data);
|
|
379
|
+
return generateReport(reportData, options, rawData);
|
|
332
380
|
|
|
333
381
|
};
|