@dev-blinq/cucumber-js 1.0.90-main → 1.0.90-stage
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/download-install.js +14 -2
- package/lib/formatter/api.js +7 -1
- package/lib/formatter/api.js.map +1 -1
- package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
- package/lib/formatter/bvt_analysis_formatter.js +139 -50
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +0 -1
- package/lib/formatter/feature_data_format.js.map +1 -1
- package/lib/formatter/helpers/constants.d.ts +50 -0
- package/lib/formatter/helpers/constants.js +60 -0
- package/lib/formatter/helpers/constants.js.map +1 -0
- package/lib/formatter/helpers/report_generator.d.ts +19 -2
- package/lib/formatter/helpers/report_generator.js +290 -26
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +13 -1
- package/lib/formatter/helpers/upload_serivce.js +71 -4
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.js +11 -14
- package/lib/formatter/helpers/uploader.js.map +1 -1
- package/lib/formatter/summary_formatter.js +4 -0
- package/lib/formatter/summary_formatter.js.map +1 -1
- package/lib/runtime/test_case_runner.d.ts +1 -0
- package/lib/runtime/test_case_runner.js +10 -1
- package/lib/runtime/test_case_runner.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 +4 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ActionEvents = exports.SERVICES_URI = exports.CUSTOM = exports.STAGE = exports.PROD = exports.DEV = exports.LOCAL = void 0;
|
|
4
|
+
exports.LOCAL = {
|
|
5
|
+
SSO: 'http://localhost:5000/api/auth',
|
|
6
|
+
WORKSPACE: 'http://localhost:6000/api/workspace',
|
|
7
|
+
RUNS: 'http://localhost:5001/api/runs',
|
|
8
|
+
STORAGE: 'http://localhost:5050/api/storage',
|
|
9
|
+
};
|
|
10
|
+
exports.DEV = {
|
|
11
|
+
SSO: 'https://dev.api.blinq.io/api/auth',
|
|
12
|
+
WORKSPACE: 'https://dev.api.blinq.io/api/workspace',
|
|
13
|
+
RUNS: 'https://dev.api.blinq.io/api/runs',
|
|
14
|
+
STORAGE: 'https://dev.api.blinq.io/api/storage',
|
|
15
|
+
};
|
|
16
|
+
exports.PROD = {
|
|
17
|
+
SSO: 'https://api.blinq.io/api/auth',
|
|
18
|
+
WORKSPACE: 'https://api.blinq.io/api/workspace',
|
|
19
|
+
RUNS: 'https://api.blinq.io/api/runs',
|
|
20
|
+
STORAGE: 'https://api.blinq.io/api/storage',
|
|
21
|
+
};
|
|
22
|
+
exports.STAGE = {
|
|
23
|
+
SSO: 'https://stage.api.blinq.io/api/auth',
|
|
24
|
+
WORKSPACE: 'https://stage.api.blinq.io/api/workspace',
|
|
25
|
+
RUNS: 'https://stage.api.blinq.io/api/runs',
|
|
26
|
+
STORAGE: 'https://stage.api.blinq.io/api/storage',
|
|
27
|
+
};
|
|
28
|
+
exports.CUSTOM = {
|
|
29
|
+
SSO: `${process.env.NODE_ENV_BLINQ}/api/auth`,
|
|
30
|
+
WORKSPACE: `${process.env.NODE_ENV_BLINQ}/api/workspace`,
|
|
31
|
+
RUNS: `${process.env.NODE_ENV_BLINQ}/api/runs`,
|
|
32
|
+
STORAGE: `${process.env.NODE_ENV_BLINQ}/api/storage`,
|
|
33
|
+
};
|
|
34
|
+
exports.SERVICES_URI = process.env.NODE_ENV_BLINQ === 'local'
|
|
35
|
+
? exports.LOCAL // eslint-disable-line
|
|
36
|
+
: process.env.NODE_ENV_BLINQ === 'dev'
|
|
37
|
+
? exports.DEV // eslint-disable-line
|
|
38
|
+
: process.env.NODE_ENV_BLINQ === 'stage'
|
|
39
|
+
? exports.STAGE // eslint-disable-line
|
|
40
|
+
: process.env.NODE_ENV_BLINQ === 'prod'
|
|
41
|
+
? exports.PROD // eslint-disable-line
|
|
42
|
+
: !process.env.NODE_ENV_BLINQ
|
|
43
|
+
? exports.PROD // eslint-disable-line
|
|
44
|
+
: exports.CUSTOM; // eslint-disable-line
|
|
45
|
+
var ActionEvents;
|
|
46
|
+
(function (ActionEvents) {
|
|
47
|
+
ActionEvents["record_scenario"] = "record_scenario";
|
|
48
|
+
ActionEvents["download_editor"] = "download_editor";
|
|
49
|
+
ActionEvents["launch_editor"] = "launch_editor";
|
|
50
|
+
ActionEvents["click_start_recording"] = "click_start_recording";
|
|
51
|
+
ActionEvents["click_run_scenario"] = "click_run_scenario";
|
|
52
|
+
ActionEvents["publish_scenario"] = "publish_scenario";
|
|
53
|
+
ActionEvents["click_ai_generate"] = "click_ai_generate";
|
|
54
|
+
ActionEvents["click_run_all"] = "click_run_all";
|
|
55
|
+
ActionEvents["click_open_vscode"] = "click_open_vscode";
|
|
56
|
+
ActionEvents["error_open_vscode"] = "error_open_vscode";
|
|
57
|
+
ActionEvents["cli_run_tests"] = "cli_run_tests";
|
|
58
|
+
ActionEvents["upload_report"] = "upload_report";
|
|
59
|
+
})(ActionEvents = exports.ActionEvents || (exports.ActionEvents = {}));
|
|
60
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/formatter/helpers/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,KAAK,GAAG;IACnB,GAAG,EAAE,gCAAgC;IACrC,SAAS,EAAE,qCAAqC;IAChD,IAAI,EAAE,gCAAgC;IACtC,OAAO,EAAE,mCAAmC;CAC7C,CAAA;AACY,QAAA,GAAG,GAAG;IACjB,GAAG,EAAE,mCAAmC;IACxC,SAAS,EAAE,wCAAwC;IACnD,IAAI,EAAE,mCAAmC;IACzC,OAAO,EAAE,sCAAsC;CAChD,CAAA;AACY,QAAA,IAAI,GAAG;IAClB,GAAG,EAAE,+BAA+B;IACpC,SAAS,EAAE,oCAAoC;IAC/C,IAAI,EAAE,+BAA+B;IACrC,OAAO,EAAE,kCAAkC;CAC5C,CAAA;AACY,QAAA,KAAK,GAAG;IACnB,GAAG,EAAE,qCAAqC;IAC1C,SAAS,EAAE,0CAA0C;IACrD,IAAI,EAAE,qCAAqC;IAC3C,OAAO,EAAE,wCAAwC;CAClD,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW;IAC7C,SAAS,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,gBAAgB;IACxD,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW;IAC9C,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,cAAc;CACrD,CAAA;AAEY,QAAA,YAAY,GACvB,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;IACpC,CAAC,CAAC,aAAK,CAAC,sBAAsB;IAC9B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,KAAK;QACtC,CAAC,CAAC,WAAG,CAAC,sBAAsB;QAC5B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;YACxC,CAAC,CAAC,aAAK,CAAC,sBAAsB;YAC9B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM;gBACvC,CAAC,CAAC,YAAI,CAAC,sBAAsB;gBAC7B,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc;oBAC7B,CAAC,CAAC,YAAI,CAAC,sBAAsB;oBAC7B,CAAC,CAAC,cAAM,CAAA,CAAC,sBAAsB;AAEnC,IAAY,YAaX;AAbD,WAAY,YAAY;IACtB,mDAAmC,CAAA;IACnC,mDAAmC,CAAA;IACnC,+CAA+B,CAAA;IAC/B,+DAA+C,CAAA;IAC/C,yDAAyC,CAAA;IACzC,qDAAqC,CAAA;IACrC,uDAAuC,CAAA;IACvC,+CAA+B,CAAA;IAC/B,uDAAuC,CAAA;IACvC,uDAAuC,CAAA;IACvC,+CAA+B,CAAA;IAC/B,+CAA+B,CAAA;AACjC,CAAC,EAbW,YAAY,GAAZ,oBAAY,KAAZ,oBAAY,QAavB","sourcesContent":["export const LOCAL = {\n SSO: 'http://localhost:5000/api/auth',\n WORKSPACE: 'http://localhost:6000/api/workspace',\n RUNS: 'http://localhost:5001/api/runs',\n STORAGE: 'http://localhost:5050/api/storage',\n}\nexport const DEV = {\n SSO: 'https://dev.api.blinq.io/api/auth',\n WORKSPACE: 'https://dev.api.blinq.io/api/workspace',\n RUNS: 'https://dev.api.blinq.io/api/runs',\n STORAGE: 'https://dev.api.blinq.io/api/storage',\n}\nexport const PROD = {\n SSO: 'https://api.blinq.io/api/auth',\n WORKSPACE: 'https://api.blinq.io/api/workspace',\n RUNS: 'https://api.blinq.io/api/runs',\n STORAGE: 'https://api.blinq.io/api/storage',\n}\nexport const STAGE = {\n SSO: 'https://stage.api.blinq.io/api/auth',\n WORKSPACE: 'https://stage.api.blinq.io/api/workspace',\n RUNS: 'https://stage.api.blinq.io/api/runs',\n STORAGE: 'https://stage.api.blinq.io/api/storage',\n}\n\nexport const CUSTOM = {\n SSO: `${process.env.NODE_ENV_BLINQ}/api/auth`,\n WORKSPACE: `${process.env.NODE_ENV_BLINQ}/api/workspace`,\n RUNS: `${process.env.NODE_ENV_BLINQ}/api/runs`,\n STORAGE: `${process.env.NODE_ENV_BLINQ}/api/storage`,\n}\n\nexport const SERVICES_URI =\n process.env.NODE_ENV_BLINQ === 'local'\n ? LOCAL // eslint-disable-line\n : process.env.NODE_ENV_BLINQ === 'dev'\n ? DEV // eslint-disable-line\n : process.env.NODE_ENV_BLINQ === 'stage'\n ? STAGE // eslint-disable-line\n : process.env.NODE_ENV_BLINQ === 'prod'\n ? PROD // eslint-disable-line\n : !process.env.NODE_ENV_BLINQ\n ? PROD // eslint-disable-line\n : CUSTOM // eslint-disable-line\n\nexport enum ActionEvents {\n record_scenario = 'record_scenario',\n download_editor = 'download_editor',\n launch_editor = 'launch_editor',\n click_start_recording = 'click_start_recording',\n click_run_scenario = 'click_run_scenario',\n publish_scenario = 'publish_scenario',\n click_ai_generate = 'click_ai_generate',\n click_run_all = 'click_run_all',\n click_open_vscode = 'click_open_vscode',\n error_open_vscode = 'error_open_vscode',\n cli_run_tests = 'cli_run_tests',\n upload_report = 'upload_report',\n}\n"]}
|
|
@@ -48,7 +48,6 @@ type JsonCommand = {
|
|
|
48
48
|
text: string;
|
|
49
49
|
screenshotId?: string;
|
|
50
50
|
result: JsonCommandResult;
|
|
51
|
-
webLog?: webLog[];
|
|
52
51
|
netWorkLog?: any[];
|
|
53
52
|
};
|
|
54
53
|
type webLog = {
|
|
@@ -63,7 +62,13 @@ export type JsonStep = {
|
|
|
63
62
|
text: string;
|
|
64
63
|
commands: JsonCommand[];
|
|
65
64
|
result: JsonStepResult;
|
|
65
|
+
webLog: webLog[];
|
|
66
|
+
networkData: any[];
|
|
66
67
|
data?: any;
|
|
68
|
+
ariaSnapshot: string;
|
|
69
|
+
traceFilePath?: string;
|
|
70
|
+
brunoData?: any;
|
|
71
|
+
interceptResults?: any;
|
|
67
72
|
};
|
|
68
73
|
export type RetrainStats = {
|
|
69
74
|
result: JsonTestResult;
|
|
@@ -80,8 +85,10 @@ export type JsonTestProgress = {
|
|
|
80
85
|
steps: JsonStep[];
|
|
81
86
|
result: JsonTestResult;
|
|
82
87
|
retrainStats?: RetrainStats;
|
|
88
|
+
initialAriaSnapshot?: string;
|
|
83
89
|
webLog: any;
|
|
84
90
|
networkLog: any;
|
|
91
|
+
logFileId?: string;
|
|
85
92
|
env: {
|
|
86
93
|
name: string;
|
|
87
94
|
baseUrl: string;
|
|
@@ -113,10 +120,16 @@ export default class ReportGenerator {
|
|
|
113
120
|
private scenarioIterationCountMap;
|
|
114
121
|
private logs;
|
|
115
122
|
private networkLog;
|
|
123
|
+
private stepLogs;
|
|
124
|
+
private stepNetworkLogs;
|
|
116
125
|
private runName;
|
|
126
|
+
private ariaSnapshot;
|
|
127
|
+
private initialAriaSnapshot;
|
|
128
|
+
private testCaseLog;
|
|
129
|
+
private loggingOverridden;
|
|
117
130
|
reportFolder: null | string;
|
|
118
131
|
private uploadService;
|
|
119
|
-
handleMessage(envelope: EnvelopeWithMetaMessage): Promise<
|
|
132
|
+
handleMessage(envelope: EnvelopeWithMetaMessage | messages.Envelope, reRunId?: string): Promise<any>;
|
|
120
133
|
getReport(): JsonReport;
|
|
121
134
|
private handleParseError;
|
|
122
135
|
private onGherkinDocument;
|
|
@@ -129,11 +142,15 @@ export default class ReportGenerator {
|
|
|
129
142
|
private onTestCaseStarted;
|
|
130
143
|
private onTestStepStarted;
|
|
131
144
|
private onAttachment;
|
|
145
|
+
private getFailedTestStepResult;
|
|
132
146
|
private onTestStepFinished;
|
|
133
147
|
getLogFileContent(): any;
|
|
134
148
|
private getTestCaseResult;
|
|
135
149
|
private onTestCaseFinished;
|
|
150
|
+
private readonly retryCount;
|
|
136
151
|
private uploadTestCase;
|
|
152
|
+
private tryUpload;
|
|
153
|
+
private writeTestCaseReportToDisk;
|
|
137
154
|
private onTestRunFinished;
|
|
138
155
|
}
|
|
139
156
|
export {};
|
|
@@ -1,19 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
var _a, _b;
|
|
6
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
const messages = __importStar(require("@cucumber/messages"));
|
|
7
31
|
const fs_1 = __importDefault(require("fs"));
|
|
8
32
|
const path_1 = __importDefault(require("path"));
|
|
9
33
|
const upload_serivce_1 = require("./upload_serivce");
|
|
34
|
+
const fs_extra_1 = require("fs-extra");
|
|
35
|
+
// type JsonException = messages.Exception
|
|
36
|
+
const object_path_1 = __importDefault(require("object-path"));
|
|
10
37
|
const URL = process.env.NODE_ENV_BLINQ === 'dev'
|
|
11
38
|
? 'https://dev.api.blinq.io/api/runs'
|
|
12
39
|
: process.env.NODE_ENV_BLINQ === 'local'
|
|
13
40
|
? 'http://localhost:5001/api/runs'
|
|
14
41
|
: process.env.NODE_ENV_BLINQ === 'stage'
|
|
15
42
|
? 'https://stage.api.blinq.io/api/runs'
|
|
16
|
-
:
|
|
43
|
+
: process.env.NODE_ENV_BLINQ === 'prod'
|
|
44
|
+
? 'https://api.blinq.io/api/runs'
|
|
45
|
+
: !process.env.NODE_ENV_BLINQ
|
|
46
|
+
? 'https://api.blinq.io/api/runs'
|
|
47
|
+
: `${process.env.NODE_ENV_BLINQ}/api/runs`;
|
|
17
48
|
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
18
49
|
const BATCH_SIZE = 10;
|
|
19
50
|
const MAX_RETRIES = 3;
|
|
@@ -40,12 +71,19 @@ class ReportGenerator {
|
|
|
40
71
|
this.scenarioIterationCountMap = new Map();
|
|
41
72
|
this.logs = [];
|
|
42
73
|
this.networkLog = [];
|
|
74
|
+
this.stepLogs = [];
|
|
75
|
+
this.stepNetworkLogs = [];
|
|
43
76
|
this.runName = '';
|
|
77
|
+
this.ariaSnapshot = '';
|
|
78
|
+
this.initialAriaSnapshot = '';
|
|
79
|
+
this.testCaseLog = [];
|
|
80
|
+
this.loggingOverridden = false; // Flag to track if logging is overridden
|
|
44
81
|
this.reportFolder = null;
|
|
45
82
|
this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
|
|
83
|
+
this.retryCount = 3;
|
|
46
84
|
}
|
|
47
|
-
async handleMessage(envelope) {
|
|
48
|
-
if (envelope.meta && envelope.meta
|
|
85
|
+
async handleMessage(envelope, reRunId) {
|
|
86
|
+
if (envelope.meta && 'runName' in envelope.meta) {
|
|
49
87
|
this.runName = envelope.meta.runName;
|
|
50
88
|
}
|
|
51
89
|
const type = Object.keys(envelope)[0];
|
|
@@ -72,10 +110,30 @@ class ReportGenerator {
|
|
|
72
110
|
case 'testRunStarted': {
|
|
73
111
|
const testRunStarted = envelope[type];
|
|
74
112
|
this.onTestRunStarted(testRunStarted);
|
|
113
|
+
await this.uploadService.createStatus('running');
|
|
75
114
|
break;
|
|
76
115
|
}
|
|
77
116
|
case 'testCase': {
|
|
78
117
|
const testCase = envelope[type];
|
|
118
|
+
// Initialize the log storage
|
|
119
|
+
this.testCaseLog = [];
|
|
120
|
+
if (!this.loggingOverridden) {
|
|
121
|
+
this.loggingOverridden = true;
|
|
122
|
+
// Store the original process.stdout.write, and process.stderr.write
|
|
123
|
+
const originalStdoutWrite = process.stdout.write;
|
|
124
|
+
const originalStderrWrite = process.stderr.write;
|
|
125
|
+
// Override process.stdout.write
|
|
126
|
+
process.stdout.write = (chunk, ...args) => {
|
|
127
|
+
this.testCaseLog.push(chunk.toString());
|
|
128
|
+
return originalStdoutWrite.call(process.stdout, chunk, ...args);
|
|
129
|
+
};
|
|
130
|
+
// Override process.stderr.write
|
|
131
|
+
process.stderr.write = (chunk, ...args) => {
|
|
132
|
+
this.testCaseLog.push(chunk.toString());
|
|
133
|
+
return originalStderrWrite.call(process.stderr, chunk, ...args);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Call the onTestCase method
|
|
79
137
|
this.onTestCase(testCase);
|
|
80
138
|
break;
|
|
81
139
|
}
|
|
@@ -101,13 +159,14 @@ class ReportGenerator {
|
|
|
101
159
|
}
|
|
102
160
|
case 'testCaseFinished': {
|
|
103
161
|
const testCaseFinished = envelope[type];
|
|
104
|
-
|
|
105
|
-
|
|
162
|
+
// Call the onTestCaseFinished method
|
|
163
|
+
const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
|
|
164
|
+
return result;
|
|
106
165
|
}
|
|
107
166
|
// case "hook": { break} // After Hook
|
|
108
167
|
case 'testRunFinished': {
|
|
109
168
|
const testRunFinished = envelope[type];
|
|
110
|
-
this.onTestRunFinished(testRunFinished);
|
|
169
|
+
await this.onTestRunFinished(testRunFinished);
|
|
111
170
|
break;
|
|
112
171
|
}
|
|
113
172
|
// case "parameterType" : { break}
|
|
@@ -238,6 +297,10 @@ class ReportGenerator {
|
|
|
238
297
|
result: {
|
|
239
298
|
status: 'UNKNOWN',
|
|
240
299
|
},
|
|
300
|
+
networkData: [],
|
|
301
|
+
webLog: [],
|
|
302
|
+
data: {},
|
|
303
|
+
ariaSnapshot: this.ariaSnapshot,
|
|
241
304
|
});
|
|
242
305
|
return this.stepReportMap.get(pickleStep.id);
|
|
243
306
|
});
|
|
@@ -280,6 +343,14 @@ class ReportGenerator {
|
|
|
280
343
|
this.reportFolder = body.replaceAll('\\', '/');
|
|
281
344
|
return;
|
|
282
345
|
}
|
|
346
|
+
if (mediaType === 'application/json+snapshot-before') {
|
|
347
|
+
this.initialAriaSnapshot = body;
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (mediaType === 'application/json+snapshot-after') {
|
|
351
|
+
this.ariaSnapshot = body;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
283
354
|
if (mediaType === 'application/json+env') {
|
|
284
355
|
const data = JSON.parse(body);
|
|
285
356
|
this.report.env = data;
|
|
@@ -290,13 +361,16 @@ class ReportGenerator {
|
|
|
290
361
|
}
|
|
291
362
|
if (mediaType === 'application/json+log') {
|
|
292
363
|
const log = JSON.parse(body);
|
|
293
|
-
if (this.logs.length < 1000)
|
|
364
|
+
if (this.logs.length < 1000) {
|
|
294
365
|
this.logs.push(log);
|
|
366
|
+
this.stepLogs.push(log);
|
|
367
|
+
}
|
|
295
368
|
}
|
|
296
369
|
if (mediaType === 'application/json+network') {
|
|
297
370
|
const networkLog = JSON.parse(body);
|
|
298
371
|
if (this.networkLog.length < 1000)
|
|
299
372
|
this.networkLog.push(networkLog);
|
|
373
|
+
this.stepNetworkLogs.push(networkLog);
|
|
300
374
|
}
|
|
301
375
|
const testStep = this.testStepMap.get(testStepId);
|
|
302
376
|
if (testStep.pickleStepId === undefined)
|
|
@@ -306,6 +380,47 @@ class ReportGenerator {
|
|
|
306
380
|
const command = JSON.parse(body);
|
|
307
381
|
stepProgess.commands.push(command);
|
|
308
382
|
}
|
|
383
|
+
else if (mediaType === 'application/json+trace') {
|
|
384
|
+
const data = JSON.parse(body);
|
|
385
|
+
stepProgess.traceFilePath = data.traceFilePath;
|
|
386
|
+
}
|
|
387
|
+
if (mediaType === 'application/json+bruno') {
|
|
388
|
+
try {
|
|
389
|
+
const data = JSON.parse(body);
|
|
390
|
+
stepProgess.brunoData = data;
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
console.error('Error parsing bruno data:', error);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (mediaType === 'application/json+intercept-results') {
|
|
397
|
+
console.log('Intercept results received:', body);
|
|
398
|
+
try {
|
|
399
|
+
const data = JSON.parse(body);
|
|
400
|
+
stepProgess.interceptResults = data;
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
console.error('Error parsing intercept results:', error);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
getFailedTestStepResult({ commands, startTime, endTime, result, }) {
|
|
408
|
+
for (const command of commands) {
|
|
409
|
+
if (command.result.status === 'FAILED') {
|
|
410
|
+
return {
|
|
411
|
+
status: 'FAILED',
|
|
412
|
+
message: command.result.message,
|
|
413
|
+
startTime,
|
|
414
|
+
endTime,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
status: 'FAILED',
|
|
420
|
+
startTime,
|
|
421
|
+
endTime,
|
|
422
|
+
message: result.message,
|
|
423
|
+
};
|
|
309
424
|
}
|
|
310
425
|
onTestStepFinished(testStepFinished) {
|
|
311
426
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
@@ -316,6 +431,25 @@ class ReportGenerator {
|
|
|
316
431
|
}
|
|
317
432
|
return;
|
|
318
433
|
}
|
|
434
|
+
if (testStepResult.status === 'UNDEFINED') {
|
|
435
|
+
const step = this.stepReportMap.get(testStep.pickleStepId);
|
|
436
|
+
const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
|
|
437
|
+
const undefinedCommand = {
|
|
438
|
+
testStepId: testStepId,
|
|
439
|
+
body: JSON.stringify({
|
|
440
|
+
type: 'error',
|
|
441
|
+
text: 'Undefined step: ' + stepName,
|
|
442
|
+
result: {
|
|
443
|
+
status: 'FAILED',
|
|
444
|
+
startTime: this.getTimeStamp(timestamp),
|
|
445
|
+
endTime: this.getTimeStamp(timestamp),
|
|
446
|
+
},
|
|
447
|
+
}),
|
|
448
|
+
mediaType: 'application/json',
|
|
449
|
+
contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
|
|
450
|
+
};
|
|
451
|
+
this.onAttachment(undefinedCommand);
|
|
452
|
+
}
|
|
319
453
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
320
454
|
const prevStepResult = stepProgess.result;
|
|
321
455
|
let data = {};
|
|
@@ -331,16 +465,72 @@ class ReportGenerator {
|
|
|
331
465
|
catch (error) {
|
|
332
466
|
console.log('Error reading data.json');
|
|
333
467
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
468
|
+
if (testStepResult.status === 'FAILED') {
|
|
469
|
+
stepProgess.result = this.getFailedTestStepResult({
|
|
470
|
+
commands: stepProgess.commands,
|
|
471
|
+
startTime: prevStepResult.startTime,
|
|
472
|
+
endTime: this.getTimeStamp(timestamp),
|
|
473
|
+
result: testStepResult,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
stepProgess.result = {
|
|
478
|
+
status: testStepResult.status,
|
|
479
|
+
startTime: prevStepResult.startTime,
|
|
480
|
+
endTime: this.getTimeStamp(timestamp),
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
stepProgess.webLog = this.stepLogs;
|
|
484
|
+
stepProgess.networkData = this.stepNetworkLogs;
|
|
485
|
+
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
486
|
+
this.ariaSnapshot = '';
|
|
487
|
+
this.stepNetworkLogs = [];
|
|
488
|
+
this.stepLogs = [];
|
|
341
489
|
if (Object.keys(data).length > 0) {
|
|
342
490
|
stepProgess.data = data;
|
|
491
|
+
const id = testStepFinished.testCaseStartedId;
|
|
492
|
+
const parameters = this.testCaseReportMap.get(id).parameters;
|
|
493
|
+
const _parameters = {};
|
|
494
|
+
Object.keys(parameters).map((key) => {
|
|
495
|
+
if (parameters[key].startsWith('{{') &&
|
|
496
|
+
parameters[key].endsWith('}}')) {
|
|
497
|
+
const path = parameters[key].slice(2, -2).split('.');
|
|
498
|
+
let value = String(object_path_1.default.get(data, path));
|
|
499
|
+
if (value) {
|
|
500
|
+
if (value.startsWith('secret:')) {
|
|
501
|
+
value = 'secret:****';
|
|
502
|
+
}
|
|
503
|
+
else if (value.startsWith('totp:')) {
|
|
504
|
+
value = 'totp:****';
|
|
505
|
+
}
|
|
506
|
+
else if (value.startsWith('mask:')) {
|
|
507
|
+
value = 'mask:****';
|
|
508
|
+
}
|
|
509
|
+
_parameters[key] = value;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
_parameters[key] = parameters[key];
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
this.report.testCases.find((testCase) => {
|
|
517
|
+
return testCase.id === id;
|
|
518
|
+
}).parameters = _parameters;
|
|
343
519
|
}
|
|
520
|
+
// if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
521
|
+
// this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
|
|
522
|
+
// if (!fs.existsSync(this.reportFolder)) {
|
|
523
|
+
// fs.mkdirSync(this.reportFolder)
|
|
524
|
+
// }
|
|
525
|
+
// const reportFilePath = path.join(
|
|
526
|
+
// this.reportFolder,
|
|
527
|
+
// `report.json`
|
|
528
|
+
// )
|
|
529
|
+
// writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
|
|
530
|
+
// return undefined
|
|
531
|
+
// // } else {
|
|
532
|
+
// // return await this.uploadTestCase(testProgress, reRunId)
|
|
533
|
+
// }
|
|
344
534
|
}
|
|
345
535
|
getLogFileContent() {
|
|
346
536
|
let projectPath = process.cwd();
|
|
@@ -388,24 +578,71 @@ class ReportGenerator {
|
|
|
388
578
|
status: 'PASSED',
|
|
389
579
|
};
|
|
390
580
|
}
|
|
391
|
-
async onTestCaseFinished(testCaseFinished) {
|
|
581
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
392
582
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
393
583
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
394
584
|
const prevResult = testProgress.result;
|
|
395
585
|
const steps = Object.values(testProgress.steps);
|
|
396
586
|
const result = this.getTestCaseResult(steps);
|
|
587
|
+
const endTime = this.getTimeStamp(timestamp);
|
|
397
588
|
testProgress.result = {
|
|
398
589
|
...result,
|
|
399
590
|
startTime: prevResult.startTime,
|
|
400
|
-
endTime
|
|
591
|
+
endTime,
|
|
401
592
|
};
|
|
402
593
|
testProgress.webLog = this.logs;
|
|
403
594
|
testProgress.networkLog = this.networkLog;
|
|
595
|
+
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
596
|
+
this.initialAriaSnapshot = '';
|
|
404
597
|
this.networkLog = [];
|
|
405
598
|
this.logs = [];
|
|
406
|
-
|
|
599
|
+
if (this.testCaseLog && this.testCaseLog.length > 0) {
|
|
600
|
+
// Create the logs directory
|
|
601
|
+
const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
|
|
602
|
+
const fileName = `testCaseLog_${testCaseStartedId}.log`;
|
|
603
|
+
const filePath = path_1.default.join(logsDir, fileName);
|
|
604
|
+
// Ensure the logs directory exists
|
|
605
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
606
|
+
// Write the logs to the file
|
|
607
|
+
fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
|
|
608
|
+
// Store this ID in the testProgress object so it can be accessed later
|
|
609
|
+
testProgress.logFileId = testCaseStartedId;
|
|
610
|
+
}
|
|
611
|
+
this.testCaseLog = [];
|
|
612
|
+
if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
613
|
+
this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
614
|
+
if (!fs_1.default.existsSync(this.reportFolder)) {
|
|
615
|
+
fs_1.default.mkdirSync(this.reportFolder);
|
|
616
|
+
}
|
|
617
|
+
const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
|
|
618
|
+
(0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
|
|
619
|
+
return undefined;
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
return await this.uploadTestCase(testProgress, reRunId);
|
|
623
|
+
}
|
|
407
624
|
}
|
|
408
|
-
async uploadTestCase(testCase) {
|
|
625
|
+
async uploadTestCase(testCase, rerunId) {
|
|
626
|
+
let data = null;
|
|
627
|
+
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
|
|
628
|
+
try {
|
|
629
|
+
data = await this.tryUpload(testCase, rerunId);
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
catch (e) {
|
|
633
|
+
console.error(`Attempt ${attempt} to upload testcase failed:`, e);
|
|
634
|
+
if (attempt === this.retryCount) {
|
|
635
|
+
console.error('All retry attempts failed, failed to upload testcase.');
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
|
|
639
|
+
await new Promise((r) => setTimeout(r, waitTime));
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return data;
|
|
644
|
+
}
|
|
645
|
+
async tryUpload(testCase, rerunId) {
|
|
409
646
|
let runId = '';
|
|
410
647
|
let projectId = '';
|
|
411
648
|
if (!process.env.UPLOADING_TEST_CASE) {
|
|
@@ -416,7 +653,9 @@ class ReportGenerator {
|
|
|
416
653
|
anyRemArr.push(randomID);
|
|
417
654
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
418
655
|
try {
|
|
419
|
-
if (process.env.RUN_ID &&
|
|
656
|
+
if (process.env.RUN_ID &&
|
|
657
|
+
process.env.PROJECT_ID &&
|
|
658
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
420
659
|
runId = process.env.RUN_ID;
|
|
421
660
|
projectId = process.env.PROJECT_ID;
|
|
422
661
|
}
|
|
@@ -424,13 +663,14 @@ class ReportGenerator {
|
|
|
424
663
|
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
425
664
|
runId = runDoc._id;
|
|
426
665
|
projectId = runDoc.project_id;
|
|
427
|
-
process.env.
|
|
428
|
-
|
|
666
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
667
|
+
process.env.RUN_ID = runId;
|
|
668
|
+
process.env.PROJECT_ID = projectId;
|
|
669
|
+
}
|
|
429
670
|
}
|
|
430
|
-
await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
console.error('Error uploading test case:', e);
|
|
671
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
672
|
+
this.writeTestCaseReportToDisk(testCase);
|
|
673
|
+
return data;
|
|
434
674
|
}
|
|
435
675
|
finally {
|
|
436
676
|
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
@@ -438,7 +678,30 @@ class ReportGenerator {
|
|
|
438
678
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
439
679
|
}
|
|
440
680
|
}
|
|
441
|
-
|
|
681
|
+
writeTestCaseReportToDisk(testCase) {
|
|
682
|
+
var _a;
|
|
683
|
+
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
684
|
+
if (!reportFolder) {
|
|
685
|
+
console.error('Report folder is not defined');
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
try {
|
|
689
|
+
let i = 0;
|
|
690
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
691
|
+
i++;
|
|
692
|
+
}
|
|
693
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
694
|
+
//exclude network log from the saved report
|
|
695
|
+
const networkLog = testCase.networkLog;
|
|
696
|
+
delete testCase.networkLog;
|
|
697
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
|
|
698
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
console.error('Error writing test case report to disk:', error);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
async onTestRunFinished(testRunFinished) {
|
|
442
705
|
const { timestamp, success, message } = testRunFinished;
|
|
443
706
|
const prevResult = this.report.result;
|
|
444
707
|
this.report.result = {
|
|
@@ -448,6 +711,7 @@ class ReportGenerator {
|
|
|
448
711
|
message,
|
|
449
712
|
// exception,
|
|
450
713
|
};
|
|
714
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
451
715
|
}
|
|
452
716
|
}
|
|
453
717
|
exports.default = ReportGenerator;
|