@dev-blinq/cucumber-js 1.0.100-dev → 1.0.100-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 (39) hide show
  1. package/bin/download-install.js +22 -2
  2. package/lib/api/console_logger.js.map +1 -1
  3. package/lib/cli/validate_node_engine_version.js +3 -1
  4. package/lib/cli/validate_node_engine_version.js.map +1 -1
  5. package/lib/configuration/axios_client.js +1 -1
  6. package/lib/configuration/axios_client.js.map +1 -1
  7. package/lib/formatter/api.js +16 -5
  8. package/lib/formatter/api.js.map +1 -1
  9. package/lib/formatter/builder.js +1 -3
  10. package/lib/formatter/builder.js.map +1 -1
  11. package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
  12. package/lib/formatter/bvt_analysis_formatter.js +202 -78
  13. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  14. package/lib/formatter/feature_data_format.js +3 -1
  15. package/lib/formatter/feature_data_format.js.map +1 -1
  16. package/lib/formatter/helpers/constants.d.ts +50 -0
  17. package/lib/formatter/helpers/constants.js +60 -0
  18. package/lib/formatter/helpers/constants.js.map +1 -0
  19. package/lib/formatter/helpers/report_generator.d.ts +32 -2
  20. package/lib/formatter/helpers/report_generator.js +348 -15
  21. package/lib/formatter/helpers/report_generator.js.map +1 -1
  22. package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
  23. package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
  24. package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
  25. package/lib/formatter/helpers/upload_serivce.d.ts +16 -0
  26. package/lib/formatter/helpers/upload_serivce.js +166 -0
  27. package/lib/formatter/helpers/upload_serivce.js.map +1 -1
  28. package/lib/formatter/helpers/uploader.d.ts +2 -1
  29. package/lib/formatter/helpers/uploader.js +27 -3
  30. package/lib/formatter/helpers/uploader.js.map +1 -1
  31. package/lib/formatter/summary_formatter.js +4 -0
  32. package/lib/formatter/summary_formatter.js.map +1 -1
  33. package/lib/runtime/test_case_runner.d.ts +1 -0
  34. package/lib/runtime/test_case_runner.js +10 -1
  35. package/lib/runtime/test_case_runner.js.map +1 -1
  36. package/lib/version.d.ts +1 -1
  37. package/lib/version.js +1 -1
  38. package/lib/version.js.map +1 -1
  39. package/package.json +5 -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;QACpC,CAAC,CAAC,WAAG,CAAC,sBAAsB;QAC5B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;YACtC,CAAC,CAAC,aAAK,CAAC,sBAAsB;YAC9B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM;gBACrC,CAAC,CAAC,YAAI,CAAC,sBAAsB;gBAC7B,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc;oBAC3B,CAAC,CAAC,YAAI,CAAC,sBAAsB;oBAC7B,CAAC,CAAC,cAAM,CAAA,CAAC,sBAAsB;AAE3C,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,13 @@ 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;
71
+ interceptResults?: any;
67
72
  };
68
73
  export type RetrainStats = {
69
74
  result: JsonTestResult;
@@ -80,8 +85,14 @@ 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;
92
+ env: {
93
+ name: string;
94
+ baseUrl: string;
95
+ };
85
96
  };
86
97
  export type JsonReport = {
87
98
  testCases: JsonTestProgress[];
@@ -91,6 +102,12 @@ export type JsonReport = {
91
102
  baseUrl: string;
92
103
  };
93
104
  };
