@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.
- package/bin/cucumber.ts +1 -0
- package/bin/download-install.js +22 -2
- package/lib/api/console_logger.js.map +1 -1
- package/lib/cli/run.js +1 -0
- package/lib/cli/run.js.map +1 -1
- package/lib/cli/validate_node_engine_version.js +3 -1
- package/lib/cli/validate_node_engine_version.js.map +1 -1
- package/lib/configuration/axios_client.js +1 -1
- package/lib/configuration/axios_client.js.map +1 -1
- package/lib/formatter/api.js +16 -5
- package/lib/formatter/api.js.map +1 -1
- package/lib/formatter/builder.js +1 -3
- package/lib/formatter/builder.js.map +1 -1
- package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
- package/lib/formatter/bvt_analysis_formatter.js +198 -68
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +22 -8
- package/lib/formatter/feature_data_format.js.map +1 -1
- package/lib/formatter/helpers/constants.d.ts +20 -1
- package/lib/formatter/helpers/constants.js +26 -3
- package/lib/formatter/helpers/constants.js.map +1 -1
- package/lib/formatter/helpers/report_generator.d.ts +17 -2
- package/lib/formatter/helpers/report_generator.js +236 -23
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +22 -2
- package/lib/formatter/helpers/upload_serivce.js +198 -49
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.js +6 -2
- package/lib/formatter/helpers/uploader.js.map +1 -1
- package/lib/formatter/progress_formatter.d.ts +2 -1
- package/lib/formatter/progress_formatter.js.map +1 -1
- package/lib/formatter/snippets_formatter.js.map +1 -1
- package/lib/formatter/summary_formatter.js +4 -0
- package/lib/formatter/summary_formatter.js.map +1 -1
- package/lib/formatter/usage_formatter.js.map +1 -1
- package/lib/formatter/usage_json_formatter.js.map +1 -1
- package/lib/models/definition.js.map +1 -1
- package/lib/pickle_filter.d.ts +3 -2
- package/lib/pickle_filter.js.map +1 -1
- package/lib/runtime/test_case_runner.d.ts +2 -0
- package/lib/runtime/test_case_runner.js +17 -1
- package/lib/runtime/test_case_runner.js.map +1 -1
- package/lib/support_code_library_builder/world.js.map +1 -1
- package/lib/uncaught_exception_manager.d.ts +1 -1
- package/lib/uncaught_exception_manager.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- 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
|
-
:
|
|
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;
|
|
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
|
-
|
|
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
|
-
:
|
|
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
|
|
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
|
-
|
|
131
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
515
|
-
this.
|
|
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(
|
|
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(
|
|
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
|
-
|
|
537
|
-
fs_1.default.writeFileSync(path_1.default.join(
|
|
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;
|