@dev-blinq/cucumber-js 1.0.89-main → 1.0.89-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/formatter/api.js +7 -1
  3. package/lib/formatter/api.js.map +1 -1
  4. package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
  5. package/lib/formatter/bvt_analysis_formatter.js +139 -50
  6. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  7. package/lib/formatter/feature_data_format.js +0 -1
  8. package/lib/formatter/feature_data_format.js.map +1 -1
  9. package/lib/formatter/helpers/constants.d.ts +50 -0
  10. package/lib/formatter/helpers/constants.js +60 -0
  11. package/lib/formatter/helpers/constants.js.map +1 -0
  12. package/lib/formatter/helpers/report_generator.d.ts +18 -2
  13. package/lib/formatter/helpers/report_generator.js +280 -26
  14. package/lib/formatter/helpers/report_generator.js.map +1 -1
  15. package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
  16. package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
  17. package/lib/formatter/helpers/upload_serivce.d.ts +13 -1
  18. package/lib/formatter/helpers/upload_serivce.js +72 -5
  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 +4 -2
@@ -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"]}
@@ -48,7 +48,6 @@ type JsonCommand = {
48
48
  text: string;
49
49
  screenshotId?: string;
50
50
  result: JsonCommandResult;
51
- webLog?: webLog[];
52
51
  netWorkLog?: any[];
53
52
  };
