monocart-reporter 1.6.36 → 1.7.1

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
@@ -34,6 +34,7 @@
34
34
  - [Compare Istanbul, V8 and V8 to Istanbul](#compare-istanbul-v8-and-v8-to-istanbul)
35
35
  - [Global Coverage Report](#global-coverage-report) for Component Testing
36
36
  * [Attach Network Report](#attach-network-report)
37
+ * [Global State Management](#global-state-management)
37
38
  * [Merge Shard Reports](#merge-shard-reports)
38
39
  * [onEnd hook](#onend-hook)
39
40
  - [Send Email](#send-email)
@@ -122,8 +123,6 @@ Separated metadata file (Already included in the above HTML and compressed, it c
122
123
  coverage: null,
123
124
  // coverage: {
124
125
  // entryFilter: (entry) => true,
125
- // unpackSourceMap: true,
126
- // excludeDistFile: true,
127
126
  // sourceFilter: (sourceName) => sourceName.search(/src\/.+/) !== -1,
128
127
  // },
129
128
 
@@ -628,18 +627,15 @@ Attach a code coverage report with API `attachCoverageReport(data, testInfo, opt
628
627
  - `data` There are two supported data inputs `Istanbul` (Object) or `V8` (Array)
629
628
  - `testInfo` see [TestInfo](https://playwright.dev/docs/api/class-testinfo)
630
629
  - `options` (Object)
631
- - Istanbul only:
632
- - `watermarks` (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report)
633
- - `lcov` (Boolean) Whether to create `lcov.info`
634
- - `sourcePath` (Function) source path handler, return a new source path
635
- - V8 only:
636
- - `toIstanbul` (Boolean) Whether to convert to Istanbul report
637
- - `watermarks` (Array) Defaults to `[50, 80]`
630
+ - `title` (String) report title.
631
+ - `toIstanbul` (Boolean) Whether to convert to Istanbul report from V8 list.
638
632
  - `entryFilter` (Function) A filter function to execute for each element in the V8 list.
639
- - `unpackSourceMap` (Boolean) Whether to unpack all sources from the source map if a related source map file is found.
640
- - `excludeDistFile` (Boolean) Whether to exclude the dist file (usually minified) if the sources are successfully unpacked from the source map.
641
633
  - `sourceFilter` (Function) A filter function to execute for each element in the sources which unpacked from the source map.
642
- - `inline` (Boolean) Whether inline all scripts to the single HTML file.
634
+ - `watermarks` (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report) | (Array) V8 watermarks, Defaults to `[50, 80]`.
635
+ - `lcov` (Boolean) Whether to create `lcov.info`. Istanbul only.
636
+ - `sourcePath` (Function) source path handler, return a new source path. Istanbul only.
637
+ - `inline` (Boolean) Whether inline all scripts to the single HTML file. V8 only.
638
+ - `debug` (Boolean) The dist file which has source map will be included, and the temporary artifacts will not be removed.
643
639
 
644
640
  (see example: [report-coverage.spec.js](https://github.com/cenfun/monocart-reporter/blob/main/tests/report-coverage/report-coverage.spec.js))
645
641
 
@@ -705,7 +701,7 @@ test('Take V8 and Istanbul coverage report', async ({ page }) => {
705
701
  const coverageList = [... jsCoverage, ... cssCoverage];
706
702
 
707
703
  const v8 = await attachCoverageReport(coverageList, test.info(), {
708
- excludeDistFile: false
704
+ debug: true
709
705
  });
710
706
  console.log(v8.summary);
711
707
 
@@ -745,8 +741,6 @@ module.exports = {
745
741
  // global coverage report options
746
742
  coverage: {
747
743
  entryFilter: (entry) => true,
748
- unpackSourceMap: true,
749
- excludeDistFile: true,
750
744
  sourceFilter: (sourceName) => sourceName.search(/src\/.+/) !== -1,
751
745
  }
752
746
  }]
@@ -762,7 +756,6 @@ Attach a network report with API `attachNetworkReport(har, testInfo)`. Arguments
762
756
  Generate HAR with `recordHar` option in browser.newContext() (see example: [report-network.spec.js](https://github.com/cenfun/monocart-reporter/blob/main/tests/report-network/report-network.spec.js) preview [report](https://cenfun.github.io/monocart-reporter/network-1a18723ee59b36867898/index.html))
763
757
 
764
758
  ```js
765
- // CommonJS
766
759
  const fs = require('fs');
767
760
  const path = require('path');
768
761
  const { test } = require('@playwright/test');
@@ -828,6 +821,94 @@ test('finally, attach HAR', async () => {
828
821
  ```
829
822
  Preview [Network HTML Report](https://cenfun.github.io/monocart-reporter/network-38e613e8d93547bdb27f/index.html)
830
823
 
824
+
825
+ ## Global State Management
826
+ When tests are executed in [isolation](https://playwright.dev/docs/browser-contexts) mode, the reporter and each test may run in a different process, they cannot share data with each other. we can start a local WebSocket server to serve the global data, and read/write the global data with `useState` API from a test.
827
+ - setup global state
828
+ ```js
829
+ module.exports = {
830
+ reporter: [
831
+ ['list'],
832
+ ['monocart-reporter', {
833
+ name: "My Test Report",
834
+ outputFile: './test-results/report.html',
835
+ state: {
836
+ data: {
837
+ count: 0
838
+ },
839
+ server: {
840
+ // port: 8130
841
+ },
842
+ onClose: (data, config) => {
843
+ // save state data to global metadata
844
+ Object.assign(config.metadata, data);
845
+ }
846
+ }
847
+ }]
848
+ ]
849
+ };
850
+ ```
851
+ - get/set/remove global data
852
+ ```js
853
+ const { test } = require('@playwright/test');
854
+ const { useState } = require('monocart-reporter');
855
+ test('state test', async ({ browserName }) => {
856
+ const state = useState({
857
+ // port: 8130
858
+ });
859
+
860
+ const count = await state.get('count');
861
+ console.log('count', count);
862
+
863
+ await state.set('count', count + 1);
864
+
865
+ await state.set({
866
+ browser: browserName,
867
+ someKey: 'some value'
868
+ });
869
+
870
+ const [browser, someKey] = await state.get('browser', 'someKey');
871
+ console.log(browser, someKey);
872
+
873
+ await state.remove('someKey');
874
+
875
+ const all = await state.get();
876
+ console.log(all);
877
+ });
878
+ ```
879
+ - customize sending and receiving messages
880
+ ```js
881
+ module.exports = {
882
+ reporter: [
883
+ ['list'],
884
+ ['monocart-reporter', {
885
+ name: "My Test Report",
886
+ outputFile: './test-results/report.html',
887
+ state: {
888
+ // receive messages and send back response
889
+ onReceive: function(... args) {
890
+ console.log('receive on server', args);
891
+ return ['custom response', ... args];
892
+ }
893
+ }
894
+ }]
895
+ ]
896
+ };
897
+ ```
898
+ ```js
899
+ const { test } = require('@playwright/test');
900
+ const { useState } = require('monocart-reporter');
901
+ test('state test', async ({ browserName }) => {
902
+ const state = useState({
903
+ // port: 8130
904
+ });
905
+ // send messages
906
+ const res = await state.send('string data', {});
907
+ console.log('receive on client', res);
908
+ });
909
+ ```
910
+
911
+
831
912
  ## Merge Shard Reports
832
913
  There will be multiple reports to be generated if Playwright test executes in sharding mode. for example:
833
914
  ```sh
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');
@@ -94,14 +94,17 @@ const start = function() {
94
94
  const args = process.argv.slice(2);
95
95
  const command = args.shift();
96
96
  // console.log(command, args);
97
- if (command === 'show-report') {
97
+ if (command === 'show' || command === 'show-report') {
98
98
  serveReport(args, true);
99
99
  return;
100
100
  }
101
101
 
102
- if (command === 'serve-report') {
102
+ if (command === 'serve' || command === 'serve-report') {
103
103
  serveReport(args, false);
104
+ return;
104
105
  }
106
+
107
+ EC.logRed(`Not found command: ${command}`);
105
108
  };
106
109
 
107
110
  start();
@@ -15,11 +15,11 @@ module.exports = {
15
15
  coverage: null,
16
16
  // coverage: {
17
17
  // entryFilter: (entry) => true,
18
- // unpackSourceMap: true,
19
- // excludeDistFile: true,
20
18
  // sourceFilter: (sourceName) => sourceName.search(/src\/.+/) !== -1,
21
19
  // },
22
20
 
21
+ state: null,
22
+
23
23
  // trend data handler
24
24
  trend: null,
25
25
  // trend: () => './test-results/report.json',
@@ -1,7 +1,7 @@
1
1
  const path = require('path');
2
2
  const EC = require('eight-colors');
3
3
  const CG = require('console-grid');
4
- const { nodemailer } = require('./runtime/monocart-vendor.js');
4
+ const nodemailer = require('nodemailer');
5
5
  const Util = require('./utils/util.js');
6
6
  const emailPlugin = require('./plugins/email.js');
7
7
 
package/lib/index.d.ts ADDED
@@ -0,0 +1,122 @@
1
+ import { TestInfo } from "@playwright/test"
2
+
3
+ /**
4
+ * merge
5
+ */
6
+ export function merge(
7
+ reportDataList: [],
8
+ options?: any
9
+ ): Promise<void>;
10
+
11
+ /**
12
+ * audit
13
+ */
14
+ export type AuditReportOptions = {
15
+ title?: string,
16
+ outputDir?: string,
17
+ outputName?: string
18
+ };
19
+
20
+ export function attachAuditReport(
21
+ runnerResult: any,
22
+ testInfo: TestInfo,
23
+ options?: AuditReportOptions
24
+ ): Promise<any>;
25
+
26
+
27
+ /**
28
+ * coverage
29
+ */
30
+ export function addCoverageReport(
31
+ v8list: any[],
32
+ testInfo: TestInfo
33
+ ): Promise<any | void>;
34
+
35
+ export type CoverageReportOptions = {
36
+
37
+ title?: string,
38
+ outputDir?: string,
39
+ outputName?: string,
40
+
41
+ // Whether to convert to Istanbul report
42
+ toIstanbul?: boolean,
43
+
44
+ // A filter function to execute for each element in the V8 list.
45
+ entryFilter?: (entry: any) => boolean,
46
+
47
+ // A filter function to execute for each element in the sources which unpacked from the source map.
48
+ sourceFilter?: (sourcePath: string) => boolean,
49
+
50
+ sourcePath?: (sourcePath: string) => string,
51
+
52
+ sourceFinder?: (filePath: string) => string,
53
+
54
+ // Whether to create `lcov.info`
55
+ lcov?: boolean,
56
+
57
+ watermarks?: [number, number] | {
58
+ statements: [number, number],
59
+ functions: [number, number],
60
+ branches: [number, number],
61
+ lines: [number, number]
62
+ },
63
+
64
+ // Whether inline all scripts to the single HTML file.
65
+ inline?: boolean,
66
+
67
+ debug?: boolean
68
+ };
69
+
70
+ export function attachCoverageReport(
71
+ coverage: any[] | any,
72
+ testInfo: TestInfo,
73
+ options?: CoverageReportOptions
74
+ ): Promise<any>;
75
+
76
+
77
+
78
+ /**
79
+ * network
80
+ */
81
+ export type NetworkReportOptions = {
82
+ title?: string,
83
+ outputDir?: string,
84
+ outputName?: string,
85
+
86
+ // Whether inline all scripts to the single HTML file.
87
+ inline?: boolean
88
+ };
89
+
90
+ export function attachNetworkReport(
91
+ har: string | Buffer,
92
+ testInfo: TestInfo,
93
+ options?: NetworkReportOptions
94
+ ): Promise<any>;
95
+
96
+
97
+ /**
98
+ * state
99
+ */
100
+ export type StateOptions = {
101
+ host?: string,
102
+ port?: number,
103
+ timeout?: number
104
+ };
105
+
106
+ export type State = {
107
+ get: {
108
+ (key: string): Promise<any>,
109
+ (...args: string[]): Promise<any[]>
110
+ },
111
+ set: {
112
+ (key: string, value: any): Promise<void>,
113
+ (obj: object): Promise<void>
114
+ },
115
+ remove: {
116
+ (key: string): Promise<void>,
117
+ (...args: string[]): Promise<void>
118
+ },
119
+ send: (...args: any[]) => Promise<any>
120
+ }
121
+
122
+ export function useState(options?: StateOptions): State;
package/lib/index.js CHANGED
@@ -10,18 +10,23 @@ const { attachAuditReport } = require('./plugins/audit/audit.js');
10
10
  const { addCoverageReport, attachCoverageReport } = require('./plugins/coverage/coverage.js');
11
11
  const { attachNetworkReport } = require('./plugins/network/network.js');
12
12
 
13
+ const { createStateServer, useState } = require('./plugins/state/state.js');
14
+
13
15
  // custom reporter
14
16
  // https://playwright.dev/docs/test-reporters#custom-reporters
15
17
  class Reporter {
16
18
 
17
19
  static merge = merge;
18
20
 
19
- static addCoverageReport = addCoverageReport;
20
-
21
21
  static attachAuditReport = attachAuditReport;
22
+
23
+ static addCoverageReport = addCoverageReport;
22
24
  static attachCoverageReport = attachCoverageReport;
25
+
23
26
  static attachNetworkReport = attachNetworkReport;
24
27
 
28
+ static useState = useState;
29
+
25
30
  constructor(userOptions = {}) {
26
31
 
27
32
  const timestampStart = Date.now();
@@ -41,6 +46,11 @@ class Reporter {
41
46
 
42
47
  this.tickTime = this.options.tickTime || 1000;
43
48
  this.tickStart();
49
+
50
+ const stateOptions = this.options.state;
51
+ if (stateOptions) {
52
+ this.stateServer = createStateServer(stateOptions);
53
+ }
44
54
  }
45
55
 
46
56
  printsToStdio() {
@@ -67,14 +77,14 @@ class Reporter {
67
77
  // console.log(`onBegin: ${suite.allTests().length} tests`);
68
78
  }
69
79
 
70
- // Called on some global error, for example unhandled exception in the worker process.
71
- onError(error) {
72
- // EC.logRed(error);
73
- }
74
-
75
80
  onTestBegin(test, result) {
76
81
  // console.log(`onTestBegin ${test.title}`);
77
82
 
83
+ // there maybe multiple test running at same time
84
+ // currentTest only for missing logs
85
+ // do NOT using for test info
86
+ this.currentTest = test;
87
+
78
88
  // Note that do not use this because is parallel
79
89
  if (!test.timestamps) {
80
90
  test.timestamps = [];
@@ -93,6 +103,7 @@ class Reporter {
93
103
 
94
104
  onStdErr(chunk, test, result) {
95
105
  // Note that output may happen when no test is running, in which case this will be void.
106
+ test = test || this.currentTest;
96
107
  if (test) {
97
108
  test.logs.push(EC.red(chunk));
98
109
  }
@@ -100,11 +111,23 @@ class Reporter {
100
111
 
101
112
  onStdOut(chunk, test, result) {
102
113
  // Note that output may happen when no test is running, in which case this will be void.
114
+ test = test || this.currentTest;
103
115
  if (test) {
104
116
  test.logs.push(chunk);
105
117
  }
106
118
  }
107
119
 
120
+ // Called on some global error, for example unhandled exception in the worker process.
121
+ onError(error) {
122
+ // EC.logRed(error);
123
+
124
+ // add the error to test logs
125
+ if (this.currentTest) {
126
+ this.currentTest.logs.push(EC.red(error.message));
127
+ }
128
+
129
+ }
130
+
108
131
  // onStepBegin(test, result, step)
109
132
  // onStepEnd(test, result, step)
110
133
 
@@ -123,6 +146,14 @@ class Reporter {
123
146
  }
124
147
 
125
148
  async onEnd(result) {
149
+
150
+ this.currentTest = null;
151
+
152
+ if (this.stateServer) {
153
+ await this.stateServer.close(this.config);
154
+ this.stateServer = null;
155
+ }
156
+
126
157
  // console.log(`onEnd: ${result.status}`);
127
158
  // console.log(result);
128
159
  this.tickStop();
package/lib/index.mjs CHANGED
@@ -5,8 +5,11 @@ export { MonocartReporter };
5
5
 
6
6
  export const merge = MonocartReporter.merge;
7
7
 
8
- export const addCoverageReport = MonocartReporter.addCoverageReport;
9
-
10
8
  export const attachAuditReport = MonocartReporter.attachAuditReport;
9
+
10
+ export const addCoverageReport = MonocartReporter.addCoverageReport;
11
11
  export const attachCoverageReport = MonocartReporter.attachCoverageReport;
12
+
12
13
  export const attachNetworkReport = MonocartReporter.attachNetworkReport;
14
+
15
+ export const useState = MonocartReporter.useState;
@@ -5,45 +5,30 @@ const EC = require('eight-colors');
5
5
  const Util = require('../../utils/util.js');
6
6
  const { convertV8ToIstanbul, saveIstanbulReport } = require('./istanbul/istanbul.js');
7
7
  const {
8
- initV8ListAndSourcemap, unpackV8List, mergeV8Coverage, saveV8Report
8
+ initV8ListAndSourcemap, mergeV8Coverage, saveV8Report
9
9
  } = require('./v8/v8.js');
10
10
 
11
- // ========================================================================================================
11
+ const { convertFunctionsToRanges } = require('./coverage-utils.js');
12
+ const { unpackSourceMaps } = require('./v8/source-map.js');
12
13
 
13
- const defaultV8Options = {
14
+ const defaultOptions = {
14
15
 
15
16
  // Defaults to test title
16
- // title: '',
17
+ // title
18
+ // outputDir
19
+ // outputName
17
20
 
18
21
  // (Boolean) Whether to convert to Istanbul report
19
22
  toIstanbul: false,
20
23
 
21
24
  // (Function) A filter function to execute for each element in the V8 list.
22
25
  entryFilter: null,
23
- // (Boolean) Whether to unpack all sources from the source map if a related source map file is found.
24
- unpackSourceMap: true,
25
- // (Boolean) Whether to exclude the dist file (usually minified) if the sources are successfully unpacked from the source map.
26
- excludeDistFile: true,
27
- // (Function) A filter function to execute for each element in the sources which unpacked from the source map.
28
- sourceFilter: null
29
-
30
- // (Array) Defaults to `[50, 80]`
31
- // watermarks: [50, 80],
32
-
33
- // (Boolean) Whether inline all scripts to the single HTML file.
34
- // inline: false
35
- };
36
-
37
- const defaultIstanbulOptions = {
38
26
 
39
- // Defaults to test title
40
- // title: '',
41
-
42
- // when toIstanbul = true
43
- entryFilter: null,
44
- unpackSourceMap: true,
27
+ // (Function) A filter function to execute for each element in the sources which unpacked from the source map.
45
28
  sourceFilter: null,
46
29
 
30
+ // Istanbul Only
31
+
47
32
  // source path handler
48
33
  sourcePath: null,
49
34
 
@@ -51,10 +36,34 @@ const defaultIstanbulOptions = {
51
36
  sourceFinder: null,
52
37
 
53
38
  // (Boolean) Whether to create `lcov.info`
54
- lcov: false
39
+ lcov: false,
55
40
 
56
41
  // (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report)
57
42
  // watermarks: {},
43
+ // (Array) V8 watermarks, Defaults to `[50, 80]`
44
+ // watermarks: [50, 80],
45
+
46
+ // (Boolean) Whether inline all scripts to the single HTML file. V8 only.
47
+ inline: false,
48
+
49
+ // (Boolean) The dist file which has source map will be included, and the temporary artifacts will not be removed.
50
+ debug: false
51
+ };
52
+
53
+ // ========================================================================================================
54
+
55
+ const unpackV8List = async (v8list, options) => {
56
+ v8list.forEach((item, i) => {
57
+ if (item.type === 'js') {
58
+ item.ranges = convertFunctionsToRanges(item.functions);
59
+ delete item.functions;
60
+ }
61
+ });
62
+
63
+ // requires ranges before unpack
64
+ await unpackSourceMaps(v8list, options);
65
+
66
+ // console.log(v8list.length);
58
67
  };
59
68
 
60
69
  // ========================================================================================================
@@ -77,12 +86,9 @@ const saveReportAttachment = (testInfo, report, htmlDir) => {
77
86
 
78
87
  const generateIstanbulReport = (coverageData, testInfo, options) => {
79
88
 
80
- options = {
81
- ... defaultIstanbulOptions,
82
- ... options
83
- };
89
+ const fileSources = options.fileSources || {};
84
90
 
85
- const report = saveIstanbulReport(coverageData, options.fileSources, options);
91
+ const report = saveIstanbulReport(coverageData, fileSources, options);
86
92
 
87
93
  saveReportAttachment(testInfo, report, options.htmlDir);
88
94
 
@@ -94,12 +100,6 @@ const generateIstanbulReport = (coverageData, testInfo, options) => {
94
100
 
95
101
  const generateV8Coverage = async (v8list, testInfo, options) => {
96
102
 
97
- // v8list options, also for init / source map handler
98
- options = {
99
- ... defaultV8Options,
100
- ... options
101
- };
102
-
103
103
  // init v8list and unpack sourcemap
104
104
  const inlineSourceMap = true;
105
105
  v8list = await initV8ListAndSourcemap(v8list, options, inlineSourceMap);
@@ -107,10 +107,6 @@ const generateV8Coverage = async (v8list, testInfo, options) => {
107
107
  // ================================================================
108
108
 
109
109
  if (options.toIstanbul) {
110
- options = {
111
- ... defaultIstanbulOptions,
112
- ... options
113
- };
114
110
 
115
111
  const { coverageData, fileSources } = await convertV8ToIstanbul(v8list, options);
116
112
 
@@ -121,7 +117,7 @@ const generateV8Coverage = async (v8list, testInfo, options) => {
121
117
  return report;
122
118
  }
123
119
 
124
- // ================================================================
120
+ // =================================================================
125
121
 
126
122
  // functions to ranges, and unpack source maps
127
123
  await unpackV8List(v8list, options);
@@ -141,6 +137,7 @@ const attachCoverageReport = (coverageInput, testInfo, options = {}) => {
141
137
  }
142
138
 
143
139
  options = {
140
+ ... defaultOptions,
144
141
  // default title
145
142
  title: `Coverage Report - ${testInfo.title}`,
146
143
  outputDir: Util.resolveOutputDir(testInfo),
@@ -187,7 +184,7 @@ const addCoverageReport = async (v8list, testInfo) => {
187
184
  const outputDir = path.dirname(outputFile);
188
185
 
189
186
  const options = {
190
- ... defaultV8Options,
187
+ ... defaultOptions,
191
188
  // use reporter dir as output dir, NOT test output dir
192
189
  outputDir,
193
190
  outputName: 'coverage',
@@ -237,21 +234,13 @@ const addCoverageReport = async (v8list, testInfo) => {
237
234
 
238
235
  const getGlobalCoverageData = async (dataList, options) => {
239
236
 
240
- options = {
241
- ... defaultV8Options,
242
- ... options
243
- };
244
-
245
237
  // merge v8list first
246
238
  const v8list = await mergeV8Coverage(dataList, options);
247
239
  // console.log('after merge', v8list.map((it) => it.url));
248
240
 
249
- if (options.toIstanbul) {
241
+ // ================================================================
250
242
 
251
- options = {
252
- ... defaultIstanbulOptions,
253
- ... options
254
- };
243
+ if (options.toIstanbul) {
255
244
 
256
245
  const { coverageData, fileSources } = await convertV8ToIstanbul(v8list, options);
257
246
 
@@ -262,6 +251,8 @@ const getGlobalCoverageData = async (dataList, options) => {
262
251
  return report;
263
252
  }
264
253
 
254
+ // ================================================================
255
+
265
256
  // functions to ranges, and unpack source maps
266
257
  await unpackV8List(v8list, options);
267
258
 
@@ -279,6 +270,7 @@ const generateGlobalCoverageReport = async (dataList, reporterOptions) => {
279
270
 
280
271
  const coverageOptions = reporterOptions.coverage || {};
281
272
  const options = {
273
+ ... defaultOptions,
282
274
  title: `Coverage Report - ${reporterOptions.name}`,
283
275
  outputDir,
284
276
  outputName: 'coverage',