@dev-blinq/cucumber-js 1.0.138-dev → 1.0.138
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 +18 -2
- package/lib/formatter/helpers/report_generator.js +264 -27
- 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 -46
- 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;
|
|
@@ -132,11 +145,14 @@ export default class ReportGenerator {
|
|
|
132
145
|
private onTestCaseStarted;
|
|
133
146
|
private onTestStepStarted;
|
|
134
147
|
private onAttachment;
|
|
148
|
+
private getFailedTestStepResult;
|
|
135
149
|
private onTestStepFinished;
|
|
136
150
|
getLogFileContent(): any;
|
|
137
151
|
private getTestCaseResult;
|
|
138
152
|
private onTestCaseFinished;
|
|
153
|
+
private readonly retryCount;
|
|
139
154
|
private uploadTestCase;
|
|
155
|
+
private tryUpload;
|
|
140
156
|
private writeTestCaseReportToDisk;
|
|
141
157
|
private onTestRunFinished;
|
|
142
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,12 +386,79 @@ 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
|
+
}
|
|
411
|
+
}
|
|
412
|
+
getFailedTestStepResult({ commands, startTime, endTime, result, stepName, }) {
|
|
413
|
+
for (const command of commands) {
|
|
414
|
+
if (command.result.status === 'FAILED') {
|
|
415
|
+
return {
|
|
416
|
+
status: 'FAILED',
|
|
417
|
+
message: command.result.message,
|
|
418
|
+
name: stepName,
|
|
419
|
+
startTime,
|
|
420
|
+
endTime,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
status: 'FAILED',
|
|
426
|
+
startTime,
|
|
427
|
+
endTime,
|
|
428
|
+
message: result.message,
|
|
429
|
+
name: stepName,
|
|
430
|
+
};
|
|
340
431
|
}
|
|
341
432
|
onTestStepFinished(testStepFinished) {
|
|
342
433
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
343
434
|
const testStep = this.testStepMap.get(testStepId);
|
|
344
435
|
if (testStep.pickleStepId === undefined) {
|
|
345
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);
|
|
346
462
|
console.error(`Before/After hook failed with message: ${testStepResult.message}`);
|
|
347
463
|
}
|
|
348
464
|
return;
|
|
@@ -381,20 +497,74 @@ class ReportGenerator {
|
|
|
381
497
|
catch (error) {
|
|
382
498
|
console.log('Error reading data.json');
|
|
383
499
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
500
|
+
if (testStepResult.status === 'FAILED') {
|
|
501
|
+
stepProgess.result = this.getFailedTestStepResult({
|
|
502
|
+
commands: stepProgess.commands,
|
|
503
|
+
startTime: prevStepResult.startTime,
|
|
504
|
+
endTime: this.getTimeStamp(timestamp),
|
|
505
|
+
result: testStepResult,
|
|
506
|
+
stepName: stepProgess.text,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
stepProgess.result = {
|
|
511
|
+
status: testStepResult.status,
|
|
512
|
+
startTime: prevStepResult.startTime,
|
|
513
|
+
endTime: this.getTimeStamp(timestamp),
|
|
514
|
+
};
|
|
515
|
+
}
|
|
391
516
|
stepProgess.webLog = this.stepLogs;
|
|
392
517
|
stepProgess.networkData = this.stepNetworkLogs;
|
|
518
|
+
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
519
|
+
this.ariaSnapshot = '';
|
|
393
520
|
this.stepNetworkLogs = [];
|
|
394
521
|
this.stepLogs = [];
|
|
395
522
|
if (Object.keys(data).length > 0) {
|
|
396
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;
|
|
397
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
|
+
// }
|
|
398
568
|
}
|
|
399
569
|
getLogFileContent() {
|
|
400
570
|
let projectPath = process.cwd();
|
|
@@ -421,6 +591,12 @@ class ReportGenerator {
|
|
|
421
591
|
}
|
|
422
592
|
}
|
|
423
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
|
+
}
|
|
424
600
|
for (const step of steps) {
|
|
425
601
|
switch (step.result.status) {
|
|
426
602
|
case 'FAILED':
|
|
@@ -442,24 +618,79 @@ class ReportGenerator {
|
|
|
442
618
|
status: 'PASSED',
|
|
443
619
|
};
|
|
444
620
|
}
|
|
445
|
-
async onTestCaseFinished(testCaseFinished) {
|
|
621
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
446
622
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
447
623
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
448
624
|
const prevResult = testProgress.result;
|
|
449
625
|
const steps = Object.values(testProgress.steps);
|
|
450
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);
|
|
451
631
|
testProgress.result = {
|
|
452
632
|
...result,
|
|
453
633
|
startTime: prevResult.startTime,
|
|
454
|
-
endTime
|
|
634
|
+
endTime,
|
|
455
635
|
};
|
|
456
636
|
testProgress.webLog = this.logs;
|
|
457
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 = '';
|
|
458
643
|
this.networkLog = [];
|
|
459
644
|
this.logs = [];
|
|
460
|
-
|
|
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
|
+
}
|
|
461
672
|
}
|
|
462
|
-
async uploadTestCase(testCase) {
|
|
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;
|
|
692
|
+
}
|
|
693
|
+
async tryUpload(testCase, rerunId) {
|
|
463
694
|
let runId = '';
|
|
464
695
|
let projectId = '';
|
|
465
696
|
if (!process.env.UPLOADING_TEST_CASE) {
|
|
@@ -477,7 +708,7 @@ class ReportGenerator {
|
|
|
477
708
|
projectId = process.env.PROJECT_ID;
|
|
478
709
|
}
|
|
479
710
|
else {
|
|
480
|
-
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
711
|
+
const runDoc = await this.uploadService.createRunDocument(this.runName, testCase.env);
|
|
481
712
|
runId = runDoc._id;
|
|
482
713
|
projectId = runDoc.project_id;
|
|
483
714
|
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
@@ -485,11 +716,9 @@ class ReportGenerator {
|
|
|
485
716
|
process.env.PROJECT_ID = projectId;
|
|
486
717
|
}
|
|
487
718
|
}
|
|
488
|
-
await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
|
|
489
719
|
this.writeTestCaseReportToDisk(testCase);
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
console.error('Error uploading test case:', e);
|
|
720
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
721
|
+
return data;
|
|
493
722
|
}
|
|
494
723
|
finally {
|
|
495
724
|
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
@@ -498,23 +727,30 @@ class ReportGenerator {
|
|
|
498
727
|
}
|
|
499
728
|
}
|
|
500
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;
|
|
735
|
+
}
|
|
501
736
|
try {
|
|
502
737
|
let i = 0;
|
|
503
|
-
while (fs_1.default.existsSync(path_1.default.join(
|
|
738
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
504
739
|
i++;
|
|
505
740
|
}
|
|
506
|
-
fs_1.default.mkdirSync(path_1.default.join(
|
|
741
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
507
742
|
//exclude network log from the saved report
|
|
508
743
|
const networkLog = testCase.networkLog;
|
|
509
744
|
delete testCase.networkLog;
|
|
510
|
-
|
|
511
|
-
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));
|
|
512
748
|
}
|
|
513
749
|
catch (error) {
|
|
514
750
|
console.error('Error writing test case report to disk:', error);
|
|
515
751
|
}
|
|
516
752
|
}
|
|
517
|
-
onTestRunFinished(testRunFinished) {
|
|
753
|
+
async onTestRunFinished(testRunFinished) {
|
|
518
754
|
const { timestamp, success, message } = testRunFinished;
|
|
519
755
|
const prevResult = this.report.result;
|
|
520
756
|
this.report.result = {
|
|
@@ -524,6 +760,7 @@ class ReportGenerator {
|
|
|
524
760
|
message,
|
|
525
761
|
// exception,
|
|
526
762
|
};
|
|
763
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
527
764
|
}
|
|
528
765
|
}
|
|
529
766
|
exports.default = ReportGenerator;
|