54
53
  type webLog = {
@@ -63,7 +62,12 @@ export type JsonStep = {
63
62
  text: string;
64
63
  commands: JsonCommand[];
65
64
  result: JsonStepResult;
65
+ webLog: webLog[];
66
+ networkData: any[];
66
67
  data?: any;
68
+ ariaSnapshot: string;
69
+ traceFilePath?: string;
70
+ brunoData?: any;
67
71
  };
68
72
  export type RetrainStats = {
69
73
  result: JsonTestResult;
@@ -80,8 +84,10 @@ export type JsonTestProgress = {
80
84
  steps: JsonStep[];
81
85
  result: JsonTestResult;
82
86
  retrainStats?: RetrainStats;
87
+ initialAriaSnapshot?: string;
83
88
  webLog: any;
84
89
  networkLog: any;
90
+ logFileId?: string;
85
91
  env: {
86
92
  name: string;
87
93
  baseUrl: string;
@@ -113,10 +119,16 @@ export default class ReportGenerator {
113
119
  private scenarioIterationCountMap;
114
120
  private logs;
115
121
  private networkLog;
122
+ private stepLogs;
123
+ private stepNetworkLogs;
116
124
  private runName;
125
+ private ariaSnapshot;
126
+ private initialAriaSnapshot;
127
+ private testCaseLog;
128
+ private loggingOverridden;
117
129
  reportFolder: null | string;
118
130
  private uploadService;
119
- handleMessage(envelope: EnvelopeWithMetaMessage): Promise<void>;
131
+ handleMessage(envelope: EnvelopeWithMetaMessage | messages.Envelope, reRunId?: string): Promise<any>;
120
132
  getReport(): JsonReport;
121
133
  private handleParseError;
122
134
  private onGherkinDocument;
@@ -129,11 +141,15 @@ export default class ReportGenerator {
129
141
  private onTestCaseStarted;
130
142
  private onTestStepStarted;
131
143
  private onAttachment;
144
+ private getFailedTestStepResult;
132
145
  private onTestStepFinished;
133
146
  getLogFileContent(): any;
134
147
  private getTestCaseResult;
135
148
  private onTestCaseFinished;
149
+ private readonly retryCount;
136
150
  private uploadTestCase;
151
+ private tryUpload;
152
+ private writeTestCaseReportToDisk;
137
153
  private onTestRunFinished;
138
154
  }
139
155
  export {};
@@ -1,19 +1,50 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  var _a, _b;
6
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
+ const messages = __importStar(require("@cucumber/messages"));
7
31
  const fs_1 = __importDefault(require("fs"));
8
32
  const path_1 = __importDefault(require("path"));
9
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"));
10
37
  const URL = process.env.NODE_ENV_BLINQ === 'dev'
11
38
  ? 'https://dev.api.blinq.io/api/runs'
12
39
  : process.env.NODE_ENV_BLINQ === 'local'
13
40
  ? 'http://localhost:5001/api/runs'
14
41
  : process.env.NODE_ENV_BLINQ === 'stage'
15
42
  ? 'https://stage.api.blinq.io/api/runs'
16
- : '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`;
17
48
  const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
18
49
  const BATCH_SIZE = 10;
19
50
  const MAX_RETRIES = 3;
@@ -40,12 +71,19 @@ class ReportGenerator {
40
71
  this.scenarioIterationCountMap = new Map();
41
72
  this.logs = [];
42
73
  this.networkLog = [];
74
+ this.stepLogs = [];
75
+ this.stepNetworkLogs = [];
43
76
  this.runName = '';
77
+ this.ariaSnapshot = '';
78
+ this.initialAriaSnapshot = '';
79
+ this.testCaseLog = [];
80
+ this.loggingOverridden = false; // Flag to track if logging is overridden
44
81
  this.reportFolder = null;
45
82
  this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
83
+ this.retryCount = 3;
46
84
  }
47
- async handleMessage(envelope) {
48
- if (envelope.meta && envelope.meta.runName) {
85
+ async handleMessage(envelope, reRunId) {
86
+ if (envelope.meta && 'runName' in envelope.meta) {
49
87
  this.runName = envelope.meta.runName;
50
88
  }
51
89
  const type = Object.keys(envelope)[0];
@@ -72,10 +110,30 @@ class ReportGenerator {
72
110
  case 'testRunStarted': {
73
111
  const testRunStarted = envelope[type];
74
112
  this.onTestRunStarted(testRunStarted);
113
+ await this.uploadService.createStatus('running');
75
114
  break;
76
115
  }
77
116
  case 'testCase': {
78
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
79
137
  this.onTestCase(testCase);
80
138
  break;
81
139
  }
@@ -101,13 +159,14 @@ class ReportGenerator {
101
159
  }
102
160
  case 'testCaseFinished': {
103
161
  const testCaseFinished = envelope[type];
104
- await this.onTestCaseFinished(testCaseFinished);
105
- break;
162
+ // Call the onTestCaseFinished method
163
+ const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
164
+ return result;
106
165
  }
107
166
  // case "hook": { break} // After Hook
108
167
  case 'testRunFinished': {
109
168
  const testRunFinished = envelope[type];
110
- this.onTestRunFinished(testRunFinished);
169
+ await this.onTestRunFinished(testRunFinished);
111
170
  break;
112
171
  }
113
172
  // case "parameterType" : { break}
@@ -238,6 +297,10 @@ class ReportGenerator {
238
297
  result: {
239
298
  status: 'UNKNOWN',
240
299
  },
300
+ networkData: [],
301
+ webLog: [],
302
+ data: {},
303
+ ariaSnapshot: this.ariaSnapshot,
241
304
  });
242
305
  return this.stepReportMap.get(pickleStep.id);
243
306
  });
@@ -280,6 +343,14 @@ class ReportGenerator {
280
343
  this.reportFolder = body.replaceAll('\\', '/');
281
344
  return;
282
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
+ }
283
354
  if (mediaType === 'application/json+env') {
284
355
  const data = JSON.parse(body);
285
356
  this.report.env = data;
@@ -290,13 +361,16 @@ class ReportGenerator {
290
361
  }
291
362
  if (mediaType === 'application/json+log') {
292
363
  const log = JSON.parse(body);
293
- if (this.logs.length < 1000)
364
+ if (this.logs.length < 1000) {
294
365
  this.logs.push(log);
366
+ this.stepLogs.push(log);
367
+ }
295
368
  }
296
369
  if (mediaType === 'application/json+network') {
297
370
  const networkLog = JSON.parse(body);
298
371
  if (this.networkLog.length < 1000)
299
372
  this.networkLog.push(networkLog);
373
+ this.stepNetworkLogs.push(networkLog);
300
374
  }
301
375
  const testStep = this.testStepMap.get(testStepId);
302
376
  if (testStep.pickleStepId === undefined)
@@ -306,6 +380,37 @@ class ReportGenerator {
306
380
  const command = JSON.parse(body);
307
381
  stepProgess.commands.push(command);
308
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
+ }
397
+ getFailedTestStepResult({ commands, startTime, endTime, result, }) {
398
+ for (const command of commands) {
399
+ if (command.result.status === 'FAILED') {
400
+ return {
401
+ status: 'FAILED',
402
+ message: command.result.message,
403
+ startTime,
404
+ endTime,
405
+ };
406
+ }
407
+ }
408
+ return {
409
+ status: 'FAILED',
410
+ startTime,
411
+ endTime,
412
+ message: result.message,
413
+ };
309
414
  }
310
415
  onTestStepFinished(testStepFinished) {
311
416
  const { testStepId, testStepResult, timestamp } = testStepFinished;
@@ -316,6 +421,25 @@ class ReportGenerator {
316
421
  }
317
422
  return;
318
423
  }
424
+ if (testStepResult.status === 'UNDEFINED') {
425
+ const step = this.stepReportMap.get(testStep.pickleStepId);
426
+ const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
427
+ const undefinedCommand = {
428
+ testStepId: testStepId,
429
+ body: JSON.stringify({
430
+ type: 'error',
431
+ text: 'Undefined step: ' + stepName,
432
+ result: {
433
+ status: 'FAILED',
434
+ startTime: this.getTimeStamp(timestamp),
435
+ endTime: this.getTimeStamp(timestamp),
436
+ },
437
+ }),
438
+ mediaType: 'application/json',
439
+ contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
440
+ };
441
+ this.onAttachment(undefinedCommand);
442
+ }
319
443
  const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
320
444
  const prevStepResult = stepProgess.result;
321
445
  let data = {};
@@ -331,16 +455,72 @@ class ReportGenerator {
331
455
  catch (error) {
332
456
  console.log('Error reading data.json');
333
457
  }
334
- stepProgess.result = {
335
- status: testStepResult.status,
336
- startTime: prevStepResult.startTime,
337
- endTime: this.getTimeStamp(timestamp),
338
- message: testStepResult.message,
339
- // exception: testStepResult.exception,
340
- };
458
+ if (testStepResult.status === 'FAILED') {
459
+ stepProgess.result = this.getFailedTestStepResult({
460
+ commands: stepProgess.commands,
461
+ startTime: prevStepResult.startTime,
462
+ endTime: this.getTimeStamp(timestamp),
463
+ result: testStepResult,
464
+ });
465
+ }
466
+ else {
467
+ stepProgess.result = {
468
+ status: testStepResult.status,
469
+ startTime: prevStepResult.startTime,
470
+ endTime: this.getTimeStamp(timestamp),
471
+ };
472
+ }
473
+ stepProgess.webLog = this.stepLogs;
474
+ stepProgess.networkData = this.stepNetworkLogs;
475
+ stepProgess.ariaSnapshot = this.ariaSnapshot;
476
+ this.ariaSnapshot = '';
477
+ this.stepNetworkLogs = [];
478
+ this.stepLogs = [];
341
479
  if (Object.keys(data).length > 0) {
342
480
  stepProgess.data = data;
481
+ const id = testStepFinished.testCaseStartedId;
482
+ const parameters = this.testCaseReportMap.get(id).parameters;
483
+ const _parameters = {};
484
+ Object.keys(parameters).map((key) => {
485
+ if (parameters[key].startsWith('{{') &&
486
+ parameters[key].endsWith('}}')) {
487
+ const path = parameters[key].slice(2, -2).split('.');
488
+ let value = String(object_path_1.default.get(data, path));
489
+ if (value) {
490
+ if (value.startsWith('secret:')) {
491
+ value = 'secret:****';
492
+ }
493
+ else if (value.startsWith('totp:')) {
494
+ value = 'totp:****';
495
+ }
496
+ else if (value.startsWith('mask:')) {
497
+ value = 'mask:****';
498
+ }
499
+ _parameters[key] = value;
500
+ }
501
+ }
502
+ else {
503
+ _parameters[key] = parameters[key];
504
+ }
505
+ });
506
+ this.report.testCases.find((testCase) => {
507
+ return testCase.id === id;
508
+ }).parameters = _parameters;
343
509
  }
510
+ // if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
511
+ // this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
512
+ // if (!fs.existsSync(this.reportFolder)) {
513
+ // fs.mkdirSync(this.reportFolder)
514
+ // }
515
+ // const reportFilePath = path.join(
516
+ // this.reportFolder,
517
+ // `report.json`
518
+ // )
519
+ // writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
520
+ // return undefined
521
+ // // } else {
522
+ // // return await this.uploadTestCase(testProgress, reRunId)
523
+ // }
344
524
  }
345
525
  getLogFileContent() {
346
526
  let projectPath = process.cwd();
@@ -388,24 +568,71 @@ class ReportGenerator {
388
568
  status: 'PASSED',
389
569
  };
390
570
  }
391
- async onTestCaseFinished(testCaseFinished) {
571
+ async onTestCaseFinished(testCaseFinished, reRunId) {
392
572
  const { testCaseStartedId, timestamp } = testCaseFinished;
393
573
  const testProgress = this.testCaseReportMap.get(testCaseStartedId);
394
574
  const prevResult = testProgress.result;
395
575
  const steps = Object.values(testProgress.steps);
396
576
  const result = this.getTestCaseResult(steps);
577
+ const endTime = this.getTimeStamp(timestamp);
397
578
  testProgress.result = {
398
579
  ...result,
399
580
  startTime: prevResult.startTime,
400
- endTime: this.getTimeStamp(timestamp),
581
+ endTime,
401
582
  };
402
583
  testProgress.webLog = this.logs;
403
584
  testProgress.networkLog = this.networkLog;
585
+ testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
586
+ this.initialAriaSnapshot = '';
404
587
  this.networkLog = [];
405
588
  this.logs = [];
406
- await this.uploadTestCase(testProgress);
589
+ if (this.testCaseLog && this.testCaseLog.length > 0) {
590
+ // Create the logs directory
591
+ const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
592
+ const fileName = `testCaseLog_${testCaseStartedId}.log`;
593
+ const filePath = path_1.default.join(logsDir, fileName);
594
+ // Ensure the logs directory exists
595
+ fs_1.default.mkdirSync(logsDir, { recursive: true });
596
+ // Write the logs to the file
597
+ fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
598
+ // Store this ID in the testProgress object so it can be accessed later
599
+ testProgress.logFileId = testCaseStartedId;
600
+ }
601
+ this.testCaseLog = [];
602
+ if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
603
+ this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
604
+ if (!fs_1.default.existsSync(this.reportFolder)) {
605
+ fs_1.default.mkdirSync(this.reportFolder);
606
+ }
607
+ const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
608
+ (0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
609
+ return undefined;
610
+ }
611
+ else {
612
+ return await this.uploadTestCase(testProgress, reRunId);
613
+ }
614
+ }
615
+ async uploadTestCase(testCase, rerunId) {
616
+ let data = null;
617
+ for (let attempt = 1; attempt <= this.retryCount; attempt++) {
618
+ try {
619
+ data = await this.tryUpload(testCase, rerunId);
620
+ break;
621
+ }
622
+ catch (e) {
623
+ console.error(`Attempt ${attempt} to upload testcase failed:`, e);
624
+ if (attempt === this.retryCount) {
625
+ console.error('All retry attempts failed, failed to upload testcase.');
626
+ }
627
+ else {
628
+ const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
629
+ await new Promise((r) => setTimeout(r, waitTime));
630
+ }
631
+ }
632
+ }
633
+ return data;
407
634
  }
408
- async uploadTestCase(testCase) {
635
+ async tryUpload(testCase, rerunId) {
409
636
  let runId = '';
410
637
  let projectId = '';
411
638
  if (!process.env.UPLOADING_TEST_CASE) {
@@ -416,7 +643,9 @@ class ReportGenerator {
416
643
  anyRemArr.push(randomID);
417
644
  process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
418
645
  try {
419
- if (process.env.RUN_ID && process.env.PROJECT_ID) {
646
+ if (process.env.RUN_ID &&
647
+ process.env.PROJECT_ID &&
648
+ !process.env.IGNORE_ENV_VARIABLES) {
420
649
  runId = process.env.RUN_ID;
421
650
  projectId = process.env.PROJECT_ID;
422
651
  }
@@ -424,13 +653,14 @@ class ReportGenerator {
424
653
  const runDoc = await this.uploadService.createRunDocument(this.runName);
425
654
  runId = runDoc._id;
426
655
  projectId = runDoc.project_id;
427
- process.env.RUN_ID = runId;
428
- process.env.PROJECT_ID = projectId;
656
+ if (!process.env.IGNORE_ENV_VARIABLES) {
657
+ process.env.RUN_ID = runId;
658
+ process.env.PROJECT_ID = projectId;
659
+ }
429
660
  }
430
- await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
431
- }
432
- catch (e) {
433
- console.error('Error uploading test case:', e);
661
+ const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
662
+ this.writeTestCaseReportToDisk(testCase);
663
+ return data;
434
664
  }
435
665
  finally {
436
666
  const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
@@ -438,7 +668,30 @@ class ReportGenerator {
438
668
  process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
439
669
  }
440
670
  }
441
- onTestRunFinished(testRunFinished) {
671
+ writeTestCaseReportToDisk(testCase) {
672
+ var _a;
673
+ const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
674
+ if (!reportFolder) {
675
+ console.error('Report folder is not defined');
676
+ return;
677
+ }
678
+ try {
679
+ let i = 0;
680
+ while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
681
+ i++;
682
+ }
683
+ fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
684
+ //exclude network log from the saved report
685
+ const networkLog = testCase.networkLog;
686
+ delete testCase.networkLog;
687
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
688
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
689
+ }
690
+ catch (error) {
691
+ console.error('Error writing test case report to disk:', error);
692
+ }
693
+ }
694
+ async onTestRunFinished(testRunFinished) {
442
695
  const { timestamp, success, message } = testRunFinished;
443
696
  const prevResult = this.report.result;
444
697
  this.report.result = {
@@ -448,6 +701,7 @@ class ReportGenerator {
448
701
  message,
449
702
  // exception,
450
703
  };
704
+ await this.uploadService.createStatus(success ? 'passed' : 'failed');
451
705
  }
452
706
  }
453
707
  exports.default = ReportGenerator;