@dev-blinq/cucumber-js 1.0.69-dev → 1.0.69-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.
Files changed (35) hide show
  1. package/bin/download-install.js +48 -32
  2. package/lib/api/gherkin.js +6 -1
  3. package/lib/api/gherkin.js.map +1 -1
  4. package/lib/configuration/axios_client.js +1 -1
  5. package/lib/configuration/axios_client.js.map +1 -1
  6. package/lib/formatter/api.d.ts +2 -0
  7. package/lib/formatter/api.js +53 -0
  8. package/lib/formatter/api.js.map +1 -0
  9. package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
  10. package/lib/formatter/bvt_analysis_formatter.js +213 -73
  11. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  12. package/lib/formatter/feature_data_format.d.ts +2 -2
  13. package/lib/formatter/feature_data_format.js +52 -7
  14. package/lib/formatter/feature_data_format.js.map +1 -1
  15. package/lib/formatter/helpers/constants.d.ts +44 -0
  16. package/lib/formatter/helpers/constants.js +50 -0
  17. package/lib/formatter/helpers/constants.js.map +1 -0
  18. package/lib/formatter/helpers/report_generator.d.ts +34 -1
  19. package/lib/formatter/helpers/report_generator.js +235 -19
  20. package/lib/formatter/helpers/report_generator.js.map +1 -1
  21. package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
  22. package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
  23. package/lib/formatter/helpers/upload_serivce.d.ts +15 -2
  24. package/lib/formatter/helpers/upload_serivce.js +145 -16
  25. package/lib/formatter/helpers/upload_serivce.js.map +1 -1
  26. package/lib/formatter/helpers/uploader.d.ts +2 -1
  27. package/lib/formatter/helpers/uploader.js +71 -9
  28. package/lib/formatter/helpers/uploader.js.map +1 -1
  29. package/lib/runtime/test_case_runner.d.ts +1 -0
  30. package/lib/runtime/test_case_runner.js +10 -1
  31. package/lib/runtime/test_case_runner.js.map +1 -1
  32. package/lib/version.d.ts +1 -1
  33. package/lib/version.js +1 -1
  34. package/lib/version.js.map +1 -1
  35. package/package.json +3 -2
@@ -3,14 +3,23 @@ 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 fs_1 = require("fs");
13
- const tmp_promise_1 = require("tmp-promise");
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");
21
+ const util_1 = require("util");
22
+ const child_process_2 = require("child_process");
14
23
  //User token
15
24
  const TOKEN = process.env.TOKEN;