105
+ interface MetaMessage extends messages.Meta {
106
+ runName: string;
107
+ }
108
+ interface EnvelopeWithMetaMessage extends messages.Envelope {
109
+ meta: MetaMessage;
110
+ }
94
111
  export default class ReportGenerator {
95
112
  private report;
96
113
  private gherkinDocumentMap;
@@ -103,8 +120,16 @@ export default class ReportGenerator {
103
120
  private scenarioIterationCountMap;
104
121
  private logs;
105
122
  private networkLog;
123
+ private stepLogs;
124
+ private stepNetworkLogs;
125
+ private runName;
126
+ private ariaSnapshot;
127
+ private initialAriaSnapshot;
128
+ private testCaseLog;
129
+ private loggingOverridden;
106
130
  reportFolder: null | string;
107
- handleMessage(envelope: messages.Envelope): void;
131
+ private uploadService;
132
+ handleMessage(envelope: EnvelopeWithMetaMessage | messages.Envelope, reRunId?: string): Promise<any>;
108
133
  getReport(): JsonReport;
109
134
  private handleParseError;
110
135
  private onGherkinDocument;
@@ -117,10 +142,15 @@ export default class ReportGenerator {
117
142
  private onTestCaseStarted;
118
143
  private onTestStepStarted;
119
144
  private onAttachment;
145
+ private getFailedTestStepResult;
120
146
  private onTestStepFinished;
121
147
  getLogFileContent(): any;
122
148
  private getTestCaseResult;
123
149
  private onTestCaseFinished;
150
+ private readonly retryCount;
151
+ private uploadTestCase;
152
+ private tryUpload;
153
+ private writeTestCaseReportToDisk;
124
154
  private onTestRunFinished;
125
155
  }
126
156
  export {};
@@ -1,10 +1,54 @@
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
  };
28
+ var _a, _b;
5
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
+ const messages = __importStar(require("@cucumber/messages"));
6
31
  const fs_1 = __importDefault(require("fs"));
7
32
  const path_1 = __importDefault(require("path"));
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"));
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
+ : !process.env.NODE_ENV_BLINQ
46
+ ? 'https://api.blinq.io/api/runs'
47
+ : `${process.env.NODE_ENV_BLINQ}/api/runs`;
48
+ const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
49
+ const BATCH_SIZE = 10;
50
+ const MAX_RETRIES = 3;
51
+ const REPORT_SERVICE_TOKEN = (_b = process.env.TOKEN) !== null && _b !== void 0 ? _b : process.env.REPORT_SERVICE_TOKEN;
8
52
  class ReportGenerator {
9
53
  constructor() {
10
54
  this.report = {
@@ -27,9 +71,21 @@ class ReportGenerator {
27
71
  this.scenarioIterationCountMap = new Map();
28
72
  this.logs = [];
29
73
  this.networkLog = [];
74
+ this.stepLogs = [];
75
+ this.stepNetworkLogs = [];
76
+ this.runName = '';
77
+ this.ariaSnapshot = '';
78
+ this.initialAriaSnapshot = '';
79
+ this.testCaseLog = [];
80
+ this.loggingOverridden = false; // Flag to track if logging is overridden
30
81
  this.reportFolder = null;
82
+ this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
83
+ this.retryCount = 3;
31
84
  }
32
- handleMessage(envelope) {
85
+ async handleMessage(envelope, reRunId) {
86
+ if (envelope.meta && 'runName' in envelope.meta) {
87
+ this.runName = envelope.meta.runName;
88
+ }
33
89
  const type = Object.keys(envelope)[0];
34
90
  switch (type) {
35
91
  // case "meta": { break}
@@ -54,10 +110,30 @@ class ReportGenerator {
54
110
  case 'testRunStarted': {
55
111
  const testRunStarted = envelope[type];
56
112
  this.onTestRunStarted(testRunStarted);
113
+ await this.uploadService.createStatus('running');
57
114
  break;
58
115
  }
59
116
  case 'testCase': {
60
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
61
137
  this.onTestCase(testCase);
62
138
  break;
63
139
  }
@@ -83,13 +159,14 @@ class ReportGenerator {
83
159
  }
84
160
  case 'testCaseFinished': {
85
161
  const testCaseFinished = envelope[type];
86
- this.onTestCaseFinished(testCaseFinished);
87
- break;
162
+ // Call the onTestCaseFinished method
163
+ const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
164
+ return result;
88
165
  }
89
166
  // case "hook": { break} // After Hook
90
167
  case 'testRunFinished': {
91
168
  const testRunFinished = envelope[type];
92
- this.onTestRunFinished(testRunFinished);
169
+ await this.onTestRunFinished(testRunFinished);
93
170
  break;
94
171
  }
95
172
  // case "parameterType" : { break}
@@ -220,6 +297,10 @@ class ReportGenerator {
220
297
  result: {
221
298
  status: 'UNKNOWN',
222
299
  },
300
+ networkData: [],
301
+ webLog: [],
302
+ data: {},
303
+ ariaSnapshot: this.ariaSnapshot,
223
304
  });
224
305
  return this.stepReportMap.get(pickleStep.id);
225
306
  });
@@ -236,6 +317,10 @@ class ReportGenerator {
236
317
  },
237
318
  webLog: [],
238
319
  networkLog: [],
320
+ env: {
321
+ name: this.report.env.name,
322
+ baseUrl: this.report.env.baseUrl,
323
+ },
239
324
  });
240
325
  this.report.testCases.push(this.testCaseReportMap.get(id));
241
326
  }
@@ -258,19 +343,34 @@ class ReportGenerator {
258
343
  this.reportFolder = body.replaceAll('\\', '/');
259
344
  return;
260
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
+ }
261
354
  if (mediaType === 'application/json+env') {
262
355
  const data = JSON.parse(body);
263
356
  this.report.env = data;
357
+ this.report.testCases.map((testCase) => {
358
+ testCase.env = data;
359
+ return testCase;
360
+ });
264
361
  }
265
362
  if (mediaType === 'application/json+log') {
266
363
  const log = JSON.parse(body);
267
- if (this.logs.length < 1000)
364
+ if (this.logs.length < 1000) {
268
365
  this.logs.push(log);
366
+ this.stepLogs.push(log);
367
+ }
269
368
  }
270
369
  if (mediaType === 'application/json+network') {
271
370
  const networkLog = JSON.parse(body);
272
371
  if (this.networkLog.length < 1000)
273
372
  this.networkLog.push(networkLog);
373
+ this.stepNetworkLogs.push(networkLog);
274
374
  }
275
375
  const testStep = this.testStepMap.get(testStepId);
276
376
  if (testStep.pickleStepId === undefined)
@@ -280,6 +380,46 @@ class ReportGenerator {
280
380
  const command = JSON.parse(body);
281
381
  stepProgess.commands.push(command);
282
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
+ };
283
423
  }
284
424
  onTestStepFinished(testStepFinished) {
285
425
  const { testStepId, testStepResult, timestamp } = testStepFinished;
@@ -290,6 +430,25 @@ class ReportGenerator {
290
430
  }
291
431
  return;
292
432
  }
433
+ if (testStepResult.status === 'UNDEFINED') {
434
+ const step = this.stepReportMap.get(testStep.pickleStepId);
435
+ const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
436
+ const undefinedCommand = {
437
+ testStepId: testStepId,
438
+ body: JSON.stringify({
439
+ type: 'error',
440
+ text: 'Undefined step: ' + stepName,
441
+ result: {
442
+ status: 'FAILED',
443
+ startTime: this.getTimeStamp(timestamp),
444
+ endTime: this.getTimeStamp(timestamp),
445
+ },
446
+ }),
447
+ mediaType: 'application/json',
448
+ contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
449
+ };
450
+ this.onAttachment(undefinedCommand);
451
+ }
293
452
  const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
294
453
  const prevStepResult = stepProgess.result;
295
454
  let data = {};
@@ -305,16 +464,73 @@ class ReportGenerator {
305
464
  catch (error) {
306
465
  console.log('Error reading data.json');
307
466
  }
308
- stepProgess.result = {
309
- status: testStepResult.status,
310
- startTime: prevStepResult.startTime,
311
- endTime: this.getTimeStamp(timestamp),
312
- message: testStepResult.message,
313
- // exception: testStepResult.exception,
314
- };
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
+ }
482
+ stepProgess.webLog = this.stepLogs;
483
+ stepProgess.networkData = this.stepNetworkLogs;
484
+ stepProgess.ariaSnapshot = this.ariaSnapshot;
485
+ this.ariaSnapshot = '';
486
+ this.stepNetworkLogs = [];
487
+ this.stepLogs = [];
315
488
  if (Object.keys(data).length > 0) {
316
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;
317
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
+ // }
318
534
  }
319
535
  getLogFileContent() {
320
536
  let projectPath = process.cwd();
@@ -341,6 +557,12 @@ class ReportGenerator {
341
557
  }
342
558
  }
343
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
+ }
344
566
  for (const step of steps) {
345
567
  switch (step.result.status) {
346
568
  case 'FAILED':
@@ -362,23 +584,133 @@ class ReportGenerator {
362
584
  status: 'PASSED',
363
585
  };
364
586
  }
365
- onTestCaseFinished(testCaseFinished) {
587
+ async onTestCaseFinished(testCaseFinished, reRunId) {
366
588
  const { testCaseStartedId, timestamp } = testCaseFinished;
367
589
  const testProgress = this.testCaseReportMap.get(testCaseStartedId);
368
590
  const prevResult = testProgress.result;
369
591
  const steps = Object.values(testProgress.steps);
370
592
  const result = this.getTestCaseResult(steps);
593
+ if (result.status === 'PASSED' && reRunId) {
594
+ this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
595
+ }
596
+ const endTime = this.getTimeStamp(timestamp);
371
597
  testProgress.result = {
372
598
  ...result,
373
599
  startTime: prevResult.startTime,
374
- endTime: this.getTimeStamp(timestamp),
600
+ endTime,
375
601
  };
376
602
  testProgress.webLog = this.logs;
377
603
  testProgress.networkLog = this.networkLog;
604
+ testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
605
+ this.initialAriaSnapshot = '';
378
606
  this.networkLog = [];
379
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 = [];
621
+ if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
622
+ this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
623
+ if (!fs_1.default.existsSync(this.reportFolder)) {
624
+ fs_1.default.mkdirSync(this.reportFolder);
625
+ }
626
+ const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
627
+ (0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
628
+ return undefined;
629
+ }
630
+ else {
631
+ return await this.uploadTestCase(testProgress, reRunId);
632
+ }
633
+ }
634
+ async uploadTestCase(testCase, rerunId) {
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 = '';
657
+ if (!process.env.UPLOADING_TEST_CASE) {
658
+ process.env.UPLOADING_TEST_CASE = '[]';
659
+ }
660
+ const anyRemArr = JSON.parse(process.env.UPLOADING_TEST_CASE);
661
+ const randomID = Math.random().toString(36).substring(7);
662
+ anyRemArr.push(randomID);
663
+ process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
664
+ try {
665
+ if (process.env.RUN_ID &&
666
+ process.env.PROJECT_ID &&
667
+ !process.env.IGNORE_ENV_VARIABLES) {
668
+ runId = process.env.RUN_ID;
669
+ projectId = process.env.PROJECT_ID;
670
+ }
671
+ else {
672
+ const runDoc = await this.uploadService.createRunDocument(this.runName);
673
+ runId = runDoc._id;
674
+ projectId = runDoc.project_id;
675
+ if (!process.env.IGNORE_ENV_VARIABLES) {
676
+ process.env.RUN_ID = runId;
677
+ process.env.PROJECT_ID = projectId;
678
+ }
679
+ }
680
+ const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
681
+ this.writeTestCaseReportToDisk(testCase);
682
+ return data;
683
+ }
684
+ finally {
685
+ const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
686
+ arrRem.splice(arrRem.indexOf(randomID), 1);
687
+ process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
688
+ }
689
+ }
690
+ writeTestCaseReportToDisk(testCase) {
691
+ var _a;
692
+ const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
693
+ if (!reportFolder) {
694
+ console.error('Report folder is not defined');
695
+ return;
696
+ }
697
+ try {
698
+ let i = 0;
699
+ while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
700
+ i++;
701
+ }
702
+ fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
703
+ //exclude network log from the saved report
704
+ const networkLog = testCase.networkLog;
705
+ delete testCase.networkLog;
706
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
707
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
708
+ }
709
+ catch (error) {
710
+ console.error('Error writing test case report to disk:', error);
711
+ }
380
712
  }
381
- onTestRunFinished(testRunFinished) {
713
+ async onTestRunFinished(testRunFinished) {
382
714
  const { timestamp, success, message } = testRunFinished;
383
715
  const prevResult = this.report.result;
384
716
  this.report.result = {
@@ -388,6 +720,7 @@ class ReportGenerator {
388
720
  message,
389
721
  // exception,
390
722
  };
723
+ await this.uploadService.createStatus(success ? 'passed' : 'failed');
391
724
  }
392
725
  }
393
726
  exports.default = ReportGenerator;