@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.
Files changed (41) hide show
  1. package/bin/cucumber.ts +1 -0
  2. package/bin/download-install.js +22 -2
  3. package/lib/api/console_logger.js.map +1 -1
  4. package/lib/cli/run.js +1 -0
  5. package/lib/cli/run.js.map +1 -1
  6. package/lib/cli/validate_node_engine_version.js +3 -1
  7. package/lib/cli/validate_node_engine_version.js.map +1 -1
  8. package/lib/configuration/axios_client.js +1 -1
  9. package/lib/configuration/axios_client.js.map +1 -1
  10. package/lib/formatter/api.js +16 -5
  11. package/lib/formatter/api.js.map +1 -1
  12. package/lib/formatter/builder.js +1 -3
  13. package/lib/formatter/builder.js.map +1 -1
  14. package/lib/formatter/bvt_analysis_formatter.d.ts +12 -1
  15. package/lib/formatter/bvt_analysis_formatter.js +161 -55
  16. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  17. package/lib/formatter/feature_data_format.js +22 -8
  18. package/lib/formatter/feature_data_format.js.map +1 -1
  19. package/lib/formatter/helpers/constants.d.ts +50 -0
  20. package/lib/formatter/helpers/constants.js +60 -0
  21. package/lib/formatter/helpers/constants.js.map +1 -0
  22. package/lib/formatter/helpers/report_generator.d.ts +22 -3
  23. package/lib/formatter/helpers/report_generator.js +336 -27
  24. package/lib/formatter/helpers/report_generator.js.map +1 -1
  25. package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
  26. package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
  27. package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
  28. package/lib/formatter/helpers/upload_serivce.d.ts +20 -2
  29. package/lib/formatter/helpers/upload_serivce.js +210 -17
  30. package/lib/formatter/helpers/upload_serivce.js.map +1 -1
  31. package/lib/formatter/helpers/uploader.js +6 -2
  32. package/lib/formatter/helpers/uploader.js.map +1 -1
  33. package/lib/formatter/summary_formatter.js +4 -0
  34. package/lib/formatter/summary_formatter.js.map +1 -1
  35. package/lib/runtime/test_case_runner.d.ts +2 -0
  36. package/lib/runtime/test_case_runner.js +17 -1
  37. package/lib/runtime/test_case_runner.js.map +1 -1
  38. package/lib/version.d.ts +1 -1
  39. package/lib/version.js +1 -1
  40. package/lib/version.js.map +1 -1
  41. 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
- //iterate over all the files in the JsonCommand.screenshotId and insert them into the fileUris array
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('screenshots' + '/' + String(command.screenshotId) + '.png');
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
- const preSignedUrls = await this.getPreSignedUrls(fileUris, runId);
100
- //upload all the files in the fileUris array
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
- const success = await this.uploadFile(path_1.default.join(reportFolder, fileUri), preSignedUrls[fileUri]);
109
- if (success) {
110
- return;
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('Failed to upload file:', fileUri);
173
+ console.error(`Failed to upload file after retries: ${fileUri}`);
114
174
  }));
115
175
  }
116
- await axios_client_1.axiosClient.post(this.runsApiBaseURL + '/cucumber-runs/createNewTestCase', {
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
- (0, bvt_analysis_formatter_1.logReportLink)(runId, projectId);
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
- console.error(`failed to upload the test case: ${testCaseReport.id} ${e}`);
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.NODE_ENV_BLINQ === 'dev') {
147
- console.error('Error uploading file:', error);
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
- : 'https://api.blinq.io/api/runs';
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":"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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 : 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":"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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'\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 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"]}
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
- this.eventBroadcaster.emit('envelope', testCaseFinished);
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) {