@dev-blinq/cucumber-js 1.0.102-dev → 1.0.102-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/cucumber.ts +1 -0
- package/bin/download-install.js +22 -2
- package/lib/api/console_logger.js.map +1 -1
- package/lib/cli/validate_node_engine_version.js +3 -1
- package/lib/cli/validate_node_engine_version.js.map +1 -1
- package/lib/configuration/axios_client.js +1 -1
- package/lib/configuration/axios_client.js.map +1 -1
- package/lib/formatter/api.js +16 -5
- package/lib/formatter/api.js.map +1 -1
- package/lib/formatter/builder.js +1 -3
- package/lib/formatter/builder.js.map +1 -1
- package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
- package/lib/formatter/bvt_analysis_formatter.js +202 -78
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +12 -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 +32 -2
- package/lib/formatter/helpers/report_generator.js +348 -15
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
- package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +16 -0
- package/lib/formatter/helpers/upload_serivce.js +166 -0
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.d.ts +2 -1
- package/lib/formatter/helpers/uploader.js +17 -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/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,10 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
28
|
+
var _a, _b;
|
|
5
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
const messages = __importStar(require("@cucumber/messages"));
|
|
6
31
|
const fs_1 = __importDefault(require("fs"));
|
|
7
32
|
const path_1 = __importDefault(require("path"));
|
|
33
|
+
const upload_serivce_1 = require("./upload_serivce");
|
|
34
|
+
const fs_extra_1 = require("fs-extra");
|
|
35
|
+
// type JsonException = messages.Exception
|
|
36
|
+
const object_path_1 = __importDefault(require("object-path"));
|
|
37
|
+
const URL = process.env.NODE_ENV_BLINQ === 'dev'
|
|
38
|
+
? 'https://dev.api.blinq.io/api/runs'
|
|
39
|
+
: process.env.NODE_ENV_BLINQ === 'local'
|
|
40
|
+
? 'http://localhost:5001/api/runs'
|
|
41
|
+
: process.env.NODE_ENV_BLINQ === 'stage'
|
|
42
|
+
? 'https://stage.api.blinq.io/api/runs'
|
|
43
|
+
: process.env.NODE_ENV_BLINQ === 'prod'
|
|
44
|
+
? 'https://api.blinq.io/api/runs'
|
|
45
|
+
: !process.env.NODE_ENV_BLINQ
|
|
46
|
+
? 'https://api.blinq.io/api/runs'
|
|
47
|
+
: `${process.env.NODE_ENV_BLINQ}/api/runs`;
|
|
48
|
+
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
49
|
+
const BATCH_SIZE = 10;
|
|
50
|
+
const MAX_RETRIES = 3;
|
|
51
|
+
const REPORT_SERVICE_TOKEN = (_b = process.env.TOKEN) !== null && _b !== void 0 ? _b : process.env.REPORT_SERVICE_TOKEN;
|
|
8
52
|
class ReportGenerator {
|
|
9
53
|
constructor() {
|
|
10
54
|
this.report = {
|
|
@@ -27,9 +71,21 @@ class ReportGenerator {
|
|
|
27
71
|
this.scenarioIterationCountMap = new Map();
|
|
28
72
|
this.logs = [];
|
|
29
73
|
this.networkLog = [];
|
|
74
|
+
this.stepLogs = [];
|
|
75
|
+
this.stepNetworkLogs = [];
|
|
76
|
+
this.runName = '';
|
|
77
|
+
this.ariaSnapshot = '';
|
|
78
|
+
this.initialAriaSnapshot = '';
|
|
79
|
+
this.testCaseLog = [];
|
|
80
|
+
this.loggingOverridden = false; // Flag to track if logging is overridden
|
|
30
81
|
this.reportFolder = null;
|
|
82
|
+
this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
|
|
83
|
+
this.retryCount = 3;
|
|
31
84
|
}
|
|
32
|
-
handleMessage(envelope) {
|
|
85
|
+
async handleMessage(envelope, reRunId) {
|
|
86
|
+
if (envelope.meta && 'runName' in envelope.meta) {
|
|
87
|
+
this.runName = envelope.meta.runName;
|
|
88
|
+
}
|
|
33
89
|
const type = Object.keys(envelope)[0];
|
|
34
90
|
switch (type) {
|
|
35
91
|
// case "meta": { break}
|
|
@@ -54,10 +110,30 @@ class ReportGenerator {
|
|
|
54
110
|
case 'testRunStarted': {
|
|
55
111
|
const testRunStarted = envelope[type];
|
|
56
112
|
this.onTestRunStarted(testRunStarted);
|
|
113
|
+
await this.uploadService.createStatus('running');
|
|
57
114
|
break;
|
|
58
115
|
}
|
|
59
116
|
case 'testCase': {
|
|
60
117
|
const testCase = envelope[type];
|
|
118
|
+
// Initialize the log storage
|
|
119
|
+
this.testCaseLog = [];
|
|
120
|
+
if (!this.loggingOverridden) {
|
|
121
|
+
this.loggingOverridden = true;
|
|
122
|
+
// Store the original process.stdout.write, and process.stderr.write
|
|
123
|
+
const originalStdoutWrite = process.stdout.write;
|
|
124
|
+
const originalStderrWrite = process.stderr.write;
|
|
125
|
+
// Override process.stdout.write
|
|
126
|
+
process.stdout.write = (chunk, ...args) => {
|
|
127
|
+
this.testCaseLog.push(chunk.toString());
|
|
128
|
+
return originalStdoutWrite.call(process.stdout, chunk, ...args);
|
|
129
|
+
};
|
|
130
|
+
// Override process.stderr.write
|
|
131
|
+
process.stderr.write = (chunk, ...args) => {
|
|
132
|
+
this.testCaseLog.push(chunk.toString());
|
|
133
|
+
return originalStderrWrite.call(process.stderr, chunk, ...args);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Call the onTestCase method
|
|
61
137
|
this.onTestCase(testCase);
|
|
62
138
|
break;
|
|
63
139
|
}
|
|
@@ -83,13 +159,14 @@ class ReportGenerator {
|
|
|
83
159
|
}
|
|
84
160
|
case 'testCaseFinished': {
|
|
85
161
|
const testCaseFinished = envelope[type];
|
|
86
|
-
|
|
87
|
-
|
|
162
|
+
// Call the onTestCaseFinished method
|
|
163
|
+
const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
|
|
164
|
+
return result;
|
|
88
165
|
}
|
|
89
166
|
// case "hook": { break} // After Hook
|
|
90
167
|
case 'testRunFinished': {
|
|
91
168
|
const testRunFinished = envelope[type];
|
|
92
|
-
this.onTestRunFinished(testRunFinished);
|
|
169
|
+
await this.onTestRunFinished(testRunFinished);
|
|
93
170
|
break;
|
|
94
171
|
}
|
|
95
172
|
// case "parameterType" : { break}
|
|
@@ -220,6 +297,10 @@ class ReportGenerator {
|
|
|
220
297
|
result: {
|
|
221
298
|
status: 'UNKNOWN',
|
|
222
299
|
},
|
|
300
|
+
networkData: [],
|
|
301
|
+
webLog: [],
|
|
302
|
+
data: {},
|
|
303
|
+
ariaSnapshot: this.ariaSnapshot,
|
|
223
304
|
});
|
|
224
305
|
return this.stepReportMap.get(pickleStep.id);
|
|
225
306
|
});
|
|
@@ -236,6 +317,10 @@ class ReportGenerator {
|
|
|
236
317
|
},
|
|
237
318
|
webLog: [],
|
|
238
319
|
networkLog: [],
|
|
320
|
+
env: {
|
|
321
|
+
name: this.report.env.name,
|
|
322
|
+
baseUrl: this.report.env.baseUrl,
|
|
323
|
+
},
|
|
239
324
|
});
|
|
240
325
|
this.report.testCases.push(this.testCaseReportMap.get(id));
|
|
241
326
|
}
|
|
@@ -258,19 +343,34 @@ class ReportGenerator {
|
|
|
258
343
|
this.reportFolder = body.replaceAll('\\', '/');
|
|
259
344
|
return;
|
|
260
345
|
}
|
|
346
|
+
if (mediaType === 'application/json+snapshot-before') {
|
|
347
|
+
this.initialAriaSnapshot = body;
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (mediaType === 'application/json+snapshot-after') {
|
|
351
|
+
this.ariaSnapshot = body;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
261
354
|
if (mediaType === 'application/json+env') {
|
|
262
355
|
const data = JSON.parse(body);
|
|
263
356
|
this.report.env = data;
|
|
357
|
+
this.report.testCases.map((testCase) => {
|
|
358
|
+
testCase.env = data;
|
|
359
|
+
return testCase;
|
|
360
|
+
});
|
|
264
361
|
}
|
|
265
362
|
if (mediaType === 'application/json+log') {
|
|
266
363
|
const log = JSON.parse(body);
|
|
267
|
-
if (this.logs.length < 1000)
|
|
364
|
+
if (this.logs.length < 1000) {
|
|
268
365
|
this.logs.push(log);
|
|
366
|
+
this.stepLogs.push(log);
|
|
367
|
+
}
|
|
269
368
|
}
|
|
270
369
|
if (mediaType === 'application/json+network') {
|
|
271
370
|
const networkLog = JSON.parse(body);
|
|
272
371
|
if (this.networkLog.length < 1000)
|
|
273
372
|
this.networkLog.push(networkLog);
|
|
373
|
+
this.stepNetworkLogs.push(networkLog);
|
|
274
374
|
}
|
|
275
375
|
const testStep = this.testStepMap.get(testStepId);
|
|
276
376
|
if (testStep.pickleStepId === undefined)
|
|
@@ -280,6 +380,46 @@ class ReportGenerator {
|
|
|
280
380
|
const command = JSON.parse(body);
|
|
281
381
|
stepProgess.commands.push(command);
|
|
282
382
|
}
|
|
383
|
+
else if (mediaType === 'application/json+trace') {
|
|
384
|
+
const data = JSON.parse(body);
|
|
385
|
+
stepProgess.traceFilePath = data.traceFilePath;
|
|
386
|
+
}
|
|
387
|
+
if (mediaType === 'application/json+bruno') {
|
|
388
|
+
try {
|
|
389
|
+
const data = JSON.parse(body);
|
|
390
|
+
stepProgess.brunoData = data;
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
console.error('Error parsing bruno data:', error);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (mediaType === 'application/json+intercept-results') {
|
|
397
|
+
try {
|
|
398
|
+
const data = JSON.parse(body);
|
|
399
|
+
stepProgess.interceptResults = data;
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
console.error('Error parsing intercept results:', error);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
getFailedTestStepResult({ commands, startTime, endTime, result, }) {
|
|
407
|
+
for (const command of commands) {
|
|
408
|
+
if (command.result.status === 'FAILED') {
|
|
409
|
+
return {
|
|
410
|
+
status: 'FAILED',
|
|
411
|
+
message: command.result.message,
|
|
412
|
+
startTime,
|
|
413
|
+
endTime,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
status: 'FAILED',
|
|
419
|
+
startTime,
|
|
420
|
+
endTime,
|
|
421
|
+
message: result.message,
|
|
422
|
+
};
|
|
283
423
|
}
|
|
284
424
|
onTestStepFinished(testStepFinished) {
|
|
285
425
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
@@ -290,6 +430,25 @@ class ReportGenerator {
|
|
|
290
430
|
}
|
|
291
431
|
return;
|
|
292
432
|
}
|
|
433
|
+
if (testStepResult.status === 'UNDEFINED') {
|
|
434
|
+
const step = this.stepReportMap.get(testStep.pickleStepId);
|
|
435
|
+
const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
|
|
436
|
+
const undefinedCommand = {
|
|
437
|
+
testStepId: testStepId,
|
|
438
|
+
body: JSON.stringify({
|
|
439
|
+
type: 'error',
|
|
440
|
+
text: 'Undefined step: ' + stepName,
|
|
441
|
+
result: {
|
|
442
|
+
status: 'FAILED',
|
|
443
|
+
startTime: this.getTimeStamp(timestamp),
|
|
444
|
+
endTime: this.getTimeStamp(timestamp),
|
|
445
|
+
},
|
|
446
|
+
}),
|
|
447
|
+
mediaType: 'application/json',
|
|
448
|
+
contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
|
|
449
|
+
};
|
|
450
|
+
this.onAttachment(undefinedCommand);
|
|
451
|
+
}
|
|
293
452
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
294
453
|
const prevStepResult = stepProgess.result;
|
|
295
454
|
let data = {};
|
|
@@ -305,16 +464,73 @@ class ReportGenerator {
|
|
|
305
464
|
catch (error) {
|
|
306
465
|
console.log('Error reading data.json');
|
|
307
466
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
467
|
+
if (testStepResult.status === 'FAILED') {
|
|
468
|
+
stepProgess.result = this.getFailedTestStepResult({
|
|
469
|
+
commands: stepProgess.commands,
|
|
470
|
+
startTime: prevStepResult.startTime,
|
|
471
|
+
endTime: this.getTimeStamp(timestamp),
|
|
472
|
+
result: testStepResult,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
stepProgess.result = {
|
|
477
|
+
status: testStepResult.status,
|
|
478
|
+
startTime: prevStepResult.startTime,
|
|
479
|
+
endTime: this.getTimeStamp(timestamp),
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
stepProgess.webLog = this.stepLogs;
|
|
483
|
+
stepProgess.networkData = this.stepNetworkLogs;
|
|
484
|
+
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
485
|
+
this.ariaSnapshot = '';
|
|
486
|
+
this.stepNetworkLogs = [];
|
|
487
|
+
this.stepLogs = [];
|
|
315
488
|
if (Object.keys(data).length > 0) {
|
|
316
489
|
stepProgess.data = data;
|
|
490
|
+
const id = testStepFinished.testCaseStartedId;
|
|
491
|
+
const parameters = this.testCaseReportMap.get(id).parameters;
|
|
492
|
+
const _parameters = {};
|
|
493
|
+
Object.keys(parameters).map((key) => {
|
|
494
|
+
var _a;
|
|
495
|
+
if (parameters[key].startsWith('{{') &&
|
|
496
|
+
parameters[key].endsWith('}}')) {
|
|
497
|
+
const path = parameters[key].slice(2, -2).split('.');
|
|
498
|
+
let value = String((_a = object_path_1.default.get(data, path)) !== null && _a !== void 0 ? _a : parameters[key]);
|
|
499
|
+
if (value) {
|
|
500
|
+
if (value.startsWith('secret:')) {
|
|
501
|
+
value = 'secret:****';
|
|
502
|
+
}
|
|
503
|
+
else if (value.startsWith('totp:')) {
|
|
504
|
+
value = 'totp:****';
|
|
505
|
+
}
|
|
506
|
+
else if (value.startsWith('mask:')) {
|
|
507
|
+
value = 'mask:****';
|
|
508
|
+
}
|
|
509
|
+
_parameters[key] = value;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
_parameters[key] = parameters[key];
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
this.report.testCases.find((testCase) => {
|
|
517
|
+
return testCase.id === id;
|
|
518
|
+
}).parameters = _parameters;
|
|
317
519
|
}
|
|
520
|
+
// if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
521
|
+
// this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH
|
|
522
|
+
// if (!fs.existsSync(this.reportFolder)) {
|
|
523
|
+
// fs.mkdirSync(this.reportFolder)
|
|
524
|
+
// }
|
|
525
|
+
// const reportFilePath = path.join(
|
|
526
|
+
// this.reportFolder,
|
|
527
|
+
// `report.json`
|
|
528
|
+
// )
|
|
529
|
+
// writeFileSync(reportFilePath, JSON.stringify(this.report, null, 2))
|
|
530
|
+
// return undefined
|
|
531
|
+
// // } else {
|
|
532
|
+
// // return await this.uploadTestCase(testProgress, reRunId)
|
|
533
|
+
// }
|
|
318
534
|
}
|
|
319
535
|
getLogFileContent() {
|
|
320
536
|
let projectPath = process.cwd();
|
|
@@ -341,6 +557,12 @@ class ReportGenerator {
|
|
|
341
557
|
}
|
|
342
558
|
}
|
|
343
559
|
getTestCaseResult(steps) {
|
|
560
|
+
if (steps[0] && steps[0].result.status === 'SKIPPED') {
|
|
561
|
+
return {
|
|
562
|
+
status: 'FAILED',
|
|
563
|
+
message: 'Test skipped due to failure in before hooks',
|
|
564
|
+
};
|
|
565
|
+
}
|
|
344
566
|
for (const step of steps) {
|
|
345
567
|
switch (step.result.status) {
|
|
346
568
|
case 'FAILED':
|
|
@@ -362,23 +584,133 @@ class ReportGenerator {
|
|
|
362
584
|
status: 'PASSED',
|
|
363
585
|
};
|
|
364
586
|
}
|
|
365
|
-
onTestCaseFinished(testCaseFinished) {
|
|
587
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
366
588
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
367
589
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
368
590
|
const prevResult = testProgress.result;
|
|
369
591
|
const steps = Object.values(testProgress.steps);
|
|
370
592
|
const result = this.getTestCaseResult(steps);
|
|
593
|
+
if (result.status === 'PASSED' && reRunId) {
|
|
594
|
+
this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
|
|
595
|
+
}
|
|
596
|
+
const endTime = this.getTimeStamp(timestamp);
|
|
371
597
|
testProgress.result = {
|
|
372
598
|
...result,
|
|
373
599
|
startTime: prevResult.startTime,
|
|
374
|
-
endTime
|
|
600
|
+
endTime,
|
|
375
601
|
};
|
|
376
602
|
testProgress.webLog = this.logs;
|
|
377
603
|
testProgress.networkLog = this.networkLog;
|
|
604
|
+
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
605
|
+
this.initialAriaSnapshot = '';
|
|
378
606
|
this.networkLog = [];
|
|
379
607
|
this.logs = [];
|
|
608
|
+
if (this.testCaseLog && this.testCaseLog.length > 0) {
|
|
609
|
+
// Create the logs directory
|
|
610
|
+
const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
|
|
611
|
+
const fileName = `testCaseLog_${testCaseStartedId}.log`;
|
|
612
|
+
const filePath = path_1.default.join(logsDir, fileName);
|
|
613
|
+
// Ensure the logs directory exists
|
|
614
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
615
|
+
// Write the logs to the file
|
|
616
|
+
fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
|
|
617
|
+
// Store this ID in the testProgress object so it can be accessed later
|
|
618
|
+
testProgress.logFileId = testCaseStartedId;
|
|
619
|
+
}
|
|
620
|
+
this.testCaseLog = [];
|
|
621
|
+
if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
622
|
+
this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
623
|
+
if (!fs_1.default.existsSync(this.reportFolder)) {
|
|
624
|
+
fs_1.default.mkdirSync(this.reportFolder);
|
|
625
|
+
}
|
|
626
|
+
const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
|
|
627
|
+
(0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
|
|
628
|
+
return undefined;
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
return await this.uploadTestCase(testProgress, reRunId);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
async uploadTestCase(testCase, rerunId) {
|
|
635
|
+
let data = null;
|
|
636
|
+
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
|
|
637
|
+
try {
|
|
638
|
+
data = await this.tryUpload(testCase, rerunId);
|
|
639
|
+
break;
|
|
640
|
+
}
|
|
641
|
+
catch (e) {
|
|
642
|
+
console.error(`Attempt ${attempt} to upload testcase failed:`, e);
|
|
643
|
+
if (attempt === this.retryCount) {
|
|
644
|
+
console.error('All retry attempts failed, failed to upload testcase.');
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
|
|
648
|
+
await new Promise((r) => setTimeout(r, waitTime));
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return data;
|
|
653
|
+
}
|
|
654
|
+
async tryUpload(testCase, rerunId) {
|
|
655
|
+
let runId = '';
|
|
656
|
+
let projectId = '';
|
|
657
|
+
if (!process.env.UPLOADING_TEST_CASE) {
|
|
658
|
+
process.env.UPLOADING_TEST_CASE = '[]';
|
|
659
|
+
}
|
|
660
|
+
const anyRemArr = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
661
|
+
const randomID = Math.random().toString(36).substring(7);
|
|
662
|
+
anyRemArr.push(randomID);
|
|
663
|
+
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
664
|
+
try {
|
|
665
|
+
if (process.env.RUN_ID &&
|
|
666
|
+
process.env.PROJECT_ID &&
|
|
667
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
668
|
+
runId = process.env.RUN_ID;
|
|
669
|
+
projectId = process.env.PROJECT_ID;
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
673
|
+
runId = runDoc._id;
|
|
674
|
+
projectId = runDoc.project_id;
|
|
675
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
676
|
+
process.env.RUN_ID = runId;
|
|
677
|
+
process.env.PROJECT_ID = projectId;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
681
|
+
this.writeTestCaseReportToDisk(testCase);
|
|
682
|
+
return data;
|
|
683
|
+
}
|
|
684
|
+
finally {
|
|
685
|
+
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
686
|
+
arrRem.splice(arrRem.indexOf(randomID), 1);
|
|
687
|
+
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
writeTestCaseReportToDisk(testCase) {
|
|
691
|
+
var _a;
|
|
692
|
+
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
693
|
+
if (!reportFolder) {
|
|
694
|
+
console.error('Report folder is not defined');
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
try {
|
|
698
|
+
let i = 0;
|
|
699
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
700
|
+
i++;
|
|
701
|
+
}
|
|
702
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
703
|
+
//exclude network log from the saved report
|
|
704
|
+
const networkLog = testCase.networkLog;
|
|
705
|
+
delete testCase.networkLog;
|
|
706
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
|
|
707
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
708
|
+
}
|
|
709
|
+
catch (error) {
|
|
710
|
+
console.error('Error writing test case report to disk:', error);
|
|
711
|
+
}
|
|
380
712
|
}
|
|
381
|
-
onTestRunFinished(testRunFinished) {
|
|
713
|
+
async onTestRunFinished(testRunFinished) {
|
|
382
714
|
const { timestamp, success, message } = testRunFinished;
|
|
383
715
|
const prevResult = this.report.result;
|
|
384
716
|
this.report.result = {
|
|
@@ -388,6 +720,7 @@ class ReportGenerator {
|
|
|
388
720
|
message,
|
|
389
721
|
// exception,
|
|
390
722
|
};
|
|
723
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
391
724
|
}
|
|
392
725
|
}
|
|
393
726
|
exports.default = ReportGenerator;
|