@dev-blinq/cucumber-js 1.0.123-dev → 1.0.123
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 +163 -55
- 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 +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 +21 -3
- package/lib/formatter/helpers/report_generator.js +333 -27
- 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 +15 -2
- package/lib/formatter/helpers/upload_serivce.js +153 -7
- 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/summary_formatter.js +4 -0
- package/lib/formatter/summary_formatter.js.map +1 -1
- package/lib/importer.js +0 -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/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +6 -3
|
@@ -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,20 @@ 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.retryTestCaseId = null;
|
|
84
|
+
this.retryCount = 3;
|
|
46
85
|
}
|
|
47
|
-
async handleMessage(envelope) {
|
|
48
|
-
if (envelope.meta && envelope.meta
|
|
86
|
+
async handleMessage(envelope, reRunId) {
|
|
87
|
+
if (envelope.meta && 'runName' in envelope.meta) {
|
|
49
88
|
this.runName = envelope.meta.runName;
|
|
50
89
|
}
|
|
51
90
|
const type = Object.keys(envelope)[0];
|
|
@@ -72,14 +111,35 @@ class ReportGenerator {
|
|
|
72
111
|
case 'testRunStarted': {
|
|
73
112
|
const testRunStarted = envelope[type];
|
|
74
113
|
this.onTestRunStarted(testRunStarted);
|
|
114
|
+
await this.uploadService.createStatus('running');
|
|
75
115
|
break;
|
|
76
116
|
}
|
|
77
117
|
case 'testCase': {
|
|
78
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
|
|
79
138
|
this.onTestCase(testCase);
|
|
80
139
|
break;
|
|
81
140
|
}
|
|
82
141
|
case 'testCaseStarted': {
|
|
142
|
+
this.retryTestCaseId = envelope[type].retryTestCaseId;
|
|
83
143
|
const testCaseStarted = envelope[type];
|
|
84
144
|
this.onTestCaseStarted(testCaseStarted);
|
|
85
145
|
break;
|
|
@@ -101,13 +161,18 @@ class ReportGenerator {
|
|
|
101
161
|
}
|
|
102
162
|
case 'testCaseFinished': {
|
|
103
163
|
const testCaseFinished = envelope[type];
|
|
104
|
-
|
|
105
|
-
|
|
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;
|
|
106
171
|
}
|
|
107
172
|
// case "hook": { break} // After Hook
|
|
108
173
|
case 'testRunFinished': {
|
|
109
174
|
const testRunFinished = envelope[type];
|
|
110
|
-
this.onTestRunFinished(testRunFinished);
|
|
175
|
+
await this.onTestRunFinished(testRunFinished);
|
|
111
176
|
break;
|
|
112
177
|
}
|
|
113
178
|
// case "parameterType" : { break}
|
|
@@ -238,6 +303,10 @@ class ReportGenerator {
|
|
|
238
303
|
result: {
|
|
239
304
|
status: 'UNKNOWN',
|
|
240
305
|
},
|
|
306
|
+
networkData: [],
|
|
307
|
+
webLog: [],
|
|
308
|
+
data: {},
|
|
309
|
+
ariaSnapshot: this.ariaSnapshot,
|
|
241
310
|
});
|
|
242
311
|
return this.stepReportMap.get(pickleStep.id);
|
|
243
312
|
});
|
|
@@ -280,6 +349,14 @@ class ReportGenerator {
|
|
|
280
349
|
this.reportFolder = body.replaceAll('\\', '/');
|
|
281
350
|
return;
|
|
282
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
|
+
}
|
|
283
360
|
if (mediaType === 'application/json+env') {
|
|
284
361
|
const data = JSON.parse(body);
|
|
285
362
|
this.report.env = data;
|
|
@@ -290,13 +367,16 @@ class ReportGenerator {
|
|
|
290
367
|
}
|
|
291
368
|
if (mediaType === 'application/json+log') {
|
|
292
369
|
const log = JSON.parse(body);
|
|
293
|
-
if (this.logs.length < 1000)
|
|
370
|
+
if (this.logs.length < 1000) {
|
|
294
371
|
this.logs.push(log);
|
|
372
|
+
this.stepLogs.push(log);
|
|
373
|
+
}
|
|
295
374
|
}
|
|
296
375
|
if (mediaType === 'application/json+network') {
|
|
297
376
|
const networkLog = JSON.parse(body);
|
|
298
377
|
if (this.networkLog.length < 1000)
|
|
299
378
|
this.networkLog.push(networkLog);
|
|
379
|
+
this.stepNetworkLogs.push(networkLog);
|
|
300
380
|
}
|
|
301
381
|
const testStep = this.testStepMap.get(testStepId);
|
|
302
382
|
if (testStep.pickleStepId === undefined)
|
|
@@ -306,16 +386,100 @@ class ReportGenerator {
|
|
|
306
386
|
const command = JSON.parse(body);
|
|
307
387
|
stepProgess.commands.push(command);
|
|
308
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, }) {
|
|
413
|
+
for (const command of commands) {
|
|
414
|
+
if (command.result.status === 'FAILED') {
|
|
415
|
+
return {
|
|
416
|
+
status: 'FAILED',
|
|
417
|
+
message: command.result.message,
|
|
418
|
+
startTime,
|
|
419
|
+
endTime,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
status: 'FAILED',
|
|
425
|
+
startTime,
|
|
426
|
+
endTime,
|
|
427
|
+
message: result.message,
|
|
428
|
+
};
|
|
309
429
|
}
|
|
310
430
|
onTestStepFinished(testStepFinished) {
|
|
311
431
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
312
432
|
const testStep = this.testStepMap.get(testStepId);
|
|
313
433
|
if (testStep.pickleStepId === undefined) {
|
|
314
434
|
if (testStepResult.status === 'FAILED') {
|
|
435
|
+
const testCase = this.testCaseReportMap.get(testStepFinished.testCaseStartedId);
|
|
436
|
+
const type = testCase.steps[0].result.status === 'UNKNOWN' ? 'Before' : 'After';
|
|
437
|
+
const hookStep = {
|
|
438
|
+
ariaSnapshot: null,
|
|
439
|
+
commands: [],
|
|
440
|
+
keyword: type,
|
|
441
|
+
data: {},
|
|
442
|
+
networkData: [],
|
|
443
|
+
result: {
|
|
444
|
+
status: 'FAILED',
|
|
445
|
+
message: testStepResult.message,
|
|
446
|
+
startTime: this.getTimeStamp(timestamp),
|
|
447
|
+
endTime: this.getTimeStamp(timestamp),
|
|
448
|
+
},
|
|
449
|
+
text: 'Failed hook',
|
|
450
|
+
type,
|
|
451
|
+
webLog: [],
|
|
452
|
+
};
|
|
453
|
+
if (type === 'Before') {
|
|
454
|
+
testCase.steps = [hookStep, ...testCase.steps];
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
testCase.steps = [...testCase.steps, hookStep];
|
|
458
|
+
}
|
|
459
|
+
this.testCaseReportMap.set(testStepFinished.testCaseStartedId, testCase);
|
|
315
460
|
console.error(`Before/After hook failed with message: ${testStepResult.message}`);
|
|
316
461
|
}
|
|
317
462
|
return;
|
|
318
463
|
}
|
|
464
|
+
if (testStepResult.status === 'UNDEFINED') {
|
|
465
|
+
const step = this.stepReportMap.get(testStep.pickleStepId);
|
|
466
|
+
const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
|
|
467
|
+
const undefinedCommand = {
|
|
468
|
+
testStepId: testStepId,
|
|
469
|
+
body: JSON.stringify({
|
|
470
|
+
type: 'error',
|
|
471
|
+
text: 'Undefined step: ' + stepName,
|
|
472
|
+
result: {
|
|
473
|
+
status: 'FAILED',
|
|
474
|
+
startTime: this.getTimeStamp(timestamp),
|
|
475
|
+
endTime: this.getTimeStamp(timestamp),
|
|
476
|
+
},
|
|
477
|
+
}),
|
|
478
|
+
mediaType: 'application/json',
|
|
479
|
+
contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
|
|
480
|
+
};
|
|
481
|
+
this.onAttachment(undefinedCommand);
|
|
482
|
+
}
|
|
319
483
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
320
484
|
const prevStepResult = stepProgess.result;
|
|
321
485
|
let data = {};
|
|
@@ -331,16 +495,73 @@ class ReportGenerator {
|
|
|
331
495
|
catch (error) {
|
|
332
496
|
console.log('Error reading data.json');
|
|
333
497
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
498
|
+
if (testStepResult.status === 'FAILED') {
|
|
499
|
+
stepProgess.result = this.getFailedTestStepResult({
|
|
500
|
+
commands: stepProgess.commands,
|
|
501
|
+
startTime: prevStepResult.startTime,
|
|
502
|
+
endTime: this.getTimeStamp(timestamp),
|
|
503
|
+
result: testStepResult,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
stepProgess.result = {
|
|
508
|
+
status: testStepResult.status,
|
|
509
|
+
startTime: prevStepResult.startTime,
|
|
510
|
+
endTime: this.getTimeStamp(timestamp),
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
stepProgess.webLog = this.stepLogs;
|
|
514
|
+
stepProgess.networkData = this.stepNetworkLogs;
|
|
515
|
+
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
516
|
+
this.ariaSnapshot = '';
|
|
517
|
+
this.stepNetworkLogs = [];
|
|
518
|
+
this.stepLogs = [];
|
|
341
519
|
if (Object.keys(data).length > 0) {
|
|
342
520
|
stepProgess.data = data;
|
|
521
|
+
const id = testStepFinished.testCaseStartedId;
|
|
522
|
+
const parameters = this.testCaseReportMap.get(id).parameters;
|
|
523
|
+
const _parameters = {};
|
|
524
|
+
Object.keys(parameters).map((key) => {
|
|
525
|
+
var _a;
|
|
526
|
+
const valueParam = parameters[key].toString();
|
|
527
|
+
if (valueParam.startsWith('{{') && valueParam.endsWith('}}')) {
|
|
528
|
+
const path = valueParam.slice(2, -2).split('.');
|
|
529
|
+
let value = String((_a = object_path_1.default.get(data, path)) !== null && _a !== void 0 ? _a : valueParam);
|
|
530
|
+
if (value) {
|
|
531
|
+
if (value.startsWith('secret:')) {
|
|
532
|
+
value = 'secret:****';
|
|
533
|
+
}
|
|
534
|
+
else if (value.startsWith('totp:')) {
|
|
535
|
+
value = 'totp:****';
|
|
536
|
+
}
|
|
537
|
+
else if (value.startsWith('mask:')) {
|
|
538
|
+
value = 'mask:****';
|
|
539
|
+
}
|
|
540
|
+
_parameters[key] = value;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
_parameters[key] = parameters[key];
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
this.report.testCases.find((testCase) => {
|
|
548
|
+
return testCase.id === id;
|
|
549
|
+
}).parameters = _parameters;
|
|
343
550
|
}
|
|
551
|
+
// if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
552
|
+
// this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
|
|
553
|
+
// if (!fs.existsSync(this.reportFolder)) {
|
|
554
|
+
// fs.mkdirSync(this.reportFolder)
|
|
555
|
+
// }
|
|
556
|
+
// const reportFilePath = path.join(
|
|
557
|
+
// this.reportFolder,
|
|
558
|
+
// `report.json`
|
|
559
|
+
// )
|
|
560
|
+
// writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
|
|
561
|
+
// return undefined
|
|
562
|
+
// // } else {
|
|
563
|
+
// // return await this.uploadTestCase(testProgress, reRunId)
|
|
564
|
+
// }
|
|
344
565
|
}
|
|
345
566
|
getLogFileContent() {
|
|
346
567
|
let projectPath = process.cwd();
|
|
@@ -367,6 +588,12 @@ class ReportGenerator {
|
|
|
367
588
|
}
|
|
368
589
|
}
|
|
369
590
|
getTestCaseResult(steps) {
|
|
591
|
+
if (steps[0] && steps[0].result.status === 'SKIPPED') {
|
|
592
|
+
return {
|
|
593
|
+
status: 'FAILED',
|
|
594
|
+
message: 'Test skipped due to failure in before hooks',
|
|
595
|
+
};
|
|
596
|
+
}
|
|
370
597
|
for (const step of steps) {
|
|
371
598
|
switch (step.result.status) {
|
|
372
599
|
case 'FAILED':
|
|
@@ -388,24 +615,76 @@ class ReportGenerator {
|
|
|
388
615
|
status: 'PASSED',
|
|
389
616
|
};
|
|
390
617
|
}
|
|
391
|
-
async onTestCaseFinished(testCaseFinished) {
|
|
618
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
392
619
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
393
620
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
394
621
|
const prevResult = testProgress.result;
|
|
395
622
|
const steps = Object.values(testProgress.steps);
|
|
396
623
|
const result = this.getTestCaseResult(steps);
|
|
624
|
+
if (result.status === 'PASSED' && reRunId) {
|
|
625
|
+
this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
|
|
626
|
+
}
|
|
627
|
+
const endTime = this.getTimeStamp(timestamp);
|
|
397
628
|
testProgress.result = {
|
|
398
629
|
...result,
|
|
399
630
|
startTime: prevResult.startTime,
|
|
400
|
-
endTime
|
|
631
|
+
endTime,
|
|
401
632
|
};
|
|
402
633
|
testProgress.webLog = this.logs;
|
|
403
634
|
testProgress.networkLog = this.networkLog;
|
|
635
|
+
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
636
|
+
this.initialAriaSnapshot = '';
|
|
404
637
|
this.networkLog = [];
|
|
405
638
|
this.logs = [];
|
|
406
|
-
|
|
639
|
+
if (this.testCaseLog &&
|
|
640
|
+
this.testCaseLog.length > 0 &&
|
|
641
|
+
!testProgress.logFileId) {
|
|
642
|
+
// Create the logs directory
|
|
643
|
+
const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
|
|
644
|
+
const fileName = `testCaseLog_${testCaseStartedId}.log`;
|
|
645
|
+
const filePath = path_1.default.join(logsDir, fileName);
|
|
646
|
+
// Ensure the logs directory exists
|
|
647
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
648
|
+
// Write the logs to the file
|
|
649
|
+
fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
|
|
650
|
+
// Store this ID in the testProgress object so it can be accessed later
|
|
651
|
+
testProgress.logFileId = testCaseStartedId;
|
|
652
|
+
}
|
|
653
|
+
this.testCaseLog = [];
|
|
654
|
+
if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
655
|
+
this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
656
|
+
if (!fs_1.default.existsSync(this.reportFolder)) {
|
|
657
|
+
fs_1.default.mkdirSync(this.reportFolder);
|
|
658
|
+
}
|
|
659
|
+
const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
|
|
660
|
+
(0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
|
|
661
|
+
return undefined;
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
return await this.uploadTestCase(testProgress, reRunId);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
async uploadTestCase(testCase, rerunId) {
|
|
668
|
+
let data = null;
|
|
669
|
+
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
|
|
670
|
+
try {
|
|
671
|
+
data = await this.tryUpload(testCase, rerunId);
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
674
|
+
catch (e) {
|
|
675
|
+
console.error(`Attempt ${attempt} to upload testcase failed:`, e);
|
|
676
|
+
if (attempt === this.retryCount) {
|
|
677
|
+
console.error('All retry attempts failed, failed to upload testcase.');
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
|
|
681
|
+
await new Promise((r) => setTimeout(r, waitTime));
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return data;
|
|
407
686
|
}
|
|
408
|
-
async
|
|
687
|
+
async tryUpload(testCase, rerunId) {
|
|
409
688
|
let runId = '';
|
|
410
689
|
let projectId = '';
|
|
411
690
|
if (!process.env.UPLOADING_TEST_CASE) {
|
|
@@ -416,21 +695,24 @@ class ReportGenerator {
|
|
|
416
695
|
anyRemArr.push(randomID);
|
|
417
696
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
418
697
|
try {
|
|
419
|
-
if (process.env.RUN_ID &&
|
|
698
|
+
if (process.env.RUN_ID &&
|
|
699
|
+
process.env.PROJECT_ID &&
|
|
700
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
420
701
|
runId = process.env.RUN_ID;
|
|
421
702
|
projectId = process.env.PROJECT_ID;
|
|
422
703
|
}
|
|
423
704
|
else {
|
|
424
|
-
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
705
|
+
const runDoc = await this.uploadService.createRunDocument(this.runName, testCase.env);
|
|
425
706
|
runId = runDoc._id;
|
|
426
707
|
projectId = runDoc.project_id;
|
|
427
|
-
process.env.
|
|
428
|
-
|
|
708
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
709
|
+
process.env.RUN_ID = runId;
|
|
710
|
+
process.env.PROJECT_ID = projectId;
|
|
711
|
+
}
|
|
429
712
|
}
|
|
430
|
-
await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
console.error('Error uploading test case:', e);
|
|
713
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
714
|
+
this.writeTestCaseReportToDisk(testCase);
|
|
715
|
+
return data;
|
|
434
716
|
}
|
|
435
717
|
finally {
|
|
436
718
|
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
@@ -438,7 +720,30 @@ class ReportGenerator {
|
|
|
438
720
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
439
721
|
}
|
|
440
722
|
}
|
|
441
|
-
|
|
723
|
+
writeTestCaseReportToDisk(testCase) {
|
|
724
|
+
var _a;
|
|
725
|
+
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
726
|
+
if (!reportFolder) {
|
|
727
|
+
console.error('Report folder is not defined');
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
try {
|
|
731
|
+
let i = 0;
|
|
732
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
733
|
+
i++;
|
|
734
|
+
}
|
|
735
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
736
|
+
//exclude network log from the saved report
|
|
737
|
+
const networkLog = testCase.networkLog;
|
|
738
|
+
delete testCase.networkLog;
|
|
739
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
|
|
740
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
741
|
+
}
|
|
742
|
+
catch (error) {
|
|
743
|
+
console.error('Error writing test case report to disk:', error);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
async onTestRunFinished(testRunFinished) {
|
|
442
747
|
const { timestamp, success, message } = testRunFinished;
|
|
443
748
|
const prevResult = this.report.result;
|
|
444
749
|
this.report.result = {
|
|
@@ -448,6 +753,7 @@ class ReportGenerator {
|
|
|
448
753
|
message,
|
|
449
754
|
// exception,
|
|
450
755
|
};
|
|
756
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
451
757
|
}
|
|
452
758
|
}
|
|
453
759
|
exports.default = ReportGenerator;
|