@dev-blinq/cucumber-js 1.0.130-dev → 1.0.130
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 +14 -1
- package/lib/formatter/bvt_analysis_formatter.js +207 -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 +20 -2
- package/lib/formatter/helpers/report_generator.js +329 -26
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +22 -2
- package/lib/formatter/helpers/upload_serivce.js +214 -34
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.js +6 -2
- package/lib/formatter/helpers/uploader.js.map +1 -1
- package/lib/formatter/progress_formatter.d.ts +2 -1
- package/lib/formatter/progress_formatter.js.map +1 -1
- package/lib/formatter/snippets_formatter.js.map +1 -1
- package/lib/formatter/summary_formatter.js +4 -0
- package/lib/formatter/summary_formatter.js.map +1 -1
- package/lib/formatter/usage_formatter.js.map +1 -1
- package/lib/formatter/usage_json_formatter.js.map +1 -1
- package/lib/pickle_filter.d.ts +3 -2
- package/lib/pickle_filter.js.map +1 -1
- package/lib/runtime/test_case_runner.d.ts +2 -0
- package/lib/runtime/test_case_runner.js +17 -1
- package/lib/runtime/test_case_runner.js.map +1 -1
- package/lib/uncaught_exception_manager.d.ts +1 -1
- package/lib/uncaught_exception_manager.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +7 -3
|
@@ -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;
|
|
@@ -41,12 +72,19 @@ class ReportGenerator {
|
|
|
41
72
|
this.logs = [];
|
|
42
73
|
this.networkLog = [];
|
|
43
74
|
this.stepLogs = [];
|
|
75
|
+
this.stepNetworkLogs = [];
|
|
44
76
|
this.runName = '';
|
|
77
|
+
this.ariaSnapshot = '';
|
|
78
|
+
this.initialAriaSnapshot = '';
|
|
79
|
+
this.testCaseLog = [];
|
|
80
|
+
this.loggingOverridden = false; // Flag to track if logging is overridden
|
|
45
81
|
this.reportFolder = null;
|
|
46
82
|
this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
|
|
83
|
+
this.retryTestCaseId = null;
|
|
84
|
+
this.retryCount = 3;
|
|
47
85
|
}
|
|
48
|
-
async handleMessage(envelope) {
|
|
49
|
-
if (envelope.meta && envelope.meta
|
|
86
|
+
async handleMessage(envelope, reRunId) {
|
|
87
|
+
if (envelope.meta && 'runName' in envelope.meta) {
|
|
50
88
|
this.runName = envelope.meta.runName;
|
|
51
89
|
}
|
|
52
90
|
const type = Object.keys(envelope)[0];
|
|
@@ -73,14 +111,35 @@ class ReportGenerator {
|
|
|
73
111
|
case 'testRunStarted': {
|
|
74
112
|
const testRunStarted = envelope[type];
|
|
75
113
|
this.onTestRunStarted(testRunStarted);
|
|
114
|
+
await this.uploadService.createStatus('running');
|
|
76
115
|
break;
|
|
77
116
|
}
|
|
78
117
|
case 'testCase': {
|
|
79
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
|
|
80
138
|
this.onTestCase(testCase);
|
|
81
139
|
break;
|
|
82
140
|
}
|
|
83
141
|
case 'testCaseStarted': {
|
|
142
|
+
this.retryTestCaseId = envelope[type].retryTestCaseId;
|
|
84
143
|
const testCaseStarted = envelope[type];
|
|
85
144
|
this.onTestCaseStarted(testCaseStarted);
|
|
86
145
|
break;
|
|
@@ -102,13 +161,18 @@ class ReportGenerator {
|
|
|
102
161
|
}
|
|
103
162
|
case 'testCaseFinished': {
|
|
104
163
|
const testCaseFinished = envelope[type];
|
|
105
|
-
|
|
106
|
-
|
|
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;
|
|
107
171
|
}
|
|
108
172
|
// case "hook": { break} // After Hook
|
|
109
173
|
case 'testRunFinished': {
|
|
110
174
|
const testRunFinished = envelope[type];
|
|
111
|
-
this.onTestRunFinished(testRunFinished);
|
|
175
|
+
await this.onTestRunFinished(testRunFinished);
|
|
112
176
|
break;
|
|
113
177
|
}
|
|
114
178
|
// case "parameterType" : { break}
|
|
@@ -239,7 +303,10 @@ class ReportGenerator {
|
|
|
239
303
|
result: {
|
|
240
304
|
status: 'UNKNOWN',
|
|
241
305
|
},
|
|
306
|
+
networkData: [],
|
|
242
307
|
webLog: [],
|
|
308
|
+
data: {},
|
|
309
|
+
ariaSnapshot: this.ariaSnapshot,
|
|
243
310
|
});
|
|
244
311
|
return this.stepReportMap.get(pickleStep.id);
|
|
245
312
|
});
|
|
@@ -282,6 +349,14 @@ class ReportGenerator {
|
|
|
282
349
|
this.reportFolder = body.replaceAll('\\', '/');
|
|
283
350
|
return;
|
|
284
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
|
+
}
|
|
285
360
|
if (mediaType === 'application/json+env') {
|
|
286
361
|
const data = JSON.parse(body);
|
|
287
362
|
this.report.env = data;
|
|
@@ -301,6 +376,7 @@ class ReportGenerator {
|
|
|
301
376
|
const networkLog = JSON.parse(body);
|
|
302
377
|
if (this.networkLog.length < 1000)
|
|
303
378
|
this.networkLog.push(networkLog);
|
|
379
|
+
this.stepNetworkLogs.push(networkLog);
|
|
304
380
|
}
|
|
305
381
|
const testStep = this.testStepMap.get(testStepId);
|
|
306
382
|
if (testStep.pickleStepId === undefined)
|
|
@@ -310,16 +386,100 @@ class ReportGenerator {
|
|
|
310
386
|
const command = JSON.parse(body);
|
|
311
387
|
stepProgess.commands.push(command);
|
|
312
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
|
+
};
|
|
313
429
|
}
|
|
314
430
|
onTestStepFinished(testStepFinished) {
|
|
315
431
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
316
432
|
const testStep = this.testStepMap.get(testStepId);
|
|
317
433
|
if (testStep.pickleStepId === undefined) {
|
|
318
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);
|
|
319
460
|
console.error(`Before/After hook failed with message: ${testStepResult.message}`);
|
|
320
461
|
}
|
|
321
462
|
return;
|
|
322
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
|
+
}
|
|
323
483
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
324
484
|
const prevStepResult = stepProgess.result;
|
|
325
485
|
let data = {};
|
|
@@ -335,18 +495,73 @@ class ReportGenerator {
|
|
|
335
495
|
catch (error) {
|
|
336
496
|
console.log('Error reading data.json');
|
|
337
497
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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
|
+
}
|
|
345
513
|
stepProgess.webLog = this.stepLogs;
|
|
514
|
+
stepProgess.networkData = this.stepNetworkLogs;
|
|
515
|
+
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
516
|
+
this.ariaSnapshot = '';
|
|
517
|
+
this.stepNetworkLogs = [];
|
|
346
518
|
this.stepLogs = [];
|
|
347
519
|
if (Object.keys(data).length > 0) {
|
|
348
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;
|
|
349
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
|
+
// }
|
|
350
565
|
}
|
|
351
566
|
getLogFileContent() {
|
|
352
567
|
let projectPath = process.cwd();
|
|
@@ -373,6 +588,12 @@ class ReportGenerator {
|
|
|
373
588
|
}
|
|
374
589
|
}
|
|
375
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
|
+
}
|
|
376
597
|
for (const step of steps) {
|
|
377
598
|
switch (step.result.status) {
|
|
378
599
|
case 'FAILED':
|
|
@@ -394,24 +615,79 @@ class ReportGenerator {
|
|
|
394
615
|
status: 'PASSED',
|
|
395
616
|
};
|
|
396
617
|
}
|
|
397
|
-
async onTestCaseFinished(testCaseFinished) {
|
|
618
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
398
619
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
399
620
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
400
621
|
const prevResult = testProgress.result;
|
|
401
622
|
const steps = Object.values(testProgress.steps);
|
|
402
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);
|
|
403
628
|
testProgress.result = {
|
|
404
629
|
...result,
|
|
405
630
|
startTime: prevResult.startTime,
|
|
406
|
-
endTime
|
|
631
|
+
endTime,
|
|
407
632
|
};
|
|
408
633
|
testProgress.webLog = this.logs;
|
|
409
634
|
testProgress.networkLog = this.networkLog;
|
|
635
|
+
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
636
|
+
if (process.env.TRACE) {
|
|
637
|
+
testProgress.traceFileId = path_1.default.join(`trace-${testCaseStartedId}.zip`);
|
|
638
|
+
}
|
|
639
|
+
this.initialAriaSnapshot = '';
|
|
410
640
|
this.networkLog = [];
|
|
411
641
|
this.logs = [];
|
|
412
|
-
|
|
642
|
+
if (this.testCaseLog &&
|
|
643
|
+
this.testCaseLog.length > 0 &&
|
|
644
|
+
!testProgress.logFileId) {
|
|
645
|
+
// Create the logs directory
|
|
646
|
+
const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
|
|
647
|
+
const fileName = `testCaseLog_${testCaseStartedId}.log`;
|
|
648
|
+
const filePath = path_1.default.join(logsDir, fileName);
|
|
649
|
+
// Ensure the logs directory exists
|
|
650
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
651
|
+
// Write the logs to the file
|
|
652
|
+
fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
|
|
653
|
+
// Store this ID in the testProgress object so it can be accessed later
|
|
654
|
+
testProgress.logFileId = testCaseStartedId;
|
|
655
|
+
}
|
|
656
|
+
this.testCaseLog = [];
|
|
657
|
+
if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
658
|
+
this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
659
|
+
if (!fs_1.default.existsSync(this.reportFolder)) {
|
|
660
|
+
fs_1.default.mkdirSync(this.reportFolder);
|
|
661
|
+
}
|
|
662
|
+
const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
|
|
663
|
+
(0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
|
|
664
|
+
return undefined;
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
return await this.uploadTestCase(testProgress, reRunId);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
async uploadTestCase(testCase, rerunId) {
|
|
671
|
+
let data = null;
|
|
672
|
+
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
|
|
673
|
+
try {
|
|
674
|
+
data = await this.tryUpload(testCase, rerunId);
|
|
675
|
+
break;
|
|
676
|
+
}
|
|
677
|
+
catch (e) {
|
|
678
|
+
console.error(`Attempt ${attempt} to upload testcase failed:`, e);
|
|
679
|
+
if (attempt === this.retryCount) {
|
|
680
|
+
console.error('All retry attempts failed, failed to upload testcase.');
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
|
|
684
|
+
await new Promise((r) => setTimeout(r, waitTime));
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return data;
|
|
413
689
|
}
|
|
414
|
-
async
|
|
690
|
+
async tryUpload(testCase, rerunId) {
|
|
415
691
|
let runId = '';
|
|
416
692
|
let projectId = '';
|
|
417
693
|
if (!process.env.UPLOADING_TEST_CASE) {
|
|
@@ -422,21 +698,24 @@ class ReportGenerator {
|
|
|
422
698
|
anyRemArr.push(randomID);
|
|
423
699
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
424
700
|
try {
|
|
425
|
-
if (process.env.RUN_ID &&
|
|
701
|
+
if (process.env.RUN_ID &&
|
|
702
|
+
process.env.PROJECT_ID &&
|
|
703
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
426
704
|
runId = process.env.RUN_ID;
|
|
427
705
|
projectId = process.env.PROJECT_ID;
|
|
428
706
|
}
|
|
429
707
|
else {
|
|
430
|
-
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
708
|
+
const runDoc = await this.uploadService.createRunDocument(this.runName, testCase.env);
|
|
431
709
|
runId = runDoc._id;
|
|
432
710
|
projectId = runDoc.project_id;
|
|
433
|
-
process.env.
|
|
434
|
-
|
|
711
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
712
|
+
process.env.RUN_ID = runId;
|
|
713
|
+
process.env.PROJECT_ID = projectId;
|
|
714
|
+
}
|
|
435
715
|
}
|
|
436
|
-
await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
console.error('Error uploading test case:', e);
|
|
716
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
717
|
+
this.writeTestCaseReportToDisk(testCase);
|
|
718
|
+
return data;
|
|
440
719
|
}
|
|
441
720
|
finally {
|
|
442
721
|
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
@@ -444,7 +723,30 @@ class ReportGenerator {
|
|
|
444
723
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
445
724
|
}
|
|
446
725
|
}
|
|
447
|
-
|
|
726
|
+
writeTestCaseReportToDisk(testCase) {
|
|
727
|
+
var _a;
|
|
728
|
+
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
729
|
+
if (!reportFolder) {
|
|
730
|
+
console.error('Report folder is not defined');
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
try {
|
|
734
|
+
let i = 0;
|
|
735
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
736
|
+
i++;
|
|
737
|
+
}
|
|
738
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
739
|
+
//exclude network log from the saved report
|
|
740
|
+
const networkLog = testCase.networkLog;
|
|
741
|
+
delete testCase.networkLog;
|
|
742
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
|
|
743
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
744
|
+
}
|
|
745
|
+
catch (error) {
|
|
746
|
+
console.error('Error writing test case report to disk:', error);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
async onTestRunFinished(testRunFinished) {
|
|
448
750
|
const { timestamp, success, message } = testRunFinished;
|
|
449
751
|
const prevResult = this.report.result;
|
|
450
752
|
this.report.result = {
|
|
@@ -454,6 +756,7 @@ class ReportGenerator {
|
|
|
454
756
|
message,
|
|
455
757
|
// exception,
|
|
456
758
|
};
|
|
759
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
457
760
|
}
|
|
458
761
|
}
|
|
459
762
|
exports.default = ReportGenerator;
|