@dev-blinq/cucumber-js 1.0.103 → 1.0.104-stage

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,40 +1,40 @@
1
- import * as messages from "@cucumber/messages";
1
+ import * as messages from '@cucumber/messages';
2
2
  type JsonTimestamp = number;
3
- type JsonStepType = "Unknown" | "Context" | "Action" | "Outcome" | "Conjunction";
3
+ type JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome' | 'Conjunction';
4
4
  export type JsonResultUnknown = {
5
- status: "UNKNOWN";
5
+ status: 'UNKNOWN';
6
6
  };
7
7
  type JsonResultSkipped = {
8
- status: "SKIPPED";
8
+ status: 'SKIPPED';
9
9
  };
10
10
  type JsonResultUndefined = {
11
- status: "UNDEFINED";
11
+ status: 'UNDEFINED';
12
12
  };
13
13
  type JsonResultAmbiguous = {
14
- status: "AMBIGUOUS";
14
+ status: 'AMBIGUOUS';
15
15
  };
16
16
  export type JsonResultStarted = {
17
- status: "STARTED";
17
+ status: 'STARTED';
18
18
  startTime: JsonTimestamp;
19
19
  };
20
20
  type JsonResultPending = {
21
- status: "PENDING";
21
+ status: 'PENDING';
22
22
  startTime: JsonTimestamp;
23
23
  endTime: JsonTimestamp;
24
24
  };
25
25
  export type JsonResultPassed = {
26
- status: "PASSED";
26
+ status: 'PASSED';
27
27
  startTime: JsonTimestamp;
28
28
  endTime: JsonTimestamp;
29
29
  };
30
30
  export type JsonResultFailed = {
31
- status: "FAILED";
31
+ status: 'FAILED';
32
32
  startTime: JsonTimestamp;
33
33
  endTime: JsonTimestamp;
34
34
  message?: string;
35
35
  };
36
36
  export type JsonFixedByAi = {
37
- status: "FIXED_BY_AI";
37
+ status: 'FIXED_BY_AI';
38
38
  startTime: JsonTimestamp;
39
39
  endTime: JsonTimestamp;
40
40
  };
@@ -68,6 +68,7 @@ export type JsonStep = {
68
68
  ariaSnapshot: string;
69
69
  traceFilePath?: string;
70
70
  brunoData?: any;
71
+ interceptResults?: any;
71
72
  };
