@dev-blinq/cucumber-js 1.0.140-dev → 1.0.140

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 (50) hide show
  1. package/bin/cucumber.ts +1 -0
  2. package/bin/download-install.js +22 -2
  3. package/lib/api/console_logger.js.map +1 -1
  4. package/lib/cli/run.js +1 -0
  5. package/lib/cli/run.js.map +1 -1
  6. package/lib/cli/validate_node_engine_version.js +3 -1
  7. package/lib/cli/validate_node_engine_version.js.map +1 -1
  8. package/lib/configuration/axios_client.js +1 -1
  9. package/lib/configuration/axios_client.js.map +1 -1
  10. package/lib/formatter/api.js +16 -5
  11. package/lib/formatter/api.js.map +1 -1
  12. package/lib/formatter/builder.js +1 -3
  13. package/lib/formatter/builder.js.map +1 -1
  14. package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
  15. package/lib/formatter/bvt_analysis_formatter.js +198 -68
  16. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  17. package/lib/formatter/feature_data_format.js +22 -8
  18. package/lib/formatter/feature_data_format.js.map +1 -1
  19. package/lib/formatter/helpers/constants.d.ts +20 -1
  20. package/lib/formatter/helpers/constants.js +26 -3
  21. package/lib/formatter/helpers/constants.js.map +1 -1
  22. package/lib/formatter/helpers/report_generator.d.ts +17 -2
  23. package/lib/formatter/helpers/report_generator.js +236 -23
  24. package/lib/formatter/helpers/report_generator.js.map +1 -1
  25. package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
  26. package/lib/formatter/helpers/upload_serivce.d.ts +22 -2
  27. package/lib/formatter/helpers/upload_serivce.js +198 -49
  28. package/lib/formatter/helpers/upload_serivce.js.map +1 -1
  29. package/lib/formatter/helpers/uploader.js +6 -2
  30. package/lib/formatter/helpers/uploader.js.map +1 -1
  31. package/lib/formatter/progress_formatter.d.ts +2 -1
  32. package/lib/formatter/progress_formatter.js.map +1 -1
  33. package/lib/formatter/snippets_formatter.js.map +1 -1
  34. package/lib/formatter/summary_formatter.js +4 -0
  35. package/lib/formatter/summary_formatter.js.map +1 -1
  36. package/lib/formatter/usage_formatter.js.map +1 -1
  37. package/lib/formatter/usage_json_formatter.js.map +1 -1
  38. package/lib/models/definition.js.map +1 -1
  39. package/lib/pickle_filter.d.ts +3 -2
  40. package/lib/pickle_filter.js.map +1 -1
  41. package/lib/runtime/test_case_runner.d.ts +2 -0
  42. package/lib/runtime/test_case_runner.js +17 -1
  43. package/lib/runtime/test_case_runner.js.map +1 -1
  44. package/lib/support_code_library_builder/world.js.map +1 -1
  45. package/lib/uncaught_exception_manager.d.ts +1 -1
  46. package/lib/uncaught_exception_manager.js.map +1 -1
  47. package/lib/version.d.ts +1 -1
  48. package/lib/version.js +1 -1
  49. package/lib/version.js.map +1 -1
  50. package/package.json +7 -3
@@ -22,6 +22,12 @@ export declare const STAGE: {
22
22
  RUNS: string;
23
23
  STORAGE: string;
24
24
  };
