monocart-reporter 1.6.24 → 1.6.26
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 +31 -10
- package/lib/default/options.js +4 -1
- package/lib/default/template.html +36 -1
- package/lib/generate-data.js +1 -0
- package/lib/platform/share.js +0 -24
- package/lib/plugins/comments.js +8 -4
- package/lib/plugins/coverage/coverage-utils.js +154 -0
- package/lib/plugins/coverage/coverage.js +97 -75
- package/lib/plugins/coverage/istanbul/istanbul.js +143 -24
- package/lib/plugins/coverage/v8/dedupe.js +64 -59
- package/lib/plugins/coverage/v8/position-mapping.js +49 -35
- package/lib/plugins/coverage/v8/source-map.js +218 -245
- package/lib/plugins/coverage/v8/v8-summary.js +9 -18
- package/lib/plugins/coverage/v8/v8.js +55 -96
- package/lib/runtime/monocart-code-viewer.js +1 -1
- package/lib/runtime/monocart-coverage.js +11 -11
- package/lib/runtime/monocart-formatter.js +1 -1
- package/lib/runtime/monocart-network.js +1 -1
- package/lib/runtime/monocart-reporter.js +1 -1
- package/lib/runtime/monocart-v8.js +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
* [Playwright Config](#playwright-config)
|
|
19
19
|
* [Examples](#examples)
|
|
20
20
|
* [Output](#output) HTML and JSON
|
|
21
|
-
* [View Trace Online](#view-trace-online)
|
|
22
21
|
* [Reporter Options](#reporter-options)
|
|
22
|
+
* [View Trace Online](#view-trace-online)
|
|
23
23
|
* [Custom Columns](#custom-columns) (Extra properties for suite/case/step)
|
|
24
24
|
- [Custom Formatter](#custom-formatter)
|
|
25
25
|
- [Searchable Fields](#searchable-fields)
|
|
@@ -105,12 +105,6 @@ module.exports = {
|
|
|
105
105
|
- path-to/your-filename.json
|
|
106
106
|
Separated metadata file (Already included in the above HTML and compressed, it can be deleted). Can be used for debugging or custom data collection.
|
|
107
107
|
|
|
108
|
-
## View Trace Online
|
|
109
|
-
> The [Trace Viewer](https://trace.playwright.dev/) requires that the trace file must be loaded over the http:// or https:// protocols without [CORS](https://developer.mozilla.org/en-US/docs/Glossary/CORS) issue, try following start a local web server:
|
|
110
|
-
```sh
|
|
111
|
-
npx monocart show-report <your-outputFile-path>
|
|
112
|
-
```
|
|
113
|
-
|
|
114
108
|
## Reporter Options
|
|
115
109
|
```js
|
|
116
110
|
{
|
|
@@ -124,6 +118,17 @@ npx monocart show-report <your-outputFile-path>
|
|
|
124
118
|
attachmentPath: null,
|
|
125
119
|
// attachmentPath: (currentPath, extras) => `https://another-path/${currentPath}`,
|
|
126
120
|
|
|
121
|
+
traceViewerUrl: 'https://trace.playwright.dev/?trace={traceUrl}',
|
|
122
|
+
|
|
123
|
+
// global coverage settings for addCoverageReport API
|
|
124
|
+
coverage: null,
|
|
125
|
+
// coverage: {
|
|
126
|
+
// entryFilter: (entry) => true,
|
|
127
|
+
// unpackSourceMap: true,
|
|
128
|
+
// excludeDistFile: true,
|
|
129
|
+
// sourceFilter: (sourceName) => sourceName.search(/\/src\/.+/) !== -1,
|
|
130
|
+
// },
|
|
131
|
+
|
|
127
132
|
// trend data handler
|
|
128
133
|
trend: null,
|
|
129
134
|
// trend: () => './test-results/report.json',
|
|
@@ -153,6 +158,13 @@ npx monocart show-report <your-outputFile-path>
|
|
|
153
158
|
}
|
|
154
159
|
```
|
|
155
160
|
|
|
161
|
+
## View Trace Online
|
|
162
|
+
> The [Trace Viewer](https://trace.playwright.dev/) requires that the trace file must be loaded over the http:// or https:// protocols without [CORS](https://developer.mozilla.org/en-US/docs/Glossary/CORS) issue, try following start a local web server:
|
|
163
|
+
```sh
|
|
164
|
+
npx monocart show-report <your-outputFile-path>
|
|
165
|
+
```
|
|
166
|
+
Or customize your own trace viewer url with option `traceViewerUrl` defaults to `https://trace.playwright.dev/?trace={traceUrl}`
|
|
167
|
+
|
|
156
168
|
## Custom Columns
|
|
157
169
|
The report will be displayed in a `Tree Grid`. The `columns` function is used to customize the grid columns. The column properties following:
|
|
158
170
|
- `id` (String) Column id (required)
|
|
@@ -624,8 +636,17 @@ Attach a code coverage report with API `attachCoverageReport(data, testInfo, opt
|
|
|
624
636
|
- `data` There are two supported data inputs `Istanbul` (Object) or `V8` (Array)
|
|
625
637
|
- `testInfo` see [TestInfo](https://playwright.dev/docs/api/class-testinfo)
|
|
626
638
|
- `options` (Object)
|
|
627
|
-
-
|
|
628
|
-
- `
|
|
639
|
+
- Istanbul only:
|
|
640
|
+
- `watermarks` (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report)
|
|
641
|
+
- `lcov` (Boolean) Whether to create `lcov.info`
|
|
642
|
+
- V8 only:
|
|
643
|
+
- `toIstanbul` (Boolean) Whether to convert to Istanbul report
|
|
644
|
+
- `watermarks` (Array) Defaults to `[50, 80]`
|
|
645
|
+
- `entryFilter` (Function) A filter function to execute for each element in the V8 list.
|
|
646
|
+
- `unpackSourceMap` (Boolean) Whether to unpack all sources from the source map if a related source map file is found.
|
|
647
|
+
- `excludeDistFile` (Boolean) Whether to exclude the dist file (usually minified) if the sources are successfully unpacked from the source map.
|
|
648
|
+
- `sourceFilter` (Function) A filter function to execute for each element in the sources which unpacked from the source map.
|
|
649
|
+
- `inline` (Boolean) Whether inline all scripts to the single HTML file.
|
|
629
650
|
|
|
630
651
|
(see example: [report-coverage.spec.js](https://github.com/cenfun/monocart-reporter/blob/main/tests/report-coverage/report-coverage.spec.js))
|
|
631
652
|
|
|
@@ -737,10 +758,10 @@ module.exports = {
|
|
|
737
758
|
outputFile: './test-results/report.html',
|
|
738
759
|
// global coverage report options
|
|
739
760
|
coverage: {
|
|
761
|
+
entryFilter: (entry) => true,
|
|
740
762
|
unpackSourceMap: true,
|
|
741
763
|
excludeDistFile: true,
|
|
742
764
|
sourceFilter: (sourceName) => sourceName.search(/\/src\/.+/) !== -1,
|
|
743
|
-
entryFilter: (entry) => {}
|
|
744
765
|
}
|
|
745
766
|
}]
|
|
746
767
|
]
|
package/lib/default/options.js
CHANGED
|
@@ -9,12 +9,15 @@ module.exports = {
|
|
|
9
9
|
attachmentPath: null,
|
|
10
10
|
// attachmentPath: (currentPath, extras) => `https://cenfun.github.io/monocart-reporter/${currentPath}`,
|
|
11
11
|
|
|
12
|
+
traceViewerUrl: 'https://trace.playwright.dev/?trace={traceUrl}',
|
|
13
|
+
|
|
12
14
|
// global coverage settings for addCoverageReport API
|
|
13
15
|
coverage: null,
|
|
14
16
|
// coverage: {
|
|
17
|
+
// entryFilter: (entry) => true,
|
|
15
18
|
// unpackSourceMap: true,
|
|
19
|
+
// excludeDistFile: true,
|
|
16
20
|
// sourceFilter: (sourceName) => sourceName.search(/\/src\/.+/) !== -1,
|
|
17
|
-
// entryFilter: (entry) => {}
|
|
18
21
|
// },
|
|
19
22
|
|
|
20
23
|
// trend data handler
|
|
@@ -2,11 +2,46 @@
|
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<link rel="icon" href="data:,">
|
|
7
7
|
<title>{title}</title>
|
|
8
|
+
<style>
|
|
9
|
+
@keyframes fs-loading-animation {
|
|
10
|
+
0% {
|
|
11
|
+
transform: rotate(0deg);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
100% {
|
|
15
|
+
transform: rotate(360deg);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.fs-loading {
|
|
20
|
+
position: absolute;
|
|
21
|
+
top: 50%;
|
|
22
|
+
left: 50%;
|
|
23
|
+
z-index: 100;
|
|
24
|
+
width: 50px;
|
|
25
|
+
height: 50px;
|
|
26
|
+
margin-top: -25px;
|
|
27
|
+
margin-left: -25px;
|
|
28
|
+
animation: 0.382s fs-loading-animation linear infinite;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.fs-loading svg {
|
|
32
|
+
display: block;
|
|
33
|
+
width: 100%;
|
|
34
|
+
height: 100%;
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
8
38
|
</head>
|
|
9
39
|
<body>
|
|
40
|
+
<div class="fs-loading">
|
|
41
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
|
42
|
+
<path d="M1,8 A7 7 0 1 1 8 15" stroke="#999" stroke-width="2" stroke-linecap="round" fill="none"/>
|
|
43
|
+
</svg>
|
|
44
|
+
</div>
|
|
10
45
|
{content}
|
|
11
46
|
</body>
|
|
12
47
|
</html>
|
package/lib/generate-data.js
CHANGED
|
@@ -74,6 +74,7 @@ const generateData = async (results) => {
|
|
|
74
74
|
// suite and case types
|
|
75
75
|
data.suiteTypes = ['project', 'file', 'describe', 'shard'];
|
|
76
76
|
data.caseTypes = ['passed', 'flaky', 'skipped', 'failed'];
|
|
77
|
+
data.traceViewerUrl = options.traceViewerUrl;
|
|
77
78
|
|
|
78
79
|
calculateSummary(data, options);
|
|
79
80
|
|
package/lib/platform/share.js
CHANGED
|
@@ -158,30 +158,6 @@ const Util = {
|
|
|
158
158
|
return info;
|
|
159
159
|
},
|
|
160
160
|
|
|
161
|
-
getFlatRanges: (functions) => {
|
|
162
|
-
const flatRanges = [];
|
|
163
|
-
if (functions && functions.length) {
|
|
164
|
-
functions.forEach((fun) => {
|
|
165
|
-
const ranges = fun.ranges;
|
|
166
|
-
if (ranges && ranges.length) {
|
|
167
|
-
ranges.forEach((range) => {
|
|
168
|
-
flatRanges.push(range);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
flatRanges.sort((a, b) => {
|
|
173
|
-
if (a.startOffset === b.startOffset) {
|
|
174
|
-
if (a.endOffset === b.endOffset) {
|
|
175
|
-
return a.count - b.count;
|
|
176
|
-
}
|
|
177
|
-
return a.endOffset - b.endOffset;
|
|
178
|
-
}
|
|
179
|
-
return a.startOffset - b.startOffset;
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
return flatRanges;
|
|
183
|
-
},
|
|
184
|
-
|
|
185
161
|
isTagItem: (item) => {
|
|
186
162
|
if (item.type === 'case' || (item.type === 'suite' && item.suiteType === 'describe')) {
|
|
187
163
|
return true;
|
package/lib/plugins/comments.js
CHANGED
|
@@ -6,10 +6,14 @@ const Util = require('../utils/util.js');
|
|
|
6
6
|
const cacheMap = new Map();
|
|
7
7
|
|
|
8
8
|
function getEmptyLines(lines) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const emptyLines = [];
|
|
10
|
+
const reg = /\S/;
|
|
11
|
+
lines.forEach((text, i) => {
|
|
12
|
+
if (!reg.test(text)) {
|
|
13
|
+
emptyLines.push(i + 1);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
return emptyLines;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
const getFileComments = (filePath, parserOptions = {}) => {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const Util = require('../../utils/util.js');
|
|
2
|
+
const Concurrency = require('../../platform/concurrency.js');
|
|
3
|
+
const { convertSourceMap, axios } = require('../../runtime/monocart-coverage.js');
|
|
4
|
+
|
|
5
|
+
const sortRanges = (ranges) => {
|
|
6
|
+
ranges.sort((a, b) => {
|
|
7
|
+
if (a.start === b.start) {
|
|
8
|
+
return a.end - b.end;
|
|
9
|
+
}
|
|
10
|
+
return a.start - b.start;
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const resolveUrl = (input) => {
|
|
15
|
+
let url;
|
|
16
|
+
try {
|
|
17
|
+
url = new URL(input);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
// console.error('error url', input);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
return url;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const filterPath = (str) => {
|
|
26
|
+
str = decodeURI(str);
|
|
27
|
+
// remove / of start, end or double, ./ ../
|
|
28
|
+
const ls = str.split('/').map((it) => {
|
|
29
|
+
it = it.trim();
|
|
30
|
+
// remove illegal characters except /
|
|
31
|
+
it = it.replace(/[\\:*?"<>|]/g, '');
|
|
32
|
+
// space
|
|
33
|
+
it = it.replace(/\s+/g, '-');
|
|
34
|
+
return it;
|
|
35
|
+
}).filter((item) => {
|
|
36
|
+
if (!item || item === '.' || item === '..') {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
});
|
|
41
|
+
return ls.join('/');
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getSourcePath = (url, index = '', type = '') => {
|
|
45
|
+
|
|
46
|
+
if (!url) {
|
|
47
|
+
// anonymous scripts will have __playwright_evaluation_script__ as their URL.
|
|
48
|
+
url = ['file://anonymous', index ? `-${index}` : '', type ? `.${type}` : ''].join('');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const u = resolveUrl(url);
|
|
52
|
+
if (u) {
|
|
53
|
+
const host = [u.hostname, u.port].filter((it) => it).join('-');
|
|
54
|
+
// always start with '/'
|
|
55
|
+
const pathname = u.pathname;
|
|
56
|
+
|
|
57
|
+
let p = host + pathname;
|
|
58
|
+
// webpack://monocart-v8/packages/v8/src/app.vue?5cc4
|
|
59
|
+
if (u.search) {
|
|
60
|
+
p += `/${u.search}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return filterPath(p);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const relPath = Util.relativePath(url);
|
|
67
|
+
return filterPath(relPath);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// ================================================================================================
|
|
71
|
+
|
|
72
|
+
const request = async (options) => {
|
|
73
|
+
if (typeof options === 'string') {
|
|
74
|
+
options = {
|
|
75
|
+
url: options
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
let err;
|
|
79
|
+
const res = await axios(options).catch((e) => {
|
|
80
|
+
err = e;
|
|
81
|
+
});
|
|
82
|
+
return [err, res];
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const getSourceMapUrl = (content, url) => {
|
|
86
|
+
|
|
87
|
+
const m = content.match(convertSourceMap.mapFileCommentRegex);
|
|
88
|
+
if (!m) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const comment = m.pop();
|
|
93
|
+
const r = convertSourceMap.mapFileCommentRegex.exec(comment);
|
|
94
|
+
// for some odd reason //# .. captures in 1 and /* .. */ in 2
|
|
95
|
+
const filename = r[1] || r[2];
|
|
96
|
+
|
|
97
|
+
let mapUrl;
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
mapUrl = new URL(filename, url);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
// console.log(e)
|
|
103
|
+
}
|
|
104
|
+
if (mapUrl) {
|
|
105
|
+
return mapUrl.toString();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const resolveSourceMap = (data) => {
|
|
110
|
+
if (data) {
|
|
111
|
+
const { sources, sourcesContent } = data;
|
|
112
|
+
if (!sources || !sourcesContent) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const collectSourceMaps = async (v8list) => {
|
|
120
|
+
const concurrency = new Concurrency();
|
|
121
|
+
for (const item of v8list) {
|
|
122
|
+
// useless for css
|
|
123
|
+
if (item.type === 'css') {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const source = item.source;
|
|
128
|
+
const converter = convertSourceMap.fromSource(source);
|
|
129
|
+
if (converter) {
|
|
130
|
+
item.sourceMap = resolveSourceMap(converter.sourcemap);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const sourceMapUrl = getSourceMapUrl(source, item.url);
|
|
134
|
+
if (sourceMapUrl) {
|
|
135
|
+
item.sourceMapUrl = sourceMapUrl;
|
|
136
|
+
concurrency.addItem(item);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
await concurrency.start(async (item) => {
|
|
140
|
+
const [err, res] = await request({
|
|
141
|
+
url: item.sourceMapUrl
|
|
142
|
+
});
|
|
143
|
+
if (!err && res) {
|
|
144
|
+
item.sourceMap = resolveSourceMap(res.data);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
module.exports = {
|
|
151
|
+
sortRanges,
|
|
152
|
+
getSourcePath,
|
|
153
|
+
collectSourceMaps
|
|
154
|
+
};
|
|
@@ -4,7 +4,9 @@ const EC = require('eight-colors');
|
|
|
4
4
|
|
|
5
5
|
const Util = require('../../utils/util.js');
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
convertV8ToIstanbul, mergeIstanbulList, saveIstanbulReport
|
|
9
|
+
} = require('./istanbul/istanbul.js');
|
|
8
10
|
|
|
9
11
|
const {
|
|
10
12
|
initV8List, mergeV8List, saveV8Report
|
|
@@ -12,31 +14,40 @@ const {
|
|
|
12
14
|
|
|
13
15
|
// ========================================================================================================
|
|
14
16
|
|
|
15
|
-
// high performance
|
|
16
|
-
// str.search(reg) -> index
|
|
17
|
-
// reg.test(str) -> boolean
|
|
18
|
-
const defaultSourceFilter = (sourceName) => {
|
|
19
|
-
// sourceName.search(/\/src\/.+/) !== -1
|
|
20
|
-
return true;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
17
|
const defaultV8Options = {
|
|
18
|
+
// (Boolean) Whether to convert to Istanbul report
|
|
24
19
|
toIstanbul: false,
|
|
25
20
|
|
|
21
|
+
// (Function) A filter function to execute for each element in the V8 list.
|
|
22
|
+
entryFilter: null,
|
|
23
|
+
// (Boolean) Whether to unpack all sources from the source map if a related source map file is found.
|
|
26
24
|
unpackSourceMap: true,
|
|
25
|
+
// (Boolean) Whether to exclude the dist file (usually minified) if the sources are successfully unpacked from the source map.
|
|
27
26
|
excludeDistFile: true,
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
// (Function) A filter function to execute for each element in the sources which unpacked from the source map.
|
|
28
|
+
sourceFilter: null
|
|
30
29
|
|
|
30
|
+
// (Array) Defaults to `[50, 80]`
|
|
31
31
|
// watermarks: [50, 80],
|
|
32
|
+
|
|
33
|
+
// (Boolean) Whether inline all scripts to the single HTML file.
|
|
32
34
|
// inline: false
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
const defaultIstanbulOptions = {
|
|
38
|
+
|
|
39
|
+
// when toIstanbul = true
|
|
36
40
|
entryFilter: null,
|
|
41
|
+
unpackSourceMap: true,
|
|
42
|
+
sourceFilter: null,
|
|
43
|
+
|
|
44
|
+
// (usually not used) source finder for Istanbul HTML report
|
|
37
45
|
sourceFinder: null,
|
|
46
|
+
|
|
47
|
+
// (Boolean) Whether to create `lcov.info`
|
|
38
48
|
lcov: false
|
|
39
49
|
|
|
50
|
+
// (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report)
|
|
40
51
|
// watermarks: {},
|
|
41
52
|
};
|
|
42
53
|
|
|
@@ -58,42 +69,51 @@ const saveReportAttachment = (testInfo, report, htmlDir) => {
|
|
|
58
69
|
|
|
59
70
|
// ========================================================================================================
|
|
60
71
|
|
|
61
|
-
const generateIstanbulReport = (
|
|
72
|
+
const generateIstanbulReport = (coverageData, testInfo, options) => {
|
|
62
73
|
|
|
63
74
|
options = {
|
|
64
75
|
... defaultIstanbulOptions,
|
|
65
76
|
... options
|
|
66
77
|
};
|
|
67
78
|
|
|
68
|
-
const report = saveIstanbulReport(
|
|
79
|
+
const report = saveIstanbulReport(coverageData, options.fileSources, options);
|
|
69
80
|
|
|
70
81
|
saveReportAttachment(testInfo, report, options.htmlDir);
|
|
71
82
|
|
|
72
83
|
return report;
|
|
73
84
|
};
|
|
74
85
|
|
|
86
|
+
|
|
75
87
|
// ========================================================================================================
|
|
76
88
|
|
|
77
|
-
const
|
|
89
|
+
const generateV8Coverage = async (v8list, testInfo, options) => {
|
|
78
90
|
|
|
91
|
+
// v8list options, also for init / source map handler
|
|
79
92
|
options = {
|
|
80
|
-
...
|
|
93
|
+
... defaultV8Options,
|
|
81
94
|
... options
|
|
82
95
|
};
|
|
83
96
|
|
|
84
|
-
|
|
97
|
+
// ================================================================
|
|
85
98
|
|
|
86
|
-
|
|
99
|
+
if (options.toIstanbul) {
|
|
100
|
+
options = {
|
|
101
|
+
... defaultIstanbulOptions,
|
|
102
|
+
... options
|
|
103
|
+
};
|
|
87
104
|
|
|
88
|
-
|
|
89
|
-
};
|
|
105
|
+
const { coverageData, fileSources } = await convertV8ToIstanbul(v8list, options);
|
|
90
106
|
|
|
91
|
-
|
|
107
|
+
const report = await saveIstanbulReport(coverageData, fileSources, options);
|
|
92
108
|
|
|
109
|
+
saveReportAttachment(testInfo, report, options.htmlDir);
|
|
93
110
|
|
|
94
|
-
|
|
111
|
+
return report;
|
|
112
|
+
}
|
|
95
113
|
|
|
96
|
-
|
|
114
|
+
// ================================================================
|
|
115
|
+
|
|
116
|
+
v8list = await initV8List(v8list, options);
|
|
97
117
|
|
|
98
118
|
const report = await saveV8Report(v8list, options);
|
|
99
119
|
|
|
@@ -102,31 +122,6 @@ const generateV8Report = async (v8list, testInfo, options) => {
|
|
|
102
122
|
return report;
|
|
103
123
|
};
|
|
104
124
|
|
|
105
|
-
// ========================================================================================================
|
|
106
|
-
|
|
107
|
-
const generateV8Coverage = async (v8list, testInfo, options) => {
|
|
108
|
-
|
|
109
|
-
// v8list options, also for init / source map handler
|
|
110
|
-
options = {
|
|
111
|
-
... defaultV8Options,
|
|
112
|
-
... options
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
v8list = await initV8List(v8list, options);
|
|
116
|
-
|
|
117
|
-
if (options.toIstanbul) {
|
|
118
|
-
return toIstanbulReport(v8list, testInfo, options);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return generateV8Report(v8list, testInfo, options);
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* @parameters
|
|
126
|
-
* (@input istanbul.__coverage__: Object, testInfo, options: { watermarks: {} }) -> @output istanbul report
|
|
127
|
-
* (@input v8list: Array, testInfo, options: { toIstanbul: true, watermarks: {} }) -> @output istanbul report (without css supported)
|
|
128
|
-
* (@input v8list: Array, testInfo, options: { watermarks: [], inline: Boolean }) -> @output v8 report (css supported and minified code formatting)
|
|
129
|
-
*/
|
|
130
125
|
const attachCoverageReport = (coverageInput, testInfo, options = {}) => {
|
|
131
126
|
|
|
132
127
|
if (!coverageInput) {
|
|
@@ -135,6 +130,7 @@ const attachCoverageReport = (coverageInput, testInfo, options = {}) => {
|
|
|
135
130
|
}
|
|
136
131
|
|
|
137
132
|
options = {
|
|
133
|
+
title: `Coverage Report - ${testInfo.title}`,
|
|
138
134
|
outputDir: Util.resolveOutputDir(testInfo),
|
|
139
135
|
outputName: `coverage-${Util.shortTestId(testInfo.testId)}`,
|
|
140
136
|
... options
|
|
@@ -157,10 +153,25 @@ const attachCoverageReport = (coverageInput, testInfo, options = {}) => {
|
|
|
157
153
|
|
|
158
154
|
// ========================================================================================================
|
|
159
155
|
|
|
160
|
-
|
|
161
|
-
|
|
156
|
+
const generateArtifactData = (v8list, options) => {
|
|
157
|
+
options = {
|
|
158
|
+
... defaultV8Options,
|
|
159
|
+
... options
|
|
160
|
+
};
|
|
161
|
+
if (options.toIstanbul) {
|
|
162
|
+
options = {
|
|
163
|
+
... defaultIstanbulOptions,
|
|
164
|
+
... options
|
|
165
|
+
};
|
|
166
|
+
return convertV8ToIstanbul(v8list, options);
|
|
167
|
+
}
|
|
168
|
+
return initV8List(v8list, options);
|
|
169
|
+
};
|
|
162
170
|
|
|
163
|
-
|
|
171
|
+
// add coverage report to global, v8list only
|
|
172
|
+
const addCoverageReport = async (coverageInput, testInfo) => {
|
|
173
|
+
|
|
174
|
+
if (!coverageInput) {
|
|
164
175
|
EC.logRed('[MCR] invalid coverage input');
|
|
165
176
|
return;
|
|
166
177
|
}
|
|
@@ -176,33 +187,29 @@ const addCoverageReport = async (v8list, testInfo) => {
|
|
|
176
187
|
// use reporter dir as output dir, NOT test output dir
|
|
177
188
|
outputDir,
|
|
178
189
|
outputName: 'coverage',
|
|
179
|
-
|
|
180
|
-
... defaultV8Options,
|
|
181
190
|
... coverageOptions
|
|
182
191
|
};
|
|
183
192
|
|
|
184
|
-
// The source map must be fetched before page closed
|
|
185
|
-
// or it may be deleted
|
|
186
|
-
v8list = await initV8List(v8list, options);
|
|
187
|
-
|
|
188
193
|
const id = Util.shortTestId(testInfo.testId);
|
|
189
194
|
const filename = `artifact-${id}.json`;
|
|
190
195
|
const jsonDir = path.resolve(options.outputDir, options.outputName);
|
|
191
196
|
const jsonPath = path.resolve(jsonDir, filename);
|
|
192
197
|
|
|
198
|
+
const data = await generateArtifactData(coverageInput, options);
|
|
199
|
+
|
|
200
|
+
// console.log('addCoverageReport keys', Object.keys(data.coverageData));
|
|
201
|
+
|
|
193
202
|
const report = {
|
|
194
203
|
id,
|
|
195
|
-
title: testInfo.title,
|
|
196
204
|
outputFile: Util.relativePath(jsonPath),
|
|
197
|
-
|
|
198
|
-
type: 'v8',
|
|
199
|
-
data: v8list
|
|
205
|
+
data
|
|
200
206
|
};
|
|
201
207
|
|
|
202
208
|
const artifactContent = JSON.stringify({
|
|
203
209
|
type: 'coverage',
|
|
204
210
|
data: report
|
|
205
211
|
});
|
|
212
|
+
|
|
206
213
|
await Util.writeFile(jsonPath, artifactContent);
|
|
207
214
|
|
|
208
215
|
const definition = Util.attachments.artifact;
|
|
@@ -215,6 +222,34 @@ const addCoverageReport = async (v8list, testInfo) => {
|
|
|
215
222
|
return report;
|
|
216
223
|
};
|
|
217
224
|
|
|
225
|
+
// ========================================================================================================
|
|
226
|
+
|
|
227
|
+
const generateGlobalCoverageReport = async (dataList, options) => {
|
|
228
|
+
|
|
229
|
+
options = {
|
|
230
|
+
... defaultV8Options,
|
|
231
|
+
... options
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
if (options.toIstanbul) {
|
|
235
|
+
options = {
|
|
236
|
+
... defaultIstanbulOptions,
|
|
237
|
+
... options
|
|
238
|
+
};
|
|
239
|
+
const istanbulList = dataList.map((it) => it.data);
|
|
240
|
+
const { coverageData, fileSources } = mergeIstanbulList(istanbulList);
|
|
241
|
+
return saveIstanbulReport(coverageData, fileSources, options);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let v8list = [];
|
|
245
|
+
dataList.forEach((item) => {
|
|
246
|
+
v8list = v8list.concat(item.data);
|
|
247
|
+
});
|
|
248
|
+
// merge list again for multiple v8list, maybe collected multiple times
|
|
249
|
+
v8list = await mergeV8List(v8list, options);
|
|
250
|
+
return saveV8Report(v8list, options);
|
|
251
|
+
};
|
|
252
|
+
|
|
218
253
|
// global coverage report, run different process with addCoverageReport
|
|
219
254
|
const generateCoverageReport = async (dataList, reporterOptions) => {
|
|
220
255
|
|
|
@@ -224,6 +259,7 @@ const generateCoverageReport = async (dataList, reporterOptions) => {
|
|
|
224
259
|
|
|
225
260
|
const coverageOptions = reporterOptions.coverage || {};
|
|
226
261
|
const options = {
|
|
262
|
+
title: `Coverage Report - ${reporterOptions.name}`,
|
|
227
263
|
outputDir,
|
|
228
264
|
outputName: 'coverage',
|
|
229
265
|
... coverageOptions
|
|
@@ -237,21 +273,7 @@ const generateCoverageReport = async (dataList, reporterOptions) => {
|
|
|
237
273
|
}
|
|
238
274
|
options.htmlDir = htmlDir;
|
|
239
275
|
|
|
240
|
-
|
|
241
|
-
dataList.forEach((item) => {
|
|
242
|
-
v8list = v8list.concat(item.data);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
// merge list again for multiple v8list, maybe collected multiple times
|
|
246
|
-
v8list = await mergeV8List(v8list, options);
|
|
247
|
-
|
|
248
|
-
// const v8Path = path.resolve(__dirname, '../../.temp/v8-data.js');
|
|
249
|
-
// const v8Data = `module.exports = ${JSON.stringify(v8list, null, 4)};`;
|
|
250
|
-
// fs.writeFileSync(v8Path, v8Data);
|
|
251
|
-
|
|
252
|
-
options.title = `Coverage Report - ${reporterOptions.name}`;
|
|
253
|
-
|
|
254
|
-
const report = await saveV8Report(v8list, options);
|
|
276
|
+
const report = await generateGlobalCoverageReport(dataList, options);
|
|
255
277
|
|
|
256
278
|
return {
|
|
257
279
|
type: 'coverage',
|