@dev-blinq/cucumber-js 1.0.94 → 1.0.95-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.
Files changed (30) hide show
  1. package/bin/download-install.js +14 -2
  2. package/lib/cli/validate_node_engine_version.js +3 -1
  3. package/lib/cli/validate_node_engine_version.js.map +1 -1
  4. package/lib/formatter/api.js +7 -1
  5. package/lib/formatter/api.js.map +1 -1
  6. package/lib/formatter/bvt_analysis_formatter.d.ts +12 -1
  7. package/lib/formatter/bvt_analysis_formatter.js +137 -52
  8. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  9. package/lib/formatter/feature_data_format.js +0 -1
  10. package/lib/formatter/feature_data_format.js.map +1 -1
  11. package/lib/formatter/helpers/constants.d.ts +50 -0
  12. package/lib/formatter/helpers/constants.js +60 -0
  13. package/lib/formatter/helpers/constants.js.map +1 -0
  14. package/lib/formatter/helpers/report_generator.d.ts +17 -1
  15. package/lib/formatter/helpers/report_generator.js +236 -22
  16. package/lib/formatter/helpers/report_generator.js.map +1 -1
  17. package/lib/formatter/helpers/upload_serivce.d.ts +14 -1
  18. package/lib/formatter/helpers/upload_serivce.js +86 -4
  19. package/lib/formatter/helpers/upload_serivce.js.map +1 -1
  20. package/lib/formatter/helpers/uploader.js +11 -14
  21. package/lib/formatter/helpers/uploader.js.map +1 -1
  22. package/lib/formatter/summary_formatter.js +4 -0
  23. package/lib/formatter/summary_formatter.js.map +1 -1
  24. package/lib/runtime/test_case_runner.d.ts +1 -0
  25. package/lib/runtime/test_case_runner.js +10 -1
  26. package/lib/runtime/test_case_runner.js.map +1 -1
  27. package/lib/version.d.ts +1 -1
  28. package/lib/version.js +1 -1
  29. package/lib/version.js.map +1 -1
  30. package/package.json +3 -1