25
+ export declare const CUSTOM: {
26
+ SSO: string;
27
+ WORKSPACE: string;
28
+ RUNS: string;
29
+ STORAGE: string;
30
+ };
25
31
  export declare const SERVICES_URI: {
26
32
  SSO: string;
27
33
  WORKSPACE: string;
@@ -40,5 +46,18 @@ export declare enum ActionEvents {
40
46
  click_open_vscode = "click_open_vscode",
41
47
  error_open_vscode = "error_open_vscode",
42
48
  cli_run_tests = "cli_run_tests",
43
- upload_report = "upload_report"
49
+ upload_report = "upload_report",
50
+ signup = "signup",
51
+ create_project = "create_project",
52
+ create_scenario = "create_scenario",
53
+ launched_chromium_success = "launched_chromium_success",
54
+ launched_chromium_failed = "launched_chromium_failed",
55
+ update_started = "update_started",
56
+ update_downloaded = "update_downloaded",
57
+ update_error = "update_error",
58
+ package_sync_error_minor = "package_sync_error_minor",
59
+ package_sync_error_major = "package_sync_error_major",
60
+ package_sync_error_fatal = "package_sync_error_fatal",
61
+ draft_recovered = "draft_recovered",
62
+ draft_deleted = "draft_deleted"
44
63
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ActionEvents = exports.SERVICES_URI = exports.STAGE = exports.PROD = exports.DEV = exports.LOCAL = void 0;
3
+ exports.ActionEvents = exports.SERVICES_URI = exports.CUSTOM = exports.STAGE = exports.PROD = exports.DEV = exports.LOCAL = void 0;
4
4
  exports.LOCAL = {
5
5
  SSO: 'http://localhost:5000/api/auth',
6
6
  WORKSPACE: 'http://localhost:6000/api/workspace',
@@ -25,13 +25,23 @@ exports.STAGE = {
25
25
  RUNS: 'https://stage.api.blinq.io/api/runs',
26
26
  STORAGE: 'https://stage.api.blinq.io/api/storage',
27
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
+ };
28
34
  exports.SERVICES_URI = process.env.NODE_ENV_BLINQ === 'local'
29
35
  ? exports.LOCAL // eslint-disable-line
30
36
  : process.env.NODE_ENV_BLINQ === 'dev'
31
37
  ? exports.DEV // eslint-disable-line
32
38
  : process.env.NODE_ENV_BLINQ === 'stage'
33
- ? exports.STAGE
34
- : exports.PROD; // eslint-disable-line
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
35
45
  var ActionEvents;
36
46
  (function (ActionEvents) {
37
47
  ActionEvents["record_scenario"] = "record_scenario";
@@ -46,5 +56,18 @@ var ActionEvents;
46
56
  ActionEvents["error_open_vscode"] = "error_open_vscode";
47
57
  ActionEvents["cli_run_tests"] = "cli_run_tests";
48
58
  ActionEvents["upload_report"] = "upload_report";
59
+ ActionEvents["signup"] = "signup";
60
+ ActionEvents["create_project"] = "create_project";
61
+ ActionEvents["create_scenario"] = "create_scenario";
62
+ ActionEvents["launched_chromium_success"] = "launched_chromium_success";
63
+ ActionEvents["launched_chromium_failed"] = "launched_chromium_failed";
64
+ ActionEvents["update_started"] = "update_started";
65
+ ActionEvents["update_downloaded"] = "update_downloaded";
66
+ ActionEvents["update_error"] = "update_error";
67
+ ActionEvents["package_sync_error_minor"] = "package_sync_error_minor";
68
+ ActionEvents["package_sync_error_major"] = "package_sync_error_major";
69
+ ActionEvents["package_sync_error_fatal"] = "package_sync_error_fatal";
70
+ ActionEvents["draft_recovered"] = "draft_recovered";
71
+ ActionEvents["draft_deleted"] = "draft_deleted";
49
72
  })(ActionEvents = exports.ActionEvents || (exports.ActionEvents = {}));
50
73
  //# sourceMappingURL=constants.js.map
@@ -1 +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,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;YACP,CAAC,CAAC,YAAI,CAAA,CAAC,sBAAsB;AAEjC,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 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\n : PROD // 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"]}
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,YA0BX;AA1BD,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;IAC/B,iCAAiB,CAAA;IACjB,iDAAiC,CAAA;IACjC,mDAAmC,CAAA;IACnC,uEAAuD,CAAA;IACvD,qEAAqD,CAAA;IACrD,iDAAiC,CAAA;IACjC,uDAAuC,CAAA;IACvC,6CAA6B,CAAA;IAC7B,qEAAqD,CAAA;IACrD,qEAAqD,CAAA;IACrD,qEAAqD,CAAA;IACrD,mDAAmC,CAAA;IACnC,+CAA+B,CAAA;AACjC,CAAC,EA1BW,YAAY,GAAZ,oBAAY,KAAZ,oBAAY,QA0BvB","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 signup = 'signup',\n create_project = 'create_project',\n create_scenario = 'create_scenario',\n launched_chromium_success = 'launched_chromium_success',\n launched_chromium_failed = 'launched_chromium_failed',\n update_started = 'update_started',\n update_downloaded = 'update_downloaded',\n update_error = 'update_error',\n package_sync_error_minor = 'package_sync_error_minor', // Detected but did not block operation\n package_sync_error_major = 'package_sync_error_major', // Detected and caused degraded experience\n package_sync_error_fatal = 'package_sync_error_fatal', // Undetected and blocked operation\n draft_recovered = 'draft_recovered',\n draft_deleted = 'draft_deleted',\n}\n"]}
@@ -1,6 +1,6 @@
1
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' | 'After' | 'Before';
4
4
  export type JsonResultUnknown = {
5
5
  status: 'UNKNOWN';
6
6
  };
@@ -32,6 +32,7 @@ export type JsonResultFailed = {
32
32
  startTime: JsonTimestamp;
33
33
  endTime: JsonTimestamp;
34
34
  message?: string;
35
+ name?: string;
35
36
  };
36
37
  export type JsonFixedByAi = {
37
38
  status: 'FIXED_BY_AI';
@@ -65,6 +66,10 @@ export type JsonStep = {
65
66
  webLog: webLog[];
66
67
  networkData: any[];
67
68
  data?: any;
69
+ ariaSnapshot: string;
70
+ traceFilePath?: string;
71
+ brunoData?: any;
72
+ interceptResults?: any;
68
73
  };
69
74
  export type RetrainStats = {
70
75
  result: JsonTestResult;
@@ -81,12 +86,15 @@ export type JsonTestProgress = {
81
86
  steps: JsonStep[];
82
87
  result: JsonTestResult;
83
88
  retrainStats?: RetrainStats;
89
+ initialAriaSnapshot?: string;
84
90
  webLog: any;
85
91
  networkLog: any;
92
+ logFileId?: string;
86
93
  env: {
87
94
  name: string;
88
95
  baseUrl: string;
89
96
  };
97
+ traceFileId?: string;
90
98
  };
91
99
  export type JsonReport = {
92
100
  testCases: JsonTestProgress[];
@@ -117,9 +125,14 @@ export default class ReportGenerator {
117
125
  private stepLogs;
118
126
  private stepNetworkLogs;
119
127
  private runName;
128
+ private ariaSnapshot;
129
+ private initialAriaSnapshot;
130
+ private testCaseLog;
131
+ private loggingOverridden;
120
132
  reportFolder: null | string;
121
133
  private uploadService;
122
- handleMessage(envelope: EnvelopeWithMetaMessage): Promise<void>;
134
+ private retryTestCaseId;
135
+ handleMessage(envelope: EnvelopeWithMetaMessage | messages.Envelope, reRunId?: string): Promise<any>;
123
136
  getReport(): JsonReport;
124
137
  private handleParseError;
125
138
  private onGherkinDocument;
@@ -137,7 +150,9 @@ export default class ReportGenerator {
137
150
  getLogFileContent(): any;
138
151
  private getTestCaseResult;
139
152
  private onTestCaseFinished;
153
+ private readonly retryCount;
140
154
  private uploadTestCase;
155
+ private tryUpload;
141
156
  private writeTestCaseReportToDisk;
142
157
  private onTestRunFinished;
143
158
  }
@@ -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;
@@ -67,11 +74,17 @@ class ReportGenerator {
67
74
  this.stepLogs = [];
68
75
  this.stepNetworkLogs = [];
69
76
  this.runName = '';
77
+ this.ariaSnapshot = '';
78
+ this.initialAriaSnapshot = '';
79
+ this.testCaseLog = [];
80
+ this.loggingOverridden = false; // Flag to track if logging is overridden
70
81
  this.reportFolder = null;
71
82
  this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
83
+ this.retryTestCaseId = null;
84
+ this.retryCount = 3;
72
85
  }
73
- async handleMessage(envelope) {
74
- if (envelope.meta && envelope.meta.runName) {
86
+ async handleMessage(envelope, reRunId) {
87
+ if (envelope.meta && 'runName' in envelope.meta) {
75
88
  this.runName = envelope.meta.runName;
76
89
  }
77
90
  const type = Object.keys(envelope)[0];
@@ -98,14 +111,35 @@ class ReportGenerator {
98
111
  case 'testRunStarted': {
99
112
  const testRunStarted = envelope[type];
100
113
  this.onTestRunStarted(testRunStarted);
114
+ await this.uploadService.createStatus('running');
101
115
  break;
102
116
  }
103
117
  case 'testCase': {
104
118
  const testCase = envelope[type];
119
+ // Initialize the log storage
120
+ this.testCaseLog = [];
121
+ if (!this.loggingOverridden) {
122
+ this.loggingOverridden = true;
123
+ // Store the original process.stdout.write, and process.stderr.write
124
+ const originalStdoutWrite = process.stdout.write;
125
+ const originalStderrWrite = process.stderr.write;
126
+ // Override process.stdout.write
127
+ process.stdout.write = (chunk, ...args) => {
128
+ this.testCaseLog.push(chunk.toString());
129
+ return originalStdoutWrite.call(process.stdout, chunk, ...args);
130
+ };
131
+ // Override process.stderr.write
132
+ process.stderr.write = (chunk, ...args) => {
133
+ this.testCaseLog.push(chunk.toString());
134
+ return originalStderrWrite.call(process.stderr, chunk, ...args);
135
+ };
136
+ }
137
+ // Call the onTestCase method
105
138
  this.onTestCase(testCase);
106
139
  break;
107
140
  }
108
141
  case 'testCaseStarted': {
142
+ this.retryTestCaseId = envelope[type].retryTestCaseId;
109
143
  const testCaseStarted = envelope[type];
110
144
  this.onTestCaseStarted(testCaseStarted);
111
145
  break;
@@ -127,13 +161,18 @@ class ReportGenerator {
127
161
  }
128
162
  case 'testCaseFinished': {
129
163
  const testCaseFinished = envelope[type];
130
- await this.onTestCaseFinished(testCaseFinished);
131
- break;
164
+ let reRunIdFinal = this.retryTestCaseId;
165
+ if (reRunId) {
166
+ reRunIdFinal = reRunId;
167
+ }
168
+ // Call the onTestCaseFinished method
169
+ const result = await this.onTestCaseFinished(testCaseFinished, reRunIdFinal);
170
+ return result;
132
171
  }
133
172
  // case "hook": { break} // After Hook
134
173
  case 'testRunFinished': {
135
174
  const testRunFinished = envelope[type];
136
- this.onTestRunFinished(testRunFinished);
175
+ await this.onTestRunFinished(testRunFinished);
137
176
  break;
138
177
  }
139
178
  // case "parameterType" : { break}
@@ -266,6 +305,8 @@ class ReportGenerator {
266
305
  },
267
306
  networkData: [],
268
307
  webLog: [],
308
+ data: {},
309
+ ariaSnapshot: this.ariaSnapshot,
269
310
  });
270
311
  return this.stepReportMap.get(pickleStep.id);
271
312
  });
@@ -308,6 +349,14 @@ class ReportGenerator {
308
349
  this.reportFolder = body.replaceAll('\\', '/');
309
350
  return;
310
351
  }
352
+ if (mediaType === 'application/json+snapshot-before') {
353
+ this.initialAriaSnapshot = body;
354
+ return;
355
+ }
356
+ if (mediaType === 'application/json+snapshot-after') {
357
+ this.ariaSnapshot = body;
358
+ return;
359
+ }
311
360
  if (mediaType === 'application/json+env') {
312
361
  const data = JSON.parse(body);
313
362
  this.report.env = data;
@@ -337,13 +386,36 @@ class ReportGenerator {
337
386
  const command = JSON.parse(body);
338
387
  stepProgess.commands.push(command);
339
388
  }
389
+ else if (mediaType === 'application/json+trace') {
390
+ const data = JSON.parse(body);
391
+ stepProgess.traceFilePath = data.traceFilePath;
392
+ }
393
+ if (mediaType === 'application/json+bruno') {
394
+ try {
395
+ const data = JSON.parse(body);
396
+ stepProgess.brunoData = data;
397
+ }
398
+ catch (error) {
399
+ console.error('Error parsing bruno data:', error);
400
+ }
401
+ }
402
+ if (mediaType === 'application/json+intercept-results') {
403
+ try {
404
+ const data = JSON.parse(body);
405
+ stepProgess.interceptResults = data;
406
+ }
407
+ catch (error) {
408
+ console.error('Error parsing intercept results:', error);
409
+ }
410
+ }
340
411
  }
341
- getFailedTestStepResult({ commands, startTime, endTime, result }) {
412
+ getFailedTestStepResult({ commands, startTime, endTime, result, stepName, }) {
342
413
  for (const command of commands) {
343
414
  if (command.result.status === 'FAILED') {
344
415
  return {
345
416
  status: 'FAILED',
346
417
  message: command.result.message,
418
+ name: stepName,
347
419
  startTime,
348
420
  endTime,
349
421
  };
@@ -354,6 +426,7 @@ class ReportGenerator {
354
426
  startTime,
355
427
  endTime,
356
428
  message: result.message,
429
+ name: stepName,
357
430
  };
358
431
  }
359
432
  onTestStepFinished(testStepFinished) {
@@ -361,6 +434,31 @@ class ReportGenerator {
361
434
  const testStep = this.testStepMap.get(testStepId);
362
435
  if (testStep.pickleStepId === undefined) {
363
436
  if (testStepResult.status === 'FAILED') {
437
+ const testCase = this.testCaseReportMap.get(testStepFinished.testCaseStartedId);
438
+ const type = testCase.steps[0].result.status === 'UNKNOWN' ? 'Before' : 'After';
439
+ const hookStep = {
440
+ ariaSnapshot: null,
441
+ commands: [],
442
+ keyword: type,
443
+ data: {},
444
+ networkData: [],
445
+ result: {
446
+ status: 'FAILED',
447
+ message: testStepResult.message,
448
+ startTime: this.getTimeStamp(timestamp),
449
+ endTime: this.getTimeStamp(timestamp),
450
+ },
451
+ text: 'Failed hook',
452
+ type,
453
+ webLog: [],
454
+ };
455
+ if (type === 'Before') {
456
+ testCase.steps = [hookStep, ...testCase.steps];
457
+ }
458
+ else {
459
+ testCase.steps = [...testCase.steps, hookStep];
460
+ }
461
+ this.testCaseReportMap.set(testStepFinished.testCaseStartedId, testCase);
364
462
  console.error(`Before/After hook failed with message: ${testStepResult.message}`);
365
463
  }
366
464
  return;
@@ -404,7 +502,8 @@ class ReportGenerator {
404
502
  commands: stepProgess.commands,
405
503
  startTime: prevStepResult.startTime,
406
504
  endTime: this.getTimeStamp(timestamp),
407
- result: testStepResult
505
+ result: testStepResult,
506
+ stepName: stepProgess.text,
408
507
  });
409
508
  }
410
509
  else {
@@ -416,11 +515,56 @@ class ReportGenerator {
416
515
  }
417
516
  stepProgess.webLog = this.stepLogs;
418
517
  stepProgess.networkData = this.stepNetworkLogs;
518
+ stepProgess.ariaSnapshot = this.ariaSnapshot;
519
+ this.ariaSnapshot = '';
419
520
  this.stepNetworkLogs = [];
420
521
  this.stepLogs = [];
421
522
  if (Object.keys(data).length > 0) {
422
523
  stepProgess.data = data;
524
+ const id = testStepFinished.testCaseStartedId;
525
+ const parameters = this.testCaseReportMap.get(id).parameters;
526
+ const _parameters = {};
527
+ Object.keys(parameters).map((key) => {
528
+ var _a;
529
+ const valueParam = parameters[key].toString();
530
+ if (valueParam.startsWith('{{') && valueParam.endsWith('}}')) {
531
+ const path = valueParam.slice(2, -2).split('.');
532
+ let value = String((_a = object_path_1.default.get(data, path)) !== null && _a !== void 0 ? _a : valueParam);
533
+ if (value) {
534
+ if (value.startsWith('secret:')) {
535
+ value = 'secret:****';
536
+ }
537
+ else if (value.startsWith('totp:')) {
538
+ value = 'totp:****';
539
+ }
540
+ else if (value.startsWith('mask:')) {
541
+ value = 'mask:****';
542
+ }
543
+ _parameters[key] = value;
544
+ }
545
+ }
546
+ else {
547
+ _parameters[key] = parameters[key];
548
+ }
549
+ });
550
+ this.report.testCases.find((testCase) => {
551
+ return testCase.id === id;
552
+ }).parameters = _parameters;
423
553
  }
554
+ // if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
555
+ // this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
556
+ // if (!fs.existsSync(this.reportFolder)) {
557
+ // fs.mkdirSync(this.reportFolder)
558
+ // }
559
+ // const reportFilePath = path.join(
560
+ // this.reportFolder,
561
+ // `report.json`
562
+ // )
563
+ // writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
564
+ // return undefined
565
+ // // } else {
566
+ // // return await this.uploadTestCase(testProgress, reRunId)
567
+ // }
424
568
  }
425
569
  getLogFileContent() {
426
570
  let projectPath = process.cwd();
@@ -447,6 +591,12 @@ class ReportGenerator {
447
591
  }
448
592
  }
449
593
  getTestCaseResult(steps) {
594
+ if (steps[0] && steps[0].result.status === 'SKIPPED') {
595
+ return {
596
+ status: 'FAILED',
597
+ message: 'Test skipped due to failure in before hooks',
598
+ };
599
+ }
450
600
  for (const step of steps) {
451
601
  switch (step.result.status) {
452
602
  case 'FAILED':
@@ -468,24 +618,79 @@ class ReportGenerator {
468
618
  status: 'PASSED',
469
619
  };
470
620
  }
471
- async onTestCaseFinished(testCaseFinished) {
621
+ async onTestCaseFinished(testCaseFinished, reRunId) {
472
622
  const { testCaseStartedId, timestamp } = testCaseFinished;
473
623
  const testProgress = this.testCaseReportMap.get(testCaseStartedId);
474
624
  const prevResult = testProgress.result;
475
625
  const steps = Object.values(testProgress.steps);
476
626
  const result = this.getTestCaseResult(steps);
627
+ if (result.status === 'PASSED' && reRunId) {
628
+ this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
629
+ }
630
+ const endTime = this.getTimeStamp(timestamp);
477
631
  testProgress.result = {
478
632
  ...result,
479
633
  startTime: prevResult.startTime,
480
- endTime: this.getTimeStamp(timestamp),
634
+ endTime,
481
635
  };
482
636
  testProgress.webLog = this.logs;
483
637
  testProgress.networkLog = this.networkLog;
638
+ testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
639
+ if (process.env.TRACE) {
640
+ testProgress.traceFileId = path_1.default.join(`trace-${testCaseStartedId}.zip`);
641
+ }
642
+ this.initialAriaSnapshot = '';
484
643
  this.networkLog = [];
485
644
  this.logs = [];
486
- await this.uploadTestCase(testProgress);
645
+ if (this.testCaseLog &&
646
+ this.testCaseLog.length > 0 &&
647
+ !testProgress.logFileId) {
648
+ // Create the logs directory
649
+ const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
650
+ const fileName = `testCaseLog_${testCaseStartedId}.log`;
651
+ const filePath = path_1.default.join(logsDir, fileName);
652
+ // Ensure the logs directory exists
653
+ fs_1.default.mkdirSync(logsDir, { recursive: true });
654
+ // Write the logs to the file
655
+ fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
656
+ // Store this ID in the testProgress object so it can be accessed later
657
+ testProgress.logFileId = testCaseStartedId;
658
+ }
659
+ this.testCaseLog = [];
660
+ if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
661
+ this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
662
+ if (!fs_1.default.existsSync(this.reportFolder)) {
663
+ fs_1.default.mkdirSync(this.reportFolder);
664
+ }
665
+ const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
666
+ (0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
667
+ return undefined;
668
+ }
669
+ else {
670
+ return await this.uploadTestCase(testProgress, reRunId);
671
+ }
672
+ }
673
+ async uploadTestCase(testCase, rerunId) {
674
+ let data = null;
675
+ for (let attempt = 1; attempt <= this.retryCount; attempt++) {
676
+ try {
677
+ data = await this.tryUpload(testCase, rerunId);
678
+ break;
679
+ }
680
+ catch (e) {
681
+ console.error(`Attempt ${attempt} to upload testcase failed:`, e);
682
+ if (attempt === this.retryCount) {
683
+ console.error('All retry attempts failed, failed to upload testcase.');
684
+ }
685
+ else {
686
+ const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
687
+ await new Promise((r) => setTimeout(r, waitTime));
688
+ }
689
+ }
690
+ }
691
+ return data;
487
692
  }
488
- async uploadTestCase(testCase) {
693
+ async tryUpload(testCase, rerunId) {
489
694
  let runId = '';
490
695
  let projectId = '';
491
696
  if (!process.env.UPLOADING_TEST_CASE) {
@@ -503,7 +708,7 @@ class ReportGenerator {
503
708
  projectId = process.env.PROJECT_ID;
504
709
  }
505
710
  else {
506
- const runDoc = await this.uploadService.createRunDocument(this.runName);
711
+ const runDoc = await this.uploadService.createRunDocument(this.runName, testCase.env);
507
712
  runId = runDoc._id;
508
713
  projectId = runDoc.project_id;
509
714
  if (!process.env.IGNORE_ENV_VARIABLES) {
@@ -511,11 +716,9 @@ class ReportGenerator {
511
716
  process.env.PROJECT_ID = projectId;
512
717
  }
513
718
  }
514
- await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
515
- this.writeTestCaseReportToDisk(testCase);
516
- }
517
- catch (e) {
518
- console.error('Error uploading test case:', e);
719
+ const reportIndex = this.writeTestCaseReportToDisk(testCase);
720
+ const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, reportIndex, rerunId);
721
+ return data;
519
722
  }
520
723
  finally {
521
724
  const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
@@ -524,23 +727,32 @@ class ReportGenerator {
524
727
  }
525
728
  }
526
729
  writeTestCaseReportToDisk(testCase) {
730
+ var _a;
731
+ const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
732
+ if (!reportFolder) {
733
+ console.error('Report folder is not defined');
734
+ return -1;
735
+ }
527
736
  try {
528
737
  let i = 0;
529
- while (fs_1.default.existsSync(path_1.default.join(this.reportFolder, `${i}`))) {
738
+ while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
530
739
  i++;
531
740
  }
532
- fs_1.default.mkdirSync(path_1.default.join(this.reportFolder, `${i}`));
741
+ fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
533
742
  //exclude network log from the saved report
534
743
  const networkLog = testCase.networkLog;
535
744
  delete testCase.networkLog;
536
- fs_1.default.writeFileSync(path_1.default.join(this.reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
537
- fs_1.default.writeFileSync(path_1.default.join(this.reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
745
+ delete testCase.webLog;
746
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
747
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
748
+ return i;
538
749
  }
539
750
  catch (error) {
540
751
  console.error('Error writing test case report to disk:', error);
752
+ return -1;
541
753
  }
542
754
  }
543
- onTestRunFinished(testRunFinished) {
755
+ async onTestRunFinished(testRunFinished) {
544
756
  const { timestamp, success, message } = testRunFinished;
545
757
  const prevResult = this.report.result;
546
758
  this.report.result = {
@@ -550,6 +762,7 @@ class ReportGenerator {
550
762
  message,
551
763
  // exception,
552
764
  };
765
+ await this.uploadService.createStatus(success ? 'passed' : 'failed');
553
766
  }
554
767
  }
555
768
  exports.default = ReportGenerator;