@dev-blinq/cucumber-js 1.0.64 → 1.0.65-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 +48 -32
- package/lib/api/gherkin.js +6 -1
- package/lib/api/gherkin.js.map +1 -1
- package/lib/formatter/api.d.ts +2 -0
- package/lib/formatter/api.js +53 -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 +199 -71
- package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
- package/lib/formatter/feature_data_format.d.ts +2 -2
- package/lib/formatter/feature_data_format.js +52 -7
- package/lib/formatter/feature_data_format.js.map +1 -1
- package/lib/formatter/helpers/constants.d.ts +44 -0
- package/lib/formatter/helpers/constants.js +50 -0
- package/lib/formatter/helpers/constants.js.map +1 -0
- package/lib/formatter/helpers/report_generator.d.ts +41 -1
- package/lib/formatter/helpers/report_generator.js +267 -12
- 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 +16 -3
- package/lib/formatter/helpers/upload_serivce.js +151 -18
- 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 +87 -14
- package/lib/formatter/helpers/uploader.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 +3 -2
|
@@ -3,14 +3,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logReportLink = void 0;
|
|
6
7
|
const child_process_1 = require("child_process");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const promises_1 = require("fs/promises");
|
|
7
10
|
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const tmp_1 = require("tmp");
|
|
8
12
|
const _1 = __importDefault(require("."));
|
|
9
13
|
const value_checker_1 = require("../value_checker");
|
|
10
14
|
const report_generator_1 = __importDefault(require("./helpers/report_generator"));
|
|
11
15
|
const uploader_1 = __importDefault(require("./helpers/uploader"));
|
|
12
|
-
const
|
|
13
|
-
const
|
|
16
|
+
const os_1 = __importDefault(require("os"));
|
|
17
|
+
const api_1 = require("./api");
|
|
18
|
+
const summary_formatter_1 = __importDefault(require("./summary_formatter"));
|
|
19
|
+
const constants_1 = require("./helpers/constants");
|
|
20
|
+
const axios_client_1 = require("../configuration/axios_client");
|
|
14
21
|
//User token
|
|
15
22
|
const TOKEN = process.env.TOKEN;
|
|
16
23
|
class BVTAnalysisFormatter extends _1.default {
|
|
@@ -19,28 +26,62 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
19
26
|
this.reportGenerator = new report_generator_1.default();
|
|
20
27
|
this.uploader = new uploader_1.default(this.reportGenerator);
|
|
21
28
|
this.exit = false;
|
|
29
|
+
this.rootCauseArray = [];
|
|
30
|
+
this.summaryFormatter = new summary_formatter_1.default(options);
|
|
31
|
+
BVTAnalysisFormatter.reportGenerator = this.reportGenerator;
|
|
32
|
+
this.rootCauseArray = [];
|
|
33
|
+
this.failedStepsIndex = [];
|
|
34
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex = process.env.RERUN
|
|
35
|
+
? JSON.parse(process.env.RERUN)
|
|
36
|
+
: null;
|
|
22
37
|
if (!TOKEN && process.env.BVT_FORMATTER === 'ANALYSIS') {
|
|
23
38
|
throw new Error('TOKEN must be set');
|
|
24
39
|
}
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
this.sendEvent(constants_1.ActionEvents.cli_run_tests);
|
|
41
|
+
options.eventBroadcaster.on('envelope', async (envelope, data) => {
|
|
42
|
+
if ((0, value_checker_1.doesHaveValue)(envelope.testCaseFinished) && data) {
|
|
43
|
+
const { rootCause, report } = data;
|
|
44
|
+
if (!rootCause.status) {
|
|
45
|
+
console.error(`Root cause: ${rootCause.failClass}\n, ${rootCause.analysis}\nfailing step: ${rootCause.failedStep}`);
|
|
46
|
+
this.rootCauseArray.push({ rootCause, report });
|
|
47
|
+
this.failedStepsIndex.push({
|
|
48
|
+
testCaseId: report.id,
|
|
49
|
+
failedStepIndex: rootCause.failedStep,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
await this.reportGenerator.handleMessage(envelope);
|
|
27
55
|
if ((0, value_checker_1.doesHaveValue)(envelope.meta) &&
|
|
28
56
|
(0, value_checker_1.doesHaveValue)(envelope.meta.runName)) {
|
|
29
57
|
this.runName = envelope.meta.runName;
|
|
30
58
|
}
|
|
31
59
|
if ((0, value_checker_1.doesHaveValue)(envelope.testRunFinished)) {
|
|
32
|
-
const report = this.reportGenerator.getReport();
|
|
33
60
|
this.START = Date.now();
|
|
34
61
|
if (process.env.BVT_FORMATTER === 'ANALYSIS') {
|
|
35
|
-
await this.analyzeReport(
|
|
62
|
+
await this.analyzeReport();
|
|
36
63
|
}
|
|
37
64
|
else {
|
|
38
|
-
await this.uploadReport(report)
|
|
65
|
+
// await this.uploadReport(report)
|
|
39
66
|
}
|
|
40
67
|
this.exit = true;
|
|
41
68
|
}
|
|
42
69
|
});
|
|
43
70
|
}
|
|
71
|
+
sendEvent(event) {
|
|
72
|
+
axios_client_1.axiosClient
|
|
73
|
+
.post(`${constants_1.SERVICES_URI.STORAGE}/event`, {
|
|
74
|
+
event,
|
|
75
|
+
}, {
|
|
76
|
+
headers: {
|
|
77
|
+
Authorization: `Bearer ${TOKEN}`,
|
|
78
|
+
'x-source': 'cucumber_js',
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
.catch((err) => {
|
|
82
|
+
// Error with events, ignoring
|
|
83
|
+
});
|
|
84
|
+
}
|
|
44
85
|
async uploadReport(report) {
|
|
45
86
|
const uploadSuccessful = await this.uploadFinalReport(report);
|
|
46
87
|
if (uploadSuccessful && report.result.status !== 'FAILED') {
|
|
@@ -51,76 +92,80 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
51
92
|
async finished() {
|
|
52
93
|
await new Promise((resolve) => {
|
|
53
94
|
const checkInterval = setInterval(() => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
95
|
+
let anyRem;
|
|
96
|
+
if (process.env.UPLOADING_TEST_CASE) {
|
|
97
|
+
anyRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
anyRem = undefined;
|
|
101
|
+
}
|
|
102
|
+
if (this.exit && (!anyRem || anyRem.length === 0)) {
|
|
103
|
+
// clearInterval(checkInterval)
|
|
104
|
+
// resolve(null)
|
|
105
|
+
if (this.reportGenerator.getReport().result.status === 'FAILED') {
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
57
111
|
}
|
|
58
112
|
}, 100); // check every 100ms
|
|
59
113
|
});
|
|
60
114
|
}
|
|
61
|
-
async analyzeReport(
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
process.exit(0);
|
|
115
|
+
async analyzeReport() {
|
|
116
|
+
if (this.rootCauseArray.length === 0 ||
|
|
117
|
+
process.env.NO_RETRAIN === 'false') {
|
|
118
|
+
if (this.rootCauseArray.length === 0) {
|
|
119
|
+
this.log('No test failed. No need to retrain\n');
|
|
67
120
|
}
|
|
68
|
-
process.
|
|
121
|
+
if (process.env.NO_RETRAIN === 'false') {
|
|
122
|
+
this.log('Retraining is skipped since the failed step contains an API request\n');
|
|
123
|
+
}
|
|
124
|
+
// const uploadSuccessful = await this.uploadFinalReport(report)
|
|
125
|
+
// process.exit(0)
|
|
126
|
+
this.exit = true;
|
|
127
|
+
return;
|
|
69
128
|
}
|
|
70
129
|
//checking if the type of report.result is JsonResultFailed or not
|
|
71
130
|
this.log('Some tests failed, starting the retraining...\n');
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await this.uploadFinalReport(report);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const finalReport = await this.processTestCases(report);
|
|
78
|
-
const uploadSuccessful = await this.uploadFinalReport(finalReport);
|
|
79
|
-
if (finalReport.result.status !== 'FAILED' && uploadSuccessful) {
|
|
80
|
-
process.exit(0);
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
131
|
+
await this.processTestCases();
|
|
132
|
+
if (this.reportGenerator.getReport().result.status === 'FAILED') {
|
|
83
133
|
process.exit(1);
|
|
84
134
|
}
|
|
135
|
+
process.exit(0);
|
|
85
136
|
}
|
|
86
|
-
async processTestCases(
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
const modifiedTestCase = await this.processTestCase(testCase, report);
|
|
90
|
-
finalTestCases.push(modifiedTestCase);
|
|
137
|
+
async processTestCases() {
|
|
138
|
+
for (const { rootCause, report } of this.rootCauseArray) {
|
|
139
|
+
await this.processTestCase(rootCause, report);
|
|
91
140
|
}
|
|
92
|
-
const finalResult = finalTestCases.some((tc) => tc.result.status !== 'PASSED')
|
|
93
|
-
? report.result
|
|
94
|
-
: {
|
|
95
|
-
...report.result,
|
|
96
|
-
status: 'PASSED',
|
|
97
|
-
};
|
|
98
|
-
return {
|
|
99
|
-
result: finalResult,
|
|
100
|
-
testCases: finalTestCases,
|
|
101
|
-
};
|
|
102
141
|
}
|
|
103
|
-
async processTestCase(
|
|
104
|
-
|
|
105
|
-
|
|
142
|
+
async processTestCase(rootCause, report) {
|
|
143
|
+
const failedTestSteps = rootCause.failedStep;
|
|
144
|
+
if (BVTAnalysisFormatter.reRunFailedStepsIndex &&
|
|
145
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex.length > 0) {
|
|
146
|
+
const previousRun = BVTAnalysisFormatter.reRunFailedStepsIndex[0];
|
|
147
|
+
if (previousRun.failedStepIndex === failedTestSteps) {
|
|
148
|
+
console.log('Same step has failed again, skipping retraining');
|
|
149
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
|
|
106
153
|
}
|
|
107
|
-
const
|
|
108
|
-
.map((step, i) => (step.result.status !== 'PASSED' ? i : null))
|
|
109
|
-
.filter((i) => i !== null);
|
|
110
|
-
const retrainStats = await this.retrain(failedTestSteps, testCase);
|
|
154
|
+
const retrainStats = await this.retrain(failedTestSteps, report);
|
|
111
155
|
if (!retrainStats) {
|
|
112
|
-
return
|
|
156
|
+
return;
|
|
113
157
|
}
|
|
114
|
-
|
|
115
|
-
...
|
|
158
|
+
await this.uploader.modifyTestCase({
|
|
159
|
+
...report,
|
|
116
160
|
retrainStats,
|
|
117
|
-
};
|
|
161
|
+
});
|
|
162
|
+
await this.rerun(report);
|
|
118
163
|
}
|
|
119
164
|
async uploadFinalReport(finalReport) {
|
|
120
165
|
let success = true;
|
|
121
166
|
try {
|
|
122
167
|
const { projectId, runId } = await this.uploader.uploadRun(finalReport, this.runName);
|
|
123
|
-
|
|
168
|
+
logReportLink(runId, projectId);
|
|
124
169
|
}
|
|
125
170
|
catch (err) {
|
|
126
171
|
this.log('Error uploading report\n');
|
|
@@ -129,12 +174,56 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
129
174
|
}
|
|
130
175
|
success = false;
|
|
131
176
|
}
|
|
177
|
+
finally {
|
|
178
|
+
try {
|
|
179
|
+
(0, fs_1.writeFileSync)(path_1.default.join(this.reportGenerator.reportFolder, 'report.json'), JSON.stringify(finalReport, null, 2), 'utf-8');
|
|
180
|
+
}
|
|
181
|
+
catch (e) {
|
|
182
|
+
console.error('failed to write report.json to local disk');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
132
185
|
//this.log(JSON.stringify(finalReport, null, 2))
|
|
133
186
|
return success;
|
|
134
187
|
}
|
|
135
188
|
async retrain(failedTestCases, testCase) {
|
|
136
|
-
const
|
|
137
|
-
|
|
189
|
+
const data = await (0, api_1.getProjectByAccessKey)(TOKEN);
|
|
190
|
+
const currentTimestampInSeconds = Math.floor(Date.now() / 1000);
|
|
191
|
+
if (data.project.expriration_date < currentTimestampInSeconds) {
|
|
192
|
+
console.log('Warning: Your project has expired, retraining is restricted. Please contact sales.');
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
return await this.call_cucumber_client(failedTestCases, testCase);
|
|
196
|
+
}
|
|
197
|
+
async rerun(report) {
|
|
198
|
+
await new Promise((resolve) => {
|
|
199
|
+
const node_path = process.argv.shift();
|
|
200
|
+
const args = [
|
|
201
|
+
path_1.default.join(process.cwd(), 'node_modules', '@dev-blinq', 'cucumber-js', 'bin', 'cucumber.js'),
|
|
202
|
+
'--name',
|
|
203
|
+
`^${report.scenarioName}$`,
|
|
204
|
+
'--exit',
|
|
205
|
+
'--format',
|
|
206
|
+
'bvt',
|
|
207
|
+
'--run-name',
|
|
208
|
+
`${report.scenarioName}@debug`,
|
|
209
|
+
path_1.default.join(process.cwd(), 'features', `${report.featureName}.feature`),
|
|
210
|
+
];
|
|
211
|
+
const cucumberClient = (0, child_process_1.spawn)(node_path, args, {
|
|
212
|
+
env: {
|
|
213
|
+
...process.env,
|
|
214
|
+
RERUN: JSON.stringify(this.failedStepsIndex),
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
cucumberClient.stdout.on('data', (data) => {
|
|
218
|
+
console.log(data.toString());
|
|
219
|
+
});
|
|
220
|
+
cucumberClient.stderr.on('data', (data) => {
|
|
221
|
+
console.error(data.toString());
|
|
222
|
+
});
|
|
223
|
+
cucumberClient.on('close', () => {
|
|
224
|
+
resolve();
|
|
225
|
+
});
|
|
226
|
+
});
|
|
138
227
|
}
|
|
139
228
|
async call_cucumber_client(stepsToRetrain, testCase) {
|
|
140
229
|
return new Promise((resolve, reject) => {
|
|
@@ -143,14 +232,21 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
143
232
|
process.cwd(),
|
|
144
233
|
path_1.default.join(process.cwd(), testCase.uri),
|
|
145
234
|
`${testCase.scenarioName}`,
|
|
146
|
-
|
|
235
|
+
'undefined',
|
|
236
|
+
`${stepsToRetrain},`,
|
|
147
237
|
];
|
|
148
238
|
if (process.env.BLINQ_ENV) {
|
|
149
239
|
args.push(`--env=${process.env.BLINQ_ENV}`);
|
|
150
240
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
241
|
+
if (!(0, fs_1.existsSync)(path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp'))) {
|
|
242
|
+
(0, promises_1.mkdir)(path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp'), {
|
|
243
|
+
recursive: true,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
(0, tmp_1.tmpName)(async (err, name) => {
|
|
247
|
+
const tempFile = path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp', path_1.default.basename(name));
|
|
248
|
+
console.log('File path: ', tempFile);
|
|
249
|
+
await (0, promises_1.writeFile)(tempFile, '', 'utf-8');
|
|
154
250
|
args.push(`--temp-file=${tempFile}`);
|
|
155
251
|
const cucumberClient = (0, child_process_1.spawn)('node', [cucumber_client_path, ...args], {
|
|
156
252
|
env: {
|
|
@@ -163,31 +259,63 @@ class BVTAnalysisFormatter extends _1.default {
|
|
|
163
259
|
cucumberClient.stderr.on('data', (data) => {
|
|
164
260
|
console.error(data.toString());
|
|
165
261
|
});
|
|
166
|
-
cucumberClient.on('close', (code) => {
|
|
262
|
+
cucumberClient.on('close', async (code) => {
|
|
167
263
|
if (code === 0) {
|
|
168
264
|
const reportData = (0, fs_1.readFileSync)(tempFile, 'utf-8');
|
|
169
265
|
const retrainStats = JSON.parse(reportData);
|
|
266
|
+
await (0, promises_1.unlink)(tempFile);
|
|
170
267
|
resolve(retrainStats);
|
|
171
268
|
}
|
|
172
269
|
else {
|
|
173
270
|
this.log('Error retraining\n');
|
|
174
|
-
|
|
271
|
+
try {
|
|
272
|
+
const reportData = (0, fs_1.readFileSync)(tempFile, 'utf-8');
|
|
273
|
+
const retrainStats = JSON.parse(reportData);
|
|
274
|
+
await (0, promises_1.unlink)(tempFile);
|
|
275
|
+
resolve(retrainStats);
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
278
|
+
this.log('Error reading scenario report\n ' + e);
|
|
279
|
+
resolve(null);
|
|
280
|
+
}
|
|
175
281
|
}
|
|
176
282
|
});
|
|
177
283
|
});
|
|
178
284
|
});
|
|
179
285
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
reportLinkBaseUrl = 'http://localhost:3000';
|
|
286
|
+
getAppDataDir() {
|
|
287
|
+
if (process.env.BLINQ_APPDATA_DIR) {
|
|
288
|
+
return process.env.BLINQ_APPDATA_DIR;
|
|
184
289
|
}
|
|
185
|
-
|
|
186
|
-
|
|
290
|
+
let appDataDir;
|
|
291
|
+
switch (process.platform) {
|
|
292
|
+
case 'win32':
|
|
293
|
+
appDataDir = process.env.APPDATA;
|
|
294
|
+
break;
|
|
295
|
+
case 'darwin':
|
|
296
|
+
appDataDir = path_1.default.join(os_1.default.homedir(), 'Library', 'Application Support');
|
|
297
|
+
break;
|
|
298
|
+
default:
|
|
299
|
+
appDataDir = path_1.default.join(os_1.default.homedir(), '.config');
|
|
300
|
+
break;
|
|
187
301
|
}
|
|
188
|
-
|
|
189
|
-
this.log(`Report link: ${reportLink}\n`);
|
|
302
|
+
return appDataDir;
|
|
190
303
|
}
|
|
191
304
|
}
|
|
192
305
|
exports.default = BVTAnalysisFormatter;
|
|
306
|
+
function logReportLink(runId, projectId) {
|
|
307
|
+
let reportLinkBaseUrl = 'https://app.blinq.io';
|
|
308
|
+
if (process.env.NODE_ENV_BLINQ === 'local') {
|
|
309
|
+
reportLinkBaseUrl = 'http://localhost:3000';
|
|
310
|
+
}
|
|
311
|
+
else if (process.env.NODE_ENV_BLINQ === 'dev') {
|
|
312
|
+
reportLinkBaseUrl = 'https://dev.app.blinq.io';
|
|
313
|
+
}
|
|
314
|
+
else if (process.env.NODE_ENV_BLINQ === 'stage') {
|
|
315
|
+
reportLinkBaseUrl = 'https://stage.app.blinq.io';
|
|
316
|
+
}
|
|
317
|
+
const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
|
|
318
|
+
console.log(`Report link: ${reportLink}\n`);
|
|
319
|
+
}
|
|
320
|
+
exports.logReportLink = logReportLink;
|
|
193
321
|
//# sourceMappingURL=bvt_analysis_formatter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bvt_analysis_formatter.js","sourceRoot":"","sources":["../../src/formatter/bvt_analysis_formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Envelope, Meta } from '@cucumber/messages'\nimport { spawn } from 'child_process'\nimport path from 'path'\nimport Formatter, { IFormatterOptions } from '.'\nimport { doesHaveValue } from '../value_checker'\nimport ReportGenerator, {\n JsonFixedByAi,\n JsonReport,\n JsonResultFailed,\n JsonResultPassed,\n JsonStep,\n JsonTestProgress,\n JsonTestResult,\n RetrainStats,\n} from './helpers/report_generator'\nimport ReportUploader from './helpers/uploader'\nimport { readFileSync } from 'fs'\nimport { withFile } from 'tmp-promise'\n//User token\nconst TOKEN = process.env.TOKEN\ninterface MetaMessage extends Meta {\n runName: string\n}\n\ninterface EnvelopeWithMetaMessage extends Envelope {\n meta: MetaMessage\n}\nexport default class BVTAnalysisFormatter extends Formatter {\n private reportGenerator = new ReportGenerator()\n private uploader = new ReportUploader(this.reportGenerator)\n private exit = false\n private START: number\n private runName: string\n constructor(options: IFormatterOptions) {\n super(options)\n if (!TOKEN && process.env.BVT_FORMATTER === 'ANALYSIS') {\n throw new Error('TOKEN must be set')\n }\n options.eventBroadcaster.on(\n 'envelope',\n async (envelope: EnvelopeWithMetaMessage) => {\n this.reportGenerator.handleMessage(envelope)\n if (\n doesHaveValue(envelope.meta) &&\n doesHaveValue(envelope.meta.runName)\n ) {\n this.runName = envelope.meta.runName\n }\n if (doesHaveValue(envelope.testRunFinished)) {\n const report = this.reportGenerator.getReport()\n this.START = Date.now()\n if (process.env.BVT_FORMATTER === 'ANALYSIS') {\n await this.analyzeReport(report)\n } else {\n await this.uploadReport(report)\n }\n this.exit = true\n }\n }\n )\n }\n\n private async uploadReport(report: JsonReport) {\n const uploadSuccessful = await this.uploadFinalReport(report)\n if (uploadSuccessful && report.result.status !== 'FAILED') {\n process.exit(0)\n }\n process.exit(1)\n }\n\n async finished(): Promise<any> {\n await new Promise((resolve) => {\n const checkInterval = setInterval(() => {\n if (this.exit) {\n clearInterval(checkInterval)\n resolve(null)\n }\n }, 100) // check every 100ms\n })\n }\n private async analyzeReport(report: JsonReport) {\n if (report.result.status === 'PASSED') {\n this.log('All tests passed. No need to retrain\\n')\n const uploadSuccessful = await this.uploadFinalReport(report)\n if (uploadSuccessful) {\n process.exit(0)\n }\n\n process.exit(1)\n }\n //checking if the type of report.result is JsonResultFailed or not\n this.log('Some tests failed, starting the retraining...\\n')\n if (!('startTime' in report.result) || !('endTime' in report.result)) {\n this.log('Unknown error occured,not retraining\\n')\n await this.uploadFinalReport(report)\n return\n }\n const finalReport = await this.processTestCases(report)\n const uploadSuccessful = await this.uploadFinalReport(finalReport)\n if (finalReport.result.status !== 'FAILED' && uploadSuccessful) {\n process.exit(0)\n } else {\n process.exit(1)\n }\n }\n private async processTestCases(report: JsonReport): Promise<JsonReport> {\n const finalTestCases = []\n for (const testCase of report.testCases) {\n const modifiedTestCase = await this.processTestCase(testCase, report)\n\n finalTestCases.push(modifiedTestCase)\n }\n const finalResult = finalTestCases.some(\n (tc) => tc.result.status !== 'PASSED'\n )\n ? report.result\n : ({\n ...report.result,\n status: 'PASSED',\n } as JsonTestResult)\n return {\n result: finalResult,\n testCases: finalTestCases,\n }\n }\n private async processTestCase(\n testCase: JsonTestProgress,\n report: JsonReport\n ): Promise<JsonTestProgress> {\n if (testCase.result.status === 'PASSED') {\n return testCase\n }\n const failedTestSteps = testCase.steps\n .map((step, i) => (step.result.status !== 'PASSED' ? i : null))\n .filter((i) => i !== null)\n const retrainStats = await this.retrain(failedTestSteps, testCase)\n\n if (!retrainStats) {\n return testCase\n }\n\n return {\n ...testCase,\n retrainStats,\n }\n }\n\n private async uploadFinalReport(finalReport: JsonReport) {\n let success = true\n try {\n const { projectId, runId } = await this.uploader.uploadRun(\n finalReport,\n this.runName\n )\n this.logReportLink(runId, projectId)\n } catch (err) {\n this.log('Error uploading report\\n')\n if ('stack' in err) {\n this.log(err.stack)\n }\n success = false\n }\n\n //this.log(JSON.stringify(finalReport, null, 2))\n return success\n }\n private async retrain(\n failedTestCases: number[],\n testCase: JsonTestProgress\n ): Promise<RetrainStats | null> {\n const stepsToRetrain = testCase.steps.map((_, i) => i)\n return await this.call_cucumber_client(stepsToRetrain, testCase)\n }\n\n private async call_cucumber_client(\n stepsToRetrain: number[],\n testCase: JsonTestProgress\n ): Promise<RetrainStats | null> {\n return new Promise((resolve, reject) => {\n const cucumber_client_path = path.resolve(\n process.cwd(),\n 'node_modules',\n '@dev-blinq',\n 'cucumber_client',\n 'bin',\n 'client',\n 'cucumber.js'\n )\n\n const args: string[] = [\n process.cwd(),\n path.join(process.cwd(), testCase.uri),\n `${testCase.scenarioName}`,\n `${stepsToRetrain.join(',')}`,\n ]\n\n if (process.env.BLINQ_ENV) {\n args.push(`--env=${process.env.BLINQ_ENV}`)\n }\n // const temporaryFileTask = await import('tempy')\n withFile(async ({ path: tempFile, fd }) => {\n // when this function returns or throws - release the file\n args.push(`--temp-file=${tempFile}`)\n const cucumberClient = spawn('node', [cucumber_client_path, ...args], {\n env: {\n ...process.env,\n },\n })\n\n cucumberClient.stdout.on('data', (data) => {\n console.log(data.toString())\n })\n\n cucumberClient.stderr.on('data', (data) => {\n console.error(data.toString())\n })\n\n cucumberClient.on('close', (code) => {\n if (code === 0) {\n const reportData = readFileSync(tempFile, 'utf-8')\n const retrainStats = JSON.parse(reportData) as RetrainStats\n resolve(retrainStats)\n } else {\n this.log('Error retraining\\n')\n resolve(null)\n }\n })\n })\n })\n }\n private logReportLink(runId: string, projectId: string) {\n let reportLinkBaseUrl = 'https://app.blinq.io'\n if (process.env.NODE_ENV_BLINQ === 'local') {\n reportLinkBaseUrl = 'http://localhost:3000'\n } else if (process.env.NODE_ENV_BLINQ === 'dev') {\n reportLinkBaseUrl = 'https://dev.app.blinq.io'\n }\n const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`\n this.log(`Report link: ${reportLink}\\n`)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bvt_analysis_formatter.js","sourceRoot":"","sources":["../../src/formatter/bvt_analysis_formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Envelope, Meta } from '@cucumber/messages'\nimport { spawn } from 'child_process'\nimport { readFileSync, existsSync, writeFileSync } from 'fs'\nimport { mkdir, unlink, writeFile } from 'fs/promises'\nimport path from 'path'\nimport { tmpName } from 'tmp'\nimport Formatter, { IFormatterOptions } from '.'\nimport { doesHaveValue } from '../value_checker'\nimport ReportGenerator, {\n JsonReport,\n JsonTestProgress,\n JsonTestResult,\n RetrainStats,\n} from './helpers/report_generator'\nimport ReportUploader from './helpers/uploader'\nimport os from 'os'\nimport { getProjectByAccessKey } from './api'\nimport SummaryFormatter from './summary_formatter'\nimport { ActionEvents, SERVICES_URI } from './helpers/constants'\nimport { axiosClient } from '../configuration/axios_client'\nimport {\n FinishTestCaseResponse,\n RootCauseProps,\n} from './helpers/upload_serivce'\n\n//User token\nconst TOKEN = process.env.TOKEN\ninterface MetaMessage extends Meta {\n runName: string\n}\n\ninterface EnvelopeWithMetaMessage extends Envelope {\n meta: MetaMessage\n}\nexport default class BVTAnalysisFormatter extends Formatter {\n static reportGenerator: ReportGenerator\n static reRunFailedStepsIndex:\n | { testCaseId: string; failedStepIndex: number }[]\n | null\n private reportGenerator = new ReportGenerator()\n private uploader = new ReportUploader(this.reportGenerator)\n private exit = false\n private START: number\n private runName: string\n private failedStepsIndex: { testCaseId: string; failedStepIndex: number }[]\n private summaryFormatter: SummaryFormatter\n private rootCauseArray: {\n rootCause: RootCauseProps\n report: JsonTestProgress\n }[] = []\n\n constructor(options: IFormatterOptions) {\n super(options)\n this.summaryFormatter = new SummaryFormatter(options)\n BVTAnalysisFormatter.reportGenerator = this.reportGenerator\n this.rootCauseArray = []\n this.failedStepsIndex = []\n BVTAnalysisFormatter.reRunFailedStepsIndex = process.env.RERUN\n ? JSON.parse(process.env.RERUN)\n : null\n\n if (!TOKEN && process.env.BVT_FORMATTER === 'ANALYSIS') {\n throw new Error('TOKEN must be set')\n }\n this.sendEvent(ActionEvents.cli_run_tests)\n options.eventBroadcaster.on(\n 'envelope',\n async (envelope: EnvelopeWithMetaMessage, data?: any) => {\n if (doesHaveValue(envelope.testCaseFinished) && data) {\n const { rootCause, report } = data as FinishTestCaseResponse\n\n if (!rootCause.status) {\n console.error(\n `Root cause: ${rootCause.failClass}\\n, ${rootCause.analysis}\\nfailing step: ${rootCause.failedStep}`\n )\n this.rootCauseArray.push({ rootCause, report })\n this.failedStepsIndex.push({\n testCaseId: report.id,\n failedStepIndex: rootCause.failedStep,\n })\n }\n return\n }\n await this.reportGenerator.handleMessage(envelope)\n\n if (\n doesHaveValue(envelope.meta) &&\n doesHaveValue(envelope.meta.runName)\n ) {\n this.runName = envelope.meta.runName\n }\n if (doesHaveValue(envelope.testRunFinished)) {\n this.START = Date.now()\n if (process.env.BVT_FORMATTER === 'ANALYSIS') {\n await this.analyzeReport()\n } else {\n // await this.uploadReport(report)\n }\n this.exit = true\n }\n }\n )\n }\n\n private sendEvent(event: ActionEvents) {\n axiosClient\n .post(\n `${SERVICES_URI.STORAGE}/event`,\n {\n event,\n },\n {\n headers: {\n Authorization: `Bearer ${TOKEN}`,\n 'x-source': 'cucumber_js',\n },\n }\n )\n .catch((err) => {\n // Error with events, ignoring\n })\n }\n\n private async uploadReport(report: JsonReport) {\n const uploadSuccessful = await this.uploadFinalReport(report)\n if (uploadSuccessful && report.result.status !== 'FAILED') {\n process.exit(0)\n }\n process.exit(1)\n }\n\n async finished(): Promise<any> {\n await new Promise((resolve) => {\n const checkInterval = setInterval(() => {\n let anyRem\n if (process.env.UPLOADING_TEST_CASE) {\n anyRem = JSON.parse(process.env.UPLOADING_TEST_CASE) as string[]\n } else {\n anyRem = undefined\n }\n\n if (this.exit && (!anyRem || anyRem.length === 0)) {\n // clearInterval(checkInterval)\n // resolve(null)\n if (this.reportGenerator.getReport().result.status === 'FAILED') {\n process.exit(1)\n } else {\n process.exit(0)\n }\n }\n }, 100) // check every 100ms\n })\n }\n private async analyzeReport() {\n if (\n this.rootCauseArray.length === 0 ||\n process.env.NO_RETRAIN === 'false'\n ) {\n if (this.rootCauseArray.length === 0) {\n this.log('No test failed. No need to retrain\\n')\n }\n if (process.env.NO_RETRAIN === 'false') {\n this.log(\n 'Retraining is skipped since the failed step contains an API request\\n'\n )\n }\n // const uploadSuccessful = await this.uploadFinalReport(report)\n // process.exit(0)\n this.exit = true\n return\n }\n\n //checking if the type of report.result is JsonResultFailed or not\n\n this.log('Some tests failed, starting the retraining...\\n')\n await this.processTestCases()\n if (this.reportGenerator.getReport().result.status === 'FAILED') {\n process.exit(1)\n }\n process.exit(0)\n }\n private async processTestCases() {\n for (const { rootCause, report } of this.rootCauseArray) {\n await this.processTestCase(rootCause, report)\n }\n }\n private async processTestCase(\n rootCause: RootCauseProps,\n report: JsonTestProgress\n ) {\n const failedTestSteps = rootCause.failedStep\n\n if (\n BVTAnalysisFormatter.reRunFailedStepsIndex &&\n BVTAnalysisFormatter.reRunFailedStepsIndex.length > 0\n ) {\n const previousRun = BVTAnalysisFormatter.reRunFailedStepsIndex[0]\n if (previousRun.failedStepIndex === failedTestSteps) {\n console.log('Same step has failed again, skipping retraining')\n BVTAnalysisFormatter.reRunFailedStepsIndex.shift()\n return\n }\n BVTAnalysisFormatter.reRunFailedStepsIndex.shift()\n }\n\n const retrainStats = await this.retrain(failedTestSteps, report)\n\n if (!retrainStats) {\n return\n }\n\n await this.uploader.modifyTestCase({\n ...report,\n retrainStats,\n })\n\n await this.rerun(report)\n }\n\n private async uploadFinalReport(finalReport: JsonReport) {\n let success = true\n try {\n const { projectId, runId } = await this.uploader.uploadRun(\n finalReport,\n this.runName\n )\n logReportLink(runId, projectId)\n } catch (err) {\n this.log('Error uploading report\\n')\n if ('stack' in err) {\n this.log(err.stack)\n }\n success = false\n } finally {\n try {\n writeFileSync(\n path.join(this.reportGenerator.reportFolder, 'report.json'),\n JSON.stringify(finalReport, null, 2),\n 'utf-8'\n )\n } catch (e) {\n console.error('failed to write report.json to local disk')\n }\n }\n\n //this.log(JSON.stringify(finalReport, null, 2))\n return success\n }\n private async retrain(\n failedTestCases: number,\n testCase: JsonTestProgress\n ): Promise<RetrainStats | null> {\n const data = await getProjectByAccessKey(TOKEN)\n const currentTimestampInSeconds = Math.floor(Date.now() / 1000)\n if (data.project.expriration_date < currentTimestampInSeconds) {\n console.log(\n 'Warning: Your project has expired, retraining is restricted. Please contact sales.'\n )\n process.exit(1)\n }\n return await this.call_cucumber_client(failedTestCases, testCase)\n }\n\n private async rerun(report: JsonTestProgress) {\n await new Promise<void>((resolve) => {\n const node_path = process.argv.shift()\n const args = [\n path.join(\n process.cwd(),\n 'node_modules',\n '@dev-blinq',\n 'cucumber-js',\n 'bin',\n 'cucumber.js'\n ),\n '--name',\n `^${report.scenarioName}$`,\n '--exit',\n '--format',\n 'bvt',\n '--run-name',\n `${report.scenarioName}@debug`,\n path.join(process.cwd(), 'features', `${report.featureName}.feature`),\n ]\n const cucumberClient = spawn(node_path, args, {\n env: {\n ...process.env,\n RERUN: JSON.stringify(this.failedStepsIndex),\n },\n })\n\n cucumberClient.stdout.on('data', (data) => {\n console.log(data.toString())\n })\n\n cucumberClient.stderr.on('data', (data) => {\n console.error(data.toString())\n })\n\n cucumberClient.on('close', () => {\n resolve()\n })\n })\n }\n\n private async call_cucumber_client(\n stepsToRetrain: number,\n testCase: JsonTestProgress\n ): Promise<RetrainStats | null> {\n return new Promise((resolve, reject) => {\n const cucumber_client_path = path.resolve(\n process.cwd(),\n 'node_modules',\n '@dev-blinq',\n 'cucumber_client',\n 'bin',\n 'client',\n 'cucumber.js'\n )\n\n const args: string[] = [\n process.cwd(),\n path.join(process.cwd(), testCase.uri),\n `${testCase.scenarioName}`,\n 'undefined',\n `${stepsToRetrain},`,\n ]\n\n if (process.env.BLINQ_ENV) {\n args.push(`--env=${process.env.BLINQ_ENV}`)\n }\n\n if (!existsSync(path.join(this.getAppDataDir(), 'blinq.io', '.temp'))) {\n mkdir(path.join(this.getAppDataDir(), 'blinq.io', '.temp'), {\n recursive: true,\n })\n }\n\n tmpName(async (err, name) => {\n const tempFile = path.join(\n this.getAppDataDir(),\n 'blinq.io',\n '.temp',\n path.basename(name)\n )\n console.log('File path: ', tempFile)\n await writeFile(tempFile, '', 'utf-8')\n\n args.push(`--temp-file=${tempFile}`)\n const cucumberClient = spawn('node', [cucumber_client_path, ...args], {\n env: {\n ...process.env,\n },\n })\n\n cucumberClient.stdout.on('data', (data) => {\n console.log(data.toString())\n })\n\n cucumberClient.stderr.on('data', (data) => {\n console.error(data.toString())\n })\n\n cucumberClient.on('close', async (code) => {\n if (code === 0) {\n const reportData = readFileSync(tempFile, 'utf-8')\n const retrainStats = JSON.parse(reportData) as RetrainStats\n await unlink(tempFile)\n resolve(retrainStats)\n } else {\n this.log('Error retraining\\n')\n try {\n const reportData = readFileSync(tempFile, 'utf-8')\n const retrainStats = JSON.parse(reportData) as RetrainStats\n await unlink(tempFile)\n resolve(retrainStats)\n } catch (e) {\n this.log('Error reading scenario report\\n ' + e)\n resolve(null)\n }\n }\n })\n })\n })\n }\n\n private getAppDataDir() {\n if (process.env.BLINQ_APPDATA_DIR) {\n return process.env.BLINQ_APPDATA_DIR\n }\n\n let appDataDir: string\n\n switch (process.platform) {\n case 'win32':\n appDataDir = process.env.APPDATA!\n break\n case 'darwin':\n appDataDir = path.join(os.homedir(), 'Library', 'Application Support')\n break\n default:\n appDataDir = path.join(os.homedir(), '.config')\n break\n }\n return appDataDir\n }\n}\n\nexport function logReportLink(runId: string, projectId: string) {\n let reportLinkBaseUrl = 'https://app.blinq.io'\n if (process.env.NODE_ENV_BLINQ === 'local') {\n reportLinkBaseUrl = 'http://localhost:3000'\n } else if (process.env.NODE_ENV_BLINQ === 'dev') {\n reportLinkBaseUrl = 'https://dev.app.blinq.io'\n } else if (process.env.NODE_ENV_BLINQ === 'stage') {\n reportLinkBaseUrl = 'https://stage.app.blinq.io'\n }\n const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`\n console.log(`Report link: ${reportLink}\\n`)\n}\n"]}
|
|
@@ -2,12 +2,12 @@ import { TableCell } from '@cucumber/messages';
|
|
|
2
2
|
declare const generateTestData: (featureFileContent: string, vars?: any, fakeData?: {
|
|
3
3
|
var: string;
|
|
4
4
|
fake: string;
|
|
5
|
-
}[]) => {
|
|
5
|
+
}[], projectDir?: string) => {
|
|
6
6
|
newContent: string;
|
|
7
7
|
variables: any;
|
|
8
8
|
otherFakeData: {
|
|
9
9
|
var: string;
|
|
10
|
-
fake:
|
|
10
|
+
fake: any;
|
|
11
11
|
}[];
|
|
12
12
|
changed: boolean;
|
|
13
13
|
fakeIndex: number;
|
|
@@ -7,15 +7,29 @@ exports.generateExamplesFromFunctionGherkin = exports.generateExamplesFromFuncti
|
|
|
7
7
|
const faker_1 = require("@faker-js/faker");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const
|
|
11
|
-
|
|
10
|
+
const json5_1 = __importDefault(require("json5"));
|
|
11
|
+
const generateTestData = (featureFileContent, vars, fakeData, projectDir) => {
|
|
12
|
+
const regexp = /\{\{([^}]*\([^)]*\))\}\}/g;
|
|
12
13
|
const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g;
|
|
13
14
|
let newContent = featureFileContent;
|
|
14
15
|
let match;
|
|
16
|
+
if (!projectDir) {
|
|
17
|
+
projectDir = process.cwd();
|
|
18
|
+
}
|
|
19
|
+
const namespacePath = path_1.default.join(projectDir, 'features', 'step_definitions', 'namespaces.json');
|
|
20
|
+
let namespaces = fs_1.default.existsSync(namespacePath)
|
|
21
|
+
? JSON.parse(fs_1.default.readFileSync(namespacePath, 'utf-8'))
|
|
22
|
+
: [];
|
|
23
|
+
if (!Array.isArray(namespaces)) {
|
|
24
|
+
namespaces = [];
|
|
25
|
+
}
|
|
15
26
|
const matches = [];
|
|
16
27
|
// collect all matches
|
|
17
28
|
while ((match = regexp.exec(featureFileContent)) !== null) {
|
|
18
|
-
|
|
29
|
+
// match[0] is the full match, match[1] is the first capturing group
|
|
30
|
+
// Eg:- match[0] = {{name}}, match[1] = name
|
|
31
|
+
if (!namespaces.includes(match[1].split('.')[0]))
|
|
32
|
+
matches.push(match);
|
|
19
33
|
}
|
|
20
34
|
// find all variables in the matches
|
|
21
35
|
const variables = { ...vars };
|
|
@@ -48,7 +62,7 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
48
62
|
}
|
|
49
63
|
for (const key in variables) {
|
|
50
64
|
const variable = variables[key];
|
|
51
|
-
const fake =
|
|
65
|
+
const fake = getFakeString(variable.toFake.substring(2, variable.toFake.length - 2));
|
|
52
66
|
newContent = newContent.replaceAll(`{{${variable.var}}}`, fake);
|
|
53
67
|
variables[key].fake = fake;
|
|
54
68
|
}
|
|
@@ -58,10 +72,14 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
58
72
|
const duplicateFakeData = fakeData ? [...fakeData] : [];
|
|
59
73
|
let fakeIndex = 0;
|
|
60
74
|
while ((match = regexp.exec(featureFileContent)) !== null) {
|
|
75
|
+
if (namespaces.includes(match[1].split('.')[0]))
|
|
76
|
+
continue;
|
|
61
77
|
try {
|
|
62
|
-
const fake = duplicateFakeData &&
|
|
78
|
+
const fake = duplicateFakeData &&
|
|
79
|
+
duplicateFakeData.length > 0 &&
|
|
80
|
+
duplicateFakeData[0].var === match[0]
|
|
63
81
|
? duplicateFakeData.shift().fake
|
|
64
|
-
:
|
|
82
|
+
: getFakeString(match[0].substring(2, match[0].length - 2));
|
|
65
83
|
otherFakeData.push({
|
|
66
84
|
var: match[0],
|
|
67
85
|
fake,
|
|
@@ -71,7 +89,7 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
71
89
|
}
|
|
72
90
|
catch (err) {
|
|
73
91
|
// eslint-disable-next-line no-console
|
|
74
|
-
console.log('unknown faker variable:' + match[0])
|
|
92
|
+
//console.log('unknown faker variable:' + match[0])
|
|
75
93
|
}
|
|
76
94
|
}
|
|
77
95
|
return {
|
|
@@ -83,6 +101,33 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
|
|
|
83
101
|
};
|
|
84
102
|
};
|
|
85
103
|
exports.generateTestData = generateTestData;
|
|
104
|
+
const getFakeString = (content) => {
|
|
105
|
+
// content example: helpers.fromRegExp('#{2,9}')
|
|
106
|
+
const faking = content.split('(')[0].split('.');
|
|
107
|
+
// faking example: ['helpers', 'fromRegExp']
|
|
108
|
+
const argument = content.substring(content.indexOf('(') + 1, content.lastIndexOf(')'));
|
|
109
|
+
// argument example: '#{2,9}'
|
|
110
|
+
let fakeFunc = faker_1.faker;
|
|
111
|
+
faking.forEach((f) => {
|
|
112
|
+
fakeFunc = fakeFunc[f];
|
|
113
|
+
});
|
|
114
|
+
let regexpParam = false;
|
|
115
|
+
if (faking.length === 2 && faking[1] === 'fromRegExp') {
|
|
116
|
+
regexpParam = true;
|
|
117
|
+
}
|
|
118
|
+
if (regexpParam) {
|
|
119
|
+
return fakeFunc(new RegExp(argument));
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
return fakeFunc(json5_1.default.parse(argument));
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (!argument) {
|
|
126
|
+
return fakeFunc();
|
|
127
|
+
}
|
|
128
|
+
return fakeFunc(argument);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
86
131
|
const getDefinitionFunction = (feature_path, functionName, functionFile) => {
|
|
87
132
|
const mjsFiles = fs_1.default
|
|
88
133
|
.readdirSync(path_1.default.join(feature_path, '../step_definitions'))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature_data_format.js","sourceRoot":"","sources":["../../src/formatter/feature_data_format.ts"],"names":[],"mappings":"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","sourcesContent":["import { faker } from '@faker-js/faker'\nimport fs from 'fs'\nimport path from 'path'\nimport { TableCell } from '@cucumber/messages'\n\nconst generateTestData = (\n featureFileContent: string,\n vars?: any,\n fakeData?: {\n var: string\n fake: string\n }[]\n) => {\n const regexp = /\\{\\{([^}]+)\\}\\}/g\n const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g\n let newContent = featureFileContent\n let match: RegExpExecArray\n const matches = []\n // collect all matches\n while ((match = regexp.exec(featureFileContent)) !== null) {\n matches.push(match)\n }\n // find all variables in the matches\n const variables: any = { ...vars }\n\n if (Object.keys(variables).length > 0) {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n newContent = newContent.replaceAll(`{{${variable.var}}}`, variable.fake)\n }\n } else {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n variables[variableMatch[1]] = {\n var: variableMatch[1],\n toFake: variableMatch[2],\n }\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n const fake = faker.helpers.fake(`{{${variable.toFake}}}`)\n newContent = newContent.replaceAll(`{{${variable.var}}}`, fake)\n variables[key].fake = fake\n }\n }\n\n regexp.lastIndex = 0\n const otherFakeData = []\n const duplicateFakeData = fakeData ? [...fakeData] : []\n let fakeIndex = 0\n\n while ((match = regexp.exec(featureFileContent)) !== null) {\n try {\n const fake =\n duplicateFakeData && duplicateFakeData.length > 0\n ? duplicateFakeData.shift().fake\n : faker.helpers.fake(match[0])\n otherFakeData.push({\n var: match[0],\n fake,\n })\n newContent = newContent.replace(match[0], fake)\n fakeIndex++\n } catch (err) {\n // eslint-disable-next-line no-console\n console.log('unknown faker variable:' + match[0])\n }\n }\n\n return {\n newContent,\n variables,\n otherFakeData,\n changed: newContent !== featureFileContent,\n fakeIndex,\n }\n}\n\nconst getDefinitionFunction = (\n feature_path: string,\n functionName: string,\n functionFile: string\n) => {\n const mjsFiles = fs\n .readdirSync(path.join(feature_path, '../step_definitions'))\n .filter((file) => file === `${functionFile}.js`)\n\n if (mjsFiles.length === 0) {\n throw new Error(`File ${functionFile} not found in step_definitions folder`)\n }\n\n const [mjsData] = mjsFiles.map((file) => {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { [functionName]: func } = require(path.join(\n feature_path,\n '../step_definitions',\n file\n ))\n if (!func)\n throw new Error(`Function ${functionName} not found in file ${file}`)\n\n return func()\n })\n\n return mjsData\n}\n\nconst generateExamplesFromFunction = (\n data: string,\n feature_path: string,\n functionName: string,\n functionFile: string\n) => {\n const examples = data.split('Examples:')[1].split('\\n').slice(1)\n const headers = examples[0]\n .split('|')\n .map((header) => header.trim())\n .filter((header) => header !== '')\n const values = examples[1]\n .split('|')\n .map((value) => value.trim())\n .filter((header) => header !== '')\n\n const mjsData = getDefinitionFunction(\n feature_path,\n functionName,\n functionFile\n )\n\n const newExamples = headers.map((header) => {\n if (mjsData[header]) {\n return mjsData[header]\n }\n return values[headers.indexOf(header)]\n })\n\n let newExamplesString = data.split('Examples:')[1]\n newExamples.forEach((example, index) => {\n newExamplesString = newExamplesString.replace(values[index], example)\n })\n\n const newData = data.replace(data.split('Examples:')[1], newExamplesString)\n\n return { newData, mjsData }\n}\n\nconst generateExamplesFromFunctionGherkin = (\n headers: readonly TableCell[],\n values: readonly TableCell[],\n mjsData: any\n) => {\n const newExamples = headers.map(({ value: header }, index) => {\n if (mjsData[header]) {\n return { header, value: mjsData[header] }\n }\n return { header, value: values[index].value }\n })\n\n return newExamples\n}\n\nexport {\n generateTestData,\n generateExamplesFromFunction,\n generateExamplesFromFunctionGherkin,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"feature_data_format.js","sourceRoot":"","sources":["../../src/formatter/feature_data_format.ts"],"names":[],"mappings":"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","sourcesContent":["import { faker } from '@faker-js/faker'\nimport fs from 'fs'\nimport path from 'path'\nimport { TableCell } from '@cucumber/messages'\nimport JSON5 from 'json5'\n\nconst generateTestData = (\n featureFileContent: string,\n vars?: any,\n fakeData?: {\n var: string\n fake: string\n }[],\n projectDir?: string\n) => {\n const regexp = /\\{\\{([^}]*\\([^)]*\\))\\}\\}/g\n const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g\n let newContent = featureFileContent\n let match: RegExpExecArray\n if (!projectDir) {\n projectDir = process.cwd()\n }\n const namespacePath = path.join(\n projectDir,\n 'features',\n 'step_definitions',\n 'namespaces.json'\n )\n let namespaces: string[] = fs.existsSync(namespacePath)\n ? JSON.parse(fs.readFileSync(namespacePath, 'utf-8'))\n : []\n if (!Array.isArray(namespaces)) {\n namespaces = []\n }\n const matches = []\n // collect all matches\n while ((match = regexp.exec(featureFileContent)) !== null) {\n // match[0] is the full match, match[1] is the first capturing group\n // Eg:- match[0] = {{name}}, match[1] = name\n if (!namespaces.includes(match[1].split('.')[0])) matches.push(match)\n }\n // find all variables in the matches\n const variables: any = { ...vars }\n\n if (Object.keys(variables).length > 0) {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n newContent = newContent.replaceAll(`{{${variable.var}}}`, variable.fake)\n }\n } else {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n variables[variableMatch[1]] = {\n var: variableMatch[1],\n toFake: variableMatch[2],\n }\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n const fake = getFakeString(\n variable.toFake.substring(2, variable.toFake.length - 2)\n )\n newContent = newContent.replaceAll(`{{${variable.var}}}`, fake)\n variables[key].fake = fake\n }\n }\n\n regexp.lastIndex = 0\n const otherFakeData = []\n const duplicateFakeData = fakeData ? [...fakeData] : []\n let fakeIndex = 0\n while ((match = regexp.exec(featureFileContent)) !== null) {\n if (namespaces.includes(match[1].split('.')[0])) continue\n try {\n const fake =\n duplicateFakeData &&\n duplicateFakeData.length > 0 &&\n duplicateFakeData[0].var === match[0]\n ? duplicateFakeData.shift().fake\n : getFakeString(match[0].substring(2, match[0].length - 2))\n otherFakeData.push({\n var: match[0],\n fake,\n })\n newContent = newContent.replace(match[0], fake)\n fakeIndex++\n } catch (err) {\n // eslint-disable-next-line no-console\n //console.log('unknown faker variable:' + match[0])\n }\n }\n\n return {\n newContent,\n variables,\n otherFakeData,\n changed: newContent !== featureFileContent,\n fakeIndex,\n }\n}\n\nconst getFakeString = (content: string) => {\n // content example: helpers.fromRegExp('#{2,9}')\n const faking = content.split('(')[0].split('.')\n // faking example: ['helpers', 'fromRegExp']\n const argument = content.substring(\n content.indexOf('(') + 1,\n content.lastIndexOf(')')\n )\n // argument example: '#{2,9}'\n\n let fakeFunc: any = faker\n faking.forEach((f: string) => {\n fakeFunc = fakeFunc[f]\n })\n let regexpParam = false\n if (faking.length === 2 && faking[1] === 'fromRegExp') {\n regexpParam = true\n }\n if (regexpParam) {\n return fakeFunc(new RegExp(argument))\n }\n try {\n return fakeFunc(JSON5.parse(argument))\n } catch (error) {\n if (!argument) {\n return fakeFunc()\n }\n\n return fakeFunc(argument)\n }\n}\n\nconst getDefinitionFunction = (\n feature_path: string,\n functionName: string,\n functionFile: string\n) => {\n const mjsFiles = fs\n .readdirSync(path.join(feature_path, '../step_definitions'))\n .filter((file) => file === `${functionFile}.js`)\n\n if (mjsFiles.length === 0) {\n throw new Error(`File ${functionFile} not found in step_definitions folder`)\n }\n\n const [mjsData] = mjsFiles.map((file) => {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { [functionName]: func } = require(path.join(\n feature_path,\n '../step_definitions',\n file\n ))\n if (!func)\n throw new Error(`Function ${functionName} not found in file ${file}`)\n\n return func()\n })\n\n return mjsData\n}\n\nconst generateExamplesFromFunction = (\n data: string,\n feature_path: string,\n functionName: string,\n functionFile: string\n) => {\n const examples = data.split('Examples:')[1].split('\\n').slice(1)\n const headers = examples[0]\n .split('|')\n .map((header) => header.trim())\n .filter((header) => header !== '')\n const values = examples[1]\n .split('|')\n .map((value) => value.trim())\n .filter((header) => header !== '')\n\n const mjsData = getDefinitionFunction(\n feature_path,\n functionName,\n functionFile\n )\n\n const newExamples = headers.map((header) => {\n if (mjsData[header]) {\n return mjsData[header]\n }\n return values[headers.indexOf(header)]\n })\n\n let newExamplesString = data.split('Examples:')[1]\n newExamples.forEach((example, index) => {\n newExamplesString = newExamplesString.replace(values[index], example)\n })\n\n const newData = data.replace(data.split('Examples:')[1], newExamplesString)\n\n return { newData, mjsData }\n}\n\nconst generateExamplesFromFunctionGherkin = (\n headers: readonly TableCell[],\n values: readonly TableCell[],\n mjsData: any\n) => {\n const newExamples = headers.map(({ value: header }, index) => {\n if (mjsData[header]) {\n return { header, value: mjsData[header] }\n }\n return { header, value: values[index].value }\n })\n\n return newExamples\n}\n\nexport {\n generateTestData,\n generateExamplesFromFunction,\n generateExamplesFromFunctionGherkin,\n}\n"]}
|