@dev-blinq/cucumber-js 1.0.121-dev → 1.0.121
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 +9 -3
- 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 -3
- package/lib/formatter/helpers/report_generator.js +326 -26
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +14 -1
- package/lib/formatter/helpers/upload_serivce.js +127 -4
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.js +5 -1
- 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 +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
|
@@ -1,19 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
var _a, _b;
|
|
6
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
const messages = __importStar(require("@cucumber/messages"));
|
|
7
31
|
const fs_1 = __importDefault(require("fs"));
|
|
8
32
|
const path_1 = __importDefault(require("path"));
|
|
9
33
|
const upload_serivce_1 = require("./upload_serivce");
|
|
34
|
+
const fs_extra_1 = require("fs-extra");
|
|
35
|
+
// type JsonException = messages.Exception
|
|
36
|
+
const object_path_1 = __importDefault(require("object-path"));
|
|
10
37
|
const URL = process.env.NODE_ENV_BLINQ === 'dev'
|
|
11
38
|
? 'https://dev.api.blinq.io/api/runs'
|
|
12
39
|
: process.env.NODE_ENV_BLINQ === 'local'
|
|
13
40
|
? 'http://localhost:5001/api/runs'
|
|
14
41
|
: process.env.NODE_ENV_BLINQ === 'stage'
|
|
15
42
|
? 'https://stage.api.blinq.io/api/runs'
|
|
16
|
-
:
|
|
43
|
+
: process.env.NODE_ENV_BLINQ === 'prod'
|
|
44
|
+
? 'https://api.blinq.io/api/runs'
|
|
45
|
+
: !process.env.NODE_ENV_BLINQ
|
|
46
|
+
? 'https://api.blinq.io/api/runs'
|
|
47
|
+
: `${process.env.NODE_ENV_BLINQ}/api/runs`;
|
|
17
48
|
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
18
49
|
const BATCH_SIZE = 10;
|
|
19
50
|
const MAX_RETRIES = 3;
|
|
@@ -40,12 +71,19 @@ class ReportGenerator {
|
|
|
40
71
|
this.scenarioIterationCountMap = new Map();
|
|
41
72
|
this.logs = [];
|
|
42
73
|
this.networkLog = [];
|
|
74
|
+
this.stepLogs = [];
|
|
75
|
+
this.stepNetworkLogs = [];
|
|
43
76
|
this.runName = '';
|
|
77
|
+
this.ariaSnapshot = '';
|
|
78
|
+
this.initialAriaSnapshot = '';
|
|
79
|
+
this.testCaseLog = [];
|
|
80
|
+
this.loggingOverridden = false; // Flag to track if logging is overridden
|
|
44
81
|
this.reportFolder = null;
|
|
45
82
|
this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
|
|
83
|
+
this.retryCount = 3;
|
|
46
84
|
}
|
|
47
|
-
async handleMessage(envelope) {
|
|
48
|
-
if (envelope.meta && envelope.meta
|
|
85
|
+
async handleMessage(envelope, reRunId) {
|
|
86
|
+
if (envelope.meta && 'runName' in envelope.meta) {
|
|
49
87
|
this.runName = envelope.meta.runName;
|
|
50
88
|
}
|
|
51
89
|
const type = Object.keys(envelope)[0];
|
|
@@ -72,10 +110,30 @@ class ReportGenerator {
|
|
|
72
110
|
case 'testRunStarted': {
|
|
73
111
|
const testRunStarted = envelope[type];
|
|
74
112
|
this.onTestRunStarted(testRunStarted);
|
|
113
|
+
await this.uploadService.createStatus('running');
|
|
75
114
|
break;
|
|
76
115
|
}
|
|
77
116
|
case 'testCase': {
|
|
78
117
|
const testCase = envelope[type];
|
|
118
|
+
// Initialize the log storage
|
|
119
|
+
this.testCaseLog = [];
|
|
120
|
+
if (!this.loggingOverridden) {
|
|
121
|
+
this.loggingOverridden = true;
|
|
122
|
+
// Store the original process.stdout.write, and process.stderr.write
|
|
123
|
+
const originalStdoutWrite = process.stdout.write;
|
|
124
|
+
const originalStderrWrite = process.stderr.write;
|
|
125
|
+
// Override process.stdout.write
|
|
126
|
+
process.stdout.write = (chunk, ...args) => {
|
|
127
|
+
this.testCaseLog.push(chunk.toString());
|
|
128
|
+
return originalStdoutWrite.call(process.stdout, chunk, ...args);
|
|
129
|
+
};
|
|
130
|
+
// Override process.stderr.write
|
|
131
|
+
process.stderr.write = (chunk, ...args) => {
|
|
132
|
+
this.testCaseLog.push(chunk.toString());
|
|
133
|
+
return originalStderrWrite.call(process.stderr, chunk, ...args);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Call the onTestCase method
|
|
79
137
|
this.onTestCase(testCase);
|
|
80
138
|
break;
|
|
81
139
|
}
|
|
@@ -101,13 +159,14 @@ class ReportGenerator {
|
|
|
101
159
|
}
|
|
102
160
|
case 'testCaseFinished': {
|
|
103
161
|
const testCaseFinished = envelope[type];
|
|
104
|
-
|
|
105
|
-
|
|
162
|
+
// Call the onTestCaseFinished method
|
|
163
|
+
const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
|
|
164
|
+
return result;
|
|
106
165
|
}
|
|
107
166
|
// case "hook": { break} // After Hook
|
|
108
167
|
case 'testRunFinished': {
|
|
109
168
|
const testRunFinished = envelope[type];
|
|
110
|
-
this.onTestRunFinished(testRunFinished);
|
|
169
|
+
await this.onTestRunFinished(testRunFinished);
|
|
111
170
|
break;
|
|
112
171
|
}
|
|
113
172
|
// case "parameterType" : { break}
|
|
@@ -238,6 +297,10 @@ class ReportGenerator {
|
|
|
238
297
|
result: {
|
|
239
298
|
status: 'UNKNOWN',
|
|
240
299
|
},
|
|
300
|
+
networkData: [],
|
|
301
|
+
webLog: [],
|
|
302
|
+
data: {},
|
|
303
|
+
ariaSnapshot: this.ariaSnapshot,
|
|
241
304
|
});
|
|
242
305
|
return this.stepReportMap.get(pickleStep.id);
|
|
243
306
|
});
|
|
@@ -280,6 +343,14 @@ class ReportGenerator {
|
|
|
280
343
|
this.reportFolder = body.replaceAll('\\', '/');
|
|
281
344
|
return;
|
|
282
345
|
}
|
|
346
|
+
if (mediaType === 'application/json+snapshot-before') {
|
|
347
|
+
this.initialAriaSnapshot = body;
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (mediaType === 'application/json+snapshot-after') {
|
|
351
|
+
this.ariaSnapshot = body;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
283
354
|
if (mediaType === 'application/json+env') {
|
|
284
355
|
const data = JSON.parse(body);
|
|
285
356
|
this.report.env = data;
|
|
@@ -290,13 +361,16 @@ class ReportGenerator {
|
|
|
290
361
|
}
|
|
291
362
|
if (mediaType === 'application/json+log') {
|
|
292
363
|
const log = JSON.parse(body);
|
|
293
|
-
if (this.logs.length < 1000)
|
|
364
|
+
if (this.logs.length < 1000) {
|
|
294
365
|
this.logs.push(log);
|
|
366
|
+
this.stepLogs.push(log);
|
|
367
|
+
}
|
|
295
368
|
}
|
|
296
369
|
if (mediaType === 'application/json+network') {
|
|
297
370
|
const networkLog = JSON.parse(body);
|
|
298
371
|
if (this.networkLog.length < 1000)
|
|
299
372
|
this.networkLog.push(networkLog);
|
|
373
|
+
this.stepNetworkLogs.push(networkLog);
|
|
300
374
|
}
|
|
301
375
|
const testStep = this.testStepMap.get(testStepId);
|
|
302
376
|
if (testStep.pickleStepId === undefined)
|
|
@@ -306,16 +380,100 @@ class ReportGenerator {
|
|
|
306
380
|
const command = JSON.parse(body);
|
|
307
381
|
stepProgess.commands.push(command);
|
|
308
382
|
}
|
|
383
|
+
else if (mediaType === 'application/json+trace') {
|
|
384
|
+
const data = JSON.parse(body);
|
|
385
|
+
stepProgess.traceFilePath = data.traceFilePath;
|
|
386
|
+
}
|
|
387
|
+
if (mediaType === 'application/json+bruno') {
|
|
388
|
+
try {
|
|
389
|
+
const data = JSON.parse(body);
|
|
390
|
+
stepProgess.brunoData = data;
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
console.error('Error parsing bruno data:', error);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (mediaType === 'application/json+intercept-results') {
|
|
397
|
+
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
|
+
};
|
|
309
423
|
}
|
|
310
424
|
onTestStepFinished(testStepFinished) {
|
|
311
425
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
312
426
|
const testStep = this.testStepMap.get(testStepId);
|
|
313
427
|
if (testStep.pickleStepId === undefined) {
|
|
314
428
|
if (testStepResult.status === 'FAILED') {
|
|
429
|
+
const testCase = this.testCaseReportMap.get(testStepFinished.testCaseStartedId);
|
|
430
|
+
const type = testCase.steps[0].result.status === 'UNKNOWN' ? 'Before' : 'After';
|
|
431
|
+
const hookStep = {
|
|
432
|
+
ariaSnapshot: null,
|
|
433
|
+
commands: [],
|
|
434
|
+
keyword: type,
|
|
435
|
+
data: {},
|
|
436
|
+
networkData: [],
|
|
437
|
+
result: {
|
|
438
|
+
status: 'FAILED',
|
|
439
|
+
message: testStepResult.message,
|
|
440
|
+
startTime: this.getTimeStamp(timestamp),
|
|
441
|
+
endTime: this.getTimeStamp(timestamp),
|
|
442
|
+
},
|
|
443
|
+
text: 'Failed hook',
|
|
444
|
+
type,
|
|
445
|
+
webLog: [],
|
|
446
|
+
};
|
|
447
|
+
if (type === 'Before') {
|
|
448
|
+
testCase.steps = [hookStep, ...testCase.steps];
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
testCase.steps = [...testCase.steps, hookStep];
|
|
452
|
+
}
|
|
453
|
+
this.testCaseReportMap.set(testStepFinished.testCaseStartedId, testCase);
|
|
315
454
|
console.error(`Before/After hook failed with message: ${testStepResult.message}`);
|
|
316
455
|
}
|
|
317
456
|
return;
|
|
318
457
|
}
|
|
458
|
+
if (testStepResult.status === 'UNDEFINED') {
|
|
459
|
+
const step = this.stepReportMap.get(testStep.pickleStepId);
|
|
460
|
+
const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
|
|
461
|
+
const undefinedCommand = {
|
|
462
|
+
testStepId: testStepId,
|
|
463
|
+
body: JSON.stringify({
|
|
464
|
+
type: 'error',
|
|
465
|
+
text: 'Undefined step: ' + stepName,
|
|
466
|
+
result: {
|
|
467
|
+
status: 'FAILED',
|
|
468
|
+
startTime: this.getTimeStamp(timestamp),
|
|
469
|
+
endTime: this.getTimeStamp(timestamp),
|
|
470
|
+
},
|
|
471
|
+
}),
|
|
472
|
+
mediaType: 'application/json',
|
|
473
|
+
contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
|
|
474
|
+
};
|
|
475
|
+
this.onAttachment(undefinedCommand);
|
|
476
|
+
}
|
|
319
477
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
320
478
|
const prevStepResult = stepProgess.result;
|
|
321
479
|
let data = {};
|
|
@@ -331,16 +489,73 @@ class ReportGenerator {
|
|
|
331
489
|
catch (error) {
|
|
332
490
|
console.log('Error reading data.json');
|
|
333
491
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
492
|
+
if (testStepResult.status === 'FAILED') {
|
|
493
|
+
stepProgess.result = this.getFailedTestStepResult({
|
|
494
|
+
commands: stepProgess.commands,
|
|
495
|
+
startTime: prevStepResult.startTime,
|
|
496
|
+
endTime: this.getTimeStamp(timestamp),
|
|
497
|
+
result: testStepResult,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
stepProgess.result = {
|
|
502
|
+
status: testStepResult.status,
|
|
503
|
+
startTime: prevStepResult.startTime,
|
|
504
|
+
endTime: this.getTimeStamp(timestamp),
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
stepProgess.webLog = this.stepLogs;
|
|
508
|
+
stepProgess.networkData = this.stepNetworkLogs;
|
|
509
|
+
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
510
|
+
this.ariaSnapshot = '';
|
|
511
|
+
this.stepNetworkLogs = [];
|
|
512
|
+
this.stepLogs = [];
|
|
341
513
|
if (Object.keys(data).length > 0) {
|
|
342
514
|
stepProgess.data = data;
|
|
515
|
+
const id = testStepFinished.testCaseStartedId;
|
|
516
|
+
const parameters = this.testCaseReportMap.get(id).parameters;
|
|
517
|
+
const _parameters = {};
|
|
518
|
+
Object.keys(parameters).map((key) => {
|
|
519
|
+
var _a;
|
|
520
|
+
if (parameters[key].startsWith('{{') &&
|
|
521
|
+
parameters[key].endsWith('}}')) {
|
|
522
|
+
const path = parameters[key].slice(2, -2).split('.');
|
|
523
|
+
let value = String((_a = object_path_1.default.get(data, path)) !== null && _a !== void 0 ? _a : parameters[key]);
|
|
524
|
+
if (value) {
|
|
525
|
+
if (value.startsWith('secret:')) {
|
|
526
|
+
value = 'secret:****';
|
|
527
|
+
}
|
|
528
|
+
else if (value.startsWith('totp:')) {
|
|
529
|
+
value = 'totp:****';
|
|
530
|
+
}
|
|
531
|
+
else if (value.startsWith('mask:')) {
|
|
532
|
+
value = 'mask:****';
|
|
533
|
+
}
|
|
534
|
+
_parameters[key] = value;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
_parameters[key] = parameters[key];
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
this.report.testCases.find((testCase) => {
|
|
542
|
+
return testCase.id === id;
|
|
543
|
+
}).parameters = _parameters;
|
|
343
544
|
}
|
|
545
|
+
// if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
546
|
+
// this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
|
|
547
|
+
// if (!fs.existsSync(this.reportFolder)) {
|
|
548
|
+
// fs.mkdirSync(this.reportFolder)
|
|
549
|
+
// }
|
|
550
|
+
// const reportFilePath = path.join(
|
|
551
|
+
// this.reportFolder,
|
|
552
|
+
// `report.json`
|
|
553
|
+
// )
|
|
554
|
+
// writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
|
|
555
|
+
// return undefined
|
|
556
|
+
// // } else {
|
|
557
|
+
// // return await this.uploadTestCase(testProgress, reRunId)
|
|
558
|
+
// }
|
|
344
559
|
}
|
|
345
560
|
getLogFileContent() {
|
|
346
561
|
let projectPath = process.cwd();
|
|
@@ -367,6 +582,12 @@ class ReportGenerator {
|
|
|
367
582
|
}
|
|
368
583
|
}
|
|
369
584
|
getTestCaseResult(steps) {
|
|
585
|
+
if (steps[0] && steps[0].result.status === 'SKIPPED') {
|
|
586
|
+
return {
|
|
587
|
+
status: 'FAILED',
|
|
588
|
+
message: 'Test skipped due to failure in before hooks',
|
|
589
|
+
};
|
|
590
|
+
}
|
|
370
591
|
for (const step of steps) {
|
|
371
592
|
switch (step.result.status) {
|
|
372
593
|
case 'FAILED':
|
|
@@ -388,24 +609,76 @@ class ReportGenerator {
|
|
|
388
609
|
status: 'PASSED',
|
|
389
610
|
};
|
|
390
611
|
}
|
|
391
|
-
async onTestCaseFinished(testCaseFinished) {
|
|
612
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
392
613
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
393
614
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
394
615
|
const prevResult = testProgress.result;
|
|
395
616
|
const steps = Object.values(testProgress.steps);
|
|
396
617
|
const result = this.getTestCaseResult(steps);
|
|
618
|
+
if (result.status === 'PASSED' && reRunId) {
|
|
619
|
+
this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
|
|
620
|
+
}
|
|
621
|
+
const endTime = this.getTimeStamp(timestamp);
|
|
397
622
|
testProgress.result = {
|
|
398
623
|
...result,
|
|
399
624
|
startTime: prevResult.startTime,
|
|
400
|
-
endTime
|
|
625
|
+
endTime,
|
|
401
626
|
};
|
|
402
627
|
testProgress.webLog = this.logs;
|
|
403
628
|
testProgress.networkLog = this.networkLog;
|
|
629
|
+
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
630
|
+
this.initialAriaSnapshot = '';
|
|
404
631
|
this.networkLog = [];
|
|
405
632
|
this.logs = [];
|
|
406
|
-
|
|
633
|
+
if (this.testCaseLog &&
|
|
634
|
+
this.testCaseLog.length > 0 &&
|
|
635
|
+
!testProgress.logFileId) {
|
|
636
|
+
// Create the logs directory
|
|
637
|
+
const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
|
|
638
|
+
const fileName = `testCaseLog_${testCaseStartedId}.log`;
|
|
639
|
+
const filePath = path_1.default.join(logsDir, fileName);
|
|
640
|
+
// Ensure the logs directory exists
|
|
641
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
642
|
+
// Write the logs to the file
|
|
643
|
+
fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
|
|
644
|
+
// Store this ID in the testProgress object so it can be accessed later
|
|
645
|
+
testProgress.logFileId = testCaseStartedId;
|
|
646
|
+
}
|
|
647
|
+
this.testCaseLog = [];
|
|
648
|
+
if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
649
|
+
this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
650
|
+
if (!fs_1.default.existsSync(this.reportFolder)) {
|
|
651
|
+
fs_1.default.mkdirSync(this.reportFolder);
|
|
652
|
+
}
|
|
653
|
+
const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
|
|
654
|
+
(0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
|
|
655
|
+
return undefined;
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
return await this.uploadTestCase(testProgress, reRunId);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
async uploadTestCase(testCase, rerunId) {
|
|
662
|
+
let data = null;
|
|
663
|
+
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
|
|
664
|
+
try {
|
|
665
|
+
data = await this.tryUpload(testCase, rerunId);
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
catch (e) {
|
|
669
|
+
console.error(`Attempt ${attempt} to upload testcase failed:`, e);
|
|
670
|
+
if (attempt === this.retryCount) {
|
|
671
|
+
console.error('All retry attempts failed, failed to upload testcase.');
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
|
|
675
|
+
await new Promise((r) => setTimeout(r, waitTime));
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
return data;
|
|
407
680
|
}
|
|
408
|
-
async
|
|
681
|
+
async tryUpload(testCase, rerunId) {
|
|
409
682
|
let runId = '';
|
|
410
683
|
let projectId = '';
|
|
411
684
|
if (!process.env.UPLOADING_TEST_CASE) {
|
|
@@ -416,7 +689,9 @@ class ReportGenerator {
|
|
|
416
689
|
anyRemArr.push(randomID);
|
|
417
690
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
418
691
|
try {
|
|
419
|
-
if (process.env.RUN_ID &&
|
|
692
|
+
if (process.env.RUN_ID &&
|
|
693
|
+
process.env.PROJECT_ID &&
|
|
694
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
420
695
|
runId = process.env.RUN_ID;
|
|
421
696
|
projectId = process.env.PROJECT_ID;
|
|
422
697
|
}
|
|
@@ -424,13 +699,14 @@ class ReportGenerator {
|
|
|
424
699
|
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
425
700
|
runId = runDoc._id;
|
|
426
701
|
projectId = runDoc.project_id;
|
|
427
|
-
process.env.
|
|
428
|
-
|
|
702
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
703
|
+
process.env.RUN_ID = runId;
|
|
704
|
+
process.env.PROJECT_ID = projectId;
|
|
705
|
+
}
|
|
429
706
|
}
|
|
430
|
-
await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
console.error('Error uploading test case:', e);
|
|
707
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
708
|
+
this.writeTestCaseReportToDisk(testCase);
|
|
709
|
+
return data;
|
|
434
710
|
}
|
|
435
711
|
finally {
|
|
436
712
|
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
@@ -438,7 +714,30 @@ class ReportGenerator {
|
|
|
438
714
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
439
715
|
}
|
|
440
716
|
}
|
|
441
|
-
|
|
717
|
+
writeTestCaseReportToDisk(testCase) {
|
|
718
|
+
var _a;
|
|
719
|
+
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
720
|
+
if (!reportFolder) {
|
|
721
|
+
console.error('Report folder is not defined');
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
try {
|
|
725
|
+
let i = 0;
|
|
726
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
727
|
+
i++;
|
|
728
|
+
}
|
|
729
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
730
|
+
//exclude network log from the saved report
|
|
731
|
+
const networkLog = testCase.networkLog;
|
|
732
|
+
delete testCase.networkLog;
|
|
733
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
|
|
734
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
735
|
+
}
|
|
736
|
+
catch (error) {
|
|
737
|
+
console.error('Error writing test case report to disk:', error);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
async onTestRunFinished(testRunFinished) {
|
|
442
741
|
const { timestamp, success, message } = testRunFinished;
|
|
443
742
|
const prevResult = this.report.result;
|
|
444
743
|
this.report.result = {
|
|
@@ -448,6 +747,7 @@ class ReportGenerator {
|
|
|
448
747
|
message,
|
|
449
748
|
// exception,
|
|
450
749
|
};
|
|
750
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
451
751
|
}
|
|
452
752
|
}
|
|
453
753
|
exports.default = ReportGenerator;
|