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