@dev-blinq/cucumber-js 1.0.128-dev → 1.0.128
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 +12 -1
- package/lib/formatter/bvt_analysis_formatter.js +161 -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 +22 -3
- package/lib/formatter/helpers/report_generator.js +336 -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 +20 -2
- package/lib/formatter/helpers/upload_serivce.js +210 -17
- 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/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,79 @@ 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
|
+
if (process.env.TRACE) {
|
|
637
|
+
testProgress.traceFileId = path_1.default.join(`trace-${testCaseStartedId}.zip`);
|
|
638
|
+
}
|
|
639
|
+
this.initialAriaSnapshot = '';
|
|
404
640
|
this.networkLog = [];
|
|
405
641
|
this.logs = [];
|
|
406
|
-
|
|
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
|
+
}
|
|
407
669
|
}
|
|
408
|
-
async uploadTestCase(testCase) {
|
|
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;
|
|
689
|
+
}
|
|
690
|
+
async tryUpload(testCase, rerunId) {
|
|
409
691
|
let runId = '';
|
|
410
692
|
let projectId = '';
|
|
411
693
|
if (!process.env.UPLOADING_TEST_CASE) {
|
|
@@ -416,21 +698,24 @@ class ReportGenerator {
|
|
|
416
698
|
anyRemArr.push(randomID);
|
|
417
699
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
418
700
|
try {
|
|
419
|
-
if (process.env.RUN_ID &&
|
|
701
|
+
if (process.env.RUN_ID &&
|
|
702
|
+
process.env.PROJECT_ID &&
|
|
703
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
420
704
|
runId = process.env.RUN_ID;
|
|
421
705
|
projectId = process.env.PROJECT_ID;
|
|
422
706
|
}
|
|
423
707
|
else {
|
|
424
|
-
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
708
|
+
const runDoc = await this.uploadService.createRunDocument(this.runName, testCase.env);
|
|
425
709
|
runId = runDoc._id;
|
|
426
710
|
projectId = runDoc.project_id;
|
|
427
|
-
process.env.
|
|
428
|
-
|
|
711
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
712
|
+
process.env.RUN_ID = runId;
|
|
713
|
+
process.env.PROJECT_ID = projectId;
|
|
714
|
+
}
|
|
429
715
|
}
|
|
430
|
-
await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder);
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
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;
|
|
434
719
|
}
|
|
435
720
|
finally {
|
|
436
721
|
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
@@ -438,7 +723,30 @@ class ReportGenerator {
|
|
|
438
723
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
439
724
|
}
|
|
440
725
|
}
|
|
441
|
-
|
|
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) {
|
|
442
750
|
const { timestamp, success, message } = testRunFinished;
|
|
443
751
|
const prevResult = this.report.result;
|
|
444
752
|
this.report.result = {
|
|
@@ -448,6 +756,7 @@ class ReportGenerator {
|
|
|
448
756
|
message,
|
|
449
757
|
// exception,
|
|
450
758
|
};
|
|
759
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
451
760
|
}
|
|
452
761
|
}
|
|
453
762
|
exports.default = ReportGenerator;
|