16
25
  class BVTAnalysisFormatter extends _1.default {
@@ -19,28 +28,62 @@ class BVTAnalysisFormatter extends _1.default {
19
28
  this.reportGenerator = new report_generator_1.default();
20
29
  this.uploader = new uploader_1.default(this.reportGenerator);
21
30
  this.exit = false;
31
+ this.rootCauseArray = [];
32
+ this.summaryFormatter = new summary_formatter_1.default(options);
33
+ BVTAnalysisFormatter.reportGenerator = this.reportGenerator;
34
+ this.rootCauseArray = [];
35
+ this.failedStepsIndex = [];
36
+ BVTAnalysisFormatter.reRunFailedStepsIndex = process.env.RERUN
37
+ ? JSON.parse(process.env.RERUN)
38
+ : null;
22
39
  if (!TOKEN && process.env.BVT_FORMATTER === 'ANALYSIS') {
23
40
  throw new Error('TOKEN must be set');
24
41
  }
25
- options.eventBroadcaster.on('envelope', async (envelope) => {
26
- this.reportGenerator.handleMessage(envelope);
42
+ this.sendEvent(constants_1.ActionEvents.cli_run_tests);
43
+ options.eventBroadcaster.on('envelope', async (envelope, data) => {
44
+ if ((0, value_checker_1.doesHaveValue)(envelope.testCaseFinished) && data) {
45
+ const { rootCause, report } = data;
46
+ if (!rootCause.status) {
47
+ console.error(`Root cause: ${rootCause.failClass}\n, ${rootCause.analysis}\nfailing step: ${rootCause.failedStep}`);
48
+ this.rootCauseArray.push({ rootCause, report });
49
+ this.failedStepsIndex.push({
50
+ testCaseId: report.id,
51
+ failedStepIndex: rootCause.failedStep,
52
+ });
53
+ }
54
+ return;
55
+ }
56
+ await this.reportGenerator.handleMessage(envelope);
27
57
  if ((0, value_checker_1.doesHaveValue)(envelope.meta) &&
28
58
  (0, value_checker_1.doesHaveValue)(envelope.meta.runName)) {
29
59
  this.runName = envelope.meta.runName;
30
60
  }
31
61
  if ((0, value_checker_1.doesHaveValue)(envelope.testRunFinished)) {
32
- const report = this.reportGenerator.getReport();
33
62
  this.START = Date.now();
34
63
  if (process.env.BVT_FORMATTER === 'ANALYSIS') {
35
- await this.analyzeReport(report);
64
+ await this.analyzeReport();
36
65
  }
37
66
  else {
38
- await this.uploadReport(report);
67
+ // await this.uploadReport(report)
39
68
  }
40
69
  this.exit = true;
41
70
  }
42
71
  });
43
72
  }
73
+ sendEvent(event) {
74
+ axios_client_1.axiosClient
75
+ .post(`${constants_1.SERVICES_URI.STORAGE}/event`, {
76
+ event,
77
+ }, {
78
+ headers: {
79
+ Authorization: `Bearer ${TOKEN}`,
80
+ 'x-source': 'cucumber_js',
81
+ },
82
+ })
83
+ .catch((err) => {
84
+ // Error with events, ignoring
85
+ });
86
+ }
44
87
  async uploadReport(report) {
45
88
  const uploadSuccessful = await this.uploadFinalReport(report);
46
89
  if (uploadSuccessful && report.result.status !== 'FAILED') {
@@ -51,77 +94,80 @@ class BVTAnalysisFormatter extends _1.default {
51
94
  async finished() {
52
95
  await new Promise((resolve) => {
53
96
  const checkInterval = setInterval(() => {
54
- if (this.exit) {
55
- clearInterval(checkInterval);
56
- resolve(null);
97
+ let anyRem;
98
+ if (process.env.UPLOADING_TEST_CASE) {
99
+ anyRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
100
+ }
101
+ else {
102
+ anyRem = undefined;
103
+ }
104
+ if (this.exit && (!anyRem || anyRem.length === 0)) {
105
+ // clearInterval(checkInterval)
106
+ // resolve(null)
107
+ if (this.reportGenerator.getReport().result.status === 'FAILED') {
108
+ process.exit(1);
109
+ }
110
+ else {
111
+ process.exit(0);
112
+ }
57
113
  }
58
114
  }, 100); // check every 100ms
59
115
  });
60
116
  }
61
- async analyzeReport(report) {
62
- if (report.result.status === 'PASSED') {
63
- this.log('All tests passed. No need to retrain\n');
64
- const uploadSuccessful = await this.uploadFinalReport(report);
65
- if (uploadSuccessful) {
66
- process.exit(0);
117
+ async analyzeReport() {
118
+ if (this.rootCauseArray.length === 0 ||
119
+ process.env.NO_RETRAIN === 'false') {
120
+ if (this.rootCauseArray.length === 0) {
121
+ this.log('No test failed. No need to retrain\n');
67
122
  }
68
- process.exit(1);
123
+ if (process.env.NO_RETRAIN === 'false') {
124
+ this.log('Retraining is skipped since the failed step contains an API request\n');
125
+ }
126
+ // const uploadSuccessful = await this.uploadFinalReport(report)
127
+ // process.exit(0)
128
+ this.exit = true;
129
+ return;
69
130
  }
70
131
  //checking if the type of report.result is JsonResultFailed or not
71
132
  this.log('Some tests failed, starting the retraining...\n');
72
- if (!('startTime' in report.result) || !('endTime' in report.result)) {
73
- this.log('Unknown error occured,not retraining\n');
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 {
133
+ await this.processTestCases();
134
+ if (this.reportGenerator.getReport().result.status === 'FAILED') {
83
135
  process.exit(1);
84
136
  }
137
+ process.exit(0);
85
138
  }
86
- async processTestCases(report) {
87
- const finalTestCases = [];
88
- for (const testCase of report.testCases) {
89
- const modifiedTestCase = await this.processTestCase(testCase, report);
90
- finalTestCases.push(modifiedTestCase);
139
+ async processTestCases() {
140
+ for (const { rootCause, report } of this.rootCauseArray) {
141
+ await this.processTestCase(rootCause, report);
91
142
  }
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
- env: report.env
102
- };
103
- }
104
- async processTestCase(testCase, report) {
105
- if (testCase.result.status === 'PASSED') {
106
- return testCase;
143
+ }
144
+ async processTestCase(rootCause, report) {
145
+ const failedTestSteps = rootCause.failedStep;
146
+ if (BVTAnalysisFormatter.reRunFailedStepsIndex &&
147
+ BVTAnalysisFormatter.reRunFailedStepsIndex.length > 0) {
148
+ const previousRun = BVTAnalysisFormatter.reRunFailedStepsIndex[0];
149
+ if (previousRun.failedStepIndex === failedTestSteps) {
150
+ console.log('Same step has failed again, skipping retraining');
151
+ BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
152
+ return;
153
+ }
154
+ BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
107
155
  }
108
- const failedTestSteps = testCase.steps
109
- .map((step, i) => (step.result.status !== 'PASSED' ? i : null))
110
- .filter((i) => i !== null);
111
- const retrainStats = await this.retrain(failedTestSteps, testCase);
156
+ const retrainStats = await this.retrain(failedTestSteps, report);
112
157
  if (!retrainStats) {
113
- return testCase;
158
+ return;
114
159
  }
115
- return {
116
- ...testCase,
160
+ await this.uploader.modifyTestCase({
161
+ ...report,
117
162
  retrainStats,
118
- };
163
+ });
164
+ await this.rerun(report);
119
165
  }
120
166
  async uploadFinalReport(finalReport) {
121
167
  let success = true;
122
168
  try {
123
169
  const { projectId, runId } = await this.uploader.uploadRun(finalReport, this.runName);
124
- this.logReportLink(runId, projectId);
170
+ logReportLink(runId, projectId);
125
171
  }
126
172
  catch (err) {
127
173
  this.log('Error uploading report\n');
@@ -130,12 +176,56 @@ class BVTAnalysisFormatter extends _1.default {
130
176
  }
131
177
  success = false;
132
178
  }
179
+ finally {
180
+ try {
181
+ (0, fs_1.writeFileSync)(path_1.default.join(this.reportGenerator.reportFolder, 'report.json'), JSON.stringify(finalReport, null, 2), 'utf-8');
182
+ }
183
+ catch (e) {
184
+ console.error('failed to write report.json to local disk');
185
+ }
186
+ }
133
187
  //this.log(JSON.stringify(finalReport, null, 2))
134
188
  return success;
135
189
  }
136
190
  async retrain(failedTestCases, testCase) {
137
- const stepsToRetrain = testCase.steps.map((_, i) => i);
138
- return await this.call_cucumber_client(stepsToRetrain, testCase);
191
+ const data = await (0, api_1.getProjectByAccessKey)(TOKEN);
192
+ const currentTimestampInSeconds = Math.floor(Date.now() / 1000);
193
+ if (data.project.expriration_date < currentTimestampInSeconds) {
194
+ console.log('Warning: Your project has expired, retraining is restricted. Please contact sales.');
195
+ process.exit(1);
196
+ }
197
+ return await this.call_cucumber_client(failedTestCases, testCase);
198
+ }
199
+ async rerun(report) {
200
+ await new Promise((resolve) => {
201
+ const node_path = process.argv.shift();
202
+ const args = [
203
+ path_1.default.join(process.cwd(), 'node_modules', '@dev-blinq', 'cucumber-js', 'bin', 'cucumber.js'),
204
+ '--name',
205
+ `^${report.scenarioName}$`,
206
+ '--exit',
207
+ '--format',
208
+ 'bvt',
209
+ '--run-name',
210
+ `${report.scenarioName}@debug`,
211
+ path_1.default.join(process.cwd(), 'features', `${report.featureName}.feature`),
212
+ ];
213
+ const cucumberClient = (0, child_process_1.spawn)(node_path, args, {
214
+ env: {
215
+ ...process.env,
216
+ RERUN: JSON.stringify(this.failedStepsIndex),
217
+ },
218
+ });
219
+ cucumberClient.stdout.on('data', (data) => {
220
+ console.log(data.toString());
221
+ });
222
+ cucumberClient.stderr.on('data', (data) => {
223
+ console.error(data.toString());
224
+ });
225
+ cucumberClient.on('close', () => {
226
+ resolve();
227
+ });
228
+ });
139
229
  }
140
230
  async call_cucumber_client(stepsToRetrain, testCase) {
141
231
  return new Promise((resolve, reject) => {
@@ -144,14 +234,21 @@ class BVTAnalysisFormatter extends _1.default {
144
234
  process.cwd(),
145
235
  path_1.default.join(process.cwd(), testCase.uri),
146
236
  `${testCase.scenarioName}`,
147
- `${stepsToRetrain.join(',')}`,
237
+ 'undefined',
238
+ `${stepsToRetrain},`,
148
239
  ];
149
240
  if (process.env.BLINQ_ENV) {
150
241
  args.push(`--env=${process.env.BLINQ_ENV}`);
151
242
  }
152
- // const temporaryFileTask = await import('tempy')
153
- (0, tmp_promise_1.withFile)(async ({ path: tempFile, fd }) => {
154
- // when this function returns or throws - release the file
243
+ if (!(0, fs_1.existsSync)(path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp'))) {
244
+ (0, promises_1.mkdir)(path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp'), {
245
+ recursive: true,
246
+ });
247
+ }
248
+ (0, tmp_1.tmpName)(async (err, name) => {
249
+ const tempFile = path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp', path_1.default.basename(name));
250
+ console.log('File path: ', tempFile);
251
+ await (0, promises_1.writeFile)(tempFile, '', 'utf-8');
155
252
  args.push(`--temp-file=${tempFile}`);
156
253
  const cucumberClient = (0, child_process_1.spawn)('node', [cucumber_client_path, ...args], {
157
254
  env: {
@@ -164,31 +261,74 @@ class BVTAnalysisFormatter extends _1.default {
164
261
  cucumberClient.stderr.on('data', (data) => {
165
262
  console.error(data.toString());
166
263
  });
167
- cucumberClient.on('close', (code) => {
264
+ cucumberClient.on('close', async (code) => {
168
265
  if (code === 0) {
169
266
  const reportData = (0, fs_1.readFileSync)(tempFile, 'utf-8');
170
267
  const retrainStats = JSON.parse(reportData);
268
+ await (0, promises_1.unlink)(tempFile);
171
269
  resolve(retrainStats);
172
270
  }
173
271
  else {
174
272
  this.log('Error retraining\n');
175
- resolve(null);
273
+ try {
274
+ const reportData = (0, fs_1.readFileSync)(tempFile, 'utf-8');
275
+ const retrainStats = JSON.parse(reportData);
276
+ await (0, promises_1.unlink)(tempFile);
277
+ resolve(retrainStats);
278
+ }
279
+ catch (e) {
280
+ this.log('Error reading scenario report\n ' + e);
281
+ resolve(null);
282
+ }
176
283
  }
177
284
  });
178
285
  });
179
286
  });
180
287
  }
181
- logReportLink(runId, projectId) {
182
- let reportLinkBaseUrl = 'https://app.blinq.io';
183
- if (process.env.NODE_ENV_BLINQ === 'local') {
184
- reportLinkBaseUrl = 'http://localhost:3000';
288
+ getAppDataDir() {
289
+ if (process.env.BLINQ_APPDATA_DIR) {
290
+ return process.env.BLINQ_APPDATA_DIR;
185
291
  }
186
- else if (process.env.NODE_ENV_BLINQ === 'dev') {
187
- reportLinkBaseUrl = 'https://dev.app.blinq.io';
292
+ let appDataDir;
293
+ switch (process.platform) {
294
+ case 'win32':
295
+ appDataDir = process.env.APPDATA;
296
+ break;
297
+ case 'darwin':
298
+ appDataDir = path_1.default.join(os_1.default.homedir(), 'Library', 'Application Support');
299
+ break;
300
+ default:
301
+ appDataDir = path_1.default.join(os_1.default.homedir(), '.config');
302
+ break;
188
303
  }
189
- const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
190
- this.log(`Report link: ${reportLink}\n`);
304
+ return appDataDir;
191
305
  }
192
306
  }
193
307
  exports.default = BVTAnalysisFormatter;
308
+ function logReportLink(runId, projectId) {
309
+ let reportLinkBaseUrl = 'https://app.blinq.io';
310
+ if (process.env.NODE_ENV_BLINQ === 'local') {
311
+ reportLinkBaseUrl = 'http://localhost:3000';
312
+ }
313
+ else if (process.env.NODE_ENV_BLINQ === 'dev') {
314
+ reportLinkBaseUrl = 'https://dev.app.blinq.io';
315
+ }
316
+ else if (process.env.NODE_ENV_BLINQ === 'stage') {
317
+ reportLinkBaseUrl = 'https://stage.app.blinq.io';
318
+ }
319
+ const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
320
+ console.log(`Report link: ${reportLink}\n`);
321
+ try {
322
+ publishReportLinkToGuacServer(reportLink);
323
+ }
324
+ catch (err) {
325
+ }
326
+ }
327
+ exports.logReportLink = logReportLink;
328
+ function publishReportLinkToGuacServer(reportLink) {
329
+ if ((0, fs_1.existsSync)("/tmp/report_publish.sh")) {
330
+ const execAsync = (0, util_1.promisify)(child_process_2.exec);
331
+ execAsync("sh /tmp/report_publish.sh " + reportLink);
332
+ }
333
+ }
194
334
  //# 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 env : report.env\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'\nimport { promisify } from 'util';\nimport { exec } from 'child_process';\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 try {\n publishReportLinkToGuacServer(reportLink);\n } catch (err) {\n }\n}\n\nfunction publishReportLinkToGuacServer(reportLink: string) {\n if (existsSync(\"/tmp/report_publish.sh\")) {\n const execAsync = promisify(exec);\n execAsync(\"sh /tmp/report_publish.sh \" + 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: string;
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 generateTestData = (featureFileContent, vars, fakeData) => {
11
- const regexp = /\{\{([^}]+)\}\}/g;
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
- matches.push(match);
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 = faker_1.faker.helpers.fake(`{{${variable.toFake}}}`);
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 && duplicateFakeData.length > 0
78
+ const fake = duplicateFakeData &&
79
+ duplicateFakeData.length > 0 &&
80
+ duplicateFakeData[0].var === match[0]
63
81
  ? duplicateFakeData.shift().fake
64
- : faker_1.faker.helpers.fake(match[0]);
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'))