@dev-blinq/cucumber-js 1.0.106 → 1.0.107-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/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/formatter/api.js +9 -4
- 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 +2 -2
- package/lib/formatter/bvt_analysis_formatter.js +36 -16
- 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.js.map +1 -1
- package/lib/formatter/helpers/report_generator.d.ts +14 -11
- package/lib/formatter/helpers/report_generator.js +159 -92
- package/lib/formatter/helpers/report_generator.js.map +1 -1
- package/lib/formatter/helpers/test_case_attempt_parser.js.map +1 -1
- package/lib/formatter/helpers/upload_serivce.d.ts +4 -2
- package/lib/formatter/helpers/upload_serivce.js +126 -56
- package/lib/formatter/helpers/upload_serivce.js.map +1 -1
- package/lib/formatter/helpers/uploader.js.map +1 -1
- package/lib/formatter/summary_formatter.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 +2 -1
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import * as messages from
|
|
1
|
+
import * as messages from '@cucumber/messages';
|
|
2
2
|
type JsonTimestamp = number;
|
|
3
|
-
type JsonStepType =
|
|
3
|
+
type JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome' | 'Conjunction' | 'After' | 'Before';
|
|
4
4
|
export type JsonResultUnknown = {
|
|
5
|
-
status:
|
|
5
|
+
status: 'UNKNOWN';
|
|
6
6
|
};
|
|
7
7
|
type JsonResultSkipped = {
|
|
8
|
-
status:
|
|
8
|
+
status: 'SKIPPED';
|
|
9
9
|
};
|
|
10
10
|
type JsonResultUndefined = {
|
|
11
|
-
status:
|
|
11
|
+
status: 'UNDEFINED';
|
|
12
12
|
};
|
|
13
13
|
type JsonResultAmbiguous = {
|
|
14
|
-
status:
|
|
14
|
+
status: 'AMBIGUOUS';
|
|
15
15
|
};
|
|
16
16
|
export type JsonResultStarted = {
|
|
17
|
-
status:
|
|
17
|
+
status: 'STARTED';
|
|
18
18
|
startTime: JsonTimestamp;
|
|
19
19
|
};
|
|
20
20
|
type JsonResultPending = {
|
|
21
|
-
status:
|
|
21
|
+
status: 'PENDING';
|
|
22
22
|
startTime: JsonTimestamp;
|
|
23
23
|
endTime: JsonTimestamp;
|
|
24
24
|
};
|
|
25
25
|
export type JsonResultPassed = {
|
|
26
|
-
status:
|
|
26
|
+
status: 'PASSED';
|
|
27
27
|
startTime: JsonTimestamp;
|
|
28
28
|
endTime: JsonTimestamp;
|
|
29
29
|
};
|
|
30
30
|
export type JsonResultFailed = {
|
|
31
|
-
status:
|
|
31
|
+
status: 'FAILED';
|
|
32
32
|
startTime: JsonTimestamp;
|
|
33
33
|
endTime: JsonTimestamp;
|
|
34
34
|
message?: string;
|
|
35
35
|
};
|
|
36
36
|
export type JsonFixedByAi = {
|
|
37
|
-
status:
|
|
37
|
+
status: 'FIXED_BY_AI';
|
|
38
38
|
startTime: JsonTimestamp;
|
|
39
39
|
endTime: JsonTimestamp;
|
|
40
40
|
};
|
|
@@ -68,6 +68,7 @@ export type JsonStep = {
|
|
|
68
68
|
ariaSnapshot: string;
|
|
69
69
|
traceFilePath?: string;
|
|
70
70
|
brunoData?: any;
|
|
71
|
+
interceptResults?: any;
|
|
71
72
|
};
|
|
72
73
|
export type RetrainStats = {
|
|
73
74
|
result: JsonTestResult;
|
|
@@ -146,7 +147,9 @@ export default class ReportGenerator {
|
|
|
146
147
|
getLogFileContent(): any;
|
|
147
148
|
private getTestCaseResult;
|
|
148
149
|
private onTestCaseFinished;
|
|
150
|
+
private readonly retryCount;
|
|
149
151
|
private uploadTestCase;
|
|
152
|
+
private tryUpload;
|
|
150
153
|
private writeTestCaseReportToDisk;
|
|
151
154
|
private onTestRunFinished;
|
|
152
155
|
}
|
|
@@ -34,16 +34,16 @@ const upload_serivce_1 = require("./upload_serivce");
|
|
|
34
34
|
const fs_extra_1 = require("fs-extra");
|
|
35
35
|
// type JsonException = messages.Exception
|
|
36
36
|
const object_path_1 = __importDefault(require("object-path"));
|
|
37
|
-
const URL = process.env.NODE_ENV_BLINQ ===
|
|
38
|
-
?
|
|
39
|
-
: process.env.NODE_ENV_BLINQ ===
|
|
40
|
-
?
|
|
41
|
-
: process.env.NODE_ENV_BLINQ ===
|
|
42
|
-
?
|
|
43
|
-
: process.env.NODE_ENV_BLINQ ===
|
|
44
|
-
?
|
|
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
45
|
: !process.env.NODE_ENV_BLINQ
|
|
46
|
-
?
|
|
46
|
+
? 'https://api.blinq.io/api/runs'
|
|
47
47
|
: `${process.env.NODE_ENV_BLINQ}/api/runs`;
|
|
48
48
|
const REPORT_SERVICE_URL = (_a = process.env.REPORT_SERVICE_URL) !== null && _a !== void 0 ? _a : URL;
|
|
49
49
|
const BATCH_SIZE = 10;
|
|
@@ -53,12 +53,12 @@ class ReportGenerator {
|
|
|
53
53
|
constructor() {
|
|
54
54
|
this.report = {
|
|
55
55
|
result: {
|
|
56
|
-
status:
|
|
56
|
+
status: 'UNKNOWN',
|
|
57
57
|
},
|
|
58
58
|
testCases: [],
|
|
59
59
|
env: {
|
|
60
|
-
name:
|
|
61
|
-
baseUrl:
|
|
60
|
+
name: '',
|
|
61
|
+
baseUrl: '',
|
|
62
62
|
},
|
|
63
63
|
};
|
|
64
64
|
this.gherkinDocumentMap = new Map();
|
|
@@ -73,45 +73,47 @@ class ReportGenerator {
|
|
|
73
73
|
this.networkLog = [];
|
|
74
74
|
this.stepLogs = [];
|
|
75
75
|
this.stepNetworkLogs = [];
|
|
76
|
-
this.runName =
|
|
77
|
-
this.ariaSnapshot =
|
|
78
|
-
this.initialAriaSnapshot =
|
|
76
|
+
this.runName = '';
|
|
77
|
+
this.ariaSnapshot = '';
|
|
78
|
+
this.initialAriaSnapshot = '';
|
|
79
79
|
this.testCaseLog = [];
|
|
80
80
|
this.loggingOverridden = false; // Flag to track if logging is overridden
|
|
81
81
|
this.reportFolder = null;
|
|
82
82
|
this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
|
|
83
|
+
this.retryCount = 3;
|
|
83
84
|
}
|
|
84
85
|
async handleMessage(envelope, reRunId) {
|
|
85
|
-
if (envelope.meta &&
|
|
86
|
+
if (envelope.meta && 'runName' in envelope.meta) {
|
|
86
87
|
this.runName = envelope.meta.runName;
|
|
87
88
|
}
|
|
88
89
|
const type = Object.keys(envelope)[0];
|
|
89
90
|
switch (type) {
|
|
90
91
|
// case "meta": { break}
|
|
91
92
|
// case "source": { break}
|
|
92
|
-
case
|
|
93
|
+
case 'parseError': {
|
|
93
94
|
const parseError = envelope[type];
|
|
94
95
|
this.handleParseError(parseError);
|
|
95
96
|
break;
|
|
96
97
|
}
|
|
97
|
-
case
|
|
98
|
+
case 'gherkinDocument': {
|
|
98
99
|
const doc = envelope[type];
|
|
99
100
|
this.onGherkinDocument(doc);
|
|
100
101
|
break;
|
|
101
102
|
}
|
|
102
|
-
case
|
|
103
|
+
case 'pickle': {
|
|
103
104
|
const pickle = envelope[type];
|
|
104
105
|
this.onPickle(pickle);
|
|
105
106
|
break;
|
|
106
107
|
}
|
|
107
108
|
// case "stepDefinition": { break}
|
|
108
109
|
// case "hook": { break} // Before Hook
|
|
109
|
-
case
|
|
110
|
+
case 'testRunStarted': {
|
|
110
111
|
const testRunStarted = envelope[type];
|
|
111
112
|
this.onTestRunStarted(testRunStarted);
|
|
113
|
+
await this.uploadService.createStatus('running');
|
|
112
114
|
break;
|
|
113
115
|
}
|
|
114
|
-
case
|
|
116
|
+
case 'testCase': {
|
|
115
117
|
const testCase = envelope[type];
|
|
116
118
|
// Initialize the log storage
|
|
117
119
|
this.testCaseLog = [];
|
|
@@ -135,36 +137,36 @@ class ReportGenerator {
|
|
|
135
137
|
this.onTestCase(testCase);
|
|
136
138
|
break;
|
|
137
139
|
}
|
|
138
|
-
case
|
|
140
|
+
case 'testCaseStarted': {
|
|
139
141
|
const testCaseStarted = envelope[type];
|
|
140
142
|
this.onTestCaseStarted(testCaseStarted);
|
|
141
143
|
break;
|
|
142
144
|
}
|
|
143
|
-
case
|
|
145
|
+
case 'testStepStarted': {
|
|
144
146
|
const testStepStarted = envelope[type];
|
|
145
147
|
this.onTestStepStarted(testStepStarted);
|
|
146
148
|
break;
|
|
147
149
|
}
|
|
148
|
-
case
|
|
150
|
+
case 'attachment': {
|
|
149
151
|
const attachment = envelope[type];
|
|
150
152
|
this.onAttachment(attachment);
|
|
151
153
|
break;
|
|
152
154
|
}
|
|
153
|
-
case
|
|
155
|
+
case 'testStepFinished': {
|
|
154
156
|
const testStepFinished = envelope[type];
|
|
155
157
|
this.onTestStepFinished(testStepFinished);
|
|
156
158
|
break;
|
|
157
159
|
}
|
|
158
|
-
case
|
|
160
|
+
case 'testCaseFinished': {
|
|
159
161
|
const testCaseFinished = envelope[type];
|
|
160
162
|
// Call the onTestCaseFinished method
|
|
161
163
|
const result = await this.onTestCaseFinished(testCaseFinished, reRunId);
|
|
162
164
|
return result;
|
|
163
165
|
}
|
|
164
166
|
// case "hook": { break} // After Hook
|
|
165
|
-
case
|
|
167
|
+
case 'testRunFinished': {
|
|
166
168
|
const testRunFinished = envelope[type];
|
|
167
|
-
this.onTestRunFinished(testRunFinished);
|
|
169
|
+
await this.onTestRunFinished(testRunFinished);
|
|
168
170
|
break;
|
|
169
171
|
}
|
|
170
172
|
// case "parameterType" : { break}
|
|
@@ -178,7 +180,7 @@ class ReportGenerator {
|
|
|
178
180
|
const { message } = parseError;
|
|
179
181
|
const timestamp = new Date().getTime();
|
|
180
182
|
this.report.result = {
|
|
181
|
-
status:
|
|
183
|
+
status: 'FAILED',
|
|
182
184
|
startTime: timestamp,
|
|
183
185
|
endTime: timestamp,
|
|
184
186
|
message: message,
|
|
@@ -221,7 +223,7 @@ class ReportGenerator {
|
|
|
221
223
|
}
|
|
222
224
|
onTestRunStarted(testRunStarted) {
|
|
223
225
|
this.report.result = {
|
|
224
|
-
status:
|
|
226
|
+
status: 'STARTED',
|
|
225
227
|
startTime: this.getTimeStamp(testRunStarted.timestamp),
|
|
226
228
|
};
|
|
227
229
|
}
|
|
@@ -254,7 +256,8 @@ class ReportGenerator {
|
|
|
254
256
|
for (const tableRow of examples.tableBody) {
|
|
255
257
|
if (tableRow.id === exampleId) {
|
|
256
258
|
for (let i = 0; i < examples.tableHeader.cells.length; i++) {
|
|
257
|
-
parameters[examples.tableHeader.cells[i].value] =
|
|
259
|
+
parameters[examples.tableHeader.cells[i].value] =
|
|
260
|
+
tableRow.cells[i].value;
|
|
258
261
|
}
|
|
259
262
|
}
|
|
260
263
|
}
|
|
@@ -292,7 +295,7 @@ class ReportGenerator {
|
|
|
292
295
|
text: step.text,
|
|
293
296
|
commands: [],
|
|
294
297
|
result: {
|
|
295
|
-
status:
|
|
298
|
+
status: 'UNKNOWN',
|
|
296
299
|
},
|
|
297
300
|
networkData: [],
|
|
298
301
|
webLog: [],
|
|
@@ -309,7 +312,7 @@ class ReportGenerator {
|
|
|
309
312
|
parameters,
|
|
310
313
|
steps,
|
|
311
314
|
result: {
|
|
312
|
-
status:
|
|
315
|
+
status: 'STARTED',
|
|
313
316
|
startTime: this.getTimeStamp(timestamp),
|
|
314
317
|
},
|
|
315
318
|
webLog: [],
|
|
@@ -330,25 +333,25 @@ class ReportGenerator {
|
|
|
330
333
|
return;
|
|
331
334
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
332
335
|
stepProgess.result = {
|
|
333
|
-
status:
|
|
336
|
+
status: 'STARTED',
|
|
334
337
|
startTime: this.getTimeStamp(timestamp),
|
|
335
338
|
};
|
|
336
339
|
}
|
|
337
340
|
onAttachment(attachment) {
|
|
338
341
|
const { testStepId, body, mediaType } = attachment;
|
|
339
|
-
if (mediaType ===
|
|
340
|
-
this.reportFolder = body.replaceAll(
|
|
342
|
+
if (mediaType === 'text/plain') {
|
|
343
|
+
this.reportFolder = body.replaceAll('\\', '/');
|
|
341
344
|
return;
|
|
342
345
|
}
|
|
343
|
-
if (mediaType ===
|
|
346
|
+
if (mediaType === 'application/json+snapshot-before') {
|
|
344
347
|
this.initialAriaSnapshot = body;
|
|
345
348
|
return;
|
|
346
349
|
}
|
|
347
|
-
if (mediaType ===
|
|
350
|
+
if (mediaType === 'application/json+snapshot-after') {
|
|
348
351
|
this.ariaSnapshot = body;
|
|
349
352
|
return;
|
|
350
353
|
}
|
|
351
|
-
if (mediaType ===
|
|
354
|
+
if (mediaType === 'application/json+env') {
|
|
352
355
|
const data = JSON.parse(body);
|
|
353
356
|
this.report.env = data;
|
|
354
357
|
this.report.testCases.map((testCase) => {
|
|
@@ -356,14 +359,14 @@ class ReportGenerator {
|
|
|
356
359
|
return testCase;
|
|
357
360
|
});
|
|
358
361
|
}
|
|
359
|
-
if (mediaType ===
|
|
362
|
+
if (mediaType === 'application/json+log') {
|
|
360
363
|
const log = JSON.parse(body);
|
|
361
364
|
if (this.logs.length < 1000) {
|
|
362
365
|
this.logs.push(log);
|
|
363
366
|
this.stepLogs.push(log);
|
|
364
367
|
}
|
|
365
368
|
}
|
|
366
|
-
if (mediaType ===
|
|
369
|
+
if (mediaType === 'application/json+network') {
|
|
367
370
|
const networkLog = JSON.parse(body);
|
|
368
371
|
if (this.networkLog.length < 1000)
|
|
369
372
|
this.networkLog.push(networkLog);
|
|
@@ -373,29 +376,38 @@ class ReportGenerator {
|
|
|
373
376
|
if (testStep.pickleStepId === undefined)
|
|
374
377
|
return;
|
|
375
378
|
const stepProgess = this.stepReportMap.get(testStep.pickleStepId);
|
|
376
|
-
if (mediaType ===
|
|
379
|
+
if (mediaType === 'application/json') {
|
|
377
380
|
const command = JSON.parse(body);
|
|
378
381
|
stepProgess.commands.push(command);
|
|
379
382
|
}
|
|
380
|
-
else if (mediaType ===
|
|
383
|
+
else if (mediaType === 'application/json+trace') {
|
|
381
384
|
const data = JSON.parse(body);
|
|
382
385
|
stepProgess.traceFilePath = data.traceFilePath;
|
|
383
386
|
}
|
|
384
|
-
if (mediaType ===
|
|
387
|
+
if (mediaType === 'application/json+bruno') {
|
|
385
388
|
try {
|
|
386
389
|
const data = JSON.parse(body);
|
|
387
390
|
stepProgess.brunoData = data;
|
|
388
391
|
}
|
|
389
392
|
catch (error) {
|
|
390
|
-
console.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);
|
|
391
403
|
}
|
|
392
404
|
}
|
|
393
405
|
}
|
|
394
406
|
getFailedTestStepResult({ commands, startTime, endTime, result, }) {
|
|
395
407
|
for (const command of commands) {
|
|
396
|
-
if (command.result.status ===
|
|
408
|
+
if (command.result.status === 'FAILED') {
|
|
397
409
|
return {
|
|
398
|
-
status:
|
|
410
|
+
status: 'FAILED',
|
|
399
411
|
message: command.result.message,
|
|
400
412
|
startTime,
|
|
401
413
|
endTime,
|
|
@@ -403,7 +415,7 @@ class ReportGenerator {
|
|
|
403
415
|
}
|
|
404
416
|
}
|
|
405
417
|
return {
|
|
406
|
-
status:
|
|
418
|
+
status: 'FAILED',
|
|
407
419
|
startTime,
|
|
408
420
|
endTime,
|
|
409
421
|
message: result.message,
|
|
@@ -413,26 +425,51 @@ class ReportGenerator {
|
|
|
413
425
|
const { testStepId, testStepResult, timestamp } = testStepFinished;
|
|
414
426
|
const testStep = this.testStepMap.get(testStepId);
|
|
415
427
|
if (testStep.pickleStepId === undefined) {
|
|
416
|
-
if (testStepResult.status ===
|
|
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);
|
|
417
454
|
console.error(`Before/After hook failed with message: ${testStepResult.message}`);
|
|
418
455
|
}
|
|
419
456
|
return;
|
|
420
457
|
}
|
|
421
|
-
if (testStepResult.status ===
|
|
458
|
+
if (testStepResult.status === 'UNDEFINED') {
|
|
422
459
|
const step = this.stepReportMap.get(testStep.pickleStepId);
|
|
423
|
-
const stepName = step ? step.keyword +
|
|
460
|
+
const stepName = step ? step.keyword + ' ' + step.text : 'Undefined step';
|
|
424
461
|
const undefinedCommand = {
|
|
425
462
|
testStepId: testStepId,
|
|
426
463
|
body: JSON.stringify({
|
|
427
|
-
type:
|
|
428
|
-
text:
|
|
464
|
+
type: 'error',
|
|
465
|
+
text: 'Undefined step: ' + stepName,
|
|
429
466
|
result: {
|
|
430
|
-
status:
|
|
467
|
+
status: 'FAILED',
|
|
431
468
|
startTime: this.getTimeStamp(timestamp),
|
|
432
469
|
endTime: this.getTimeStamp(timestamp),
|
|
433
470
|
},
|
|
434
471
|
}),
|
|
435
|
-
mediaType:
|
|
472
|
+
mediaType: 'application/json',
|
|
436
473
|
contentEncoding: messages.AttachmentContentEncoding.IDENTITY,
|
|
437
474
|
};
|
|
438
475
|
this.onAttachment(undefinedCommand);
|
|
@@ -445,14 +482,14 @@ class ReportGenerator {
|
|
|
445
482
|
if (reportFolder === null) {
|
|
446
483
|
throw new Error('"reportFolder" is "null". Failed to run BVT hooks. Please retry after running "Generate All" or "Record Scenario" ');
|
|
447
484
|
}
|
|
448
|
-
if (fs_1.default.existsSync(path_1.default.join(reportFolder,
|
|
449
|
-
data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(reportFolder,
|
|
485
|
+
if (fs_1.default.existsSync(path_1.default.join(reportFolder, 'data.json'))) {
|
|
486
|
+
data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(reportFolder, 'data.json'), 'utf8'));
|
|
450
487
|
}
|
|
451
488
|
}
|
|
452
489
|
catch (error) {
|
|
453
|
-
console.log(
|
|
490
|
+
console.log('Error reading data.json');
|
|
454
491
|
}
|
|
455
|
-
if (testStepResult.status ===
|
|
492
|
+
if (testStepResult.status === 'FAILED') {
|
|
456
493
|
stepProgess.result = this.getFailedTestStepResult({
|
|
457
494
|
commands: stepProgess.commands,
|
|
458
495
|
startTime: prevStepResult.startTime,
|
|
@@ -470,7 +507,7 @@ class ReportGenerator {
|
|
|
470
507
|
stepProgess.webLog = this.stepLogs;
|
|
471
508
|
stepProgess.networkData = this.stepNetworkLogs;
|
|
472
509
|
stepProgess.ariaSnapshot = this.ariaSnapshot;
|
|
473
|
-
this.ariaSnapshot =
|
|
510
|
+
this.ariaSnapshot = '';
|
|
474
511
|
this.stepNetworkLogs = [];
|
|
475
512
|
this.stepLogs = [];
|
|
476
513
|
if (Object.keys(data).length > 0) {
|
|
@@ -479,18 +516,20 @@ class ReportGenerator {
|
|
|
479
516
|
const parameters = this.testCaseReportMap.get(id).parameters;
|
|
480
517
|
const _parameters = {};
|
|
481
518
|
Object.keys(parameters).map((key) => {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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]);
|
|
485
524
|
if (value) {
|
|
486
|
-
if (value.startsWith(
|
|
487
|
-
value =
|
|
525
|
+
if (value.startsWith('secret:')) {
|
|
526
|
+
value = 'secret:****';
|
|
488
527
|
}
|
|
489
|
-
else if (value.startsWith(
|
|
490
|
-
value =
|
|
528
|
+
else if (value.startsWith('totp:')) {
|
|
529
|
+
value = 'totp:****';
|
|
491
530
|
}
|
|
492
|
-
else if (value.startsWith(
|
|
493
|
-
value =
|
|
531
|
+
else if (value.startsWith('mask:')) {
|
|
532
|
+
value = 'mask:****';
|
|
494
533
|
}
|
|
495
534
|
_parameters[key] = value;
|
|
496
535
|
}
|
|
@@ -523,7 +562,7 @@ class ReportGenerator {
|
|
|
523
562
|
if (process.env.PROJECT_PATH) {
|
|
524
563
|
projectPath = process.env.PROJECT_PATH;
|
|
525
564
|
}
|
|
526
|
-
const logFolder = path_1.default.join(projectPath,
|
|
565
|
+
const logFolder = path_1.default.join(projectPath, 'logs', 'web');
|
|
527
566
|
if (!fs_1.default.existsSync(logFolder)) {
|
|
528
567
|
return [];
|
|
529
568
|
}
|
|
@@ -535,7 +574,7 @@ class ReportGenerator {
|
|
|
535
574
|
return [];
|
|
536
575
|
}
|
|
537
576
|
try {
|
|
538
|
-
const logFileContent = fs_1.default.readFileSync(path_1.default.join(logFolder, `${nextId - 1}.json`),
|
|
577
|
+
const logFileContent = fs_1.default.readFileSync(path_1.default.join(logFolder, `${nextId - 1}.json`), 'utf8');
|
|
539
578
|
return JSON.parse(logFileContent);
|
|
540
579
|
}
|
|
541
580
|
catch (error) {
|
|
@@ -543,25 +582,31 @@ class ReportGenerator {
|
|
|
543
582
|
}
|
|
544
583
|
}
|
|
545
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
|
+
}
|
|
546
591
|
for (const step of steps) {
|
|
547
592
|
switch (step.result.status) {
|
|
548
|
-
case
|
|
593
|
+
case 'FAILED':
|
|
549
594
|
return {
|
|
550
595
|
status: step.result.status,
|
|
551
596
|
message: step.result.message,
|
|
552
597
|
// exception: step.result.exception,
|
|
553
598
|
};
|
|
554
|
-
case
|
|
555
|
-
case
|
|
556
|
-
case
|
|
599
|
+
case 'AMBIGUOUS':
|
|
600
|
+
case 'UNDEFINED':
|
|
601
|
+
case 'PENDING':
|
|
557
602
|
return {
|
|
558
|
-
status:
|
|
603
|
+
status: 'FAILED',
|
|
559
604
|
message: `step "${step.text}" is ${step.result.status}`,
|
|
560
605
|
};
|
|
561
606
|
}
|
|
562
607
|
}
|
|
563
608
|
return {
|
|
564
|
-
status:
|
|
609
|
+
status: 'PASSED',
|
|
565
610
|
};
|
|
566
611
|
}
|
|
567
612
|
async onTestCaseFinished(testCaseFinished, reRunId) {
|
|
@@ -570,6 +615,9 @@ class ReportGenerator {
|
|
|
570
615
|
const prevResult = testProgress.result;
|
|
571
616
|
const steps = Object.values(testProgress.steps);
|
|
572
617
|
const result = this.getTestCaseResult(steps);
|
|
618
|
+
if (result.status === 'PASSED' && reRunId) {
|
|
619
|
+
this.uploadService.updateProjectAnalytics(process.env.PROJECT_ID);
|
|
620
|
+
}
|
|
573
621
|
const endTime = this.getTimeStamp(timestamp);
|
|
574
622
|
testProgress.result = {
|
|
575
623
|
...result,
|
|
@@ -579,7 +627,7 @@ class ReportGenerator {
|
|
|
579
627
|
testProgress.webLog = this.logs;
|
|
580
628
|
testProgress.networkLog = this.networkLog;
|
|
581
629
|
testProgress.initialAriaSnapshot = this.initialAriaSnapshot;
|
|
582
|
-
this.initialAriaSnapshot =
|
|
630
|
+
this.initialAriaSnapshot = '';
|
|
583
631
|
this.networkLog = [];
|
|
584
632
|
this.logs = [];
|
|
585
633
|
if (this.testCaseLog && this.testCaseLog.length > 0) {
|
|
@@ -609,18 +657,39 @@ class ReportGenerator {
|
|
|
609
657
|
}
|
|
610
658
|
}
|
|
611
659
|
async uploadTestCase(testCase, rerunId) {
|
|
612
|
-
let
|
|
613
|
-
let
|
|
660
|
+
let data = null;
|
|
661
|
+
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
|
|
662
|
+
try {
|
|
663
|
+
data = await this.tryUpload(testCase, rerunId);
|
|
664
|
+
break;
|
|
665
|
+
}
|
|
666
|
+
catch (e) {
|
|
667
|
+
console.error(`Attempt ${attempt} to upload testcase failed:`, e);
|
|
668
|
+
if (attempt === this.retryCount) {
|
|
669
|
+
console.error('All retry attempts failed, failed to upload testcase.');
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
const waitTime = 1000 * 2 ** (attempt - 1); //? exponential backoff: 1s, 2s, 4s...
|
|
673
|
+
await new Promise((r) => setTimeout(r, waitTime));
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return data;
|
|
678
|
+
}
|
|
679
|
+
async tryUpload(testCase, rerunId) {
|
|
680
|
+
let runId = '';
|
|
681
|
+
let projectId = '';
|
|
614
682
|
if (!process.env.UPLOADING_TEST_CASE) {
|
|
615
|
-
process.env.UPLOADING_TEST_CASE =
|
|
683
|
+
process.env.UPLOADING_TEST_CASE = '[]';
|
|
616
684
|
}
|
|
617
685
|
const anyRemArr = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
618
686
|
const randomID = Math.random().toString(36).substring(7);
|
|
619
687
|
anyRemArr.push(randomID);
|
|
620
|
-
let data;
|
|
621
688
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(anyRemArr);
|
|
622
689
|
try {
|
|
623
|
-
if (process.env.RUN_ID &&
|
|
690
|
+
if (process.env.RUN_ID &&
|
|
691
|
+
process.env.PROJECT_ID &&
|
|
692
|
+
!process.env.IGNORE_ENV_VARIABLES) {
|
|
624
693
|
runId = process.env.RUN_ID;
|
|
625
694
|
projectId = process.env.PROJECT_ID;
|
|
626
695
|
}
|
|
@@ -633,24 +702,21 @@ class ReportGenerator {
|
|
|
633
702
|
process.env.PROJECT_ID = projectId;
|
|
634
703
|
}
|
|
635
704
|
}
|
|
636
|
-
data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
705
|
+
const data = await this.uploadService.uploadTestCase(testCase, runId, projectId, this.reportFolder, rerunId);
|
|
637
706
|
this.writeTestCaseReportToDisk(testCase);
|
|
638
|
-
|
|
639
|
-
catch (e) {
|
|
640
|
-
console.error("Error uploading test case:", e);
|
|
707
|
+
return data;
|
|
641
708
|
}
|
|
642
709
|
finally {
|
|
643
710
|
const arrRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
644
711
|
arrRem.splice(arrRem.indexOf(randomID), 1);
|
|
645
712
|
process.env.UPLOADING_TEST_CASE = JSON.stringify(arrRem);
|
|
646
713
|
}
|
|
647
|
-
return data ? data : null;
|
|
648
714
|
}
|
|
649
715
|
writeTestCaseReportToDisk(testCase) {
|
|
650
716
|
var _a;
|
|
651
717
|
const reportFolder = (_a = this.reportFolder) !== null && _a !== void 0 ? _a : process.env.TESTCASE_REPORT_FOLDER_PATH;
|
|
652
718
|
if (!reportFolder) {
|
|
653
|
-
console.error(
|
|
719
|
+
console.error('Report folder is not defined');
|
|
654
720
|
return;
|
|
655
721
|
}
|
|
656
722
|
try {
|
|
@@ -666,19 +732,20 @@ class ReportGenerator {
|
|
|
666
732
|
fs_1.default.writeFileSync(path_1.default.join(reportFolder, `${i}`, `network.json`), JSON.stringify(networkLog, null, 2));
|
|
667
733
|
}
|
|
668
734
|
catch (error) {
|
|
669
|
-
console.error(
|
|
735
|
+
console.error('Error writing test case report to disk:', error);
|
|
670
736
|
}
|
|
671
737
|
}
|
|
672
|
-
onTestRunFinished(testRunFinished) {
|
|
738
|
+
async onTestRunFinished(testRunFinished) {
|
|
673
739
|
const { timestamp, success, message } = testRunFinished;
|
|
674
740
|
const prevResult = this.report.result;
|
|
675
741
|
this.report.result = {
|
|
676
|
-
status: success ?
|
|
742
|
+
status: success ? 'PASSED' : 'FAILED',
|
|
677
743
|
startTime: prevResult.startTime,
|
|
678
744
|
endTime: this.getTimeStamp(timestamp),
|
|
679
745
|
message,
|
|
680
746
|
// exception,
|
|
681
747
|
};
|
|
748
|
+
await this.uploadService.createStatus(success ? 'passed' : 'failed');
|
|
682
749
|
}
|
|
683
750
|
}
|
|
684
751
|
exports.default = ReportGenerator;
|