@dev-blinq/cucumber-js 1.0.88-dev → 1.0.88-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/download-install.js +40 -13
- package/lib/configuration/axios_client.js +1 -1
- package/lib/configuration/axios_client.js.map +1 -1
- package/lib/formatter/api.d.ts +2 -0
- package/lib/formatter/api.js +59 -0
- package/lib/formatter/api.js.map +1 -0
- package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
- package/lib/formatter/bvt_analysis_formatter.js +235 -88
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.js +14 -2
- 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 +33 -2
- package/lib/formatter/helpers/report_generator.js +340 -20
- 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/upload_serivce.d.ts +15 -0
- package/lib/formatter/helpers/upload_serivce.js +173 -13
- 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 +30 -3
- 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 +4 -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,24 @@ 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
|
+
// Add this property to track if we've encountered an undefined step
|
|
83
|
+
this.hasUndefinedStep = false;
|
|
84
|
+
this.currentTestCaseId = null;
|
|
85
|
+
this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
|
|
86
|
+
this.retryCount = 3;
|
|
31
87
|
}
|
|
32
|
-
handleMessage(envelope) {
|
|
88
|
+
async handleMessage(envelope, reRunId) {
|
|
89
|
+
if (envelope.meta && 'runName' in envelope.meta) {
|
|
90
|
+
this.runName = envelope.meta.runName;
|
|
91
|
+
}
|
|
33
92
|
const type = Object.keys(envelope)[0];
|
|
34
93
|
switch (type) {
|
|
35
94
|
// case "meta": { break}
|
|
@@ -54,10 +113,30 @@ class ReportGenerator {
|
|
|
54
113
|
case 'testRunStarted': {
|
|
55
114
|
const testRunStarted = envelope[type];
|
|
56
115
|
this.onTestRunStarted(testRunStarted);
|
|
116
|
+
await this.uploadService.createStatus('running');
|
|
57
117
|
break;
|
|
58
118
|
}
|
|
59
119
|
case 'testCase': {
|
|
60
120
|
const testCase = envelope[type];
|
|
121
|
+
// Initialize the log storage
|
|
122
|
+
this.testCaseLog = [];
|
|
123
|
+
if (!this.loggingOverridden) {
|
|
124
|
+
this.loggingOverridden = true;
|
|
125
|
+
// Store the original process.stdout.write, and process.stderr.write
|
|
126
|
+
const originalStdoutWrite = process.stdout.write;
|
|
127
|
+
const originalStderrWrite = process.stderr.write;
|
|
128
|
+
// Override process.stdout.write
|
|
129
|
+
process.stdout.write = (chunk, ...args) => {
|
|
130
|
+
this.testCaseLog.push(chunk.toString());
|
|
131
|
+
return originalStdoutWrite.call(process.stdout, chunk, ...args);
|
|
132
|
+
};
|
|
133
|
+
// Override process.stderr.write
|
|
134
|
+
process.stderr.write = (chunk, ...args) => {
|
|
135
|
+
this.testCaseLog.push(chunk.toString());
|
|
136
|
+
return originalStderrWrite.call(process.stderr, chunk, ...args);
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// Call the onTestCase method
|
|
61
140
|
this.onTestCase(testCase);
|
|
62
141
|
break;
|
|
63
142
|
}
|
|
@@ -83,13 +162,14 @@ class ReportGenerator {
|
|
|
83
162
|
}
|
|
84
163
|
case 'testCaseFinished': {
|
|
85
164
|
const testCaseFinished = envelope[type];
|
|
86
|
-
|
|
87
|
-
|
|
165
|
+
// Call the onTestCaseFinished method
|
|
166
|
+
const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
|
|
167
|
+
return result;
|
|
88
168
|
}
|
|
89
169
|
// case "hook": { break} // After Hook
|
|
90
170
|
case 'testRunFinished': {
|
|
91
171
|
const testRunFinished = envelope[type];
|
|
92
|
-
this.onTestRunFinished(testRunFinished);
|
|
172
|
+
await this.onTestRunFinished(testRunFinished);
|
|
93
173
|
break;
|
|
94
174
|
}
|
|
95
175
|
// case "parameterType" : { break}
|
|
@@ -188,6 +268,9 @@ class ReportGenerator {
|
|
|
188
268
|
return parameters;
|
|
189
269
|
}
|
|
190
270
|
onTestCaseStarted(testCaseStarted) {
|
|
271
|
+
// Reset the undefined step flag for each new test case
|
|
272
|
+
this.hasUndefinedStep = false;
|
|
273
|
+
this.currentTestCaseId = testCaseStarted.id;
|
|
191
274
|
const { testCaseId, id, timestamp } = testCaseStarted;
|
|
192
275
|
const testCase = this.testCaseMap.get(testCaseId);
|
|
193
276
|
if (testCase === undefined)
|
|
@@ -220,6 +303,10 @@ class ReportGenerator {
|
|
|
220
303
|
result: {
|
|
221
304
|
status: 'UNKNOWN',
|
|
222
305
|
},
|
|
306
|
+
networkData: [],
|
|
307
|
+
webLog: [],
|
|
308
|
+
data: {},
|
|
309
|
+
ariaSnapshot: this.ariaSnapshot,
|
|
223
310
|
});
|
|
224
311
|
return this.stepReportMap.get(pickleStep.id);
|
|
225
312
|
});
|
|
@@ -236,6 +323,10 @@ class ReportGenerator {
|
|
|
236
323
|
},
|
|
237
324
|
webLog: [],
|
|
238
325
|
networkLog: [],
|
|
326
|
+
env: {
|
|
327
|
+
name: this.report.env.name,
|
|
328
|
+
baseUrl: this.report.env.baseUrl,
|
|
329
|
+
},
|
|
239
330
|
});
|
|
240
331
|
this.report.testCases.push(this.testCaseReportMap.get(id));
|
|
241
332
|
}
|
|
@@ -246,8 +337,16 @@ class ReportGenerator {
|
|
|
246
337
|
throw new Error(`testStep with id ${testStepId} not found`);
|
|
247
338
|
if (testStep.pickleStepId === undefined)
|
|
248
339
|
return;
|
|
249
|
-
|
|
250
|
-
|
|
340
|
+
// If we already have an undefined step in this test case, skip remaining steps
|
|
341
|
+
if (this.hasUndefinedStep) {
|
|
342
|
+
const stepProgress = this.stepReportMap.get(testStep.pickleStepId);
|
|
343
|
+
stepProgress.result = {
|
|
344
|
+
status: 'SKIPPED'
|
|
345
|
+
};
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const stepProgress = this.stepReportMap.get(testStep.pickleStepId);
|
|
349
|
+
stepProgress.result = {
|
|
251
350
|
status: 'STARTED',
|
|
252
351
|
startTime: this.getTimeStamp(timestamp),
|
|
253
352
|
};
|
|
@@ -258,19 +357,34 @@ class ReportGenerator {
|
|
|
258
357
|
this.reportFolder = body.replaceAll('\\', '/');
|
|
259
358
|
return;
|
|
260
359
|
}
|
|
360
|
+
if (mediaType === 'application/json+snapshot-before') {
|
|
361
|
+
this.initialAriaSnapshot = body;
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (mediaType === 'application/json+snapshot-after') {
|
|
365
|
+
this.ariaSnapshot = body;
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
261
368
|
if (mediaType === 'application/json+env') {
|
|
262
369
|
const data = JSON.parse(body);
|
|
263
370
|
this.report.env = data;
|
|
371
|
+
this.report.testCases.map((testCase) => {
|
|
372
|
+
testCase.env = data;
|
|
373
|
+
return testCase;
|
|
374
|
+
});
|
|
264
375
|
}
|
|
265
376
|
if (mediaType === 'application/json+log') {
|
|
266
377
|
const log = JSON.parse(body);
|
|
267
|
-
if (this.logs.length < 1000)
|
|
378
|
+
if (this.logs.length < 1000) {
|
|
268
379
|
this.logs.push(log);
|
|
380
|
+
this.stepLogs.push(log);
|
|
381
|
+
}
|
|
269
382
|
}
|
|
270
383
|
if (mediaType === 'application/json+network') {
|
|
271
384
|
const networkLog = JSON.parse(body);
|
|
272
385
|
if (this.networkLog.length < 1000)
|
|
273
386
|
this.networkLog.push(networkLog);
|
|
387
|
+
this.stepNetworkLogs.push(networkLog);
|
|
274
388
|
}
|
|
275
389
|
const testStep = this.testStepMap.get(testStepId);
|
|
276
390
|
if (testStep.pickleStepId === undefined)
|
|
@@ -280,6 +394,37 @@ class ReportGenerator {
|
|
|
280
394
|
const command = JSON.parse(body);
|
|
281
395
|
stepProgess.commands.push(command);
|
|
282
396
|
}
|
|
397
|
+
else if (mediaType === 'application/json+trace') {
|
|
398
|
+
const data = JSON.parse(body);
|
|
399
|
+
stepProgess.traceFilePath = data.traceFilePath;
|
|
400
|
+
}
|
|
401
|
+
if (mediaType === 'application/json+bruno') {
|
|
402
|
+
try {
|
|
403
|
+
const data = JSON.parse(body);
|
|
404
|
+
stepProgess.brunoData = data;
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
console.error('Error parsing bruno data:', error);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
getFailedTestStepResult({ commands, startTime, endTime, result, }) {
|
|
412
|
+
for (const command of commands) {
|
|
413
|
+
if (command.result.status === 'FAILED') {
|
|
414
|
+
return {
|
|
415
|
+
status: 'FAILED',
|
|
416
|
+
message: command.result.message,
|
|
417
|
+
startTime,
|
|
418
|
+
endTime,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return {
|
|
423
|
+
status: 'FAILED',
|
|
424
|
+
startTime,
|
|
425
|
+
endTime,
|
|
426
|
+
message: result.message,
|
|
427
|
+
};
|
|
283
428
|
}
|
|
284
429
|
onTestStepFinished(testStepFinished) {
|
|
285
430
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
@@ -290,8 +435,33 @@ class ReportGenerator {
|
|
|
290
435
|
}
|
|
291
436
|
return;
|
|
292
437
|
}
|
|
293
|
-
const
|
|
294
|
-
|
|
438
|
+
const stepProgress = this.stepReportMap.get(testStep.pickleStepId);
|
|
439
|
+
// If this step was skipped due to previous undefined step, don't process it
|
|
440
|
+
if (stepProgress.result.status === 'SKIPPED') {
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
if (testStepResult.status === 'UNDEFINED') {
|
|
444
|
+
// Mark that we've encountered an undefined step
|
|
445
|
+
this.hasUndefinedStep = true;
|
|
446
|
+
const step = this.stepReportMap.get(testStep.pickleStepId);
|
|
447
|
+
const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
|
|
448
|
+
const undefinedCommand = {
|
|
449
|
+
testStepId: testStepId,
|
|
450
|
+
body: JSON.stringify({
|
|
451
|
+
type: 'error',
|
|
452
|
+
text: 'Undefined step: ' + stepName,
|
|
453
|
+
result: {
|
|
454
|
+
status: 'FAILED',
|
|
455
|
+
startTime: this.getTimeStamp(timestamp),
|
|
456
|
+
endTime: this.getTimeStamp(timestamp),
|
|
457
|
+
},
|
|
458
|
+
}),
|
|
459
|
+
mediaType: 'application/json',
|
|
460
|
+
contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
|
|
461
|
+
};
|
|
462
|
+
this.onAttachment(undefinedCommand);
|
|
463
|
+
}
|
|
464
|
+
const prevStepResult = stepProgress.result;
|
|
295
465
|
let data = {};
|
|
296
466
|
try {
|
|
297
467
|
const reportFolder = this.reportFolder;
|
|
@@ -305,15 +475,57 @@ class ReportGenerator {
|
|
|
305
475
|
catch (error) {
|
|
306
476
|
console.log('Error reading data.json');
|
|
307
477
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
478
|
+
if (testStepResult.status === 'FAILED') {
|
|
479
|
+
stepProgress.result = this.getFailedTestStepResult({
|
|
480
|
+
commands: stepProgress.commands,
|
|
481
|
+
startTime: prevStepResult.startTime,
|
|
482
|
+
endTime: this.getTimeStamp(timestamp),
|
|
483
|
+
result: testStepResult,
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
stepProgress.result = {
|
|
488
|
+
status: testStepResult.status,
|
|
489
|
+
startTime: prevStepResult.startTime,
|
|
490
|
+
endTime: this.getTimeStamp(timestamp),
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
stepProgress.webLog = this.stepLogs;
|
|
494
|
+
stepProgress.networkData = this.stepNetworkLogs;
|
|
495
|
+
stepProgress.ariaSnapshot = this.ariaSnapshot;
|
|
496
|
+
this.ariaSnapshot = '';
|
|
497
|
+
this.stepNetworkLogs = [];
|
|
498
|
+
this.stepLogs = [];
|
|
315
499
|
if (Object.keys(data).length > 0) {
|
|
316
|
-
|
|
500
|
+
stepProgress.data = data;
|
|
501
|
+
const id = testStepFinished.testCaseStartedId;
|
|
502
|
+
const parameters = this.testCaseReportMap.get(id).parameters;
|
|
503
|
+
const _parameters = {};
|
|
504
|
+
Object.keys(parameters).map((key) => {
|
|
505
|
+
if (parameters[key].startsWith('{{') &&
|
|
506
|
+
parameters[key].endsWith('}}')) {
|
|
507
|
+
const path = parameters[key].slice(2, -2).split('.');
|
|
508
|
+
let value = String(object_path_1.default.get(data, path));
|
|
509
|
+
if (value) {
|
|
510
|
+
if (value.startsWith('secret:')) {
|
|
511
|
+
value = 'secret:****';
|
|
512
|
+
}
|
|
513
|
+
else if (value.startsWith('totp:')) {
|
|
514
|
+
value = 'totp:****';
|
|
515
|
+
}
|
|
516
|
+
else if (value.startsWith('mask:')) {
|
|
517
|
+
value = 'mask:****';
|
|
518
|
+
}
|
|
519
|
+
_parameters[key] = value;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
_parameters[key] = parameters[key];
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
this.report.testCases.find((testCase) => {
|
|
527
|
+
return testCase.id === id;
|
|
528
|
+
}).parameters = _parameters;
|
|
317
529
|
}
|
|
318
530
|
}
|
|
319
531
|
getLogFileContent() {
|
|
@@ -362,23 +574,130 @@ class ReportGenerator {
|
|
|
362
574
|
status: 'PASSED',
|
|
363
575
|
};
|
|
364
576
|
}
|
|
365
|
-
onTestCaseFinished(testCaseFinished) {
|
|
577
|
+
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
366
578
|
const { testCaseStartedId, timestamp } = testCaseFinished;
|
|
367
579
|
const testProgress = this.testCaseReportMap.get(testCaseStartedId);
|
|
368
580
|
const prevResult = testProgress.result;
|
|
369
581
|
const steps = Object.values(testProgress.steps);
|
|
370
582
|
const result = this.getTestCaseResult(steps);
|
|
583
|
+
const endTime = this.getTimeStamp(timestamp);
|
|
371
584
|
testProgress.result = {
|
|
372
585
|
...result,
|
|
373
586
|
startTime: prevResult.startTime,
|
|
374
|
-
endTime
|
|
587
|
+
endTime,
|
|
375
588
|
};
|
|
376
589
|
testProgress.webLog = this.logs;
|
|
377
590
|
testProgress.networkLog = this.networkLog;
|
|
591
|
+
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
592
|
+
this.initialAriaSnapshot = '';
|
|
378
593
|
this.networkLog = [];
|
|
379
594
|
this.logs = [];
|
|
595
|
+
if (this.testCaseLog && this.testCaseLog.length > 0) {
|
|
596
|
+
// Create the logs directory
|
|
597
|
+
const logsDir = path_1.default.join(this.reportFolder, 'editorLogs');
|
|
598
|
+
const fileName = `testCaseLog_${testCaseStartedId}.log`;
|
|
599
|
+
const filePath = path_1.default.join(logsDir, fileName);
|
|
600
|
+
// Ensure the logs directory exists
|
|
601
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
602
|
+
// Write the logs to the file
|
|
603
|
+
fs_1.default.writeFileSync(filePath, this.testCaseLog.join('\n'), 'utf8');
|
|
604
|
+
// Store this ID in the testProgress object so it can be accessed later
|
|
605
|
+
testProgress.logFileId = testCaseStartedId;
|
|
606
|
+
}
|
|
607
|
+
this.testCaseLog = [];
|
|
608
|
+
if (process.env.TESTCASE_REPORT_FOLDER_PATH) {
|
|
609
|
+
this.reportFolder = process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
610
|
+
if (!fs_1.default.existsSync(this.reportFolder)) {
|
|
611
|
+
fs_1.default.mkdirSync(this.reportFolder);
|
|
612
|
+
}
|
|
613
|
+
const reportFilePath = path_1.default.join(this.reportFolder, `${endTime}_${testProgress.scenarioName}.json`);
|
|
614
|
+
(0, fs_extra_1.writeFileSync)(reportFilePath, JSON.stringify(testProgress, null, 2));
|
|
615
|
+
return undefined;
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
return await this.uploadTestCase(testProgress, reRunId);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
async uploadTestCase(testCase, rerunId) {
|
|
622
|
+
let data = null;
|
|
623
|
+
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
|
|
624
|
+
try {
|
|
625
|
+
data = await this.tryUpload(testCase, rerunId);
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
catch (e) {
|
|
629
|
+
console.error(`Attempt ${attempt} to upload testcase failed:`, e);
|
|
630
|
+
if (attempt === this.retryCount) {
|
|
631
|
+
console.error('All retry attempts failed, failed to upload testcase.');
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
|
|
635
|
+
await new Promise((r) => setTimeout(r, waitTime));
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
return data;
|
|
640
|
+
}
|
|
641
|
+
async tryUpload(testCase, rerunId) {
|
|
642
|
+
let runId = '';
|
|
643
|
+
let projectId = '';
|
|
644
|
+
if (!process.env.UPLOADING_TEST_CASE) {
|
|
645
|
+
process.env.UPLOADING_TEST_CASE = '[]';
|
|
646
|
+
}
|
|
647
|
+
const anyRemArr = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
648
|
+
const randomID = Math.random().toString(36).substring(7);
|
|
649
|
+
anyRemArr.push(randomID);
|
|
650
|
+
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
651
|
+
try {
|
|
652
|
+
if (process.env.RUN_ID &&
|
|
653
|
+
process.env.PROJECT_ID &&
|
|
654
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
655
|
+
runId = process.env.RUN_ID;
|
|
656
|
+
projectId = process.env.PROJECT_ID;
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
const runDoc = await this.uploadService.createRunDocument(this.runName);
|
|
660
|
+
runId = runDoc._id;
|
|
661
|
+
projectId = runDoc.project_id;
|
|
662
|
+
if (!process.env.IGNORE_ENV_VARIABLES) {
|
|
663
|
+
process.env.RUN_ID = runId;
|
|
664
|
+
process.env.PROJECT_ID = projectId;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
668
|
+
this.writeTestCaseReportToDisk(testCase);
|
|
669
|
+
return data;
|
|
670
|
+
}
|
|
671
|
+
finally {
|
|
672
|
+
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
673
|
+
arrRem.splice(arrRem.indexOf(randomID), 1);
|
|
674
|
+
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
writeTestCaseReportToDisk(testCase) {
|
|
678
|
+
var _a;
|
|
679
|
+
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
680
|
+
if (!reportFolder) {
|
|
681
|
+
console.error('Report folder is not defined');
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
try {
|
|
685
|
+
let i = 0;
|
|
686
|
+
while (fs_1.default.existsSync(path_1.default.join(reportFolder, `${i}`))) {
|
|
687
|
+
i++;
|
|
688
|
+
}
|
|
689
|
+
fs_1.default.mkdirSync(path_1.default.join(reportFolder, `${i}`));
|
|
690
|
+
//exclude network log from the saved report
|
|
691
|
+
const networkLog = testCase.networkLog;
|
|
692
|
+
delete testCase.networkLog;
|
|
693
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `report.json`), JSON.stringify(testCase, null, 2));
|
|
694
|
+
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
695
|
+
}
|
|
696
|
+
catch (error) {
|
|
697
|
+
console.error('Error writing test case report to disk:', error);
|
|
698
|
+
}
|
|
380
699
|
}
|
|
381
|
-
onTestRunFinished(testRunFinished) {
|
|
700
|
+
async onTestRunFinished(testRunFinished) {
|
|
382
701
|
const { timestamp, success, message } = testRunFinished;
|
|
383
702
|
const prevResult = this.report.result;
|
|
384
703
|
this.report.result = {
|
|
@@ -388,6 +707,7 @@ class ReportGenerator {
|
|
|
388
707
|
message,
|
|
389
708
|
// exception,
|
|
390
709
|
};
|
|
710
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
391
711
|
}
|
|
392
712
|
}
|
|
393
713
|
exports.default = ReportGenerator;
|