@dev-blinq/cucumber-js 1.0.84-main → 1.0.84-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 +31 -19
- package/lib/formatter/api.d.ts +2 -0
- package/lib/formatter/api.js +59 -0
- package/lib/formatter/api.js.map +1 -0
- package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
- package/lib/formatter/bvt_analysis_formatter.js +197 -71
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +14 -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 +40 -13
- package/lib/formatter/helpers/report_generator.js +348 -57
- 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 +16 -3
- package/lib/formatter/helpers/upload_serivce.js +176 -34
- 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 +63 -18
- 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
|
@@ -1,20 +1,64 @@
|
|
|
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 = {
|
|
11
55
|
result: {
|
|
12
|
-
status:
|
|
56
|
+
status: "UNKNOWN",
|
|
13
57
|
},
|
|
14
58
|
testCases: [],
|
|
15
59
|
env: {
|
|
16
|
-
name:
|
|
17
|
-
baseUrl:
|
|
60
|
+
name: "",
|
|
61
|
+
baseUrl: "",
|
|
18
62
|
},
|
|
19
63
|
};
|
|
20
64
|
this.gherkinDocumentMap = new Map();
|
|
@@ -27,67 +71,98 @@ 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);
|
|
31
83
|
}
|
|
32
|
-
handleMessage(envelope) {
|
|
84
|
+
async handleMessage(envelope, reRunId) {
|
|
85
|
+
if (envelope.meta && "runName" in envelope.meta) {
|
|
86
|
+
this.runName = envelope.meta.runName;
|
|
87
|
+
}
|
|
33
88
|
const type = Object.keys(envelope)[0];
|
|
34
89
|
switch (type) {
|
|
35
90
|
// case "meta": { break}
|
|
36
91
|
// case "source": { break}
|
|
37
|
-
case
|
|
92
|
+
case "parseError": {
|
|
38
93
|
const parseError = envelope[type];
|
|
39
94
|
this.handleParseError(parseError);
|
|
40
95
|
break;
|
|
41
96
|
}
|
|
42
|
-
case
|
|
97
|
+
case "gherkinDocument": {
|
|
43
98
|
const doc = envelope[type];
|
|
44
99
|
this.onGherkinDocument(doc);
|
|
45
100
|
break;
|
|
46
101
|
}
|
|
47
|
-
case
|
|
102
|
+
case "pickle": {
|
|
48
103
|
const pickle = envelope[type];
|
|
49
104
|
this.onPickle(pickle);
|
|
50
105
|
break;
|
|
51
106
|
}
|
|
52
107
|
// case "stepDefinition": { break}
|
|
53
108
|
// case "hook": { break} // Before Hook
|
|
54
|
-
case
|
|
109
|
+
case "testRunStarted": {
|
|
55
110
|
const testRunStarted = envelope[type];
|
|
56
111
|
this.onTestRunStarted(testRunStarted);
|
|
57
112
|
break;
|
|
58
113
|
}
|
|
59
|
-
case
|
|
114
|
+
case "testCase": {
|
|
60
115
|
const testCase = envelope[type];
|
|
116
|
+
// Initialize the log storage
|
|
117
|
+
this.testCaseLog = [];
|
|
118
|
+
if (!this.loggingOverridden) {
|
|
119
|
+
this.loggingOverridden = true;
|
|
120
|
+
// Store the original process.stdout.write, and process.stderr.write
|
|
121
|
+
const originalStdoutWrite = process.stdout.write;
|
|
122
|
+
const originalStderrWrite = process.stderr.write;
|
|
123
|
+
// Override process.stdout.write
|
|
124
|
+
process.stdout.write = (chunk, ...args) => {
|
|
125
|
+
this.testCaseLog.push(chunk.toString());
|
|
126
|
+
return originalStdoutWrite.call(process.stdout, chunk, ...args);
|
|
127
|
+
};
|
|
128
|
+
// Override process.stderr.write
|
|
129
|
+
process.stderr.write = (chunk, ...args) => {
|
|
130
|
+
this.testCaseLog.push(chunk.toString());
|
|
131
|
+
return originalStderrWrite.call(process.stderr, chunk, ...args);
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Call the onTestCase method
|
|
61
135
|
this.onTestCase(testCase);
|
|
62
136
|
break;
|
|
63
137
|
}
|
|
64
|
-
case
|
|
138
|
+
case "testCaseStarted": {
|
|
65
139
|
const testCaseStarted = envelope[type];
|
|
66
140
|
this.onTestCaseStarted(testCaseStarted);
|
|
67
141
|
break;
|
|
68
142
|
}
|
|
69
|
-
case
|
|
143
|
+
case "testStepStarted": {
|
|
70
144
|
const testStepStarted = envelope[type];
|
|
71
145
|
this.onTestStepStarted(testStepStarted);
|
|
72
146
|
break;
|
|
73
147
|
}
|
|
74
|
-
case
|
|
148
|
+
case "attachment": {
|
|
75
149
|
const attachment = envelope[type];
|
|
76
150
|
this.onAttachment(attachment);
|
|
77
151
|
break;
|
|
78
152
|
}
|
|
79
|
-
case
|
|
153
|
+
case "testStepFinished": {
|
|
80
154
|
const testStepFinished = envelope[type];
|
|
81
155
|
this.onTestStepFinished(testStepFinished);
|
|
82
156
|
break;
|
|
83
157
|
}
|
|
84
|
-
case
|
|
158
|
+
case "testCaseFinished": {
|
|
85
159
|
const testCaseFinished = envelope[type];
|
|
86
|
-
|
|
87
|
-
|
|
160
|
+
// Call the onTestCaseFinished method
|
|
161
|
+
const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
|
|
162
|
+
return result;
|
|
88
163
|
}
|
|
89
164
|
// case "hook": { break} // After Hook
|
|
90
|
-
case
|
|
165
|
+
case "testRunFinished": {
|
|
91
166
|
const testRunFinished = envelope[type];
|
|
92
167
|
this.onTestRunFinished(testRunFinished);
|
|
93
168
|
break;
|
|
@@ -103,7 +178,7 @@ class ReportGenerator {
|
|
|
103
178
|
const { message } = parseError;
|
|
104
179
|
const timestamp = new Date().getTime();
|
|
105
180
|
this.report.result = {
|
|
106
|
-
status:
|
|
181
|
+
status: "FAILED",
|
|
107
182
|
startTime: timestamp,
|
|
108
183
|
endTime: timestamp,
|
|
109
184
|
message: message,
|
|
@@ -146,7 +221,7 @@ class ReportGenerator {
|
|
|
146
221
|
}
|
|
147
222
|
onTestRunStarted(testRunStarted) {
|
|
148
223
|
this.report.result = {
|
|
149
|
-
status:
|
|
224
|
+
status: "STARTED",
|
|
150
225
|
startTime: this.getTimeStamp(testRunStarted.timestamp),
|
|
151
226
|
};
|
|
152
227
|
}
|
|
@@ -179,8 +254,7 @@ class ReportGenerator {
|
|
|
179
254
|
for (const tableRow of examples.tableBody) {
|
|
180
255
|
if (tableRow.id === exampleId) {
|
|
181
256
|
for (let i = 0; i < examples.tableHeader.cells.length; i++) {
|
|
182
|
-
parameters[examples.tableHeader.cells[i].value] =
|
|
183
|
-
tableRow.cells[i].value;
|
|
257
|
+
parameters[examples.tableHeader.cells[i].value] = tableRow.cells[i].value;
|
|
184
258
|
}
|
|
185
259
|
}
|
|
186
260
|
}
|
|
@@ -218,8 +292,12 @@ class ReportGenerator {
|
|
|
218
292
|
text: step.text,
|
|
219
293
|
commands: [],
|
|
220
294
|
result: {
|
|
221
|
-
status:
|
|
295
|
+
status: "UNKNOWN",
|
|
222
296
|
},
|
|
297
|
+
networkData: [],
|
|
298
|
+
webLog: [],
|
|
299
|
+
data: {},
|
|
300
|
+
ariaSnapshot: this.ariaSnapshot,
|
|
223
301
|
});
|
|
224
302
|
return this.stepReportMap.get(pickleStep.id);
|
|
225
303
|
});
|
|
@@ -231,11 +309,15 @@ class ReportGenerator {
|
|
|
231
309
|
parameters,
|
|
232
310
|
steps,
|
|
233
311
|
result: {
|
|
234
|
-
status:
|
|
312
|
+
status: "STARTED",
|
|
235
313
|
startTime: this.getTimeStamp(timestamp),
|
|
236
314
|
},
|
|
237
315
|
webLog: [],
|
|
238
316
|
networkLog: [],
|
|
317
|
+
env: {
|
|
318
|
+
name: this.report.env.name,
|
|
319
|
+
baseUrl: this.report.env.baseUrl,
|
|
320
|
+
},
|
|
239
321
|
});
|
|
240
322
|
this.report.testCases.push(this.testCaseReportMap.get(id));
|
|
241
323
|
}
|
|
@@ -248,80 +330,200 @@ class ReportGenerator {
|
|
|
248
330
|
return;
|
|
249
331
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
250
332
|
stepProgess.result = {
|
|
251
|
-
status:
|
|
333
|
+
status: "STARTED",
|
|
252
334
|
startTime: this.getTimeStamp(timestamp),
|
|
253
335
|
};
|
|
254
336
|
}
|
|
255
337
|
onAttachment(attachment) {
|
|
256
338
|
const { testStepId, body, mediaType } = attachment;
|
|
257
|
-
if (mediaType ===
|
|
258
|
-
this.reportFolder = body.replaceAll(
|
|
339
|
+
if (mediaType === "text/plain") {
|
|
340
|
+
this.reportFolder = body.replaceAll("\\", "/");
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (mediaType === "application/json+snapshot-before") {
|
|
344
|
+
this.initialAriaSnapshot = body;
|
|
259
345
|
return;
|
|
260
346
|
}
|
|
261
|
-
if (mediaType ===
|
|
347
|
+
if (mediaType === "application/json+snapshot-after") {
|
|
348
|
+
this.ariaSnapshot = body;
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (mediaType === "application/json+env") {
|
|
262
352
|
const data = JSON.parse(body);
|
|
263
353
|
this.report.env = data;
|
|
354
|
+
this.report.testCases.map((testCase) => {
|
|
355
|
+
testCase.env = data;
|
|
356
|
+
return testCase;
|
|
357
|
+
});
|
|
264
358
|
}
|
|
265
|
-
if (mediaType ===
|
|
359
|
+
if (mediaType === "application/json+log") {
|
|
266
360
|
const log = JSON.parse(body);
|
|
267
|
-
if (this.logs.length < 1000)
|
|
361
|
+
if (this.logs.length < 1000) {
|
|
268
362
|
this.logs.push(log);
|
|
363
|
+
this.stepLogs.push(log);
|
|
364
|
+
}
|
|
269
365
|
}
|
|
270
|
-
if (mediaType ===
|
|
366
|
+
if (mediaType === "application/json+network") {
|
|
271
367
|
const networkLog = JSON.parse(body);
|
|
272
368
|
if (this.networkLog.length < 1000)
|
|
273
369
|
this.networkLog.push(networkLog);
|
|
370
|
+
this.stepNetworkLogs.push(networkLog);
|
|
274
371
|
}
|
|
275
372
|
const testStep = this.testStepMap.get(testStepId);
|
|
276
373
|
if (testStep.pickleStepId === undefined)
|
|
277
374
|
return;
|
|
278
375
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
279
|
-
if (mediaType ===
|
|
376
|
+
if (mediaType === "application/json") {
|
|
280
377
|
const command = JSON.parse(body);
|
|
281
378
|
stepProgess.commands.push(command);
|
|
282
379
|
}
|
|
380
|
+
else if (mediaType === "application/json+trace") {
|
|
381
|
+
const data = JSON.parse(body);
|
|
382
|
+
stepProgess.traceFilePath = data.traceFilePath;
|
|
383
|
+
}
|
|
384
|
+
if (mediaType === "application/json+bruno") {
|
|
385
|
+
try {
|
|
386
|
+
const data = JSON.parse(body);
|
|
387
|
+
stepProgess.brunoData = data;
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
console.error("Error parsing bruno data:", error);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
getFailedTestStepResult({ commands, startTime, endTime, result, }) {
|
|
395
|
+
for (const command of commands) {
|
|
396
|
+
if (command.result.status === "FAILED") {
|
|
397
|
+
return {
|
|
398
|
+
status: "FAILED",
|
|
399
|
+
message: command.result.message,
|
|
400
|
+
startTime,
|
|
401
|
+
endTime,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
status: "FAILED",
|
|
407
|
+
startTime,
|
|
408
|
+
endTime,
|
|
409
|
+
message: result.message,
|
|
410
|
+
};
|
|
283
411
|
}
|
|
284
412
|
onTestStepFinished(testStepFinished) {
|
|
285
413
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
286
414
|
const testStep = this.testStepMap.get(testStepId);
|
|
287
415
|
if (testStep.pickleStepId === undefined) {
|
|
288
|
-
if (testStepResult.status ===
|
|
416
|
+
if (testStepResult.status === "FAILED") {
|
|
289
417
|
console.error(`Before/After hook failed with message: ${testStepResult.message}`);
|
|
290
418
|
}
|
|
291
419
|
return;
|
|
292
420
|
}
|
|
421
|
+
if (testStepResult.status === "UNDEFINED") {
|
|
422
|
+
const step = this.stepReportMap.get(testStep.pickleStepId);
|
|
423
|
+
const stepName = step ? step.keyword + " " + step.text : "Undefined step";
|
|
424
|
+
const undefinedCommand = {
|
|
425
|
+
testStepId: testStepId,
|
|
426
|
+
body: JSON.stringify({
|
|
427
|
+
type: "error",
|
|
428
|
+
text: "Undefined step: " + stepName,
|
|
429
|
+
result: {
|
|
430
|
+
status: "FAILED",
|
|
431
|
+
startTime: this.getTimeStamp(timestamp),
|
|
432
|
+
endTime: this.getTimeStamp(timestamp),
|
|
433
|
+
},
|
|
434
|
+
}),
|
|
435
|
+
mediaType: "application/json",
|
|
436
|
+
contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
|
|
437
|
+
};
|
|
438
|
+
this.onAttachment(undefinedCommand);
|
|
439
|
+
}
|
|
293
440
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
294
441
|
const prevStepResult = stepProgess.result;
|
|
295
442
|
let data = {};
|
|
296
|
-
const reportFolder = this.reportFolder;
|
|
297
|
-
if (reportFolder === null) {
|
|
298
|
-
throw new Error('"reportFolder" is "null". Failed to run BVT hooks. Please retry after running "Generate All" or "Record Scenario" ');
|
|
299
|
-
}
|
|
300
443
|
try {
|
|
301
|
-
|
|
302
|
-
|
|
444
|
+
const reportFolder = this.reportFolder;
|
|
445
|
+
if (reportFolder === null) {
|
|
446
|
+
throw new Error('"reportFolder" is "null". Failed to run BVT hooks. Please retry after running "Generate All" or "Record Scenario" ');
|
|
447
|
+
}
|
|
448
|
+
if (fs_1.default.existsSync(path_1.default.join(reportFolder, "data.json"))) {
|
|
449
|
+
data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(reportFolder, "data.json"), "utf8"));
|
|
303
450
|
}
|
|
304
451
|
}
|
|
305
452
|
catch (error) {
|
|
306
|
-
console.log(
|
|
453
|
+
console.log("Error reading data.json");
|
|
307
454
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
455
|
+
if (testStepResult.status === "FAILED") {
|
|
456
|
+
stepProgess.result = this.getFailedTestStepResult({
|
|
457
|
+
commands: stepProgess.commands,
|
|
458
|
+
startTime: prevStepResult.startTime,
|
|
459
|
+
endTime: this.getTimeStamp(timestamp),
|
|
460
|
+
result: testStepResult,
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
stepProgess.result = {
|
|
465
|
+
status: testStepResult.status,
|
|
466
|
+
startTime: prevStepResult.startTime,
|
|
467
|
+
endTime: this.getTimeStamp(timestamp),
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
stepProgess.webLog = this.stepLogs;
|
|
471
|
+
stepProgess.networkData = this.stepNetworkLogs;
|
|
472
|
+
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
473
|
+
this.ariaSnapshot = "";
|
|
474
|
+
this.stepNetworkLogs = [];
|
|
475
|
+
this.stepLogs = [];
|
|
315
476
|
if (Object.keys(data).length > 0) {
|
|
316
477
|
stepProgess.data = data;
|
|
478
|
+
const id = testStepFinished.testCaseStartedId;
|
|
479
|
+
const parameters = this.testCaseReportMap.get(id).parameters;
|
|
480
|
+
const _parameters = {};
|
|
481
|
+
Object.keys(parameters).map((key) => {
|
|
482
|
+
if (parameters[key].startsWith("{{") && parameters[key].endsWith("}}")) {
|
|
483
|
+
const path = parameters[key].slice(2, -2).split(".");
|
|
484
|
+
let value = String(object_path_1.default.get(data, path));
|
|
485
|
+
if (value) {
|
|
486
|
+
if (value.startsWith("secret:")) {
|
|
487
|
+
value = "secret:****";
|
|
488
|
+
}
|
|
489
|
+
else if (value.startsWith("totp:")) {
|
|
490
|
+
value = "totp:****";
|
|
491
|
+
}
|
|
492
|
+
else if (value.startsWith("mask:")) {
|
|
493
|
+
value = "mask:****";
|
|
494
|
+
}
|
|
495
|
+
_parameters[key] = value;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
_parameters[key] = parameters[key];
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
this.report.testCases.find((testCase) => {
|
|
503
|
+
return testCase.id === id;
|
|
504
|
+
}).parameters = _parameters;
|
|
317
505
|
}
|
|
506
|
+
// if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
507
|
+
// this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
|
|
508
|
+
// if (!fs.existsSync(this.reportFolder)) {
|
|
509
|
+
// fs.mkdirSync(this.reportFolder)
|
|
510
|
+
// }
|
|
511
|
+
// const reportFilePath = path.join(
|
|
512
|
+
// this.reportFolder,
|
|
513
|
+
// `report.json`
|
|
514
|
+
// )
|
|
515
|
+
// writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
|
|
516
|
+
// return undefined
|
|
517
|
+
// // } else {
|
|
518
|
+
// // return await this.uploadTestCase(testProgress, reRunId)
|
|
519
|
+
// }
|
|
318
520
|
}
|
|
319
521
|
getLogFileContent() {
|
|
320
522
|
let projectPath = process.cwd();
|
|
321
523
|
if (process.env.PROJECT_PATH) {
|
|
322
524
|
projectPath = process.env.PROJECT_PATH;
|
|
323
525
|
}
|
|
324
|
-
const logFolder = path_1.default.join(projectPath,
|
|
526
|
+
const logFolder = path_1.default.join(projectPath, "logs", "web");
|
|
325
527
|
if (!fs_1.default.existsSync(logFolder)) {
|
|
326
528
|
return [];
|
|
327
529
|
}
|
|
@@ -333,7 +535,7 @@ class ReportGenerator {
|
|
|
333
535
|
return [];
|
|
334
536
|
}
|
|
335
537
|
try {
|
|
336
|
-
const logFileContent = fs_1.default.readFileSync(path_1.default.join(logFolder, `${nextId - 1}.json`),
|
|
538
|
+
const logFileContent = fs_1.default.readFileSync(path_1.default.join(logFolder, `${nextId - 1}.json`), "utf8");
|
|
337
539
|
return JSON.parse(logFileContent);
|
|
338
540
|
}
|
|
339
541
|
catch (error) {
|
|
@@ -343,46 +545,135 @@ class ReportGenerator {
|
|
|
343
545
|
getTestCaseResult(steps) {
|
|
344
546
|
for (const step of steps) {
|
|
345
547
|
switch (step.result.status) {
|
|
346
|
-
case
|
|
548
|
+
case "FAILED":
|
|
347
549
|
return {
|
|
348
550
|
status: step.result.status,
|
|
349
551
|
message: step.result.message,
|
|
350
552
|
// exception: step.result.exception,
|
|
351
553
|
};
|
|
352
|
-
case
|
|
353
|
-
case
|
|
354
|
-
case
|
|
554
|
+
case "AMBIGUOUS":
|
|
555
|
+
case "UNDEFINED":
|
|
556
|
+
case "PENDING":
|
|
355
557
|
return {
|
|
356
|
-
status:
|
|
558
|
+
status: "FAILED",
|
|
357
559
|
message: `step "${step.text}" is ${step.result.status}`,
|
|
358
560
|
};
|
|
359
561
|
}
|
|
360
562
|
}
|
|
361
563
|
return {
|
|
362
|
-
status:
|
|
564
|
+
status: "PASSED",
|
|
363
565
|
};
|
|
364
566
|
}
|
|
365
|
-
onTestCaseFinished(testCaseFinished) {
|
|
567
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
366
568
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
367
569
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
368
570
|
const prevResult = testProgress.result;
|
|
369
571
|
const steps = Object.values(testProgress.steps);
|
|
370
572
|
const result = this.getTestCaseResult(steps);
|
|
573
|
+
const endTime = this.getTimeStamp(timestamp);
|
|
371
574
|
testProgress.result = {
|
|
372
575
|
...result,
|
|
373
576
|
startTime: prevResult.startTime,
|
|
374
|
-
endTime
|
|
577
|
+
endTime,
|
|
375
578
|
};
|
|
376
579
|
testProgress.webLog = this.logs;
|
|
377
580
|
testProgress.networkLog = this.networkLog;
|
|
581
|
+
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
582
|
+
this.initialAriaSnapshot = "";
|
|
378
583
|
this.networkLog = [];
|
|
379
584
|
this.logs = [];
|
|
585
|
+
if (this.testCaseLog && this.testCaseLog.length > 0) {
|
|
586
|
+
// Create the logs directory
|
|
587
|
+
const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
|
|
588
|
+
const fileName = `testCaseLog_${testCaseStartedId}.log`;
|
|
589
|
+
const filePath = path_1.default.join(logsDir, fileName);
|
|
590
|
+
// Ensure the logs directory exists
|
|
591
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
592
|
+
// Write the logs to the file
|
|
593
|
+
fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
|
|
594
|
+
// Store this ID in the testProgress object so it can be accessed later
|
|
595
|
+
testProgress.logFileId = testCaseStartedId;
|
|
596
|
+
}
|
|
597
|
+
this.testCaseLog = [];
|
|
598
|
+
if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
599
|
+
this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
600
|
+
if (!fs_1.default.existsSync(this.reportFolder)) {
|
|
601
|
+
fs_1.default.mkdirSync(this.reportFolder);
|
|
602
|
+
}
|
|
603
|
+
const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
|
|
604
|
+
(0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
|
|
605
|
+
return undefined;
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
return await this.uploadTestCase(testProgress, reRunId);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
async uploadTestCase(testCase, rerunId) {
|
|
612
|
+
let runId = "";
|
|
613
|
+
let projectId = "";
|
|
614
|
+
if (!process.env.UPLOADING_TEST_CASE) {
|
|
615
|
+
process.env.UPLOADING_TEST_CASE = "[]";
|
|
616
|
+
}
|
|
617
|
+
const anyRemArr = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
618
|
+
const randomID = Math.random().toString(36).substring(7);
|
|
619
|
+
anyRemArr.push(randomID);
|
|
620
|
+
let data;
|
|
621
|
+
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
622
|
+
try {
|
|
623
|
+
if (process.env.RUN_ID && process.env.PROJECT_ID && !process.env.IGNORE_ENV_VARIABLES) {
|
|
624
|
+
runId = process.env.RUN_ID;
|
|
625
|
+
projectId = process.env.PROJECT_ID;
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
629
|
+
runId = runDoc._id;
|
|
630
|
+
projectId = runDoc.project_id;
|
|
631
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
632
|
+
process.env.RUN_ID = runId;
|
|
633
|
+
process.env.PROJECT_ID = projectId;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
637
|
+
this.writeTestCaseReportToDisk(testCase);
|
|
638
|
+
}
|
|
639
|
+
catch (e) {
|
|
640
|
+
console.error("Error uploading test case:", e);
|
|
641
|
+
}
|
|
642
|
+
finally {
|
|
643
|
+
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
644
|
+
arrRem.splice(arrRem.indexOf(randomID), 1);
|
|
645
|
+
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
646
|
+
}
|
|
647
|
+
return data ? data : null;
|
|
648
|
+
}
|
|
649
|
+
writeTestCaseReportToDisk(testCase) {
|
|
650
|
+
var _a;
|
|
651
|
+
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
652
|
+
if (!reportFolder) {
|
|
653
|
+
console.error("Report folder is not defined");
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
try {
|
|
657
|
+
let i = 0;
|
|
658
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
659
|
+
i++;
|
|
660
|
+
}
|
|
661
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
662
|
+
//exclude network log from the saved report
|
|
663
|
+
const networkLog = testCase.networkLog;
|
|
664
|
+
delete testCase.networkLog;
|
|
665
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
|
|
666
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
667
|
+
}
|
|
668
|
+
catch (error) {
|
|
669
|
+
console.error("Error writing test case report to disk:", error);
|
|
670
|
+
}
|
|
380
671
|
}
|
|
381
672
|
onTestRunFinished(testRunFinished) {
|
|
382
673
|
const { timestamp, success, message } = testRunFinished;
|
|
383
674
|
const prevResult = this.report.result;
|
|
384
675
|
this.report.result = {
|
|
385
|
-
status: success ?
|
|
676
|
+
status: success ? "PASSED" : "FAILED",
|
|
386
677
|
startTime: prevResult.startTime,
|
|
387
678
|
endTime: this.getTimeStamp(timestamp),
|
|
388
679
|
message,
|