monocart-reporter 2.9.4 → 2.9.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/README.md CHANGED
@@ -1066,7 +1066,11 @@ npx monocart merge <glob-patterns>
1066
1066
  npx monocart merge path-to/shard*/index.json -o merged-reports/index.html
1067
1067
 
1068
1068
  # -c --config
1069
- npx monocart merge path-to/shard*/index.json -c mr.config.js
1069
+ npx monocart merge path-to/shard*/my-report.zip -c mr.config.js
1070
+
1071
+ # NOTE: The asterisk(*) is a special character which is interpreted by some operating systems
1072
+ # For example: Mac and Linux, please put it in quotes, but NOT for Windows
1073
+ npx monocart merge 'path-to/shard*/*.zip'
1070
1074
  ```
1071
1075
  The default config files (In order of priority)
1072
1076
  - mr.config.js
package/lib/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
@@ -272,6 +272,12 @@ const resolveConfigOptions = async (configPath) => {
272
272
  return configOptions;
273
273
  };
274
274
 
275
+ const exit = (code) => {
276
+ if (code) {
277
+ process.exit(code);
278
+ }
279
+ };
280
+
275
281
  const mergeReports = async (str, cliOptions) => {
276
282
 
277
283
  await initNodeOptions(cliOptions);
@@ -285,6 +291,7 @@ const mergeReports = async (str, cliOptions) => {
285
291
  } else {
286
292
  if (customConfig) {
287
293
  Util.logError(`ERROR: not found config file: ${customConfig}`);
294
+ exit(1);
288
295
  return;
289
296
  }
290
297
  }
@@ -297,15 +304,21 @@ const mergeReports = async (str, cliOptions) => {
297
304
 
298
305
  Util.initLoggingLevel(options.logging);
299
306
 
307
+ Util.logInfo(`glob patterns: ${EC.cyan(str)}`);
308
+
300
309
  const files = await glob(str);
301
310
  if (!Util.isList(files)) {
302
311
  Util.logError(`ERROR: no files found with glob: ${str}`);
312
+ exit(1);
303
313
  return;
304
314
  }
305
- // console.log(files, options);
306
315
 
307
- await merge(files, options);
316
+ Util.logInfo(`glob files: ${files.join(', ')}`);
308
317
 
318
+ const reportData = await merge(files, options);
319
+ if (!reportData) {
320
+ exit(1);
321
+ }
309
322
  };
310
323
 
311
324
  program
@@ -18,34 +18,80 @@ const generateJson = (outputDir, filename, reportData, options) => {
18
18
  reportData.jsonPath = Util.relativePath(jsonPath);
19
19
  };
20
20
 
21
- const generateZip = (outputDir, filename, reportData, options) => {
22
-
23
- if (!options.zip) {
24
- return;
21
+ const initZipOptions = (outputDir, filename, zipOptions) => {
22
+ let clean = false;
23
+ let outputFile;
24
+ if (typeof zipOptions === 'string') {
25
+ outputFile = zipOptions;
26
+ } else if (typeof zipOptions === 'object') {
27
+ if (zipOptions.outputFile) {
28
+ outputFile = zipOptions.outputFile;
29
+ }
30
+ if (zipOptions.clean) {
31
+ clean = true;
32
+ }
25
33
  }
26
34
 
27
- let zipPath = path.resolve(outputDir, `${filename}.zip`);
28
- if (typeof options.zip === 'string') {
29
- zipPath = options.zip;
30
- if (!zipPath.endsWith('.zip')) {
31
- zipPath += '.zip';
35
+ if (outputFile) {
36
+ if (!outputFile.endsWith('.zip')) {
37
+ outputFile += '.zip';
32
38
  }
33
- const zipDir = path.dirname(zipPath);
39
+ const zipDir = path.dirname(outputFile);
34
40
  if (!fs.existsSync(zipDir)) {
35
41
  fs.mkdirSync(zipDir, {
36
42
  recursive: true
37
43
  });
38
44
  }
45
+
46
+ } else {
47
+ outputFile = path.resolve(outputDir, `${filename}.zip`);
48
+ }
49
+
50
+
51
+ return {
52
+ outputFile,
53
+ clean
54
+ };
55
+ };
56
+
57
+ const generateZip = (outputDir, filename, reportData, options) => {
58
+
59
+ const zipOptions = options.zip;
60
+ if (!zipOptions) {
61
+ return;
39
62
  }
40
63
 
64
+ const { outputFile, clean } = initZipOptions(outputDir, filename, zipOptions);
65
+
41
66
  const reportFiles = [];
42
67
  return new Promise((resolve) => {
43
68
  const zipFile = new ZipFile();
44
- zipFile.outputStream.pipe(fs.createWriteStream(zipPath)).on('close', function() {
69
+ zipFile.outputStream.pipe(fs.createWriteStream(outputFile)).on('close', function() {
45
70
 
46
- // remove files after zip
47
71
  reportData.reportFiles = reportFiles;
48
- reportData.zipPath = Util.relativePath(zipPath);
72
+
73
+ // whether to clean the files after zipped
74
+ if (clean) {
75
+ // console.log('clean', reportFiles);
76
+ const dirSet = new Set();
77
+ reportFiles.forEach((f) => {
78
+ const fp = path.resolve(outputDir, f);
79
+ dirSet.add(path.dirname(fp));
80
+ Util.rmSync(fp);
81
+ });
82
+
83
+ // clean empty dirs
84
+ const dirList = Array.from(dirSet).reverse();
85
+ dirList.forEach((dir) => {
86
+ const files = fs.readdirSync(dir);
87
+ if (files.length === 0) {
88
+ Util.rmSync(dir);
89
+ }
90
+ });
91
+
92
+ }
93
+
94
+ reportData.zipPath = Util.relativePath(outputFile);
49
95
 
50
96
  resolve();
51
97
  });
@@ -308,6 +354,7 @@ const generateReport = async (reportData, options, rawData) => {
308
354
 
309
355
  Util.logInfo(`view report: ${EC.cyan(`npx monocart show-report ${htmlPath}`)}`);
310
356
 
357
+ return reportData;
311
358
  };
312
359
 
313
360
  module.exports = generateReport;
package/lib/index.d.ts CHANGED
@@ -61,7 +61,12 @@ export type MonocartReporterOptions = {
61
61
  * {boolean} using default path
62
62
  * {string} zip file path
63
63
  */
64
- zip?: boolean | string;
64
+ zip?: boolean | string | {
65
+ /** the zip file path */
66
+ outputFile?: string;
67
+ /** whether to clean the files after zipped */
68
+ clean?: boolean;
69
+ };
65
70
 
66
71
  /**
67
72
  * whether to copy attachments to the reporter output dir, defaults to true
package/lib/merge-data.js CHANGED
@@ -36,20 +36,30 @@ const unzipDataFile = async (item, num, options) => {
36
36
  // Do not forget to close the file once you're done
37
37
  await zip.close();
38
38
 
39
- let filename = path.basename(item, '.zip');
39
+ const filename = path.basename(item, '.zip');
40
40
  let jsonPath = path.resolve(unzipDir, `${filename}.json`);
41
41
  if (fs.existsSync(jsonPath)) {
42
42
  return jsonPath;
43
43
  }
44
44
 
45
+ // filename for both html and json
46
+ const htmlMap = {};
47
+ const jsonMap = {};
45
48
  Util.forEachFile(unzipDir, (name, dir) => {
46
49
  if (name.endsWith('.html')) {
47
- filename = path.basename(name, '.html');
48
- return 'break';
50
+ htmlMap[path.basename(name, '.html')] = true;
51
+ } else if (name.endsWith('.json')) {
52
+ jsonMap[path.basename(name, '.json')] = true;
49
53
  }
50
54
  }, true);
51
55
 
52
- jsonPath = path.resolve(unzipDir, `${filename}.json`);
56
+ const keys = Object.keys(htmlMap);
57
+ for (const fn of keys) {
58
+ if (jsonMap[fn]) {
59
+ jsonPath = path.resolve(unzipDir, `${fn}.json`);
60
+ break;
61
+ }
62
+ }
53
63
 
54
64
  return jsonPath;
55
65
  };
@@ -74,7 +84,7 @@ const getReportData = async (item, num, options) => {
74
84
  // for finding attachments
75
85
  const jsonDir = Util.relativePath(path.dirname(item));
76
86
 
77
- Util.logInfo(`report data loaded: ${item}`);
87
+ Util.logInfo(`report data loaded: ${Util.relativePath(item)}`);
78
88
  return {
79
89
  jsonDir,
80
90
  data
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monocart-reporter",
3
- "version": "2.9.4",
3
+ "version": "2.9.6",
4
4
  "description": "A playwright test reporter. Shows suites/cases/steps with tree style, markdown annotations, custom columns/formatters/data collection visitors, console logs, style tags, send email.",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@babel/code-frame": "^7.25.7",
56
- "@playwright/test": "^1.47.2",
56
+ "@playwright/test": "^1.48.0",
57
57
  "ansi-to-html": "^0.7.2",
58
58
  "async-tick": "^1.0.0",
59
59
  "autolinker": "^4.0.0",