72
73
  export type RetrainStats = {
73
74
  result: JsonTestResult;
@@ -87,6 +88,7 @@ export type JsonTestProgress = {
87
88
  initialAriaSnapshot?: string;
88
89
  webLog: any;
89
90
  networkLog: any;
91
+ logFileId?: string;
90
92
  env: {
91
93
  name: string;
92
94
  baseUrl: string;
@@ -123,6 +125,8 @@ export default class ReportGenerator {
123
125
  private runName;
124
126
  private ariaSnapshot;
125
127
  private initialAriaSnapshot;
128
+ private testCaseLog;
129
+ private loggingOverridden;
126
130
  reportFolder: null | string;
127
131
  private uploadService;
128
132
  handleMessage(envelope: EnvelopeWithMetaMessage | messages.Envelope, reRunId?: string): Promise<any>;
@@ -143,7 +147,9 @@ export default class ReportGenerator {
143
147
  getLogFileContent(): any;
144
148
  private getTestCaseResult;
145
149
  private onTestCaseFinished;
150
+ private readonly retryCount;
146
151
  private uploadTestCase;
152
+ private tryUpload;
147
153
  private writeTestCaseReportToDisk;
148
154
  private onTestRunFinished;
149
155
  }
@@ -34,16 +34,16 @@ const upload_serivce_1 = require("./upload_serivce");
34
34
  const fs_extra_1 = require("fs-extra");
35
35
  // type JsonException = messages.Exception
36
36
  const object_path_1 = __importDefault(require("object-path"));
37
- const URL = process.env.NODE_ENV_BLINQ === "dev"
38
- ? "https://dev.api.blinq.io/api/runs"
39
- : process.env.NODE_ENV_BLINQ === "local"
40
- ? "http://localhost:5001/api/runs"
41
- : process.env.NODE_ENV_BLINQ === "stage"
42
- ? "https://stage.api.blinq.io/api/runs"
43
- : process.env.NODE_ENV_BLINQ === "prod"
44
- ? "https://api.blinq.io/api/runs"
37
+ const URL = process.env.NODE_ENV_BLINQ === 'dev'
38
+ ? 'https://dev.api.blinq.io/api/runs'
39
+ : process.env.NODE_ENV_BLINQ === 'local'
40
+ ? 'http://localhost:5001/api/runs'
41
+ : process.env.NODE_ENV_BLINQ === 'stage'
42
+ ? 'https://stage.api.blinq.io/api/runs'
43
+ : process.env.NODE_ENV_BLINQ === 'prod'
44
+ ? 'https://api.blinq.io/api/runs'
45
45
  : !process.env.NODE_ENV_BLINQ
46
- ? "https://api.blinq.io/api/runs"
46
+ ? 'https://api.blinq.io/api/runs'
47
47
  : `${process.env.NODE_ENV_BLINQ}/api/runs`;
48
48
  const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
49
49
  const BATCH_SIZE = 10;
@@ -53,12 +53,12 @@ class ReportGenerator {
53
53
  constructor() {
54
54
  this.report = {
55
55
  result: {
56
- status: "UNKNOWN",
56
+ status: 'UNKNOWN',
57
57
  },
58
58
  testCases: [],
59
59
  env: {
60
- name: "",
61
- baseUrl: "",
60
+ name: '',
61
+ baseUrl: '',
62
62
  },
63
63
  };
64
64
  this.gherkinDocumentMap = new Map();
@@ -73,75 +73,100 @@ class ReportGenerator {
73
73
  this.networkLog = [];
74
74
  this.stepLogs = [];
75
75
  this.stepNetworkLogs = [];
76
- this.runName = "";
77
- this.ariaSnapshot = "";
78
- this.initialAriaSnapshot = "";
76
+ this.runName = '';
77
+ this.ariaSnapshot = '';
78
+ this.initialAriaSnapshot = '';
79
+ this.testCaseLog = [];
80
+ this.loggingOverridden = false; // Flag to track if logging is overridden
79
81
  this.reportFolder = null;
80
82
  this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
83
+ this.retryCount = 3;
81
84
  }
82
85
  async handleMessage(envelope, reRunId) {
83
- if (envelope.meta && "runName" in envelope.meta) {
86
+ if (envelope.meta && 'runName' in envelope.meta) {
84
87
  this.runName = envelope.meta.runName;
85
88
  }
86
89
  const type = Object.keys(envelope)[0];
87
90
  switch (type) {
88
91
  // case "meta": { break}
89
92
  // case "source": { break}
90
- case "parseError": {
93
+ case 'parseError': {
91
94
  const parseError = envelope[type];
92
95
  this.handleParseError(parseError);
93
96
  break;
94
97
  }
95
- case "gherkinDocument": {
98
+ case 'gherkinDocument': {
96
99
  const doc = envelope[type];
97
100
  this.onGherkinDocument(doc);
98
101
  break;
99
102
  }
100
- case "pickle": {
103
+ case 'pickle': {
101
104
  const pickle = envelope[type];
102
105
  this.onPickle(pickle);
103
106
  break;
104
107
  }
105
108
  // case "stepDefinition": { break}
106
109
  // case "hook": { break} // Before Hook
107
- case "testRunStarted": {
110
+ case 'testRunStarted': {
108
111
  const testRunStarted = envelope[type];
109
112
  this.onTestRunStarted(testRunStarted);
113
+ await this.uploadService.createStatus('running');
110
114
  break;
111
115
  }
112
- case "testCase": {
116
+ case 'testCase': {
113
117
  const testCase = envelope[type];
118
+ // Initialize the log storage
119
+ this.testCaseLog = [];
120
+ if (!this.loggingOverridden) {
121
+ this.loggingOverridden = true;
122
+ // Store the original process.stdout.write, and process.stderr.write
123
+ const originalStdoutWrite = process.stdout.write;
124
+ const originalStderrWrite = process.stderr.write;
125
+ // Override process.stdout.write
126
+ process.stdout.write = (chunk, ...args) => {
127
+ this.testCaseLog.push(chunk.toString());
128
+ return originalStdoutWrite.call(process.stdout, chunk, ...args);
129
+ };
130
+ // Override process.stderr.write
131
+ process.stderr.write = (chunk, ...args) => {
132
+ this.testCaseLog.push(chunk.toString());
133
+ return originalStderrWrite.call(process.stderr, chunk, ...args);
134
+ };
135
+ }
136
+ // Call the onTestCase method
114
137
  this.onTestCase(testCase);
115
138
  break;
116
139
  }
117
- case "testCaseStarted": {
140
+ case 'testCaseStarted': {
118
141
  const testCaseStarted = envelope[type];
119
142
  this.onTestCaseStarted(testCaseStarted);
120
143
  break;
121
144
  }
122
- case "testStepStarted": {
145
+ case 'testStepStarted': {
123
146
  const testStepStarted = envelope[type];
124
147
  this.onTestStepStarted(testStepStarted);
125
148
  break;
126
149
  }
127
- case "attachment": {
150
+ case 'attachment': {
128
151
  const attachment = envelope[type];
129
152
  this.onAttachment(attachment);
130
153
  break;
131
154
  }
132
- case "testStepFinished": {
155
+ case 'testStepFinished': {
133
156
  const testStepFinished = envelope[type];
134
157
  this.onTestStepFinished(testStepFinished);
135
158
  break;
136
159
  }
137
- case "testCaseFinished": {
160
+ case 'testCaseFinished': {
138
161
  const testCaseFinished = envelope[type];
139
- return await this.onTestCaseFinished(testCaseFinished, reRunId);
162
+ // Call the onTestCaseFinished method
163
+ const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
164
+ return result;
140
165
  }
141
166
  // case "hook": { break} // After Hook
142
- case "testRunFinished": {
167
+ case 'testRunFinished': {
143
168
  const testRunFinished = envelope[type];
144
- this.onTestRunFinished(testRunFinished);
169
+ await this.onTestRunFinished(testRunFinished);
145
170
  break;
146
171
  }
147
172
  // case "parameterType" : { break}
@@ -155,7 +180,7 @@ class ReportGenerator {
155
180
  const { message } = parseError;
156
181
  const timestamp = new Date().getTime();
157
182
  this.report.result = {
158
- status: "FAILED",
183
+ status: 'FAILED',
159
184
  startTime: timestamp,
160
185
  endTime: timestamp,
161
186
  message: message,
@@ -198,7 +223,7 @@ class ReportGenerator {
198
223
  }
199
224
  onTestRunStarted(testRunStarted) {
200
225
  this.report.result = {
201
- status: "STARTED",
226
+ status: 'STARTED',
202
227
  startTime: this.getTimeStamp(testRunStarted.timestamp),
203
228
  };
204
229
  }
@@ -231,7 +256,8 @@ class ReportGenerator {
231
256
  for (const tableRow of examples.tableBody) {
232
257
  if (tableRow.id === exampleId) {
233
258
  for (let i = 0; i < examples.tableHeader.cells.length; i++) {
234
- parameters[examples.tableHeader.cells[i].value] = tableRow.cells[i].value;
259
+ parameters[examples.tableHeader.cells[i].value] =
260
+ tableRow.cells[i].value;
235
261
  }
236
262
  }
237
263
  }
@@ -269,7 +295,7 @@ class ReportGenerator {
269
295
  text: step.text,
270
296
  commands: [],
271
297
  result: {
272
- status: "UNKNOWN",
298
+ status: 'UNKNOWN',
273
299
  },
274
300
  networkData: [],
275
301
  webLog: [],
@@ -286,7 +312,7 @@ class ReportGenerator {
286
312
  parameters,
287
313
  steps,
288
314
  result: {
289
- status: "STARTED",
315
+ status: 'STARTED',
290
316
  startTime: this.getTimeStamp(timestamp),
291
317
  },
292
318
  webLog: [],
@@ -307,25 +333,25 @@ class ReportGenerator {
307
333
  return;
308
334
  const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
309
335
  stepProgess.result = {
310
- status: "STARTED",
336
+ status: 'STARTED',
311
337
  startTime: this.getTimeStamp(timestamp),
312
338
  };
313
339
  }
314
340
  onAttachment(attachment) {
315
341
  const { testStepId, body, mediaType } = attachment;
316
- if (mediaType === "text/plain") {
317
- this.reportFolder = body.replaceAll("\\", "/");
342
+ if (mediaType === 'text/plain') {
343
+ this.reportFolder = body.replaceAll('\\', '/');
318
344
  return;
319
345
  }
320
- if (mediaType === "application/json+snapshot-before") {
346
+ if (mediaType === 'application/json+snapshot-before') {
321
347
  this.initialAriaSnapshot = body;
322
348
  return;
323
349
  }
324
- if (mediaType === "application/json+snapshot-after") {
350
+ if (mediaType === 'application/json+snapshot-after') {
325
351
  this.ariaSnapshot = body;
326
352
  return;
327
353
  }
328
- if (mediaType === "application/json+env") {
354
+ if (mediaType === 'application/json+env') {
329
355
  const data = JSON.parse(body);
330
356
  this.report.env = data;
331
357
  this.report.testCases.map((testCase) => {
@@ -333,14 +359,14 @@ class ReportGenerator {
333
359
  return testCase;
334
360
  });
335
361
  }
336
- if (mediaType === "application/json+log") {
362
+ if (mediaType === 'application/json+log') {
337
363
  const log = JSON.parse(body);
338
364
  if (this.logs.length < 1000) {
339
365
  this.logs.push(log);
340
366
  this.stepLogs.push(log);
341
367
  }
342
368
  }
343
- if (mediaType === "application/json+network") {
369
+ if (mediaType === 'application/json+network') {
344
370
  const networkLog = JSON.parse(body);
345
371
  if (this.networkLog.length < 1000)
346
372
  this.networkLog.push(networkLog);
@@ -350,29 +376,38 @@ class ReportGenerator {
350
376
  if (testStep.pickleStepId === undefined)
351
377
  return;
352
378
  const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
353
- if (mediaType === "application/json") {
379
+ if (mediaType === 'application/json') {
354
380
  const command = JSON.parse(body);
355
381
  stepProgess.commands.push(command);
356
382
  }
357
- else if (mediaType === "application/json+trace") {
383
+ else if (mediaType === 'application/json+trace') {
358
384
  const data = JSON.parse(body);
359
385
  stepProgess.traceFilePath = data.traceFilePath;
360
386
  }
361
- if (mediaType === "application/json+bruno") {
387
+ if (mediaType === 'application/json+bruno') {
362
388
  try {
363
389
  const data = JSON.parse(body);
364
390
  stepProgess.brunoData = data;
365
391
  }
366
392
  catch (error) {
367
- console.error("Error parsing bruno data:", error);
393
+ console.error('Error parsing bruno data:', error);
394
+ }
395
+ }
396
+ if (mediaType === 'application/json+intercept-results') {
397
+ try {
398
+ const data = JSON.parse(body);
399
+ stepProgess.interceptResults = data;
400
+ }
401
+ catch (error) {
402
+ console.error('Error parsing intercept results:', error);
368
403
  }
369
404
  }
370
405
  }
371
406
  getFailedTestStepResult({ commands, startTime, endTime, result, }) {
372
407
  for (const command of commands) {
373
- if (command.result.status === "FAILED") {
408
+ if (command.result.status === 'FAILED') {
374
409
  return {
375
- status: "FAILED",
410
+ status: 'FAILED',
376
411
  message: command.result.message,
377
412
  startTime,
378
413
  endTime,
@@ -380,7 +415,7 @@ class ReportGenerator {
380
415
  }
381
416
  }
382
417
  return {
383
- status: "FAILED",
418
+ status: 'FAILED',
384
419
  startTime,
385
420
  endTime,
386
421
  message: result.message,
@@ -390,26 +425,26 @@ class ReportGenerator {
390
425
  const { testStepId, testStepResult, timestamp } = testStepFinished;
391
426
  const testStep = this.testStepMap.get(testStepId);
392
427
  if (testStep.pickleStepId === undefined) {
393
- if (testStepResult.status === "FAILED") {
428
+ if (testStepResult.status === 'FAILED') {
394
429
  console.error(`Before/After hook failed with message: ${testStepResult.message}`);
395
430
  }
396
431
  return;
397
432
  }
398
- if (testStepResult.status === "UNDEFINED") {
433
+ if (testStepResult.status === 'UNDEFINED') {
399
434
  const step = this.stepReportMap.get(testStep.pickleStepId);
400
- const stepName = step ? step.keyword + " " + step.text : "Undefined step";
435
+ const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
401
436
  const undefinedCommand = {
402
437
  testStepId: testStepId,
403
438
  body: JSON.stringify({
404
- type: "error",
405
- text: "Undefined step: " + stepName,
439
+ type: 'error',
440
+ text: 'Undefined step: ' + stepName,
406
441
  result: {
407
- status: "FAILED",
442
+ status: 'FAILED',
408
443
  startTime: this.getTimeStamp(timestamp),
409
444
  endTime: this.getTimeStamp(timestamp),
410
445
  },
411
446
  }),
412
- mediaType: "application/json",
447
+ mediaType: 'application/json',
413
448
  contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
414
449
  };
415
450
  this.onAttachment(undefinedCommand);
@@ -422,14 +457,14 @@ class ReportGenerator {
422
457
  if (reportFolder === null) {
423
458
  throw new Error('"reportFolder" is "null". Failed to run BVT hooks. Please retry after running "Generate All" or "Record Scenario" ');
424
459
  }
425
- if (fs_1.default.existsSync(path_1.default.join(reportFolder, "data.json"))) {
426
- data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(reportFolder, "data.json"), "utf8"));
460
+ if (fs_1.default.existsSync(path_1.default.join(reportFolder, 'data.json'))) {
461
+ data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(reportFolder, 'data.json'), 'utf8'));
427
462
  }
428
463
  }
429
464
  catch (error) {
430
- console.log("Error reading data.json");
465
+ console.log('Error reading data.json');
431
466
  }
432
- if (testStepResult.status === "FAILED") {
467
+ if (testStepResult.status === 'FAILED') {
433
468
  stepProgess.result = this.getFailedTestStepResult({
434
469
  commands: stepProgess.commands,
435
470
  startTime: prevStepResult.startTime,
@@ -447,7 +482,7 @@ class ReportGenerator {
447
482
  stepProgess.webLog = this.stepLogs;
448
483
  stepProgess.networkData = this.stepNetworkLogs;
449
484
  stepProgess.ariaSnapshot = this.ariaSnapshot;
450
- this.ariaSnapshot = "";
485
+ this.ariaSnapshot = '';
451
486
  this.stepNetworkLogs = [];
452
487
  this.stepLogs = [];
453
488
  if (Object.keys(data).length > 0) {
@@ -456,18 +491,20 @@ class ReportGenerator {
456
491
  const parameters = this.testCaseReportMap.get(id).parameters;
457
492
  const _parameters = {};
458
493
  Object.keys(parameters).map((key) => {
459
- if (parameters[key].startsWith("{{") && parameters[key].endsWith("}}")) {
460
- const path = parameters[key].slice(2, -2).split(".");
461
- let value = String(object_path_1.default.get(data, path));
494
+ var _a;
495
+ if (parameters[key].startsWith('{{') &&
496
+ parameters[key].endsWith('}}')) {
497
+ const path = parameters[key].slice(2, -2).split('.');
498
+ let value = String((_a = object_path_1.default.get(data, path)) !== null && _a !== void 0 ? _a : parameters[key]);
462
499
  if (value) {
463
- if (value.startsWith("secret:")) {
464
- value = "secret:****";
500
+ if (value.startsWith('secret:')) {
501
+ value = 'secret:****';
465
502
  }
466
- else if (value.startsWith("totp:")) {
467
- value = "totp:****";
503
+ else if (value.startsWith('totp:')) {
504
+ value = 'totp:****';
468
505
  }
469
- else if (value.startsWith("mask:")) {
470
- value = "mask:****";
506
+ else if (value.startsWith('mask:')) {
507
+ value = 'mask:****';
471
508
  }
472
509
  _parameters[key] = value;
473
510
  }
@@ -500,7 +537,7 @@ class ReportGenerator {
500
537
  if (process.env.PROJECT_PATH) {
501
538
  projectPath = process.env.PROJECT_PATH;
502
539
  }
503
- const logFolder = path_1.default.join(projectPath, "logs", "web");
540
+ const logFolder = path_1.default.join(projectPath, 'logs', 'web');
504
541
  if (!fs_1.default.existsSync(logFolder)) {
505
542
  return [];
506
543
  }
@@ -512,7 +549,7 @@ class ReportGenerator {
512
549
  return [];
513
550
  }
514
551
  try {
515
- const logFileContent = fs_1.default.readFileSync(path_1.default.join(logFolder, `${nextId - 1}.json`), "utf8");
552
+ const logFileContent = fs_1.default.readFileSync(path_1.default.join(logFolder, `${nextId - 1}.json`), 'utf8');
516
553
  return JSON.parse(logFileContent);
517
554
  }
518
555
  catch (error) {
@@ -520,25 +557,31 @@ class ReportGenerator {
520
557
  }
521
558
  }
522
559
  getTestCaseResult(steps) {
560
+ if (steps[0] && steps[0].result.status === 'SKIPPED') {
561
+ return {
562
+ status: 'FAILED',
563
+ message: 'Test skipped due to failure in before hooks',
564
+ };
565
+ }
523
566
  for (const step of steps) {
524
567
  switch (step.result.status) {
525
- case "FAILED":
568
+ case 'FAILED':
526
569
  return {
527
570
  status: step.result.status,
528
571
  message: step.result.message,
529
572
  // exception: step.result.exception,
530
573
  };
531
- case "AMBIGUOUS":
532
- case "UNDEFINED":
533
- case "PENDING":
574
+ case 'AMBIGUOUS':
575
+ case 'UNDEFINED':
576
+ case 'PENDING':
534
577
  return {
535
- status: "FAILED",
578
+ status: 'FAILED',
536
579
  message: `step "${step.text}" is ${step.result.status}`,
537
580
  };
538
581
  }
539
582
  }
540
583
  return {
541
- status: "PASSED",
584
+ status: 'PASSED',
542
585
  };
543
586
  }
544
587
  async onTestCaseFinished(testCaseFinished, reRunId) {
@@ -547,6 +590,9 @@ class ReportGenerator {
547
590
  const prevResult = testProgress.result;
548
591
  const steps = Object.values(testProgress.steps);
549
592
  const result = this.getTestCaseResult(steps);
593
+ if (result.status === 'PASSED' && reRunId) {
594
+ this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
595
+ }
550
596
  const endTime = this.getTimeStamp(timestamp);
551
597
  testProgress.result = {
552
598
  ...result,
@@ -556,9 +602,22 @@ class ReportGenerator {
556
602
  testProgress.webLog = this.logs;
557
603
  testProgress.networkLog = this.networkLog;
558
604
  testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
559
- this.initialAriaSnapshot = "";
605
+ this.initialAriaSnapshot = '';
560
606
  this.networkLog = [];
561
607
  this.logs = [];
608
+ if (this.testCaseLog && this.testCaseLog.length > 0) {
609
+ // Create the logs directory
610
+ const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
611
+ const fileName = `testCaseLog_${testCaseStartedId}.log`;
612
+ const filePath = path_1.default.join(logsDir, fileName);
613
+ // Ensure the logs directory exists
614
+ fs_1.default.mkdirSync(logsDir, { recursive: true });
615
+ // Write the logs to the file
616
+ fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
617
+ // Store this ID in the testProgress object so it can be accessed later
618
+ testProgress.logFileId = testCaseStartedId;
619
+ }
620
+ this.testCaseLog = [];
562
621
  if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
563
622
  this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
564
623
  if (!fs_1.default.existsSync(this.reportFolder)) {
@@ -573,18 +632,39 @@ class ReportGenerator {
573
632
  }
574
633
  }
575
634
  async uploadTestCase(testCase, rerunId) {
576
- let runId = "";
577
- let projectId = "";
635
+ let data = null;
636
+ for (let attempt = 1; attempt <= this.retryCount; attempt++) {
637
+ try {
638
+ data = await this.tryUpload(testCase, rerunId);
639
+ break;
640
+ }
641
+ catch (e) {
642
+ console.error(`Attempt ${attempt} to upload testcase failed:`, e);
643
+ if (attempt === this.retryCount) {
644
+ console.error('All retry attempts failed, failed to upload testcase.');
645
+ }
646
+ else {
647
+ const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
648
+ await new Promise((r) => setTimeout(r, waitTime));
649
+ }
650
+ }
651
+ }
652
+ return data;
653
+ }
654
+ async tryUpload(testCase, rerunId) {
655
+ let runId = '';
656
+ let projectId = '';
578
657
  if (!process.env.UPLOADING_TEST_CASE) {
579
- process.env.UPLOADING_TEST_CASE = "[]";
658
+ process.env.UPLOADING_TEST_CASE = '[]';
580
659
  }
581
660
  const anyRemArr = JSON.parse(process.env.UPLOADING_TEST_CASE);
582
661
  const randomID = Math.random().toString(36).substring(7);
583
662
  anyRemArr.push(randomID);
584
- let data;
585
663
  process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
586
664
  try {
587
- if (process.env.RUN_ID && process.env.PROJECT_ID && !process.env.IGNORE_ENV_VARIABLES) {
665
+ if (process.env.RUN_ID &&
666
+ process.env.PROJECT_ID &&
667
+ !process.env.IGNORE_ENV_VARIABLES) {
588
668
  runId = process.env.RUN_ID;
589
669
  projectId = process.env.PROJECT_ID;
590
670
  }
@@ -597,24 +677,21 @@ class ReportGenerator {
597
677
  process.env.PROJECT_ID = projectId;
598
678
  }
599
679
  }
600
- data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
680
+ const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
601
681
  this.writeTestCaseReportToDisk(testCase);
602
- }
603
- catch (e) {
604
- console.error("Error uploading test case:", e);
682
+ return data;
605
683
  }
606
684
  finally {
607
685
  const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
608
686
  arrRem.splice(arrRem.indexOf(randomID), 1);
609
687
  process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
610
688
  }
611
- return data ? data : null;
612
689
  }
613
690
  writeTestCaseReportToDisk(testCase) {
614
691
  var _a;
615
692
  const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
616
693
  if (!reportFolder) {
617
- console.error("Report folder is not defined");
694
+ console.error('Report folder is not defined');
618
695
  return;
619
696
  }
620
697
  try {
@@ -630,19 +707,20 @@ class ReportGenerator {
630
707
  fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
631
708
  }
632
709
  catch (error) {
633
- console.error("Error writing test case report to disk:", error);
710
+ console.error('Error writing test case report to disk:', error);
634
711
  }
635
712
  }
636
- onTestRunFinished(testRunFinished) {
713
+ async onTestRunFinished(testRunFinished) {
637
714
  const { timestamp, success, message } = testRunFinished;
638
715
  const prevResult = this.report.result;
639
716
  this.report.result = {
640
- status: success ? "PASSED" : "FAILED",
717
+ status: success ? 'PASSED' : 'FAILED',
641
718
  startTime: prevResult.startTime,
642
719
  endTime: this.getTimeStamp(timestamp),
643
720
  message,
644
721
  // exception,
645
722
  };
723
+ await this.uploadService.createStatus(success ? 'passed' : 'failed');
646
724
  }
647
725
  }
648
726
  exports.default = ReportGenerator;