@@ -0,0 +1,50 @@
1
+ export declare const LOCAL: {
2
+ SSO: string;
3
+ WORKSPACE: string;
4
+ RUNS: string;
5
+ STORAGE: string;
6
+ };
7
+ export declare const DEV: {
8
+ SSO: string;
9
+ WORKSPACE: string;
10
+ RUNS: string;
11
+ STORAGE: string;
12
+ };
13
+ export declare const PROD: {
14
+ SSO: string;
15
+ WORKSPACE: string;
16
+ RUNS: string;
17
+ STORAGE: string;
18
+ };
19
+ export declare const STAGE: {
20
+ SSO: string;
21
+ WORKSPACE: string;
22
+ RUNS: string;
23
+ STORAGE: string;
24
+ };
25
+ export declare const CUSTOM: {
26
+ SSO: string;
27
+ WORKSPACE: string;
28
+ RUNS: string;
29
+ STORAGE: string;
30
+ };
31
+ export declare const SERVICES_URI: {
32
+ SSO: string;
33
+ WORKSPACE: string;
34
+ RUNS: string;
35
+ STORAGE: string;
36
+ };
37
+ export declare enum ActionEvents {
38
+ record_scenario = "record_scenario",
39
+ download_editor = "download_editor",
40
+ launch_editor = "launch_editor",
41
+ click_start_recording = "click_start_recording",
42
+ click_run_scenario = "click_run_scenario",
43
+ publish_scenario = "publish_scenario",
44
+ click_ai_generate = "click_ai_generate",
45
+ click_run_all = "click_run_all",
46
+ click_open_vscode = "click_open_vscode",
47
+ error_open_vscode = "error_open_vscode",
48
+ cli_run_tests = "cli_run_tests",
49
+ upload_report = "upload_report"
50
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActionEvents = exports.SERVICES_URI = exports.CUSTOM = exports.STAGE = exports.PROD = exports.DEV = exports.LOCAL = void 0;
4
+ exports.LOCAL = {
5
+ SSO: 'http://localhost:5000/api/auth',
6
+ WORKSPACE: 'http://localhost:6000/api/workspace',
7
+ RUNS: 'http://localhost:5001/api/runs',
8
+ STORAGE: 'http://localhost:5050/api/storage',
9
+ };
10
+ exports.DEV = {
11
+ SSO: 'https://dev.api.blinq.io/api/auth',
12
+ WORKSPACE: 'https://dev.api.blinq.io/api/workspace',
13
+ RUNS: 'https://dev.api.blinq.io/api/runs',
14
+ STORAGE: 'https://dev.api.blinq.io/api/storage',
15
+ };
16
+ exports.PROD = {
17
+ SSO: 'https://api.blinq.io/api/auth',
18
+ WORKSPACE: 'https://api.blinq.io/api/workspace',
19
+ RUNS: 'https://api.blinq.io/api/runs',
20
+ STORAGE: 'https://api.blinq.io/api/storage',
21
+ };
22
+ exports.STAGE = {
23
+ SSO: 'https://stage.api.blinq.io/api/auth',
24
+ WORKSPACE: 'https://stage.api.blinq.io/api/workspace',
25
+ RUNS: 'https://stage.api.blinq.io/api/runs',
26
+ STORAGE: 'https://stage.api.blinq.io/api/storage',
27
+ };
28
+ exports.CUSTOM = {
29
+ SSO: `${process.env.NODE_ENV_BLINQ}/api/auth`,
30
+ WORKSPACE: `${process.env.NODE_ENV_BLINQ}/api/workspace`,
31
+ RUNS: `${process.env.NODE_ENV_BLINQ}/api/runs`,
32
+ STORAGE: `${process.env.NODE_ENV_BLINQ}/api/storage`,
33
+ };
34
+ exports.SERVICES_URI = process.env.NODE_ENV_BLINQ === 'local'
35
+ ? exports.LOCAL // eslint-disable-line
36
+ : process.env.NODE_ENV_BLINQ === 'dev'
37
+ ? exports.DEV // eslint-disable-line
38
+ : process.env.NODE_ENV_BLINQ === 'stage'
39
+ ? exports.STAGE // eslint-disable-line
40
+ : process.env.NODE_ENV_BLINQ === 'prod'
41
+ ? exports.PROD // eslint-disable-line
42
+ : !process.env.NODE_ENV_BLINQ
43
+ ? exports.PROD // eslint-disable-line
44
+ : exports.CUSTOM; // eslint-disable-line
45
+ var ActionEvents;
46
+ (function (ActionEvents) {
47
+ ActionEvents["record_scenario"] = "record_scenario";
48
+ ActionEvents["download_editor"] = "download_editor";
49
+ ActionEvents["launch_editor"] = "launch_editor";
50
+ ActionEvents["click_start_recording"] = "click_start_recording";
51
+ ActionEvents["click_run_scenario"] = "click_run_scenario";
52
+ ActionEvents["publish_scenario"] = "publish_scenario";
53
+ ActionEvents["click_ai_generate"] = "click_ai_generate";
54
+ ActionEvents["click_run_all"] = "click_run_all";
55
+ ActionEvents["click_open_vscode"] = "click_open_vscode";
56
+ ActionEvents["error_open_vscode"] = "error_open_vscode";
57
+ ActionEvents["cli_run_tests"] = "cli_run_tests";
58
+ ActionEvents["upload_report"] = "upload_report";
59
+ })(ActionEvents = exports.ActionEvents || (exports.ActionEvents = {}));
60
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/formatter/helpers/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,KAAK,GAAG;IACnB,GAAG,EAAE,gCAAgC;IACrC,SAAS,EAAE,qCAAqC;IAChD,IAAI,EAAE,gCAAgC;IACtC,OAAO,EAAE,mCAAmC;CAC7C,CAAA;AACY,QAAA,GAAG,GAAG;IACjB,GAAG,EAAE,mCAAmC;IACxC,SAAS,EAAE,wCAAwC;IACnD,IAAI,EAAE,mCAAmC;IACzC,OAAO,EAAE,sCAAsC;CAChD,CAAA;AACY,QAAA,IAAI,GAAG;IAClB,GAAG,EAAE,+BAA+B;IACpC,SAAS,EAAE,oCAAoC;IAC/C,IAAI,EAAE,+BAA+B;IACrC,OAAO,EAAE,kCAAkC;CAC5C,CAAA;AACY,QAAA,KAAK,GAAG;IACnB,GAAG,EAAE,qCAAqC;IAC1C,SAAS,EAAE,0CAA0C;IACrD,IAAI,EAAE,qCAAqC;IAC3C,OAAO,EAAE,wCAAwC;CAClD,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW;IAC7C,SAAS,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,gBAAgB;IACxD,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW;IAC9C,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,cAAc;CACrD,CAAA;AAEY,QAAA,YAAY,GACvB,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;IACpC,CAAC,CAAC,aAAK,CAAC,sBAAsB;IAC9B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,KAAK;QACtC,CAAC,CAAC,WAAG,CAAC,sBAAsB;QAC5B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;YACxC,CAAC,CAAC,aAAK,CAAC,sBAAsB;YAC9B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM;gBACvC,CAAC,CAAC,YAAI,CAAC,sBAAsB;gBAC7B,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc;oBAC7B,CAAC,CAAC,YAAI,CAAC,sBAAsB;oBAC7B,CAAC,CAAC,cAAM,CAAA,CAAC,sBAAsB;AAEnC,IAAY,YAaX;AAbD,WAAY,YAAY;IACtB,mDAAmC,CAAA;IACnC,mDAAmC,CAAA;IACnC,+CAA+B,CAAA;IAC/B,+DAA+C,CAAA;IAC/C,yDAAyC,CAAA;IACzC,qDAAqC,CAAA;IACrC,uDAAuC,CAAA;IACvC,+CAA+B,CAAA;IAC/B,uDAAuC,CAAA;IACvC,uDAAuC,CAAA;IACvC,+CAA+B,CAAA;IAC/B,+CAA+B,CAAA;AACjC,CAAC,EAbW,YAAY,GAAZ,oBAAY,KAAZ,oBAAY,QAavB","sourcesContent":["export const LOCAL = {\n SSO: 'http://localhost:5000/api/auth',\n WORKSPACE: 'http://localhost:6000/api/workspace',\n RUNS: 'http://localhost:5001/api/runs',\n STORAGE: 'http://localhost:5050/api/storage',\n}\nexport const DEV = {\n SSO: 'https://dev.api.blinq.io/api/auth',\n WORKSPACE: 'https://dev.api.blinq.io/api/workspace',\n RUNS: 'https://dev.api.blinq.io/api/runs',\n STORAGE: 'https://dev.api.blinq.io/api/storage',\n}\nexport const PROD = {\n SSO: 'https://api.blinq.io/api/auth',\n WORKSPACE: 'https://api.blinq.io/api/workspace',\n RUNS: 'https://api.blinq.io/api/runs',\n STORAGE: 'https://api.blinq.io/api/storage',\n}\nexport const STAGE = {\n SSO: 'https://stage.api.blinq.io/api/auth',\n WORKSPACE: 'https://stage.api.blinq.io/api/workspace',\n RUNS: 'https://stage.api.blinq.io/api/runs',\n STORAGE: 'https://stage.api.blinq.io/api/storage',\n}\n\nexport const CUSTOM = {\n SSO: `${process.env.NODE_ENV_BLINQ}/api/auth`,\n WORKSPACE: `${process.env.NODE_ENV_BLINQ}/api/workspace`,\n RUNS: `${process.env.NODE_ENV_BLINQ}/api/runs`,\n STORAGE: `${process.env.NODE_ENV_BLINQ}/api/storage`,\n}\n\nexport const SERVICES_URI =\n process.env.NODE_ENV_BLINQ === 'local'\n ? LOCAL // eslint-disable-line\n : process.env.NODE_ENV_BLINQ === 'dev'\n ? DEV // eslint-disable-line\n : process.env.NODE_ENV_BLINQ === 'stage'\n ? STAGE // eslint-disable-line\n : process.env.NODE_ENV_BLINQ === 'prod'\n ? PROD // eslint-disable-line\n : !process.env.NODE_ENV_BLINQ\n ? PROD // eslint-disable-line\n : CUSTOM // eslint-disable-line\n\nexport enum ActionEvents {\n record_scenario = 'record_scenario',\n download_editor = 'download_editor',\n launch_editor = 'launch_editor',\n click_start_recording = 'click_start_recording',\n click_run_scenario = 'click_run_scenario',\n publish_scenario = 'publish_scenario',\n click_ai_generate = 'click_ai_generate',\n click_run_all = 'click_run_all',\n click_open_vscode = 'click_open_vscode',\n error_open_vscode = 'error_open_vscode',\n cli_run_tests = 'cli_run_tests',\n upload_report = 'upload_report',\n}\n"]}
@@ -63,7 +63,12 @@ export type JsonStep = {
63
63
  commands: JsonCommand[];
64
64
  result: JsonStepResult;
65
65
  webLog: webLog[];
66
+ networkData: any[];
66
67
  data?: any;
68
+ ariaSnapshot: string;
69
+ traceFilePath?: string;
70
+ brunoData?: any;
71
+ interceptResults?: any;
67
72
  };
68
73
  export type RetrainStats = {
69
74
  result: JsonTestResult;
@@ -80,8 +85,10 @@ export type JsonTestProgress = {
80
85
  steps: JsonStep[];
81
86
  result: JsonTestResult;
82
87
  retrainStats?: RetrainStats;
88
+ initialAriaSnapshot?: string;
83
89
  webLog: any;
84
90
  networkLog: any;
91
+ logFileId?: string;
85
92
  env: {
86
93
  name: string;
87
94
  baseUrl: string;
@@ -114,10 +121,15 @@ export default class ReportGenerator {
114
121
  private logs;
115
122
  private networkLog;
116
123
  private stepLogs;
124
+ private stepNetworkLogs;
117
125
  private runName;
126
+ private ariaSnapshot;
127
+ private initialAriaSnapshot;
128
+ private testCaseLog;
129
+ private loggingOverridden;
118
130
  reportFolder: null | string;
119
131
  private uploadService;
120
- handleMessage(envelope: EnvelopeWithMetaMessage): Promise<void>;
132
+ handleMessage(envelope: EnvelopeWithMetaMessage | messages.Envelope, reRunId?: string): Promise<any>;
121
133
  getReport(): JsonReport;
122
134
  private handleParseError;
123
135
  private onGherkinDocument;
@@ -130,11 +142,15 @@ export default class ReportGenerator {
130
142
  private onTestCaseStarted;
131
143
  private onTestStepStarted;
132
144
  private onAttachment;
145
+ private getFailedTestStepResult;
133
146
  private onTestStepFinished;
134
147
  getLogFileContent(): any;
135
148
  private getTestCaseResult;
136
149
  private onTestCaseFinished;
150
+ private readonly retryCount;
137
151
  private uploadTestCase;
152
+ private tryUpload;
153
+ private writeTestCaseReportToDisk;
138
154
  private onTestRunFinished;
139
155
  }
140
156
  export {};
@@ -31,13 +31,20 @@ const messages = __importStar(require("@cucumber/messages"));
31
31
  const fs_1 = __importDefault(require("fs"));
32
32
  const path_1 = __importDefault(require("path"));
33
33
  const upload_serivce_1 = require("./upload_serivce");
34
+ const fs_extra_1 = require("fs-extra");
35
+ // type JsonException = messages.Exception
36
+ const object_path_1 = __importDefault(require("object-path"));
34
37
  const URL = process.env.NODE_ENV_BLINQ === 'dev'
35
38
  ? 'https://dev.api.blinq.io/api/runs'
36
39
  : process.env.NODE_ENV_BLINQ === 'local'
37
40
  ? 'http://localhost:5001/api/runs'
38
41
  : process.env.NODE_ENV_BLINQ === 'stage'
39
42
  ? 'https://stage.api.blinq.io/api/runs'
40
- : 'https://api.blinq.io/api/runs';
43
+ : process.env.NODE_ENV_BLINQ === 'prod'
44
+ ? 'https://api.blinq.io/api/runs'
45
+ : !process.env.NODE_ENV_BLINQ
46
+ ? 'https://api.blinq.io/api/runs'
47
+ : `${process.env.NODE_ENV_BLINQ}/api/runs`;
41
48
  const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
42
49
  const BATCH_SIZE = 10;
43
50
  const MAX_RETRIES = 3;
@@ -65,12 +72,18 @@ class ReportGenerator {
65
72
  this.logs = [];
66
73
  this.networkLog = [];
67
74
  this.stepLogs = [];
75
+ this.stepNetworkLogs = [];
68
76
  this.runName = '';
77
+ this.ariaSnapshot = '';
78
+ this.initialAriaSnapshot = '';
79
+ this.testCaseLog = [];
80
+ this.loggingOverridden = false; // Flag to track if logging is overridden
69
81
  this.reportFolder = null;
70
82
  this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
83
+ this.retryCount = 3;
71
84
  }
72
- async handleMessage(envelope) {
73
- if (envelope.meta && envelope.meta.runName) {
85
+ async handleMessage(envelope, reRunId) {
86
+ if (envelope.meta && 'runName' in envelope.meta) {
74
87
  this.runName = envelope.meta.runName;
75
88
  }
76
89
  const type = Object.keys(envelope)[0];
@@ -97,10 +110,30 @@ class ReportGenerator {
97
110
  case 'testRunStarted': {
98
111
  const testRunStarted = envelope[type];
99
112
  this.onTestRunStarted(testRunStarted);
113
+ await this.uploadService.createStatus('running');
100
114
  break;
101
115
  }
102
116
  case 'testCase': {
103
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
104
137
  this.onTestCase(testCase);
105
138
  break;
106
139
  }
@@ -126,13 +159,14 @@ class ReportGenerator {
126
159
  }
127
160
  case 'testCaseFinished': {
128
161
  const testCaseFinished = envelope[type];
129
- await this.onTestCaseFinished(testCaseFinished);
130
- break;
162
+ // Call the onTestCaseFinished method
163
+ const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
164
+ return result;
131
165
  }
132
166
  // case "hook": { break} // After Hook
133
167
  case 'testRunFinished': {
134
168
  const testRunFinished = envelope[type];
135
- this.onTestRunFinished(testRunFinished);
169
+ await this.onTestRunFinished(testRunFinished);
136
170
  break;
137
171
  }
138
172
  // case "parameterType" : { break}
@@ -263,7 +297,10 @@ class ReportGenerator {
263
297
  result: {
264
298
  status: 'UNKNOWN',
265
299
  },
300
+ networkData: [],
266
301
  webLog: [],
302
+ data: {},
303
+ ariaSnapshot: this.ariaSnapshot,
267
304
  });
268
305
  return this.stepReportMap.get(pickleStep.id);
269
306
  });
@@ -306,6 +343,14 @@ class ReportGenerator {
306
343
  this.reportFolder = body.replaceAll('\\', '/');
307
344
  return;
308
345
  }
346
+ if (mediaType === 'application/json+snapshot-before') {
347
+ this.initialAriaSnapshot = body;
348
+ return;
349
+ }
350
+ if (mediaType === 'application/json+snapshot-after') {
351
+ this.ariaSnapshot = body;
352
+ return;
353
+ }
309
354
  if (mediaType === 'application/json+env') {
310
355
  const data = JSON.parse(body);
311
356
  this.report.env = data;
@@ -325,6 +370,7 @@ class ReportGenerator {
325
370
  const networkLog = JSON.parse(body);
326
371
  if (this.networkLog.length < 1000)
327
372
  this.networkLog.push(networkLog);
373
+ this.stepNetworkLogs.push(networkLog);
328
374
  }
329
375
  const testStep = this.testStepMap.get(testStepId);
330
376
  if (testStep.pickleStepId === undefined)
@@ -334,6 +380,46 @@ class ReportGenerator {
334
380
  const command = JSON.parse(body);
335
381
  stepProgess.commands.push(command);
336
382
  }
383
+ else if (mediaType === 'application/json+trace') {
384
+ const data = JSON.parse(body);
385
+ stepProgess.traceFilePath = data.traceFilePath;
386
+ }
387
+ if (mediaType === 'application/json+bruno') {
388
+ try {
389
+ const data = JSON.parse(body);
390
+ stepProgess.brunoData = data;
391
+ }
392
+ catch (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);
403
+ }
404
+ }
405
+ }
406
+ getFailedTestStepResult({ commands, startTime, endTime, result, }) {
407
+ for (const command of commands) {
408
+ if (command.result.status === 'FAILED') {
409
+ return {
410
+ status: 'FAILED',
411
+ message: command.result.message,
412
+ startTime,
413
+ endTime,
414
+ };
415
+ }
416
+ }
417
+ return {
418
+ status: 'FAILED',
419
+ startTime,
420
+ endTime,
421
+ message: result.message,
422
+ };
337
423
  }
338
424
  onTestStepFinished(testStepFinished) {
339
425
  const { testStepId, testStepResult, timestamp } = testStepFinished;
@@ -378,18 +464,73 @@ class ReportGenerator {
378
464
  catch (error) {
379
465
  console.log('Error reading data.json');
380
466
  }
381
- stepProgess.result = {
382
- status: testStepResult.status,
383
- startTime: prevStepResult.startTime,
384
- endTime: this.getTimeStamp(timestamp),
385
- message: testStepResult.message,
386
- // exception: testStepResult.exception,
387
- };
467
+ if (testStepResult.status === 'FAILED') {
468
+ stepProgess.result = this.getFailedTestStepResult({
469
+ commands: stepProgess.commands,
470
+ startTime: prevStepResult.startTime,
471
+ endTime: this.getTimeStamp(timestamp),
472
+ result: testStepResult,
473
+ });
474
+ }
475
+ else {
476
+ stepProgess.result = {
477
+ status: testStepResult.status,
478
+ startTime: prevStepResult.startTime,
479
+ endTime: this.getTimeStamp(timestamp),
480
+ };
481
+ }
388
482
  stepProgess.webLog = this.stepLogs;
483
+ stepProgess.networkData = this.stepNetworkLogs;
484
+ stepProgess.ariaSnapshot = this.ariaSnapshot;
485
+ this.ariaSnapshot = '';
486
+ this.stepNetworkLogs = [];
389
487
  this.stepLogs = [];
390
488
  if (Object.keys(data).length > 0) {
391
489
  stepProgess.data = data;
490
+ const id = testStepFinished.testCaseStartedId;
491
+ const parameters = this.testCaseReportMap.get(id).parameters;
492
+ const _parameters = {};
493
+ Object.keys(parameters).map((key) => {
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]);
499
+ if (value) {
500
+ if (value.startsWith('secret:')) {
501
+ value = 'secret:****';
502
+ }
503
+ else if (value.startsWith('totp:')) {
504
+ value = 'totp:****';
505
+ }
506
+ else if (value.startsWith('mask:')) {
507
+ value = 'mask:****';
508
+ }
509
+ _parameters[key] = value;
510
+ }
511
+ }
512
+ else {
513
+ _parameters[key] = parameters[key];
514
+ }
515
+ });
516
+ this.report.testCases.find((testCase) => {
517
+ return testCase.id === id;
518
+ }).parameters = _parameters;
392
519
  }
520
+ // if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
521
+ // this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
522
+ // if (!fs.existsSync(this.reportFolder)) {
523
+ // fs.mkdirSync(this.reportFolder)
524
+ // }
525
+ // const reportFilePath = path.join(
526
+ // this.reportFolder,
527
+ // `report.json`
528
+ // )
529
+ // writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
530
+ // return undefined
531
+ // // } else {
532
+ // // return await this.uploadTestCase(testProgress, reRunId)
533
+ // }
393
534
  }
394
535
  getLogFileContent() {
395
536
  let projectPath = process.cwd();
@@ -437,24 +578,74 @@ class ReportGenerator {
437
578
  status: 'PASSED',
438
579
  };
439
580
  }
440
- async onTestCaseFinished(testCaseFinished) {
581
+ async onTestCaseFinished(testCaseFinished, reRunId) {
441
582
  const { testCaseStartedId, timestamp } = testCaseFinished;
442
583
  const testProgress = this.testCaseReportMap.get(testCaseStartedId);
443
584
  const prevResult = testProgress.result;
444
585
  const steps = Object.values(testProgress.steps);
445
586
  const result = this.getTestCaseResult(steps);
587
+ if (result.status === 'PASSED' && reRunId) {
588
+ this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
589
+ }
590
+ const endTime = this.getTimeStamp(timestamp);
446
591
  testProgress.result = {
447
592
  ...result,
448
593
  startTime: prevResult.startTime,
449
- endTime: this.getTimeStamp(timestamp),
594
+ endTime,
450
595
  };
451
596
  testProgress.webLog = this.logs;
452
597
  testProgress.networkLog = this.networkLog;
598
+ testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
599
+ this.initialAriaSnapshot = '';
453
600
  this.networkLog = [];
454
601
  this.logs = [];
455
- await this.uploadTestCase(testProgress);
602
+ if (this.testCaseLog && this.testCaseLog.length > 0) {
603
+ // Create the logs directory
604
+ const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
605
+ const fileName = `testCaseLog_${testCaseStartedId}.log`;
606
+ const filePath = path_1.default.join(logsDir, fileName);
607
+ // Ensure the logs directory exists
608
+ fs_1.default.mkdirSync(logsDir, { recursive: true });
609
+ // Write the logs to the file
610
+ fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
611
+ // Store this ID in the testProgress object so it can be accessed later
612
+ testProgress.logFileId = testCaseStartedId;
613
+ }
614
+ this.testCaseLog = [];
615
+ if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
616
+ this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
617
+ if (!fs_1.default.existsSync(this.reportFolder)) {
618
+ fs_1.default.mkdirSync(this.reportFolder);
619
+ }
620
+ const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
621
+ (0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
622
+ return undefined;
623
+ }
624
+ else {
625
+ return await this.uploadTestCase(testProgress, reRunId);
626
+ }
456
627
  }
457
- async uploadTestCase(testCase) {
628
+ async uploadTestCase(testCase, rerunId) {
629
+ let data = null;
630
+ for (let attempt = 1; attempt <= this.retryCount; attempt++) {
631
+ try {
632
+ data = await this.tryUpload(testCase, rerunId);
633
+ break;
634
+ }
635
+ catch (e) {
636
+ console.error(`Attempt ${attempt} to upload testcase failed:`, e);
637
+ if (attempt === this.retryCount) {
638
+ console.error('All retry attempts failed, failed to upload testcase.');
639
+ }
640
+ else {
641
+ const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
642
+ await new Promise((r) => setTimeout(r, waitTime));
643
+ }
644
+ }
645
+ }
646
+ return data;
647
+ }
648
+ async tryUpload(testCase, rerunId) {
458
649
  let runId = '';
459
650
  let projectId = '';
460
651
  if (!process.env.UPLOADING_TEST_CASE) {
@@ -480,10 +671,9 @@ class ReportGenerator {
480
671
  process.env.PROJECT_ID = projectId;
481
672
  }
482
673
  }
483
- await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
484
- }
485
- catch (e) {
486
- console.error('Error uploading test case:', e);
674
+ const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
675
+ this.writeTestCaseReportToDisk(testCase);
676
+ return data;
487
677
  }
488
678
  finally {
489
679
  const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
@@ -491,7 +681,30 @@ class ReportGenerator {
491
681
  process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
492
682
  }
493
683
  }
494
- onTestRunFinished(testRunFinished) {
684
+ writeTestCaseReportToDisk(testCase) {
685
+ var _a;
686
+ const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
687
+ if (!reportFolder) {
688
+ console.error('Report folder is not defined');
689
+ return;
690
+ }
691
+ try {
692
+ let i = 0;
693
+ while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
694
+ i++;
695
+ }
696
+ fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
697
+ //exclude network log from the saved report
698
+ const networkLog = testCase.networkLog;
699
+ delete testCase.networkLog;
700
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
701
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
702
+ }
703
+ catch (error) {
704
+ console.error('Error writing test case report to disk:', error);
705
+ }
706
+ }
707
+ async onTestRunFinished(testRunFinished) {
495
708
  const { timestamp, success, message } = testRunFinished;
496
709
  const prevResult = this.report.result;
497
710
  this.report.result = {
@@ -501,6 +714,7 @@ class ReportGenerator {
501
714
  message,
502
715
  // exception,
503
716
  };
717
+ await this.uploadService.createStatus(success ? 'passed' : 'failed');
504
718
  }
505
719
  }
506
720
  exports.default = ReportGenerator;