monocart-reporter 1.6.33 → 1.6.35
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 +50 -53
- package/lib/cli.js +10 -3
- package/lib/generate-data.js +7 -4
- package/lib/plugins/audit/audit.js +3 -6
- package/lib/plugins/coverage/coverage-utils.js +33 -71
- package/lib/plugins/coverage/coverage.js +84 -61
- package/lib/plugins/coverage/istanbul/istanbul.js +25 -51
- package/lib/plugins/coverage/v8/dedupe.js +8 -17
- package/lib/plugins/coverage/v8/source-map.js +187 -21
- package/lib/plugins/coverage/v8/v8.js +132 -91
- package/lib/plugins/network/network.js +7 -7
- package/lib/runtime/monocart-common.js +1 -1
- package/lib/runtime/monocart-coverage.js +14 -11
- 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/lib/utils/util.js +15 -0
- package/lib/visitor.js +17 -9
- package/package.json +5 -3
|
@@ -1,131 +1,171 @@
|
|
|
1
|
-
const
|
|
1
|
+
const EC = require('eight-colors');
|
|
2
|
+
|
|
2
3
|
const Util = require('../../../utils/util.js');
|
|
3
|
-
const { unpackSourceMaps } = require('./source-map.js');
|
|
4
4
|
const { getV8Summary } = require('./v8-summary.js');
|
|
5
|
-
const {
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const initCountRanges = (functions) => {
|
|
10
|
-
const ranges = [];
|
|
11
|
-
|
|
12
|
-
for (const fun of functions) {
|
|
13
|
-
if (fun.ranges) {
|
|
14
|
-
for (const range of fun.ranges) {
|
|
15
|
-
// rename startOffset/endOffset to start/end, keep count
|
|
16
|
-
ranges.push({
|
|
17
|
-
start: range.startOffset,
|
|
18
|
-
end: range.endOffset,
|
|
19
|
-
count: range.count
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
5
|
+
const { dedupeRanges } = require('./dedupe.js');
|
|
6
|
+
const { getSourcePath, convertFunctionsToRanges } = require('../coverage-utils.js');
|
|
7
|
+
const { collectSourceMaps, unpackSourceMaps } = require('./source-map.js');
|
|
8
|
+
const { mergeScriptCovs } = require('../../../runtime/monocart-coverage.js');
|
|
24
9
|
|
|
25
|
-
sortRanges(ranges);
|
|
26
10
|
|
|
27
|
-
|
|
28
|
-
ranges
|
|
29
|
-
};
|
|
30
|
-
};
|
|
11
|
+
// ========================================================================================================
|
|
31
12
|
|
|
32
|
-
|
|
33
|
-
const initV8List = async (v8list, options) => {
|
|
13
|
+
const initV8ListAndSourcemap = async (v8list, options, inlineSourceMap) => {
|
|
34
14
|
|
|
35
|
-
// filter list
|
|
15
|
+
// filter list first
|
|
36
16
|
const entryFilter = options.entryFilter;
|
|
37
17
|
if (typeof entryFilter === 'function') {
|
|
38
18
|
v8list = v8list.filter(entryFilter);
|
|
39
19
|
}
|
|
40
20
|
|
|
41
|
-
// filter no source or text
|
|
42
|
-
|
|
21
|
+
// filter no source or text
|
|
22
|
+
// init type and css source from text
|
|
23
|
+
// keep functions
|
|
24
|
+
|
|
25
|
+
v8list = v8list.filter((item) => {
|
|
43
26
|
if (typeof item.source === 'string' && item.functions) {
|
|
44
|
-
|
|
45
|
-
url, source, functions
|
|
46
|
-
} = item;
|
|
47
|
-
|
|
48
|
-
// functions to ranges
|
|
49
|
-
const { ranges } = initCountRanges(functions);
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
url,
|
|
53
|
-
type: 'js',
|
|
54
|
-
ranges,
|
|
55
|
-
source
|
|
56
|
-
};
|
|
27
|
+
return true;
|
|
57
28
|
}
|
|
58
29
|
if (typeof item.text === 'string' && item.ranges) {
|
|
59
|
-
|
|
60
|
-
url, text, ranges
|
|
61
|
-
} = item;
|
|
62
|
-
// rename text to source
|
|
63
|
-
return {
|
|
64
|
-
url,
|
|
65
|
-
type: 'css',
|
|
66
|
-
ranges,
|
|
67
|
-
source: text
|
|
68
|
-
};
|
|
30
|
+
return true;
|
|
69
31
|
}
|
|
70
32
|
// 404 css, text will be empty
|
|
71
33
|
// EC.logRed(`[MCR] Invalid source: ${item.url}`);
|
|
72
34
|
// console.log(item);
|
|
73
|
-
})
|
|
35
|
+
});
|
|
74
36
|
|
|
75
|
-
// unpack source maps if options.unpackSourceMap = true
|
|
76
|
-
await unpackSourceMaps(v8list, options);
|
|
77
37
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
38
|
+
// do not change original v8list, to work for multiple APIs
|
|
39
|
+
|
|
40
|
+
// init id, sourcePath
|
|
41
|
+
v8list = v8list.map((item, i) => {
|
|
42
|
+
|
|
43
|
+
const data = {
|
|
44
|
+
url: item.url
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (item.functions) {
|
|
48
|
+
data.type = 'js';
|
|
49
|
+
data.functions = item.functions;
|
|
50
|
+
data.source = item.source;
|
|
51
|
+
// useless here
|
|
52
|
+
// data.scriptId = item.scriptId;
|
|
53
|
+
} else if (item.ranges) {
|
|
54
|
+
data.type = 'css';
|
|
55
|
+
data.ranges = item.ranges;
|
|
56
|
+
data.source = item.text;
|
|
82
57
|
}
|
|
83
|
-
|
|
84
|
-
|
|
58
|
+
|
|
59
|
+
data.id = Util.calculateSha1(data.url + data.source);
|
|
60
|
+
data.sourcePath = getSourcePath(data.url, i + 1, data.type);
|
|
61
|
+
|
|
62
|
+
return data;
|
|
85
63
|
});
|
|
86
64
|
|
|
87
|
-
|
|
65
|
+
// collect sourcemap first
|
|
66
|
+
await collectSourceMaps(v8list, options, inlineSourceMap);
|
|
88
67
|
|
|
89
68
|
return v8list;
|
|
90
69
|
};
|
|
91
70
|
|
|
92
|
-
//
|
|
71
|
+
// ========================================================================================================
|
|
72
|
+
|
|
73
|
+
const unpackV8List = async (v8list, options) => {
|
|
74
|
+
v8list.forEach((item, i) => {
|
|
75
|
+
if (item.type === 'js') {
|
|
76
|
+
item.ranges = convertFunctionsToRanges(item.functions);
|
|
77
|
+
delete item.functions;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// requires ranges before unpack
|
|
82
|
+
await unpackSourceMaps(v8list, options);
|
|
83
|
+
|
|
84
|
+
// console.log(v8list.length);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// ========================================================================================================
|
|
93
88
|
|
|
94
89
|
// force to async
|
|
95
|
-
const
|
|
90
|
+
const mergeCssRanges = (itemList) => {
|
|
96
91
|
return new Promise((resolve) => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
92
|
+
|
|
93
|
+
let concatRanges = [];
|
|
94
|
+
itemList.forEach((item) => {
|
|
95
|
+
concatRanges = concatRanges.concat(item.ranges);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ranges: [ {start, end} ]
|
|
99
|
+
const ranges = dedupeRanges(concatRanges);
|
|
100
|
+
|
|
101
|
+
resolve(ranges || []);
|
|
106
102
|
});
|
|
107
103
|
};
|
|
108
104
|
|
|
109
|
-
const
|
|
105
|
+
const mergeJsFunctions = (itemList) => {
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
|
|
108
|
+
const res = mergeScriptCovs(itemList);
|
|
109
|
+
const functions = res && res.functions;
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
v8list.sort((a, b) => {
|
|
113
|
-
return a.id > b.id ? 1 : -1;
|
|
111
|
+
resolve(functions || []);
|
|
114
112
|
});
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const mergeV8Coverage = async (dataList, options) => {
|
|
115
116
|
|
|
116
|
-
let
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
let list = [];
|
|
118
|
+
dataList.forEach((d) => {
|
|
119
|
+
list = list.concat(d.data);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// console.log('before merge', list.map((it) => it.url));
|
|
123
|
+
|
|
124
|
+
// connect all functions and ranges
|
|
125
|
+
const itemMap = {};
|
|
126
|
+
const mergeMap = {};
|
|
127
|
+
list.forEach((item) => {
|
|
128
|
+
const { id } = item;
|
|
129
|
+
const prev = itemMap[id];
|
|
130
|
+
if (prev) {
|
|
131
|
+
if (mergeMap[id]) {
|
|
132
|
+
mergeMap[id].push(item);
|
|
133
|
+
} else {
|
|
134
|
+
mergeMap[id] = [prev, item];
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
itemMap[id] = item;
|
|
122
138
|
}
|
|
123
|
-
|
|
124
|
-
}
|
|
139
|
+
});
|
|
125
140
|
|
|
126
|
-
|
|
141
|
+
// merge functions and ranges
|
|
142
|
+
const mergeIds = Object.keys(mergeMap);
|
|
143
|
+
for (const id of mergeIds) {
|
|
144
|
+
const itemList = mergeMap[id];
|
|
145
|
+
const item = itemMap[id];
|
|
146
|
+
if (item.type === 'js') {
|
|
147
|
+
item.functions = await mergeJsFunctions(itemList);
|
|
148
|
+
} else {
|
|
149
|
+
item.ranges = await mergeCssRanges(itemList);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
127
152
|
|
|
128
|
-
|
|
153
|
+
list = Object.values(itemMap);
|
|
154
|
+
|
|
155
|
+
// try to load coverage and source by id
|
|
156
|
+
for (const item of list) {
|
|
157
|
+
const { id } = item;
|
|
158
|
+
const sourcePath = Util.resolveArtifactSourcePath(options.artifactsDir, id);
|
|
159
|
+
const content = await Util.readFile(sourcePath);
|
|
160
|
+
if (content) {
|
|
161
|
+
const json = JSON.parse(content);
|
|
162
|
+
item.source = json.source;
|
|
163
|
+
item.sourceMap = json.sourceMap;
|
|
164
|
+
} else {
|
|
165
|
+
EC.logRed(`[MCR] failed to read source: ${item.url}`);
|
|
166
|
+
item.source = '';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
129
169
|
|
|
130
170
|
return list;
|
|
131
171
|
};
|
|
@@ -221,7 +261,8 @@ const saveV8Report = async (v8list, options) => {
|
|
|
221
261
|
};
|
|
222
262
|
|
|
223
263
|
module.exports = {
|
|
224
|
-
|
|
225
|
-
|
|
264
|
+
initV8ListAndSourcemap,
|
|
265
|
+
unpackV8List,
|
|
266
|
+
mergeV8Coverage,
|
|
226
267
|
saveV8Report
|
|
227
268
|
};
|
|
@@ -128,14 +128,14 @@ const attachNetworkReport = async (har, testInfo, options = {}) => {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
options = {
|
|
131
|
+
// default title
|
|
132
|
+
title: `Network Report - ${testInfo.title}`,
|
|
131
133
|
outputDir: Util.resolveOutputDir(testInfo),
|
|
132
|
-
outputName: `network-${Util.
|
|
134
|
+
outputName: `network-${Util.resolveTestIdWithRetry(testInfo)}`,
|
|
133
135
|
inline: false,
|
|
134
136
|
... options
|
|
135
137
|
};
|
|
136
138
|
|
|
137
|
-
const title = options.title || `Network Report - ${testInfo.title}`;
|
|
138
|
-
|
|
139
139
|
const htmlDir = path.resolve(options.outputDir, options.outputName);
|
|
140
140
|
if (!fs.existsSync(htmlDir)) {
|
|
141
141
|
fs.mkdirSync(htmlDir, {
|
|
@@ -148,7 +148,7 @@ const attachNetworkReport = async (har, testInfo, options = {}) => {
|
|
|
148
148
|
|
|
149
149
|
// save har
|
|
150
150
|
const reportData = {
|
|
151
|
-
title,
|
|
151
|
+
title: options.title,
|
|
152
152
|
summary,
|
|
153
153
|
... harData
|
|
154
154
|
};
|
|
@@ -156,7 +156,7 @@ const attachNetworkReport = async (har, testInfo, options = {}) => {
|
|
|
156
156
|
const htmlPath = await saveNetworkHtmlReport(reportData, options);
|
|
157
157
|
|
|
158
158
|
const report = {
|
|
159
|
-
title,
|
|
159
|
+
title: options.title,
|
|
160
160
|
... harData.log,
|
|
161
161
|
htmlPath,
|
|
162
162
|
summary
|
|
@@ -182,12 +182,12 @@ const addNetworkReport = async () => {
|
|
|
182
182
|
|
|
183
183
|
};
|
|
184
184
|
|
|
185
|
-
const
|
|
185
|
+
const generateGlobalNetworkReport = async () => {
|
|
186
186
|
|
|
187
187
|
};
|
|
188
188
|
|
|
189
189
|
module.exports = {
|
|
190
190
|
addNetworkReport,
|
|
191
|
-
|
|
191
|
+
generateGlobalNetworkReport,
|
|
192
192
|
attachNetworkReport
|
|
193
193
|
};
|