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.
@@ -1,131 +1,171 @@
1
- const path = require('path');
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 { dedupeCountRanges, dedupeRanges } = require('./dedupe.js');
6
- const { sortRanges, getSourcePath } = require('../coverage-utils.js');
7
-
8
- // convert functions to ranges
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
- return {
28
- ranges
29
- };
30
- };
11
+ // ========================================================================================================
31
12
 
32
- // Unify the format of js and css
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 and init type
42
- v8list = v8list.map((item) => {
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
- const {
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
- const {
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
- }).filter((it) => it);
35
+ });
74
36
 
75
- // unpack source maps if options.unpackSourceMap = true
76
- await unpackSourceMaps(v8list, options);
77
37
 
78
- // init list properties
79
- v8list.forEach((item, i) => {
80
- if (!item.sourcePath) {
81
- item.sourcePath = getSourcePath(item.url, i + 1, item.type);
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
- item.filename = path.basename(item.sourcePath);
84
- item.id = Util.calculateSha1(item.url + item.source);
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
- v8list = await mergeV8List(v8list, options);
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 mergeV8Item = (lastItem, item) => {
90
+ const mergeCssRanges = (itemList) => {
96
91
  return new Promise((resolve) => {
97
- const concatRanges = [].concat(lastItem.ranges).concat(item.ranges);
98
- if (lastItem.type === 'css') {
99
- // ranges: [ {start, end} ]
100
- lastItem.ranges = dedupeRanges(concatRanges);
101
- } else {
102
- // ranges: [ {start, end, count} ]
103
- lastItem.ranges = dedupeCountRanges(concatRanges);
104
- }
105
- resolve(lastItem);
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 mergeV8List = async (v8list, options) => {
105
+ const mergeJsFunctions = (itemList) => {
106
+ return new Promise((resolve) => {
107
+
108
+ const res = mergeScriptCovs(itemList);
109
+ const functions = res && res.functions;
110
110
 
111
- // sort by id, id is hash from url and source
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 lastItem = {};
117
- for (const item of v8list) {
118
- if (item.id === lastItem.id) {
119
- item.dedupe = true;
120
- lastItem = await mergeV8Item(lastItem, item);
121
- continue;
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
- lastItem = item;
124
- }
139
+ });
125
140
 
126
- const list = v8list.filter((it) => !it.dedupe);
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
- // console.log(list.map((it) => it.url));
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
- initV8List,
225
- mergeV8List,
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.shortTestId(testInfo.testId)}`,
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 generateNetworkReport = async () => {
185
+ const generateGlobalNetworkReport = async () => {
186
186
 
187
187
  };
188
188
 
189
189
  module.exports = {
190
190
  addNetworkReport,
191
- generateNetworkReport,
191
+ generateGlobalNetworkReport,
192
192
  attachNetworkReport
193
193
  };