monocart-reporter 2.9.6 → 2.9.7

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,186 +1,186 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const Util = require('../../utils/util.js');
4
- const Assets = require('../../assets.js');
5
-
6
- const getHarData = (har) => {
7
- if (typeof har === 'string') {
8
- if (!fs.existsSync(har)) {
9
- return;
10
- }
11
- return Util.readJSONSync(har);
12
- }
13
- if (Buffer.isBuffer(har)) {
14
- return JSON.parse(har.toString('utf-8'));
15
- }
16
- };
17
-
18
- // http://www.softwareishard.com/blog/har-12-spec/
19
- const getNetworkSummary = (log) => {
20
-
21
- const { entries, pages } = log;
22
-
23
- const waterfalls = {};
24
- pages.forEach((page) => {
25
- const pageTimings = page.pageTimings;
26
- const timestampStart = new Date(page.startedDateTime).getTime();
27
- const time = Math.max(pageTimings.onContentLoad, pageTimings.onLoad) || 0;
28
- waterfalls[page.id] = {
29
- timestampStart,
30
- start: 0,
31
- time,
32
- ... pageTimings,
33
- entries: []
34
- };
35
- });
36
-
37
- const summary = {
38
- requests: entries.length,
39
- size: 0,
40
- status: {},
41
- methods: {},
42
- waterfalls
43
- };
44
-
45
- const countField = (k, v) => {
46
- if (summary[k][v]) {
47
- summary[k][v] += 1;
48
- } else {
49
- summary[k][v] = 1;
50
- }
51
- };
52
-
53
- const countRequest = (req) => {
54
- const {
55
- bodySize, headersSize, method
56
- } = req;
57
- countField('methods', method);
58
-
59
- summary.size += Math.max(bodySize, 0) + Math.max(headersSize, 0);
60
- };
61
-
62
- const countResponse = (res) => {
63
- const {
64
- bodySize, headersSize, status
65
- } = res;
66
- countField('status', status);
67
-
68
- summary.size += (Math.max(headersSize, 0) + Math.max(bodySize, 0));
69
- };
70
-
71
- const countWaterfall = (entry) => {
72
-
73
- const pageWaterfall = waterfalls[entry.pageref];
74
-
75
- const timestampStart = new Date(entry.startedDateTime).getTime();
76
- const entryWaterfall = {
77
- start: timestampStart - pageWaterfall.timestampStart,
78
- time: Math.max(entry.time, 0),
79
- ... entry.timings
80
- };
81
-
82
- pageWaterfall.time = Math.max(pageWaterfall.time, entryWaterfall.start + entryWaterfall.time);
83
- pageWaterfall.entries.push(entryWaterfall);
84
-
85
- };
86
-
87
- entries.forEach((entry) => {
88
-
89
- countRequest(entry.request);
90
- countResponse(entry.response);
91
- countWaterfall(entry);
92
-
93
- });
94
-
95
- return summary;
96
- };
97
-
98
- const saveNetworkHtmlReport = async (reportData, _options) => {
99
-
100
- const { htmlDir, inline } = _options;
101
-
102
- // deps
103
- const jsFiles = ['monocart-reporter-network'];
104
-
105
- const options = {
106
- inline,
107
- reportData,
108
- jsFiles,
109
- assetsPath: '../assets',
110
- outputDir: htmlDir,
111
- htmlFile: 'index.html',
112
-
113
- reportDataFile: 'network-data.js'
114
- };
115
-
116
- const htmlPath = await Assets.saveHtmlReport(options);
117
-
118
- return htmlPath;
119
- };
120
-
121
- const attachNetworkReport = async (har, testInfo, options = {}) => {
122
-
123
- const logging = Util.resolveLogging(testInfo, options);
124
- Util.initLoggingLevel(logging, 'network');
125
-
126
- const harData = getHarData(har);
127
- if (!harData || !harData.log) {
128
- Util.logError(`failed to load HAR: ${har}`);
129
- return;
130
- }
131
-
132
- const outputDir = Util.resolveOutputDir(testInfo);
133
-
134
- options = {
135
- // default title
136
- name: `Network Report - ${testInfo.title}`,
137
- outputDir,
138
- outputName: `network-${Util.resolveTestIdWithRetry(testInfo)}`,
139
- inline: false,
140
- ... options
141
- };
142
-
143
- const htmlDir = path.resolve(options.outputDir, options.outputName);
144
- if (!fs.existsSync(htmlDir)) {
145
- fs.mkdirSync(htmlDir, {
146
- recursive: true
147
- });
148
- }
149
- options.htmlDir = htmlDir;
150
-
151
- const summary = getNetworkSummary(harData.log);
152
-
153
- // save har
154
- const reportData = {
155
- name: options.name,
156
- summary,
157
- ... harData
158
- };
159
-
160
- const htmlPath = await saveNetworkHtmlReport(reportData, options);
161
-
162
- const report = {
163
- name: options.name,
164
- ... harData.log,
165
- htmlPath,
166
- summary
167
- };
168
- delete report.entries;
169
-
170
- // save report json
171
- const definition = Util.attachments.network;
172
- const reportPath = path.resolve(htmlDir, definition.reportFile);
173
- Util.writeJSONSync(reportPath, report);
174
-
175
- testInfo.attachments.push({
176
- name: definition.name,
177
- contentType: definition.contentType,
178
- path: path.resolve(htmlDir, 'index.html')
179
- });
180
-
181
- return report;
182
- };
183
-
184
- module.exports = {
185
- attachNetworkReport
186
- };
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const Util = require('../../utils/util.js');
4
+ const Assets = require('../../assets.js');
5
+
6
+ const getHarData = (har) => {
7
+ if (typeof har === 'string') {
8
+ if (!fs.existsSync(har)) {
9
+ return;
10
+ }
11
+ return Util.readJSONSync(har);
12
+ }
13
+ if (Buffer.isBuffer(har)) {
14
+ return JSON.parse(har.toString('utf-8'));
15
+ }
16
+ };
17
+
18
+ // http://www.softwareishard.com/blog/har-12-spec/
19
+ const getNetworkSummary = (log) => {
20
+
21
+ const { entries, pages } = log;
22
+
23
+ const waterfalls = {};
24
+ pages.forEach((page) => {
25
+ const pageTimings = page.pageTimings;
26
+ const timestampStart = new Date(page.startedDateTime).getTime();
27
+ const time = Math.max(pageTimings.onContentLoad, pageTimings.onLoad) || 0;
28
+ waterfalls[page.id] = {
29
+ timestampStart,
30
+ start: 0,
31
+ time,
32
+ ... pageTimings,
33
+ entries: []
34
+ };
35
+ });
36
+
37
+ const summary = {
38
+ requests: entries.length,
39
+ size: 0,
40
+ status: {},
41
+ methods: {},
42
+ waterfalls
43
+ };
44
+
45
+ const countField = (k, v) => {
46
+ if (summary[k][v]) {
47
+ summary[k][v] += 1;
48
+ } else {
49
+ summary[k][v] = 1;
50
+ }
51
+ };
52
+
53
+ const countRequest = (req) => {
54
+ const {
55
+ bodySize, headersSize, method
56
+ } = req;
57
+ countField('methods', method);
58
+
59
+ summary.size += Math.max(bodySize, 0) + Math.max(headersSize, 0);
60
+ };
61
+
62
+ const countResponse = (res) => {
63
+ const {
64
+ bodySize, headersSize, status
65
+ } = res;
66
+ countField('status', status);
67
+
68
+ summary.size += (Math.max(headersSize, 0) + Math.max(bodySize, 0));
69
+ };
70
+
71
+ const countWaterfall = (entry) => {
72
+
73
+ const pageWaterfall = waterfalls[entry.pageref];
74
+
75
+ const timestampStart = new Date(entry.startedDateTime).getTime();
76
+ const entryWaterfall = {
77
+ start: timestampStart - pageWaterfall.timestampStart,
78
+ time: Math.max(entry.time, 0),
79
+ ... entry.timings
80
+ };
81
+
82
+ pageWaterfall.time = Math.max(pageWaterfall.time, entryWaterfall.start + entryWaterfall.time);
83
+ pageWaterfall.entries.push(entryWaterfall);
84
+
85
+ };
86
+
87
+ entries.forEach((entry) => {
88
+
89
+ countRequest(entry.request);
90
+ countResponse(entry.response);
91
+ countWaterfall(entry);
92
+
93
+ });
94
+
95
+ return summary;
96
+ };
97
+
98
+ const saveNetworkHtmlReport = async (reportData, _options) => {
99
+
100
+ const { htmlDir, inline } = _options;
101
+
102
+ // deps
103
+ const jsFiles = ['monocart-reporter-network'];
104
+
105
+ const options = {
106
+ inline,
107
+ reportData,
108
+ jsFiles,
109
+ assetsPath: '../assets',
110
+ outputDir: htmlDir,
111
+ htmlFile: 'index.html',
112
+
113
+ reportDataFile: 'network-data.js'
114
+ };
115
+
116
+ const htmlPath = await Assets.saveHtmlReport(options);
117
+
118
+ return htmlPath;
119
+ };
120
+
121
+ const attachNetworkReport = async (har, testInfo, options = {}) => {
122
+
123
+ const logging = Util.resolveLogging(testInfo, options);
124
+ Util.initLoggingLevel(logging, 'network');
125
+
126
+ const harData = getHarData(har);
127
+ if (!harData || !harData.log) {
128
+ Util.logError(`failed to load HAR: ${har}`);
129
+ return;
130
+ }
131
+
132
+ const outputDir = Util.resolveOutputDir(testInfo);
133
+
134
+ options = {
135
+ // default title
136
+ name: `Network Report - ${testInfo.title}`,
137
+ outputDir,
138
+ outputName: `network-${Util.resolveTestIdWithRetry(testInfo)}`,
139
+ inline: false,
140
+ ... options
141
+ };
142
+
143
+ const htmlDir = path.resolve(options.outputDir, options.outputName);
144
+ if (!fs.existsSync(htmlDir)) {
145
+ fs.mkdirSync(htmlDir, {
146
+ recursive: true
147
+ });
148
+ }
149
+ options.htmlDir = htmlDir;
150
+
151
+ const summary = getNetworkSummary(harData.log);
152
+
153
+ // save har
154
+ const reportData = {
155
+ name: options.name,
156
+ summary,
157
+ ... harData
158
+ };
159
+
160
+ const htmlPath = await saveNetworkHtmlReport(reportData, options);
161
+
162
+ const report = {
163
+ name: options.name,
164
+ ... harData.log,
165
+ htmlPath,
166
+ summary
167
+ };
168
+ delete report.entries;
169
+
170
+ // save report json
171
+ const definition = Util.attachments.network;
172
+ const reportPath = path.resolve(htmlDir, definition.reportFile);
173
+ Util.writeJSONSync(reportPath, report);
174
+
175
+ testInfo.attachments.push({
176
+ name: definition.name,
177
+ contentType: definition.contentType,
178
+ path: path.resolve(htmlDir, 'index.html')
179
+ });
180
+
181
+ return report;
182
+ };
183
+
184
+ module.exports = {
185
+ attachNetworkReport
186
+ };
@@ -1,152 +1,152 @@
1
- const { WebSocket } = require('../../packages/monocart-reporter-vendor.js');
2
- const Util = require('../../utils/util.js');
3
-
4
- const getServerUrl = (options = {}) => {
5
- return `ws://${options.host}:${options.port}`;
6
- };
7
-
8
- class Client {
9
-
10
- constructor(clientOptions) {
11
- this.options = clientOptions;
12
- this.requests = new Map();
13
- this.resolves = [];
14
-
15
- const serverUrl = getServerUrl(clientOptions);
16
-
17
- // https://github.com/websockets/ws/blob/master/doc/ws.md
18
- const ws = new WebSocket(serverUrl);
19
-
20
- ws.on('error', (err) => {
21
-
22
- // socket hang up: the port is exists but not websocket server
23
- // connect ECONNREFUSED: websocket server unavailable
24
-
25
- if (Util.isList(this.resolves)) {
26
- this.resolves.forEach((item) => {
27
- item.reject(err);
28
- });
29
- this.resolves = null;
30
- } else {
31
- Util.logError(`websocket error: ${err.message}`);
32
- }
33
-
34
- });
35
-
36
- ws.on('message', (data) => {
37
- this.onMessage(data);
38
- });
39
-
40
- ws.on('open', () => {
41
- this.ws = ws;
42
- if (Util.isList(this.resolves)) {
43
- this.resolves.forEach((item) => {
44
- item.resolve(ws);
45
- });
46
- this.resolves = null;
47
- }
48
- });
49
- }
50
-
51
- connect() {
52
- return new Promise((resolve, reject) => {
53
-
54
- if (this.ws) {
55
- resolve(this.ws);
56
- return;
57
- }
58
-
59
- if (this.resolves) {
60
- this.resolves.push({
61
- resolve,
62
- reject
63
- });
64
- } else {
65
- reject(new Error('an error occurs when connecting websocket server'));
66
- }
67
- });
68
- }
69
-
70
- onMessage(buf) {
71
- const message = JSON.parse(buf.toString());
72
- if (!message) {
73
- return;
74
- }
75
- const { id, data } = message;
76
- if (!id) {
77
- return;
78
- }
79
-
80
- const req = this.requests.get(id);
81
- if (!req) {
82
- return;
83
- }
84
-
85
- this.requests.delete(id);
86
-
87
- clearTimeout(req.timeout_id);
88
- req.resolve(data);
89
-
90
- }
91
-
92
- async execute(data) {
93
-
94
- let err;
95
- const ws = await this.connect().catch((e) => {
96
- err = e;
97
- });
98
-
99
- return new Promise((resolve, reject) => {
100
-
101
- if (!ws) {
102
- reject(err);
103
- return;
104
- }
105
-
106
- const id = Util.uid();
107
- const timeout = this.options.timeout;
108
- const timeout_id = setTimeout(() => {
109
- this.requests.delete(id);
110
- reject(new Error(`timed out receiving message from websocket server: ${timeout}ms`));
111
- }, timeout);
112
-
113
- this.requests.set(id, {
114
- resolve,
115
- timeout_id
116
- });
117
-
118
- const message = JSON.stringify({
119
- id,
120
- data
121
- });
122
- ws.send(message);
123
- });
124
- }
125
-
126
- state() {
127
- return {
128
- get: (... args) => {
129
- return this.execute(['get', ... args]);
130
- },
131
-
132
- set: (... args) => {
133
- return this.execute(['set', ... args]);
134
- },
135
-
136
- remove: (... args) => {
137
- return this.execute(['remove', ... args]);
138
- },
139
-
140
- send: (... args) => {
141
- return this.execute(['send', ... args]);
142
- }
143
- };
144
- }
145
-
146
- }
147
-
148
-
149
- module.exports = {
150
- getServerUrl,
151
- Client
152
- };
1
+ const { WebSocket } = require('../../packages/monocart-reporter-vendor.js');
2
+ const Util = require('../../utils/util.js');
3
+
4
+ const getServerUrl = (options = {}) => {
5
+ return `ws://${options.host}:${options.port}`;
6
+ };
7
+
8
+ class Client {
9
+
10
+ constructor(clientOptions) {
11
+ this.options = clientOptions;
12
+ this.requests = new Map();
13
+ this.resolves = [];
14
+
15
+ const serverUrl = getServerUrl(clientOptions);
16
+
17
+ // https://github.com/websockets/ws/blob/master/doc/ws.md
18
+ const ws = new WebSocket(serverUrl);
19
+
20
+ ws.on('error', (err) => {
21
+
22
+ // socket hang up: the port is exists but not websocket server
23
+ // connect ECONNREFUSED: websocket server unavailable
24
+
25
+ if (Util.isList(this.resolves)) {
26
+ this.resolves.forEach((item) => {
27
+ item.reject(err);
28
+ });
29
+ this.resolves = null;
30
+ } else {
31
+ Util.logError(`websocket error: ${err.message}`);
32
+ }
33
+
34
+ });
35
+
36
+ ws.on('message', (data) => {
37
+ this.onMessage(data);
38
+ });
39
+
40
+ ws.on('open', () => {
41
+ this.ws = ws;
42
+ if (Util.isList(this.resolves)) {
43
+ this.resolves.forEach((item) => {
44
+ item.resolve(ws);
45
+ });
46
+ this.resolves = null;
47
+ }
48
+ });
49
+ }
50
+
51
+ connect() {
52
+ return new Promise((resolve, reject) => {
53
+
54
+ if (this.ws) {
55
+ resolve(this.ws);
56
+ return;
57
+ }
58
+
59
+ if (this.resolves) {
60
+ this.resolves.push({
61
+ resolve,
62
+ reject
63
+ });
64
+ } else {
65
+ reject(new Error('an error occurs when connecting websocket server'));
66
+ }
67
+ });
68
+ }
69
+
70
+ onMessage(buf) {
71
+ const message = JSON.parse(buf.toString());
72
+ if (!message) {
73
+ return;
74
+ }
75
+ const { id, data } = message;
76
+ if (!id) {
77
+ return;
78
+ }
79
+
80
+ const req = this.requests.get(id);
81
+ if (!req) {
82
+ return;
83
+ }
84
+
85
+ this.requests.delete(id);
86
+
87
+ clearTimeout(req.timeout_id);
88
+ req.resolve(data);
89
+
90
+ }
91
+
92
+ async execute(data) {
93
+
94
+ let err;
95
+ const ws = await this.connect().catch((e) => {
96
+ err = e;
97
+ });
98
+
99
+ return new Promise((resolve, reject) => {
100
+
101
+ if (!ws) {
102
+ reject(err);
103
+ return;
104
+ }
105
+
106
+ const id = Util.uid();
107
+ const timeout = this.options.timeout;
108
+ const timeout_id = setTimeout(() => {
109
+ this.requests.delete(id);
110
+ reject(new Error(`timed out receiving message from websocket server: ${timeout}ms`));
111
+ }, timeout);
112
+
113
+ this.requests.set(id, {
114
+ resolve,
115
+ timeout_id
116
+ });
117
+
118
+ const message = JSON.stringify({
119
+ id,
120
+ data
121
+ });
122
+ ws.send(message);
123
+ });
124
+ }
125
+
126
+ state() {
127
+ return {
128
+ get: (... args) => {
129
+ return this.execute(['get', ... args]);
130
+ },
131
+
132
+ set: (... args) => {
133
+ return this.execute(['set', ... args]);
134
+ },
135
+
136
+ remove: (... args) => {
137
+ return this.execute(['remove', ... args]);
138
+ },
139
+
140
+ send: (... args) => {
141
+ return this.execute(['send', ... args]);
142
+ }
143
+ };
144
+ }
145
+
146
+ }
147
+
148
+
149
+ module.exports = {
150
+ getServerUrl,
151
+ Client
152
+ };