@dev-blinq/cucumber-js 1.0.128-dev → 1.0.128
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/bin/cucumber.ts +1 -0
- package/bin/download-install.js +22 -2
- package/lib/api/console_logger.js.map +1 -1
- package/lib/cli/run.js +1 -0
- package/lib/cli/run.js.map +1 -1
- package/lib/cli/validate_node_engine_version.js +3 -1
- package/lib/cli/validate_node_engine_version.js.map +1 -1
- package/lib/configuration/axios_client.js +1 -1
- package/lib/configuration/axios_client.js.map +1 -1
- package/lib/formatter/api.js +16 -5
- package/lib/formatter/api.js.map +1 -1
- package/lib/formatter/builder.js +1 -3
- package/lib/formatter/builder.js.map +1 -1
- package/lib/formatter/bvt_analysis_formatter.d.ts +12 -1
- package/lib/formatter/bvt_analysis_formatter.js +161 -55
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +22 -8
- package/lib/formatter/feature_data_format.js.map +1 -1
- package/lib/formatter/helpers/constants.d.ts +50 -0
- package/lib/formatter/helpers/constants.js +60 -0
- package/lib/formatter/helpers/constants.js.map +1 -0
- package/lib/formatter/helpers/report_generator.d.ts +22 -3
- package/lib/formatter/helpers/report_generator.js +336 -27
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +20 -2
- package/lib/formatter/helpers/upload_serivce.js +210 -17
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.js +6 -2
- package/lib/formatter/helpers/uploader.js.map +1 -1
- package/lib/formatter/summary_formatter.js +4 -0
- package/lib/formatter/summary_formatter.js.map +1 -1
- package/lib/runtime/test_case_runner.d.ts +2 -0
- package/lib/runtime/test_case_runner.js +17 -1
- package/lib/runtime/test_case_runner.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +6 -3
|
@@ -10,6 +10,7 @@ const promises_1 = __importDefault(require("fs/promises"));
|
|
|
10
10
|
const axios_client_1 = require("../../configuration/axios_client");
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
const bvt_analysis_formatter_1 = require("../bvt_analysis_formatter");
|
|
13
|
+
const constants_1 = require("./constants");
|
|
13
14
|
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
14
15
|
const BATCH_SIZE = 10;
|
|
15
16
|
const MAX_RETRIES = 3;
|
|
@@ -19,10 +20,23 @@ class RunUploadService {
|
|
|
19
20
|
this.runsApiBaseURL = runsApiBaseURL;
|
|
20
21
|
this.accessToken = accessToken;
|
|
21
22
|
}
|
|
22
|
-
async createRunDocument(name) {
|
|
23
|
+
async createRunDocument(name, env) {
|
|
24
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
25
|
+
console.log('Skipping report upload as UPLOADREPORTS is set to false');
|
|
26
|
+
return { id: 'local-run', projectId: 'local-project' };
|
|
27
|
+
}
|
|
23
28
|
try {
|
|
24
29
|
const runDocResult = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/create', {
|
|
25
30
|
name: name ? name : 'TEST',
|
|
31
|
+
branch: process.env.GIT_BRANCH ? process.env.GIT_BRANCH : 'main',
|
|
32
|
+
video_id: process.env.VIDEO_ID,
|
|
33
|
+
browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',
|
|
34
|
+
mode: process.env.MODE === 'cloud'
|
|
35
|
+
? 'cloud'
|
|
36
|
+
: process.env.MODE === 'executions'
|
|
37
|
+
? 'executions'
|
|
38
|
+
: 'local',
|
|
39
|
+
env: { name: env === null || env === void 0 ? void 0 : env.name, baseUrl: env === null || env === void 0 ? void 0 : env.baseUrl },
|
|
26
40
|
}, {
|
|
27
41
|
headers: {
|
|
28
42
|
Authorization: 'Bearer ' + this.accessToken,
|
|
@@ -45,7 +59,28 @@ class RunUploadService {
|
|
|
45
59
|
throw new Error('Failed to create run document in the server: ' + error);
|
|
46
60
|
}
|
|
47
61
|
}
|
|
62
|
+
async updateProjectAnalytics(projectId) {
|
|
63
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/project/updateAIRecoveryCount', {
|
|
68
|
+
projectId,
|
|
69
|
+
}, {
|
|
70
|
+
headers: {
|
|
71
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
72
|
+
'x-source': 'cucumber_js',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('Failed to update project metadata:', error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
48
80
|
async upload(formData) {
|
|
81
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
49
84
|
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/upload', formData, {
|
|
50
85
|
headers: {
|
|
51
86
|
...formData.getHeaders(),
|
|
@@ -65,6 +100,9 @@ class RunUploadService {
|
|
|
65
100
|
}
|
|
66
101
|
}
|
|
67
102
|
async getPreSignedUrls(fileUris, runId) {
|
|
103
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
68
106
|
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/generateuploadurls', {
|
|
69
107
|
fileUris,
|
|
70
108
|
runId,
|
|
@@ -86,50 +124,156 @@ class RunUploadService {
|
|
|
86
124
|
}
|
|
87
125
|
return response.data.uploadUrls;
|
|
88
126
|
}
|
|
89
|
-
async uploadTestCase(testCaseReport, runId, projectId, reportFolder) {
|
|
127
|
+
async uploadTestCase(testCaseReport, runId, projectId, reportFolder, rerunId) {
|
|
128
|
+
var _a, _b, _c;
|
|
129
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
90
132
|
const fileUris = [];
|
|
91
|
-
//
|
|
133
|
+
// Collect screenshot + trace + logs
|
|
92
134
|
for (const step of testCaseReport.steps) {
|
|
93
135
|
for (const command of step.commands) {
|
|
94
136
|
if (command.screenshotId) {
|
|
95
|
-
fileUris.push(
|
|
137
|
+
fileUris.push(`screenshots/${String(command.screenshotId)}.png`);
|
|
96
138
|
}
|
|
97
139
|
}
|
|
140
|
+
if (step.traceFilePath) {
|
|
141
|
+
fileUris.push(`trace/${step.traceFilePath}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (testCaseReport.logFileId) {
|
|
145
|
+
fileUris.push(`editorLogs/testCaseLog_${testCaseReport.logFileId}.log`);
|
|
146
|
+
}
|
|
147
|
+
if (testCaseReport.traceFileId) {
|
|
148
|
+
fileUris.push(`trace/${testCaseReport.traceFileId}`);
|
|
98
149
|
}
|
|
99
|
-
|
|
100
|
-
//
|
|
150
|
+
//
|
|
151
|
+
// 🔹 UPLOAD FILES (presigned URLs)
|
|
152
|
+
//
|
|
101
153
|
try {
|
|
154
|
+
const preSignedUrls = await this.getPreSignedUrls(fileUris, runId);
|
|
102
155
|
for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {
|
|
103
156
|
const batch = fileUris.slice(i, Math.min(i + BATCH_SIZE, fileUris.length));
|
|
104
157
|
await Promise.all(batch
|
|
105
158
|
.filter((fileUri) => preSignedUrls[fileUri])
|
|
106
159
|
.map(async (fileUri) => {
|
|
107
160
|
for (let j = 0; j < MAX_RETRIES; j++) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
161
|
+
try {
|
|
162
|
+
const filePath = path_1.default.join(reportFolder, fileUri);
|
|
163
|
+
if ((0, fs_1.existsSync)(filePath)) {
|
|
164
|
+
const ok = await this.uploadFile(filePath, preSignedUrls[fileUri]);
|
|
165
|
+
if (ok)
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
// Retry silently
|
|
111
171
|
}
|
|
112
172
|
}
|
|
113
|
-
console.error(
|
|
173
|
+
console.error(`Failed to upload file after retries: ${fileUri}`);
|
|
114
174
|
}));
|
|
115
175
|
}
|
|
116
|
-
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
const sanitized = this.sanitizeError(error);
|
|
179
|
+
console.error('Error uploading files:', sanitized);
|
|
180
|
+
}
|
|
181
|
+
console.log("🟨 Screenshots:", fileUris.length);
|
|
182
|
+
//
|
|
183
|
+
// 🔹 UPLOAD FINAL TEST REPORT (JSON metadata)
|
|
184
|
+
//
|
|
185
|
+
try {
|
|
186
|
+
const mode = process.env.MODE === 'cloud'
|
|
187
|
+
? 'cloud'
|
|
188
|
+
: process.env.MODE === 'executions'
|
|
189
|
+
? 'executions'
|
|
190
|
+
: 'local';
|
|
191
|
+
let rerunIdFinal = process.env.RETRY_ID || null;
|
|
192
|
+
if (rerunId) {
|
|
193
|
+
rerunIdFinal = rerunId.includes(runId) ? rerunId : `${runId}${rerunId}`;
|
|
194
|
+
}
|
|
195
|
+
if (mode === 'executions') {
|
|
196
|
+
testCaseReport.id = process.env.VIDEO_ID || testCaseReport.id;
|
|
197
|
+
}
|
|
198
|
+
const payload = {
|
|
117
199
|
runId,
|
|
118
200
|
projectId,
|
|
119
201
|
testProgressReport: testCaseReport,
|
|
120
|
-
|
|
202
|
+
browser: process.env.BROWSER || 'chromium',
|
|
203
|
+
mode,
|
|
204
|
+
rerunId: rerunIdFinal,
|
|
205
|
+
video_id: process.env.VIDEO_ID,
|
|
206
|
+
};
|
|
207
|
+
const json = JSON.stringify(payload);
|
|
208
|
+
console.log("🟥 Payload size KB:", Buffer.byteLength(json) / 1024);
|
|
209
|
+
const start = Date.now();
|
|
210
|
+
const { data } = await axios_client_1.axiosClient.post(`${this.runsApiBaseURL}/cucumber-runs/createNewTestCase`, payload, {
|
|
121
211
|
headers: {
|
|
122
212
|
Authorization: 'Bearer ' + this.accessToken,
|
|
123
213
|
'x-source': 'cucumber_js',
|
|
124
214
|
},
|
|
125
215
|
});
|
|
126
|
-
(
|
|
216
|
+
console.log("🟩 POST /createNewTestCase finished in ms:", Date.now() - start);
|
|
217
|
+
// optional event — keep original logic
|
|
218
|
+
try {
|
|
219
|
+
await axios_client_1.axiosClient.post(`${constants_1.SERVICES_URI.STORAGE}/event`, { event: constants_1.ActionEvents.upload_report }, {
|
|
220
|
+
headers: {
|
|
221
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
222
|
+
'x-source': 'cucumber_js',
|
|
223
|
+
'x-bvt-project-id': projectId,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (_d) { }
|
|
228
|
+
(0, bvt_analysis_formatter_1.logReportLink)(runId, projectId, testCaseReport.result);
|
|
229
|
+
return data;
|
|
127
230
|
}
|
|
128
231
|
catch (e) {
|
|
129
|
-
|
|
232
|
+
const sanitized = this.sanitizeError(e);
|
|
233
|
+
console.error("🟥 Raw response snippet:", (_c = (_b = (_a = e === null || e === void 0 ? void 0 : e.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.toString()) === null || _c === void 0 ? void 0 : _c.slice(0, 300));
|
|
234
|
+
console.error(`failed to upload the test case: ${testCaseReport.id} ${sanitized}`);
|
|
235
|
+
return null;
|
|
130
236
|
}
|
|
131
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Improving error logging
|
|
240
|
+
* 🔧 Sanitizes Axios errors to avoid dumping Cloudflare HTML (524, 502, etc.)
|
|
241
|
+
*/
|
|
242
|
+
sanitizeError(error) {
|
|
243
|
+
// Handle Axios-style errors with response
|
|
244
|
+
if (error === null || error === void 0 ? void 0 : error.response) {
|
|
245
|
+
const { data, status } = error.response;
|
|
246
|
+
// If Cloudflare or HTML error page → return a short meaningful message
|
|
247
|
+
if (typeof data === 'string' && data.includes('<!DOCTYPE html')) {
|
|
248
|
+
return `[HTML_ERROR_PAGE] status=${status} - likely Cloudflare timeout or proxy error`;
|
|
249
|
+
}
|
|
250
|
+
// If data is a JSON object, stringify it with indentation for readability
|
|
251
|
+
if (typeof data === 'object') {
|
|
252
|
+
return JSON.stringify(data, null, 2); // Pretty-print the JSON response
|
|
253
|
+
}
|
|
254
|
+
// If response is a string (could be an error message), return it trimmed
|
|
255
|
+
return (data === null || data === void 0 ? void 0 : data.trim()) || `Unknown response data (status: ${status})`;
|
|
256
|
+
}
|
|
257
|
+
// System / network errors (e.g., if Axios cannot reach the server)
|
|
258
|
+
if (error === null || error === void 0 ? void 0 : error.message) {
|
|
259
|
+
return error.message;
|
|
260
|
+
}
|
|
261
|
+
// If the error has a stack (for debugging purposes)
|
|
262
|
+
if (error === null || error === void 0 ? void 0 : error.stack) {
|
|
263
|
+
return `${error.message}\n${error.stack}`;
|
|
264
|
+
}
|
|
265
|
+
// If it's a generic error object, attempt to stringify it in a readable format
|
|
266
|
+
return JSON.stringify(error, (key, value) => {
|
|
267
|
+
// Avoid circular references or sensitive data
|
|
268
|
+
if (key === 'password' || key === 'accessToken')
|
|
269
|
+
return '[REDACTED]';
|
|
270
|
+
return value;
|
|
271
|
+
}, 2); // Pretty-print the error object with indentation
|
|
272
|
+
}
|
|
132
273
|
async uploadFile(filePath, preSignedUrl) {
|
|
274
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
133
277
|
const fileStream = (0, fs_1.createReadStream)(filePath);
|
|
134
278
|
let success = true;
|
|
135
279
|
try {
|
|
@@ -143,8 +287,9 @@ class RunUploadService {
|
|
|
143
287
|
});
|
|
144
288
|
}
|
|
145
289
|
catch (error) {
|
|
146
|
-
if (process.env.
|
|
147
|
-
|
|
290
|
+
if (process.env.MODE === 'executions') {
|
|
291
|
+
const sanitized = this.sanitizeError(error);
|
|
292
|
+
console.error('❌ Error uploading file at:', filePath, 'due to', sanitized);
|
|
148
293
|
}
|
|
149
294
|
success = false;
|
|
150
295
|
}
|
|
@@ -154,9 +299,18 @@ class RunUploadService {
|
|
|
154
299
|
return success;
|
|
155
300
|
}
|
|
156
301
|
async uploadComplete(runId, projectId) {
|
|
302
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
157
305
|
const response = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/uploadCompletion', {
|
|
158
306
|
runId,
|
|
159
307
|
projectId,
|
|
308
|
+
browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',
|
|
309
|
+
mode: process.env.MODE === 'cloud'
|
|
310
|
+
? 'cloud'
|
|
311
|
+
: process.env.MODE === 'executions'
|
|
312
|
+
? 'executions'
|
|
313
|
+
: 'local',
|
|
160
314
|
}, {
|
|
161
315
|
headers: {
|
|
162
316
|
Authorization: 'Bearer ' + this.accessToken,
|
|
@@ -169,8 +323,25 @@ class RunUploadService {
|
|
|
169
323
|
if (response.data.status !== true) {
|
|
170
324
|
throw new Error('Failed to mark run as complete');
|
|
171
325
|
}
|
|
326
|
+
try {
|
|
327
|
+
await axios_client_1.axiosClient.post(`${constants_1.SERVICES_URI.STORAGE}/event`, {
|
|
328
|
+
event: constants_1.ActionEvents.upload_report,
|
|
329
|
+
}, {
|
|
330
|
+
headers: {
|
|
331
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
332
|
+
'x-source': 'cucumber_js',
|
|
333
|
+
'x-bvt-project-id': projectId,
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
// no event tracking
|
|
339
|
+
}
|
|
172
340
|
}
|
|
173
341
|
async modifyTestCase(runId, projectId, testProgressReport) {
|
|
342
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
174
345
|
try {
|
|
175
346
|
const res = await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/modifyTestCase', {
|
|
176
347
|
runId,
|
|
@@ -188,12 +359,34 @@ class RunUploadService {
|
|
|
188
359
|
if (res.data.status !== true) {
|
|
189
360
|
throw new Error('');
|
|
190
361
|
}
|
|
191
|
-
(0, bvt_analysis_formatter_1.logReportLink)(runId, projectId);
|
|
362
|
+
(0, bvt_analysis_formatter_1.logReportLink)(runId, projectId, testProgressReport.result);
|
|
192
363
|
}
|
|
193
364
|
catch (e) {
|
|
194
365
|
console.error(`failed to modify the test case: ${testProgressReport.id} ${e}`);
|
|
195
366
|
}
|
|
196
367
|
}
|
|
368
|
+
async createStatus(status) {
|
|
369
|
+
if (process.env.UPLOADREPORTS === 'false') {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (!process.env.UUID) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/scenarios/status', {
|
|
377
|
+
status: { status },
|
|
378
|
+
uuid: process.env.UUID,
|
|
379
|
+
}, {
|
|
380
|
+
headers: {
|
|
381
|
+
Authorization: 'Bearer ' + this.accessToken,
|
|
382
|
+
'x-source': 'cucumber_js',
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
console.log('Failed to send status to the server, ignoring it');
|
|
388
|
+
}
|
|
389
|
+
}
|
|
197
390
|
}
|
|
198
391
|
exports.RunUploadService = RunUploadService;
|
|
199
392
|
//# sourceMappingURL=upload_serivce.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload_serivce.js","sourceRoot":"","sources":["../../../src/formatter/helpers/upload_serivce.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport FormData from 'form-data'\nimport { createReadStream, existsSync } from 'fs'\nimport fs from 'fs/promises'\n\nimport { JsonReport, JsonTestProgress } from './report_generator'\nimport { axiosClient } from '../../configuration/axios_client'\nimport path from 'path'\nimport { logReportLink } from '../bvt_analysis_formatter'\n\nconst REPORT_SERVICE_URL = process.env.REPORT_SERVICE_URL ?? URL\nconst BATCH_SIZE = 10\nconst MAX_RETRIES = 3\nconst REPORT_SERVICE_TOKEN =\n process.env.TOKEN ?? process.env.REPORT_SERVICE_TOKEN\nclass RunUploadService {\n constructor(private runsApiBaseURL: string, private accessToken: string) {}\n async createRunDocument(name: string) {\n try {\n const runDocResult = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/create',\n {\n name: name ? name : 'TEST',\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (runDocResult.status !== 200) {\n throw new Error('Failed to create run document in the server')\n }\n if (runDocResult.data.status !== true) {\n throw new Error('Failed to create run document in the server')\n }\n return runDocResult.data.run\n } catch (error) {\n if (error.response && error.response.status === 403) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot create or upload reports.'\n )\n process.exit(1)\n }\n throw new Error('Failed to create run document in the server: ' + error)\n }\n }\n async upload(formData: FormData) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/upload',\n formData,\n {\n headers: {\n ...formData.getHeaders(),\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status === 401) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n throw new Error(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n }\n if (response.status !== 200) {\n throw new Error('Failed to upload run to the server')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to upload run to the server')\n }\n }\n async getPreSignedUrls(fileUris: string[], runId: string) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/generateuploadurls',\n {\n fileUris,\n runId,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status === 403) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n throw new Error(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n }\n if (response.status !== 200) {\n throw new Error('Failed to get pre-signed urls for the files')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to get pre-signed urls for the files')\n }\n\n return response.data.uploadUrls\n }\n\n async uploadTestCase(\n testCaseReport: JsonTestProgress,\n runId: string,\n projectId: string,\n reportFolder: string\n ) {\n const fileUris = []\n //iterate over all the files in the JsonCommand.screenshotId and insert them into the fileUris array\n for (const step of testCaseReport.steps) {\n for (const command of step.commands) {\n if (command.screenshotId) {\n fileUris.push(\n 'screenshots' + '/' + String(command.screenshotId) + '.png'\n )\n }\n }\n }\n const preSignedUrls = await this.getPreSignedUrls(fileUris, runId)\n //upload all the files in the fileUris array\n try {\n for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {\n const batch = fileUris.slice(\n i,\n Math.min(i + BATCH_SIZE, fileUris.length)\n )\n await Promise.all(\n batch\n .filter((fileUri) => preSignedUrls[fileUri])\n .map(async (fileUri) => {\n for (let j = 0; j < MAX_RETRIES; j++) {\n const success = await this.uploadFile(\n path.join(reportFolder, fileUri),\n preSignedUrls[fileUri]\n )\n if (success) {\n return\n }\n }\n console.error('Failed to upload file:', fileUri)\n })\n )\n }\n await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/createNewTestCase',\n {\n runId,\n projectId,\n testProgressReport: testCaseReport,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n logReportLink(runId, projectId)\n } catch (e) {\n console.error(`failed to upload the test case: ${testCaseReport.id} ${e}`)\n }\n }\n async uploadFile(filePath: string, preSignedUrl: string) {\n const fileStream = createReadStream(filePath)\n let success = true\n try {\n const fileStats = await fs.stat(filePath)\n const fileSize = fileStats.size\n\n await axiosClient.put(preSignedUrl, fileStream, {\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'Content-Length': fileSize,\n },\n })\n } catch (error) {\n if (process.env.NODE_ENV_BLINQ === 'dev') {\n console.error('Error uploading file:', error)\n }\n success = false\n } finally {\n fileStream.close()\n }\n return success\n }\n async uploadComplete(runId: string, projectId: string) {\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/uploadCompletion',\n {\n runId,\n projectId,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status !== 200) {\n throw new Error('Failed to mark run as complete')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to mark run as complete')\n }\n }\n async modifyTestCase(\n runId: string,\n projectId: string,\n testProgressReport: JsonTestProgress\n ) {\n try {\n const res = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/modifyTestCase',\n {\n runId,\n projectId,\n testProgressReport,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (res.status !== 200) {\n throw new Error('')\n }\n if (res.data.status !== true) {\n throw new Error('')\n }\n logReportLink(runId, projectId)\n } catch (e) {\n console.error(\n `failed to modify the test case: ${testProgressReport.id} ${e}`\n )\n }\n }\n}\n\nexport { RunUploadService }\n"]}
|
|
1
|
+
{"version":3,"file":"upload_serivce.js","sourceRoot":"","sources":["../../../src/formatter/helpers/upload_serivce.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport FormData from 'form-data'\nimport { createReadStream, existsSync, write, writeFileSync } from 'fs'\nimport fs from 'fs/promises'\n\nimport { JsonReport, JsonTestProgress } from './report_generator'\nimport { axiosClient } from '../../configuration/axios_client'\nimport path from 'path'\nimport { logReportLink } from '../bvt_analysis_formatter'\nimport { ActionEvents, SERVICES_URI } from './constants'\n\nconst REPORT_SERVICE_URL = process.env.REPORT_SERVICE_URL ?? URL\nconst BATCH_SIZE = 10\nconst MAX_RETRIES = 3\nconst REPORT_SERVICE_TOKEN =\n process.env.TOKEN ?? process.env.REPORT_SERVICE_TOKEN\n\nexport interface RootCauseProps {\n status: boolean\n analysis: string\n failedStep: number\n failClass: string\n}\n\nexport interface FinishTestCaseResponse {\n status: true\n rootCause: RootCauseProps\n report: JsonTestProgress\n}\n\nclass RunUploadService {\n constructor(\n private runsApiBaseURL: string,\n private accessToken: string\n ) { }\n async createRunDocument(name: string, env: any) {\n if (process.env.UPLOADREPORTS === 'false') {\n console.log('Skipping report upload as UPLOADREPORTS is set to false')\n return { id: 'local-run', projectId: 'local-project' }\n }\n try {\n const runDocResult = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/create',\n {\n name: name ? name : 'TEST',\n branch: process.env.GIT_BRANCH ? process.env.GIT_BRANCH : 'main',\n video_id: process.env.VIDEO_ID,\n browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',\n mode:\n process.env.MODE === 'cloud'\n ? 'cloud'\n : process.env.MODE === 'executions'\n ? 'executions'\n : 'local',\n env: { name: env?.name, baseUrl: env?.baseUrl },\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (runDocResult.status !== 200) {\n throw new Error('Failed to create run document in the server')\n }\n if (runDocResult.data.status !== true) {\n throw new Error('Failed to create run document in the server')\n }\n return runDocResult.data.run\n } catch (error) {\n if (error.response && error.response.status === 403) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot create or upload reports.'\n )\n process.exit(1)\n }\n throw new Error('Failed to create run document in the server: ' + error)\n }\n }\n async updateProjectAnalytics(projectId: string) {\n if (process.env.UPLOADREPORTS === 'false') {\n return\n }\n try {\n await axiosClient.post(\n this.runsApiBaseURL + '/project/updateAIRecoveryCount',\n {\n projectId,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n } catch (error) {\n console.error('Failed to update project metadata:', error)\n }\n }\n async upload(formData: FormData) {\n if (process.env.UPLOADREPORTS === 'false') {\n return\n }\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/upload',\n formData,\n {\n headers: {\n ...formData.getHeaders(),\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status === 401) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n throw new Error(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n }\n if (response.status !== 200) {\n throw new Error('Failed to upload run to the server')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to upload run to the server')\n }\n }\n async getPreSignedUrls(fileUris: string[], runId: string) {\n if (process.env.UPLOADREPORTS === 'false') {\n return {}\n }\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/generateuploadurls',\n {\n fileUris,\n runId,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status === 403) {\n console.log(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n throw new Error(\n 'Warning: Your trial plan has ended. Cannot upload reports and perform retraining'\n )\n }\n if (response.status !== 200) {\n throw new Error('Failed to get pre-signed urls for the files')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to get pre-signed urls for the files')\n }\n\n return response.data.uploadUrls\n }\n\n async uploadTestCase(\n testCaseReport: JsonTestProgress,\n runId: string,\n projectId: string,\n reportFolder: string,\n rerunId?: string\n ) {\n if (process.env.UPLOADREPORTS === 'false') {\n return null\n }\n\n const fileUris: string[] = []\n\n // Collect screenshot + trace + logs\n for (const step of testCaseReport.steps) {\n for (const command of step.commands) {\n if (command.screenshotId) {\n fileUris.push(`screenshots/${String(command.screenshotId)}.png`)\n }\n }\n if (step.traceFilePath) {\n fileUris.push(`trace/${step.traceFilePath}`)\n }\n }\n\n if (testCaseReport.logFileId) {\n fileUris.push(`editorLogs/testCaseLog_${testCaseReport.logFileId}.log`)\n }\n\n if (testCaseReport.traceFileId) {\n fileUris.push(`trace/${testCaseReport.traceFileId}`)\n }\n\n //\n // 🔹 UPLOAD FILES (presigned URLs)\n //\n try {\n const preSignedUrls = await this.getPreSignedUrls(fileUris, runId)\n\n for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {\n const batch = fileUris.slice(i, Math.min(i + BATCH_SIZE, fileUris.length))\n\n await Promise.all(\n batch\n .filter((fileUri) => preSignedUrls[fileUri])\n .map(async (fileUri) => {\n for (let j = 0; j < MAX_RETRIES; j++) {\n try {\n const filePath = path.join(reportFolder, fileUri)\n\n if (existsSync(filePath)) {\n const ok = await this.uploadFile(filePath, preSignedUrls[fileUri])\n if (ok) return\n }\n\n } catch (err) {\n // Retry silently\n }\n }\n\n console.error(`Failed to upload file after retries: ${fileUri}`)\n })\n )\n }\n } catch (error: any) {\n const sanitized = this.sanitizeError(error)\n console.error('Error uploading files:', sanitized)\n }\n console.log(\"🟨 Screenshots:\", fileUris.length);\n\n //\n // 🔹 UPLOAD FINAL TEST REPORT (JSON metadata)\n //\n try {\n const mode =\n process.env.MODE === 'cloud'\n ? 'cloud'\n : process.env.MODE === 'executions'\n ? 'executions'\n : 'local'\n\n let rerunIdFinal = process.env.RETRY_ID || null\n if (rerunId) {\n rerunIdFinal = rerunId.includes(runId) ? rerunId : `${runId}${rerunId}`\n }\n\n if (mode === 'executions') {\n testCaseReport.id = process.env.VIDEO_ID || testCaseReport.id\n }\n const payload = {\n runId,\n projectId,\n testProgressReport: testCaseReport,\n browser: process.env.BROWSER || 'chromium',\n mode,\n rerunId: rerunIdFinal,\n video_id: process.env.VIDEO_ID,\n };\n\n const json = JSON.stringify(payload);\n console.log(\"🟥 Payload size KB:\", Buffer.byteLength(json) / 1024);\n const start = Date.now();\n const { data } = await axiosClient.post<FinishTestCaseResponse>(\n `${this.runsApiBaseURL}/cucumber-runs/createNewTestCase`,\n payload,\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n );\n console.log(\"🟩 POST /createNewTestCase finished in ms:\", Date.now() - start);\n\n // optional event — keep original logic\n try {\n await axiosClient.post(\n `${SERVICES_URI.STORAGE}/event`,\n { event: ActionEvents.upload_report },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n 'x-bvt-project-id': projectId,\n },\n }\n )\n } catch { }\n\n logReportLink(runId, projectId, testCaseReport.result)\n return data\n } catch (e: any) {\n const sanitized = this.sanitizeError(e);\n console.error(\"🟥 Raw response snippet:\", e?.response?.data?.toString()?.slice(0, 300));\n\n console.error(`failed to upload the test case: ${testCaseReport.id} ${sanitized}`)\n return null\n }\n }\n\n /**\n * Improving error logging\n * 🔧 Sanitizes Axios errors to avoid dumping Cloudflare HTML (524, 502, etc.)\n */\n private sanitizeError(error: any) {\n // Handle Axios-style errors with response\n if (error?.response) {\n const { data, status } = error.response;\n\n // If Cloudflare or HTML error page → return a short meaningful message\n if (typeof data === 'string' && data.includes('<!DOCTYPE html')) {\n return `[HTML_ERROR_PAGE] status=${status} - likely Cloudflare timeout or proxy error`;\n }\n\n // If data is a JSON object, stringify it with indentation for readability\n if (typeof data === 'object') {\n return JSON.stringify(data, null, 2); // Pretty-print the JSON response\n }\n\n // If response is a string (could be an error message), return it trimmed\n return data?.trim() || `Unknown response data (status: ${status})`;\n }\n\n // System / network errors (e.g., if Axios cannot reach the server)\n if (error?.message) {\n return error.message;\n }\n\n // If the error has a stack (for debugging purposes)\n if (error?.stack) {\n return `${error.message}\\n${error.stack}`;\n }\n\n // If it's a generic error object, attempt to stringify it in a readable format\n return JSON.stringify(error, (key, value) => {\n // Avoid circular references or sensitive data\n if (key === 'password' || key === 'accessToken') return '[REDACTED]';\n return value;\n }, 2); // Pretty-print the error object with indentation\n }\n\n async uploadFile(filePath: string, preSignedUrl: string) {\n if (process.env.UPLOADREPORTS === 'false') {\n return true\n }\n const fileStream = createReadStream(filePath)\n let success = true\n try {\n const fileStats = await fs.stat(filePath)\n const fileSize = fileStats.size\n\n await axiosClient.put(preSignedUrl, fileStream, {\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'Content-Length': fileSize,\n },\n })\n } catch (error) {\n if (process.env.MODE === 'executions') {\n const sanitized = this.sanitizeError(error)\n console.error('❌ Error uploading file at:', filePath, 'due to', sanitized);\n }\n success = false\n } finally {\n fileStream.close()\n }\n return success\n }\n async uploadComplete(runId: string, projectId: string) {\n if (process.env.UPLOADREPORTS === 'false') {\n return\n }\n const response = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/uploadCompletion',\n {\n runId,\n projectId,\n browser: process.env.BROWSER ? process.env.BROWSER : 'chromium',\n mode:\n process.env.MODE === 'cloud'\n ? 'cloud'\n : process.env.MODE === 'executions'\n ? 'executions'\n : 'local',\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (response.status !== 200) {\n throw new Error('Failed to mark run as complete')\n }\n if (response.data.status !== true) {\n throw new Error('Failed to mark run as complete')\n }\n\n try {\n await axiosClient.post(\n `${SERVICES_URI.STORAGE}/event`,\n {\n event: ActionEvents.upload_report,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n 'x-bvt-project-id': projectId,\n },\n }\n )\n } catch (error) {\n // no event tracking\n }\n }\n async modifyTestCase(\n runId: string,\n projectId: string,\n testProgressReport: JsonTestProgress\n ) {\n if (process.env.UPLOADREPORTS === 'false') {\n return\n }\n try {\n const res = await axiosClient.post(\n this.runsApiBaseURL + '/cucumber-runs/modifyTestCase',\n {\n runId,\n projectId,\n testProgressReport,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n if (res.status !== 200) {\n throw new Error('')\n }\n if (res.data.status !== true) {\n throw new Error('')\n }\n logReportLink(runId, projectId, testProgressReport.result)\n } catch (e) {\n console.error(\n `failed to modify the test case: ${testProgressReport.id} ${e}`\n )\n }\n }\n async createStatus(status: string) {\n if (process.env.UPLOADREPORTS === 'false') {\n return\n }\n if (!process.env.UUID) {\n return\n }\n\n try {\n await axiosClient.post(\n this.runsApiBaseURL + '/scenarios/status',\n {\n status: { status },\n uuid: process.env.UUID,\n },\n {\n headers: {\n Authorization: 'Bearer ' + this.accessToken,\n 'x-source': 'cucumber_js',\n },\n }\n )\n } catch (error) {\n console.log('Failed to send status to the server, ignoring it')\n }\n }\n}\n\nexport { RunUploadService }\n"]}
|
|
@@ -38,7 +38,11 @@ const URL = process.env.NODE_ENV_BLINQ === 'dev'
|
|
|
38
38
|
? 'http://localhost:5001/api/runs'
|
|
39
39
|
: process.env.NODE_ENV_BLINQ === 'stage'
|
|
40
40
|
? 'https://stage.api.blinq.io/api/runs'
|
|
41
|
-
:
|
|
41
|
+
: process.env.NODE_ENV_BLINQ === 'prod'
|
|
42
|
+
? 'https://api.blinq.io/api/runs'
|
|
43
|
+
: !process.env.NODE_ENV_BLINQ
|
|
44
|
+
? 'https://api.blinq.io/api/runs'
|
|
45
|
+
: `${process.env.NODE_ENV_BLINQ}/api/runs`;
|
|
42
46
|
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
43
47
|
const BATCH_SIZE = 10;
|
|
44
48
|
const MAX_RETRIES = 3;
|
|
@@ -52,7 +56,7 @@ class ReportUploader {
|
|
|
52
56
|
this.reportGenerator = reportGenerator;
|
|
53
57
|
}
|
|
54
58
|
async uploadRun(report, runName) {
|
|
55
|
-
const runDoc = await this.uploadService.createRunDocument(runName);
|
|
59
|
+
const runDoc = await this.uploadService.createRunDocument(runName, report.env);
|
|
56
60
|
const runDocId = runDoc._id;
|
|
57
61
|
const reportFolder = this.reportGenerator.reportFolder;
|
|
58
62
|
if (!fs_1.default.existsSync(reportFolder)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../../src/formatter/helpers/uploader.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios'\nimport ReportGenerator, {\n JsonReport,\n JsonTestProgress,\n} from './report_generator'\nimport { RunUploadService } from './upload_serivce'\n\nimport FormData from 'form-data'\nimport fs, { writeFileSync } from 'fs'\nimport JSZip from 'jszip'\nimport path from 'path'\nconst URL =\n process.env.NODE_ENV_BLINQ === 'dev'\n ? 'https://dev.api.blinq.io/api/runs'\n : process.env.NODE_ENV_BLINQ === 'local'\n ? 'http://localhost:5001/api/runs'\n : process.env.NODE_ENV_BLINQ === 'stage'\n ? 'https://stage.api.blinq.io/api/runs'\n : 'https://api.blinq.io/api/runs'\n\nconst REPORT_SERVICE_URL = process.env.REPORT_SERVICE_URL ?? URL\nconst BATCH_SIZE = 10\nconst MAX_RETRIES = 3\nconst REPORT_SERVICE_TOKEN =\n process.env.TOKEN ?? process.env.REPORT_SERVICE_TOKEN\n\nexport default class ReportUploader {\n private uploadService = new RunUploadService(\n REPORT_SERVICE_URL,\n REPORT_SERVICE_TOKEN\n )\n private reportGenerator: ReportGenerator\n constructor(reportGenerator: ReportGenerator) {\n if (!REPORT_SERVICE_URL || !REPORT_SERVICE_TOKEN) {\n throw new Error('REPORT_SERVICE_URL and REPORT_SERVICE_TOKEN must be set')\n }\n this.reportGenerator = reportGenerator\n }\n\n async uploadRun(report: JsonReport, runName: string) {\n const runDoc = await this.uploadService.createRunDocument(runName)\n const runDocId = runDoc._id\n const reportFolder = this.reportGenerator.reportFolder\n if (!fs.existsSync(reportFolder)) {\n fs.mkdirSync(reportFolder)\n }\n writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\n )\n if (process.env.NODE_ENV_BLINQ === 'local') {\n const formData = new FormData()\n const zipPath = await this.createZip(reportFolder, report)\n formData.append(runDocId, fs.readFileSync(zipPath), 'report.zip')\n await this.uploadService.upload(formData)\n } else {\n const fileUris = [\n ...getFileUris(reportFolder, 'screenshots'),\n ...getFileUris(reportFolder, 'trace'),\n 'report.json',\n 'network.json',\n ]\n try {\n const preSignedUrls = await this.uploadService.getPreSignedUrls(\n fileUris,\n runDocId\n )\n\n for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {\n const batch = fileUris.slice(\n i,\n Math.min(i + BATCH_SIZE, fileUris.length)\n )\n await Promise.all(\n batch\n .filter((fileUri) => preSignedUrls[fileUri])\n .map(async (fileUri) => {\n for (let j = 0; j < MAX_RETRIES; j++) {\n const success = await this.uploadService.uploadFile(\n path.join(reportFolder, fileUri),\n preSignedUrls[fileUri]\n )\n if (success) {\n return\n }\n }\n console.error('Failed to upload file:', fileUri)\n })\n )\n }\n await this.uploadService.uploadComplete(runDocId, runDoc.project_id)\n } catch (err) {\n throw new Error('Failed to upload all the files')\n }\n }\n return { runId: runDoc._id, projectId: runDoc.project_id }\n }\n\n async modifyTestCase(testCase: JsonTestProgress) {\n const runId = process.env.RUN_ID\n if (!runId) {\n return\n }\n const projectId = process.env.PROJECT_ID\n if (!projectId) {\n return\n }\n await this.uploadService.modifyTestCase(runId, projectId, testCase)\n }\n async createZip(reportFolder: string | null, report: JsonReport) {\n if (reportFolder === null) {\n console.error('report folder is empty')\n console.error('it is likey that there are no scenarios to run')\n throw new Error('Empty report folder')\n }\n const zip = new JSZip()\n zip.file('report.json', JSON.stringify(report, null, 2))\n const folder = zip.folder('screenshots')\n const files = fs.readdirSync(path.join(reportFolder, 'screenshots'))\n files.forEach((file) => {\n folder.file(\n file,\n fs.readFileSync(path.join(reportFolder, 'screenshots', file))\n )\n })\n const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' })\n // save zip file\n const zipPath = path.join(reportFolder, 'report.zip')\n fs.writeFileSync(zipPath, new Uint8Array(zipBuffer))\n fs.writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\n )\n return zipPath\n }\n}\n\nconst getFileUrisScreenShotDir = (reportFolder: string) => {\n const files = fs.readdirSync(path.join(reportFolder, 'screenshots'))\n\n return files.map((file) => ['screenshots', file].join('/'))\n}\n\nconst getFileUris = (reportFolder: string, targetFolder: string) => {\n const resultFolder = path.join(reportFolder, targetFolder)\n if (!fs.existsSync(resultFolder)) {\n return []\n }\n const files = fs.readdirSync(resultFolder)\n return files.map((file) => [targetFolder, file].join('/'))\n}\n"]}
|
|
1
|
+
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../../src/formatter/helpers/uploader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,qDAAmD;AAEnD,0DAAgC;AAChC,yCAAsC;AACtC,kDAAyB;AACzB,gDAAuB;AACvB,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,KAAK;IAClC,CAAC,CAAC,mCAAmC;IACrC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;QACtC,CAAC,CAAC,gCAAgC;QAClC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;YACtC,CAAC,CAAC,qCAAqC;YACvC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM;gBACrC,CAAC,CAAC,+BAA+B;gBACjC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc;oBAC3B,CAAC,CAAC,+BAA+B;oBACjC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW,CAAA;AAEtD,MAAM,kBAAkB,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,kBAAkB,mCAAI,GAAG,CAAA;AAChE,MAAM,UAAU,GAAG,EAAE,CAAA;AACrB,MAAM,WAAW,GAAG,CAAC,CAAA;AACrB,MAAM,oBAAoB,GACxB,MAAA,OAAO,CAAC,GAAG,CAAC,KAAK,mCAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAA;AAEvD,MAAqB,cAAc;IAMjC,YAAY,eAAgC;QALpC,kBAAa,GAAG,IAAI,iCAAgB,CAC1C,kBAAkB,EAClB,oBAAoB,CACrB,CAAA;QAGC,IAAI,CAAC,kBAAkB,IAAI,CAAC,oBAAoB,EAAE;YAChD,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAA;SAC3E;QACD,IAAI,CAAC,eAAe,GAAG,eAAe,CAAA;IACxC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAAkB,EAAE,OAAe;QACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,iBAAiB,CACvD,OAAO,EACP,MAAM,CAAC,GAAG,CACX,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAA;QAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAA;QACtD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE;YAChC,YAAE,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;SAC3B;QACD,IAAA,kBAAa,EACX,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,EACtC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAChC,CAAA;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO,EAAE;YAC1C,MAAM,QAAQ,GAAG,IAAI,mBAAQ,EAAE,CAAA;YAC/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;YAC1D,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAE,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC,CAAA;YACjE,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;SAC1C;aAAM;YACL,MAAM,QAAQ,GAAG;gBACf,GAAG,WAAW,CAAC,YAAY,EAAE,aAAa,CAAC;gBAC3C,GAAG,WAAW,CAAC,YAAY,EAAE,OAAO,CAAC;gBACrC,aAAa;gBACb,cAAc;aACf,CAAA;YACD,IAAI;gBACF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAC7D,QAAQ,EACR,QAAQ,CACT,CAAA;gBAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE;oBACpD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAC1B,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAC1C,CAAA;oBACD,MAAM,OAAO,CAAC,GAAG,CACf,KAAK;yBACF,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;yBAC3C,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;wBACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE;4BACpC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CACjD,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,EAChC,aAAa,CAAC,OAAO,CAAC,CACvB,CAAA;4BACD,IAAI,OAAO,EAAE;gCACX,OAAM;6BACP;yBACF;wBACD,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAA;oBAClD,CAAC,CAAC,CACL,CAAA;iBACF;gBACD,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;aACrE;YAAC,OAAO,GAAG,EAAE;gBACZ,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;aACnD;SACF;QACD,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,CAAA;IAC5D,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAA0B;QAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAA;QAChC,IAAI,CAAC,KAAK,EAAE;YACV,OAAM;SACP;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAA;QACxC,IAAI,CAAC,SAAS,EAAE;YACd,OAAM;SACP;QACD,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;IACrE,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,YAA2B,EAAE,MAAkB;QAC7D,IAAI,YAAY,KAAK,IAAI,EAAE;YACzB,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;YACvC,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAA;YAC/D,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;SACvC;QACD,MAAM,GAAG,GAAG,IAAI,eAAK,EAAE,CAAA;QACvB,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QACxD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;QACxC,MAAM,KAAK,GAAG,YAAE,CAAC,WAAW,CAAC,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAA;QACpE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,MAAM,CAAC,IAAI,CACT,IAAI,EACJ,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,CAC9D,CAAA;QACH,CAAC,CAAC,CAAA;QACF,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAA;QACjE,gBAAgB;QAChB,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;QACrD,YAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAA;QACpD,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,EACtC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAChC,CAAA;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;CACF;AAhHD,iCAgHC;AAED,MAAM,wBAAwB,GAAG,CAAC,YAAoB,EAAE,EAAE;IACxD,MAAM,KAAK,GAAG,YAAE,CAAC,WAAW,CAAC,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAA;IAEpE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAC7D,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,CAAC,YAAoB,EAAE,YAAoB,EAAE,EAAE;IACjE,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;IAC1D,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE;QAChC,OAAO,EAAE,CAAA;KACV;IACD,MAAM,KAAK,GAAG,YAAE,CAAC,WAAW,CAAC,YAAY,CAAC,CAAA;IAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAC5D,CAAC,CAAA","sourcesContent":["import axios from 'axios'\nimport ReportGenerator, {\n JsonReport,\n JsonTestProgress,\n} from './report_generator'\nimport { RunUploadService } from './upload_serivce'\n\nimport FormData from 'form-data'\nimport fs, { writeFileSync } from 'fs'\nimport JSZip from 'jszip'\nimport path from 'path'\nconst URL =\n process.env.NODE_ENV_BLINQ === 'dev'\n ? 'https://dev.api.blinq.io/api/runs'\n : process.env.NODE_ENV_BLINQ === 'local'\n ? 'http://localhost:5001/api/runs'\n : process.env.NODE_ENV_BLINQ === 'stage'\n ? 'https://stage.api.blinq.io/api/runs'\n : process.env.NODE_ENV_BLINQ === 'prod'\n ? 'https://api.blinq.io/api/runs'\n : !process.env.NODE_ENV_BLINQ\n ? 'https://api.blinq.io/api/runs'\n : `${process.env.NODE_ENV_BLINQ}/api/runs`\n\nconst REPORT_SERVICE_URL = process.env.REPORT_SERVICE_URL ?? URL\nconst BATCH_SIZE = 10\nconst MAX_RETRIES = 3\nconst REPORT_SERVICE_TOKEN =\n process.env.TOKEN ?? process.env.REPORT_SERVICE_TOKEN\n\nexport default class ReportUploader {\n private uploadService = new RunUploadService(\n REPORT_SERVICE_URL,\n REPORT_SERVICE_TOKEN\n )\n private reportGenerator: ReportGenerator\n constructor(reportGenerator: ReportGenerator) {\n if (!REPORT_SERVICE_URL || !REPORT_SERVICE_TOKEN) {\n throw new Error('REPORT_SERVICE_URL and REPORT_SERVICE_TOKEN must be set')\n }\n this.reportGenerator = reportGenerator\n }\n\n async uploadRun(report: JsonReport, runName: string) {\n const runDoc = await this.uploadService.createRunDocument(\n runName,\n report.env\n )\n const runDocId = runDoc._id\n const reportFolder = this.reportGenerator.reportFolder\n if (!fs.existsSync(reportFolder)) {\n fs.mkdirSync(reportFolder)\n }\n writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\n )\n if (process.env.NODE_ENV_BLINQ === 'local') {\n const formData = new FormData()\n const zipPath = await this.createZip(reportFolder, report)\n formData.append(runDocId, fs.readFileSync(zipPath), 'report.zip')\n await this.uploadService.upload(formData)\n } else {\n const fileUris = [\n ...getFileUris(reportFolder, 'screenshots'),\n ...getFileUris(reportFolder, 'trace'),\n 'report.json',\n 'network.json',\n ]\n try {\n const preSignedUrls = await this.uploadService.getPreSignedUrls(\n fileUris,\n runDocId\n )\n\n for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {\n const batch = fileUris.slice(\n i,\n Math.min(i + BATCH_SIZE, fileUris.length)\n )\n await Promise.all(\n batch\n .filter((fileUri) => preSignedUrls[fileUri])\n .map(async (fileUri) => {\n for (let j = 0; j < MAX_RETRIES; j++) {\n const success = await this.uploadService.uploadFile(\n path.join(reportFolder, fileUri),\n preSignedUrls[fileUri]\n )\n if (success) {\n return\n }\n }\n console.error('Failed to upload file:', fileUri)\n })\n )\n }\n await this.uploadService.uploadComplete(runDocId, runDoc.project_id)\n } catch (err) {\n throw new Error('Failed to upload all the files')\n }\n }\n return { runId: runDoc._id, projectId: runDoc.project_id }\n }\n\n async modifyTestCase(testCase: JsonTestProgress) {\n const runId = process.env.RUN_ID\n if (!runId) {\n return\n }\n const projectId = process.env.PROJECT_ID\n if (!projectId) {\n return\n }\n await this.uploadService.modifyTestCase(runId, projectId, testCase)\n }\n async createZip(reportFolder: string | null, report: JsonReport) {\n if (reportFolder === null) {\n console.error('report folder is empty')\n console.error('it is likey that there are no scenarios to run')\n throw new Error('Empty report folder')\n }\n const zip = new JSZip()\n zip.file('report.json', JSON.stringify(report, null, 2))\n const folder = zip.folder('screenshots')\n const files = fs.readdirSync(path.join(reportFolder, 'screenshots'))\n files.forEach((file) => {\n folder.file(\n file,\n fs.readFileSync(path.join(reportFolder, 'screenshots', file))\n )\n })\n const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' })\n // save zip file\n const zipPath = path.join(reportFolder, 'report.zip')\n fs.writeFileSync(zipPath, new Uint8Array(zipBuffer))\n fs.writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\n )\n return zipPath\n }\n}\n\nconst getFileUrisScreenShotDir = (reportFolder: string) => {\n const files = fs.readdirSync(path.join(reportFolder, 'screenshots'))\n\n return files.map((file) => ['screenshots', file].join('/'))\n}\n\nconst getFileUris = (reportFolder: string, targetFolder: string) => {\n const resultFolder = path.join(reportFolder, targetFolder)\n if (!fs.existsSync(resultFolder)) {\n return []\n }\n const files = fs.readdirSync(resultFolder)\n return files.map((file) => [targetFolder, file].join('/'))\n}\n"]}
|
|
@@ -8,6 +8,7 @@ const _1 = __importDefault(require("./"));
|
|
|
8
8
|
const value_checker_1 = require("../value_checker");
|
|
9
9
|
const issue_helpers_1 = require("./helpers/issue_helpers");
|
|
10
10
|
const time_1 = require("../time");
|
|
11
|
+
const bvt_analysis_formatter_1 = require("./bvt_analysis_formatter");
|
|
11
12
|
class SummaryFormatter extends _1.default {
|
|
12
13
|
constructor(options) {
|
|
13
14
|
super(options);
|
|
@@ -43,6 +44,9 @@ class SummaryFormatter extends _1.default {
|
|
|
43
44
|
if (warnings.length > 0) {
|
|
44
45
|
this.logIssues({ issues: warnings, title: 'Warnings' });
|
|
45
46
|
}
|
|
47
|
+
if (bvt_analysis_formatter_1.globalReportLink) {
|
|
48
|
+
console.log(`Report link: ${bvt_analysis_formatter_1.globalReportLink}\n`);
|
|
49
|
+
}
|
|
46
50
|
this.log((0, helpers_1.formatSummary)({
|
|
47
51
|
colorFns: this.colorFns,
|
|
48
52
|
testCaseAttempts,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary_formatter.js","sourceRoot":"","sources":["../../src/formatter/summary_formatter.ts"],"names":[],"mappings":";;;;;AAAA,uCAA4E;AAC5E,0CAAiD;AACjD,oDAAgD;AAGhD,2DAAuE;AACvE,kCAAmD;
|
|
1
|
+
{"version":3,"file":"summary_formatter.js","sourceRoot":"","sources":["../../src/formatter/summary_formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatIssue, formatSummary, isFailure, isWarning } from './helpers'\nimport Formatter, { IFormatterOptions } from './'\nimport { doesHaveValue } from '../value_checker'\nimport * as messages from '@cucumber/messages'\nimport { ITestCaseAttempt } from './helpers/event_data_collector'\nimport { formatUndefinedParameterTypes } from './helpers/issue_helpers'\nimport { durationBetweenTimestamps } from '../time'\nimport { globalReportLink } from './bvt_analysis_formatter'\n\ninterface ILogIssuesRequest {\n issues: ITestCaseAttempt[]\n title: string\n}\n\nexport default class SummaryFormatter extends Formatter {\n public static readonly documentation: string =\n 'Summary output of feature and scenarios'\n\n constructor(options: IFormatterOptions) {\n super(options)\n let testRunStartedTimestamp: messages.Timestamp\n options.eventBroadcaster.on('envelope', (envelope: messages.Envelope) => {\n if (doesHaveValue(envelope.testRunStarted)) {\n testRunStartedTimestamp = envelope.testRunStarted.timestamp\n }\n if (doesHaveValue(envelope.testRunFinished)) {\n const testRunFinishedTimestamp = envelope.testRunFinished.timestamp\n this.logSummary(\n durationBetweenTimestamps(\n testRunStartedTimestamp,\n testRunFinishedTimestamp\n )\n )\n }\n })\n }\n\n logSummary(testRunDuration: messages.Duration): void {\n const failures: ITestCaseAttempt[] = []\n const warnings: ITestCaseAttempt[] = []\n const testCaseAttempts = this.eventDataCollector.getTestCaseAttempts()\n testCaseAttempts.forEach((testCaseAttempt) => {\n if (\n isFailure(\n testCaseAttempt.worstTestStepResult,\n testCaseAttempt.willBeRetried\n )\n ) {\n failures.push(testCaseAttempt)\n } else if (\n isWarning(\n testCaseAttempt.worstTestStepResult,\n testCaseAttempt.willBeRetried\n )\n ) {\n warnings.push(testCaseAttempt)\n }\n })\n if (this.eventDataCollector.undefinedParameterTypes.length > 0) {\n this.log(\n formatUndefinedParameterTypes(\n this.eventDataCollector.undefinedParameterTypes\n )\n )\n }\n if (failures.length > 0) {\n this.logIssues({ issues: failures, title: 'Failures' })\n }\n if (warnings.length > 0) {\n this.logIssues({ issues: warnings, title: 'Warnings' })\n }\n if (globalReportLink) {\n console.log(`Report link: ${globalReportLink}\\n`)\n }\n this.log(\n formatSummary({\n colorFns: this.colorFns,\n testCaseAttempts,\n testRunDuration,\n })\n )\n }\n\n logIssues({ issues, title }: ILogIssuesRequest): void {\n this.log(`${title}:\\n\\n`)\n issues.forEach((testCaseAttempt, index) => {\n this.log(\n formatIssue({\n colorFns: this.colorFns,\n number: index + 1,\n snippetBuilder: this.snippetBuilder,\n supportCodeLibrary: this.supportCodeLibrary,\n testCaseAttempt,\n printAttachments: this.printAttachments,\n })\n )\n })\n }\n}\n"]}
|
|
@@ -37,6 +37,8 @@ export default class TestCaseRunner {
|
|
|
37
37
|
private testStepResults;
|
|
38
38
|
private world;
|
|
39
39
|
private readonly worldParameters;
|
|
40
|
+
private retryTestCaseId;
|
|
41
|
+
private reportGenerator;
|
|
40
42
|
constructor({ eventBroadcaster, stopwatch, gherkinDocument, newId, pickle, testCase, retries, skip, filterStackTraces, supportCodeLibrary, worldParameters, }: INewTestCaseRunnerOptions);
|
|
41
43
|
resetTestProgressData(): void;
|
|
42
44
|
getBeforeStepHookDefinitions(): TestStepHookDefinition[];
|
|
@@ -32,6 +32,8 @@ const step_runner_1 = __importDefault(require("./step_runner"));
|
|
|
32
32
|
const messages = __importStar(require("@cucumber/messages"));
|
|
33
33
|
const messages_1 = require("@cucumber/messages");
|
|
34
34
|
const value_checker_1 = require("../value_checker");
|
|
35
|
+
const report_generator_1 = __importDefault(require("../formatter/helpers/report_generator"));
|
|
36
|
+
const bvt_analysis_formatter_1 = __importDefault(require("../formatter/bvt_analysis_formatter"));
|
|
35
37
|
class TestCaseRunner {
|
|
36
38
|
constructor({ eventBroadcaster, stopwatch, gherkinDocument, newId, pickle, testCase, retries = 0, skip, filterStackTraces, supportCodeLibrary, worldParameters, }) {
|
|
37
39
|
this.attachmentManager = new attachment_manager_1.default(({ data, media, fileName }) => {
|
|
@@ -62,6 +64,7 @@ class TestCaseRunner {
|
|
|
62
64
|
this.supportCodeLibrary = supportCodeLibrary;
|
|
63
65
|
this.worldParameters = worldParameters;
|
|
64
66
|
this.resetTestProgressData();
|
|
67
|
+
this.reportGenerator = new report_generator_1.default();
|
|
65
68
|
}
|
|
66
69
|
resetTestProgressData() {
|
|
67
70
|
this.world = new this.supportCodeLibrary.World({
|
|
@@ -149,9 +152,16 @@ class TestCaseRunner {
|
|
|
149
152
|
testCaseId: this.testCase.id,
|
|
150
153
|
id: this.currentTestCaseStartedId,
|
|
151
154
|
timestamp: this.stopwatch.timestamp(),
|
|
155
|
+
retryTestCaseId: this.retryTestCaseId,
|
|
152
156
|
},
|
|
153
157
|
};
|
|
158
|
+
if (process.env.NODE_ENV === 'test') {
|
|
159
|
+
delete testCaseStarted.testCaseStarted.retryTestCaseId;
|
|
160
|
+
}
|
|
154
161
|
this.eventBroadcaster.emit('envelope', testCaseStarted);
|
|
162
|
+
if (this.maxAttempts > 1 && attempt === 0) {
|
|
163
|
+
this.retryTestCaseId = this.currentTestCaseStartedId;
|
|
164
|
+
}
|
|
155
165
|
// used to determine whether a hook is a Before or After
|
|
156
166
|
let didWeRunStepsYet = false;
|
|
157
167
|
for (const testStep of this.testCase.testSteps) {
|
|
@@ -187,7 +197,13 @@ class TestCaseRunner {
|
|
|
187
197
|
willBeRetried,
|
|
188
198
|
},
|
|
189
199
|
};
|
|
190
|
-
|
|
200
|
+
const rerunId = bvt_analysis_formatter_1.default.reRunFailedStepsIndex
|
|
201
|
+
? bvt_analysis_formatter_1.default.reRunFailedStepsIndex[0].testCaseId
|
|
202
|
+
: null;
|
|
203
|
+
const data = bvt_analysis_formatter_1.default.reportGenerator
|
|
204
|
+
? await bvt_analysis_formatter_1.default.reportGenerator.handleMessage(testCaseFinished, rerunId)
|
|
205
|
+
: null;
|
|
206
|
+
this.eventBroadcaster.emit('envelope', testCaseFinished, data);
|
|
191
207
|
return willBeRetried;
|
|
192
208
|
}
|
|
193
209
|
async runHook(hookDefinition, hookParameter, isBeforeHook) {
|