@dev-blinq/cucumber-js 1.0.16 → 1.0.18-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 (33) hide show
  1. package/bin/download-install.js +167 -0
  2. package/lib/api/gherkin.js +42 -1
  3. package/lib/api/gherkin.js.map +1 -1
  4. package/lib/cli/index.js +3 -0
  5. package/lib/cli/index.js.map +1 -1
  6. package/lib/configuration/argv_parser.js +2 -1
  7. package/lib/configuration/argv_parser.js.map +1 -1
  8. package/lib/configuration/axios_client.d.ts +1 -0
  9. package/lib/configuration/axios_client.js +40 -0
  10. package/lib/configuration/axios_client.js.map +1 -0
  11. package/lib/configuration/default_configuration.js +1 -0
  12. package/lib/configuration/default_configuration.js.map +1 -1
  13. package/lib/configuration/types.d.ts +1 -0
  14. package/lib/configuration/types.js.map +1 -1
  15. package/lib/formatter/bvt_analysis_formatter.d.ts +1 -3
  16. package/lib/formatter/bvt_analysis_formatter.js +69 -110
  17. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  18. package/lib/formatter/feature_data_format.d.ts +10 -1
  19. package/lib/formatter/feature_data_format.js +58 -2
  20. package/lib/formatter/feature_data_format.js.map +1 -1
  21. package/lib/formatter/helpers/report_generator.d.ts +22 -3
  22. package/lib/formatter/helpers/report_generator.js +151 -21
  23. package/lib/formatter/helpers/report_generator.js.map +1 -1
  24. package/lib/formatter/helpers/upload_serivce.d.ts +5 -1
  25. package/lib/formatter/helpers/upload_serivce.js +73 -12
  26. package/lib/formatter/helpers/upload_serivce.js.map +1 -1
  27. package/lib/formatter/helpers/uploader.d.ts +4 -1
  28. package/lib/formatter/helpers/uploader.js +59 -6
  29. package/lib/formatter/helpers/uploader.js.map +1 -1
  30. package/lib/version.d.ts +1 -1
  31. package/lib/version.js +1 -1
  32. package/lib/version.js.map +1 -1
  33. package/package.json +6 -4
@@ -9,6 +9,8 @@ const _1 = __importDefault(require("."));
9
9
  const value_checker_1 = require("../value_checker");
10
10
  const report_generator_1 = __importDefault(require("./helpers/report_generator"));
11
11
  const uploader_1 = __importDefault(require("./helpers/uploader"));
12
+ const fs_1 = require("fs");
13
+ const tmp_promise_1 = require("tmp-promise");
12
14
  //User token
13
15
  const TOKEN = process.env.TOKEN;
14
16
  class BVTAnalysisFormatter extends _1.default {
@@ -58,7 +60,7 @@ class BVTAnalysisFormatter extends _1.default {
58
60
  }
59
61
  async analyzeReport(report) {
60
62
  if (report.result.status === 'PASSED') {
61
- this.log('All tests passed. No need to retrain\n');
63
+ this.log('No test failed. No need to retrain\n');
62
64
  const uploadSuccessful = await this.uploadFinalReport(report);
63
65
  if (uploadSuccessful) {
64
66
  process.exit(0);
@@ -66,10 +68,10 @@ class BVTAnalysisFormatter extends _1.default {
66
68
  process.exit(1);
67
69
  }
68
70
  //checking if the type of report.result is JsonResultFailed or not
69
- this.log('Some tests failed,starting the retraining...\n');
71
+ this.log('Some tests failed, starting the retraining...\n');
70
72
  if (!('startTime' in report.result) || !('endTime' in report.result)) {
71
73
  this.log('Unknown error occured,not retraining\n');
72
- await this.uploader.uploadRun(report, this.runName);
74
+ await this.uploadFinalReport(report);
73
75
  return;
74
76
  }
75
77
  const finalReport = await this.processTestCases(report);
@@ -82,108 +84,44 @@ class BVTAnalysisFormatter extends _1.default {
82
84
  }
83
85
  }
84
86
  async processTestCases(report) {
85
- const finalResults = [];
86
- const finalStepResults = [];
87
- let isFailing = true;
87
+ const finalTestCases = [];
88
88
  for (const testCase of report.testCases) {
89
- const { result, steps } = await this.processTestCase(testCase, report);
90
- finalResults.push(result);
91
- finalStepResults.push(steps);
92
- //If any of the test case fails, the whole run is considered failed
93
- if (result.status === 'FAILED') {
94
- isFailing = false;
95
- }
89
+ const modifiedTestCase = await this.processTestCase(testCase, report);
90
+ finalTestCases.push(modifiedTestCase);
96
91
  }
92
+ const finalResult = finalTestCases.some((tc) => tc.result.status !== 'PASSED')
93
+ ? report.result
94
+ : {
95
+ ...report.result,
96
+ status: 'PASSED',
97
+ };
97
98
  return {
98
- result: isFailing
99
- ? {
100
- status: 'FIXED_BY_AI',
101
- startTime: 'startTime' in report.result
102
- ? report.result.startTime
103
- : this.START,
104
- endTime: Date.now(),
105
- }
106
- : {
107
- status: 'FAILED',
108
- startTime: 'startTime' in report.result
109
- ? report.result.startTime
110
- : Date.now(),
111
- endTime: Date.now(),
112
- },
113
- testCases: report.testCases.map((testCase, i) => {
114
- return {
115
- ...testCase,
116
- result: finalResults[i],
117
- steps: testCase.steps.map((step, j) => {
118
- return {
119
- ...step,
120
- result: finalStepResults[i][j],
121
- };
122
- }),
123
- };
124
- }),
99
+ result: finalResult,
100
+ testCases: finalTestCases,
101
+ env: report.env,
125
102
  };
126
103
  }
127
104
  async processTestCase(testCase, report) {
128
105
  if (testCase.result.status === 'PASSED') {
129
- return {
130
- result: testCase.result,
131
- steps: testCase.steps.map((step) => {
132
- return step.result.status === 'PASSED'
133
- ? step.result
134
- : this.createStepResult(true, step, report);
135
- }),
136
- };
106
+ return testCase;
137
107
  }
138
- const failedTestCases = testCase.steps
108
+ const failedTestSteps = testCase.steps
139
109
  .map((step, i) => (step.result.status !== 'PASSED' ? i : null))
140
110
  .filter((i) => i !== null);
141
- const success = await this.retrain(failedTestCases, testCase);
142
- const finalResult = this.createFinalResult(success, testCase, report);
143
- return {
144
- result: finalResult,
145
- steps: testCase.steps.map((step) => step.result.status === 'PASSED'
146
- ? { ...step.result }
147
- : this.createStepResult(success, step, report)),
148
- };
149
- }
150
- createFinalResult(success, testCase, report) {
151
- const status = success ? 'FIXED_BY_AI' : 'FAILED';
152
- return {
153
- status,
154
- startTime: this.createStartTime(testCase, report),
155
- endTime: Date.now(),
156
- };
157
- }
158
- createStartTime(testCase, report) {
159
- let startTime;
160
- if ('startTime' in testCase.result) {
161
- startTime = testCase.result.startTime;
162
- }
163
- else if ('startTime' in report.result) {
164
- startTime = report.result.startTime;
111
+ const retrainStats = await this.retrain(failedTestSteps, testCase);
112
+ if (!retrainStats) {
113
+ return testCase;
165
114
  }
166
- else {
167
- startTime = Date.now();
168
- }
169
- return startTime;
170
- }
171
- createStepResult(success, step, report) {
172
- const status = success ? 'FIXED_BY_AI' : 'FAILED';
173
115
  return {
174
- status,
175
- startTime: 'startTime' in step.result
176
- ? step.result.startTime
177
- : 'startTime' in report.result
178
- ? report.result.startTime
179
- : Date.now(),
180
- endTime: Date.now(),
116
+ ...testCase,
117
+ retrainStats,
181
118
  };
182
119
  }
183
120
  async uploadFinalReport(finalReport) {
184
121
  let success = true;
185
122
  try {
186
- await this.uploader.uploadRun(finalReport, this.runName);
123
+ const { projectId, runId } = await this.uploader.uploadRun(finalReport, this.runName);
124
+ this.logReportLink(runId, projectId);
187
125
  }
188
126
  catch (err) {
189
127
  this.log('Error uploading report\n');
@@ -192,13 +130,12 @@ class BVTAnalysisFormatter extends _1.default {
192
130
  }
193
131
  success = false;
194
132
  }
195
- this.log(JSON.stringify(finalReport, null, 2));
133
+ //this.log(JSON.stringify(finalReport, null, 2))
196
134
  return success;
197
135
  }
198
136
  async retrain(failedTestCases, testCase) {
199
137
  const stepsToRetrain = testCase.steps.map((_, i) => i);
200
- const success = await this.call_cucumber_client(stepsToRetrain, testCase);
201
- return success;
138
+ return await this.call_cucumber_client(stepsToRetrain, testCase);
202
139
  }
203
140
  async call_cucumber_client(stepsToRetrain, testCase) {
204
141
  return new Promise((resolve, reject) => {
@@ -207,33 +144,55 @@ class BVTAnalysisFormatter extends _1.default {
207
144
  process.cwd(),
208
145
  path_1.default.join(process.cwd(), testCase.uri),
209
146
  `${testCase.scenarioName}`,
147
+ 'undefined',
210
148
  `${stepsToRetrain.join(',')}`,
211
149
  ];
212
150
  if (process.env.BLINQ_ENV) {
213
151
  args.push(`--env=${process.env.BLINQ_ENV}`);
214
152
  }
215
- const cucumberClient = (0, child_process_1.spawn)('node', [cucumber_client_path, ...args], {
216
- env: {
217
- ...process.env,
218
- },
219
- });
220
- cucumberClient.stdout.on('data', (data) => {
221
- console.log(data.toString());
222
- });
223
- cucumberClient.stderr.on('data', (data) => {
224
- console.error(data.toString());
225
- });
226
- cucumberClient.on('close', (code) => {
227
- if (code === 0) {
228
- resolve(true);
229
- }
230
- else {
231
- this.log('Error retraining\n');
232
- resolve(false);
233
- }
153
+ // const temporaryFileTask = await import('tempy')
154
+ (0, tmp_promise_1.withFile)(async ({ path: tempFile, fd }) => {
155
+ // when this function returns or throws - release the file
156
+ args.push(`--temp-file=${tempFile}`);
157
+ const cucumberClient = (0, child_process_1.spawn)('node', [cucumber_client_path, ...args], {
158
+ env: {
159
+ ...process.env,
160
+ },
161
+ });
162
+ cucumberClient.stdout.on('data', (data) => {
163
+ console.log(data.toString());
164
+ });
165
+ cucumberClient.stderr.on('data', (data) => {
166
+ console.error(data.toString());
167
+ });
168
+ cucumberClient.on('close', (code) => {
169
+ if (code === 0) {
170
+ const reportData = (0, fs_1.readFileSync)(tempFile, 'utf-8');
171
+ const retrainStats = JSON.parse(reportData);
172
+ resolve(retrainStats);
173
+ }
174
+ else {
175
+ this.log('Error retraining\n');
176
+ resolve(null);
177
+ }
178
+ });
234
179
  });
235
180
  });
236
181
  }
182
+ logReportLink(runId, projectId) {
183
+ let reportLinkBaseUrl = 'https://www.app.blinq.io';
184
+ if (process.env.NODE_ENV_BLINQ === 'local') {
185
+ reportLinkBaseUrl = 'http://localhost:3000';
186
+ }
187
+ else if (process.env.NODE_ENV_BLINQ === 'dev') {
188
+ reportLinkBaseUrl = 'https://dev.app.blinq.io';
189
+ }
190
+ else if (process.env.NODE_ENV_BLINQ === 'stage') {
191
+ reportLinkBaseUrl = 'https://stage.app.blinq.io';
192
+ }
193
+ const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
194
+ this.log(`Report link: ${reportLink}\n`);
195
+ }
237
196
  }
238
197
  exports.default = BVTAnalysisFormatter;
239
198
  //# 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} from './helpers/report_generator'\nimport ReportUploader from './helpers/uploader'\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.uploader.uploadRun(report, this.runName)\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 finalResults: JsonTestResult[] = []\n const finalStepResults: JsonTestResult[][] = []\n let isFailing = true\n for (const testCase of report.testCases) {\n const { result, steps } = await this.processTestCase(testCase, report)\n finalResults.push(result)\n finalStepResults.push(steps)\n //If any of the test case fails, the whole run is considered failed\n if (result.status === 'FAILED') {\n isFailing = false\n }\n }\n return {\n result: isFailing\n ? {\n status: 'FIXED_BY_AI',\n startTime:\n 'startTime' in report.result\n ? report.result.startTime\n : this.START,\n endTime: Date.now(),\n }\n : {\n status: 'FAILED',\n startTime:\n 'startTime' in report.result\n ? report.result.startTime\n : Date.now(),\n endTime: Date.now(),\n },\n testCases: report.testCases.map((testCase, i) => {\n return {\n ...testCase,\n result: finalResults[i],\n steps: testCase.steps.map((step, j) => {\n return {\n ...step,\n result: finalStepResults[i][j],\n }\n }),\n }\n }),\n }\n }\n private async processTestCase(\n testCase: JsonTestProgress,\n report: JsonReport\n ): Promise<{\n result: JsonFixedByAi | JsonResultFailed | JsonResultPassed\n steps: (JsonFixedByAi | JsonResultFailed | JsonResultPassed)[]\n }> {\n if (testCase.result.status === 'PASSED') {\n return {\n result: testCase.result,\n steps: testCase.steps.map((step) => {\n return step.result.status === 'PASSED'\n ? step.result\n : this.createStepResult(true, step, report)\n }),\n }\n }\n const failedTestCases = testCase.steps\n .map((step, i) => (step.result.status !== 'PASSED' ? i : null))\n .filter((i) => i !== null)\n const success = await this.retrain(failedTestCases, testCase)\n const finalResult = this.createFinalResult(success, testCase, report)\n\n return {\n result: finalResult,\n steps: testCase.steps.map((step) =>\n step.result.status === 'PASSED'\n ? { ...step.result }\n : this.createStepResult(success, step, report)\n ),\n }\n }\n\n private createFinalResult(\n success: boolean,\n testCase: JsonTestProgress,\n report: JsonReport\n ): JsonFixedByAi | JsonResultFailed {\n const status = success ? 'FIXED_BY_AI' : 'FAILED'\n return {\n status,\n startTime: this.createStartTime(testCase, report),\n endTime: Date.now(),\n }\n }\n private createStartTime(\n testCase: JsonTestProgress,\n report: JsonReport\n ): number {\n let startTime\n\n if ('startTime' in testCase.result) {\n startTime = testCase.result.startTime\n } else if ('startTime' in report.result) {\n startTime = report.result.startTime\n } else {\n startTime = Date.now()\n }\n\n return startTime\n }\n private createStepResult(\n success: boolean,\n step: JsonStep,\n report: JsonReport\n ): JsonFixedByAi | JsonResultFailed {\n const status = success ? 'FIXED_BY_AI' : 'FAILED'\n return {\n status,\n startTime:\n 'startTime' in step.result\n ? step.result.startTime\n : 'startTime' in report.result\n ? report.result.startTime\n : Date.now(),\n endTime: Date.now(),\n }\n }\n private async uploadFinalReport(finalReport: JsonReport) {\n let success = true\n try {\n await this.uploader.uploadRun(finalReport, this.runName)\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(failedTestCases: number[], testCase: JsonTestProgress) {\n const stepsToRetrain = testCase.steps.map((_, i) => i)\n const success = await this.call_cucumber_client(stepsToRetrain, testCase)\n return success\n }\n\n private async call_cucumber_client(\n stepsToRetrain: number[],\n testCase: JsonTestProgress\n ): Promise<boolean> {\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\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 resolve(true)\n } else {\n this.log('Error retraining\\n')\n resolve(false)\n }\n })\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 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('No test failed. 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 'undefined',\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://www.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 }\n const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`\n this.log(`Report link: ${reportLink}\\n`)\n }\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { TableCell } from '@cucumber/messages';
1
2
  declare const generateTestData: (featureFileContent: string, vars?: any, fakeData?: {
2
3
  var: string;
3
4
  fake: string;
@@ -11,4 +12,12 @@ declare const generateTestData: (featureFileContent: string, vars?: any, fakeDat
11
12
  changed: boolean;
12
13
  fakeIndex: number;
13
14
  };
14
- export { generateTestData };
15
+ declare const generateExamplesFromFunction: (data: string, feature_path: string, functionName: string, functionFile: string) => {
16
+ newData: string;
17
+ mjsData: any;
18
+ };
19
+ declare const generateExamplesFromFunctionGherkin: (headers: readonly TableCell[], values: readonly TableCell[], mjsData: any) => {
20
+ header: string;
21
+ value: any;
22
+ }[];
23
+ export { generateTestData, generateExamplesFromFunction, generateExamplesFromFunctionGherkin, };
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateTestData = void 0;
6
+ exports.generateExamplesFromFunctionGherkin = exports.generateExamplesFromFunction = exports.generateTestData = void 0;
4
7
  const faker_1 = require("@faker-js/faker");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
5
10
  const generateTestData = (featureFileContent, vars, fakeData) => {
6
11
  const regexp = /\{\{([^}]+)\}\}/g;
7
12
  const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g;
@@ -66,7 +71,7 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
66
71
  }
67
72
  catch (err) {
68
73
  // eslint-disable-next-line no-console
69
- console.log('unknown faker variable:' + match[0]);
74
+ //console.log('unknown faker variable:' + match[0])
70
75
  }
71
76
  }
72
77
  return {
@@ -78,4 +83,55 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
78
83
  };
79
84
  };
80
85
  exports.generateTestData = generateTestData;
86
+ const getDefinitionFunction = (feature_path, functionName, functionFile) => {
87
+ const mjsFiles = fs_1.default
88
+ .readdirSync(path_1.default.join(feature_path, '../step_definitions'))
89
+ .filter((file) => file === `${functionFile}.js`);
90
+ if (mjsFiles.length === 0) {
91
+ throw new Error(`File ${functionFile} not found in step_definitions folder`);
92
+ }
93
+ const [mjsData] = mjsFiles.map((file) => {
94
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
95
+ const { [functionName]: func } = require(path_1.default.join(feature_path, '../step_definitions', file));
96
+ if (!func)
97
+ throw new Error(`Function ${functionName} not found in file ${file}`);
98
+ return func();
99
+ });
100
+ return mjsData;
101
+ };
102
+ const generateExamplesFromFunction = (data, feature_path, functionName, functionFile) => {
103
+ const examples = data.split('Examples:')[1].split('\n').slice(1);
104
+ const headers = examples[0]
105
+ .split('|')
106
+ .map((header) => header.trim())
107
+ .filter((header) => header !== '');
108
+ const values = examples[1]
109
+ .split('|')
110
+ .map((value) => value.trim())
111
+ .filter((header) => header !== '');
112
+ const mjsData = getDefinitionFunction(feature_path, functionName, functionFile);
113
+ const newExamples = headers.map((header) => {
114
+ if (mjsData[header]) {
115
+ return mjsData[header];
116
+ }
117
+ return values[headers.indexOf(header)];
118
+ });
119
+ let newExamplesString = data.split('Examples:')[1];
120
+ newExamples.forEach((example, index) => {
121
+ newExamplesString = newExamplesString.replace(values[index], example);
122
+ });
123
+ const newData = data.replace(data.split('Examples:')[1], newExamplesString);
124
+ return { newData, mjsData };
125
+ };
126
+ exports.generateExamplesFromFunction = generateExamplesFromFunction;
127
+ const generateExamplesFromFunctionGherkin = (headers, values, mjsData) => {
128
+ const newExamples = headers.map(({ value: header }, index) => {
129
+ if (mjsData[header]) {
130
+ return { header, value: mjsData[header] };
131
+ }
132
+ return { header, value: values[index].value };
133
+ });
134
+ return newExamples;
135
+ };
136
+ exports.generateExamplesFromFunctionGherkin = generateExamplesFromFunctionGherkin;
81
137
  //# sourceMappingURL=feature_data_format.js.map
@@ -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'\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\n//let result = generateTestData(\"/Users/guyarieli/Documents/GitHub/ai-qa/cucumber_demo/features/create_issues.feature\");\n//console.log(result.newContent);\nexport { generateTestData }\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'\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,6 +1,6 @@
1
1
  import * as messages from '@cucumber/messages';
2
2
  type JsonTimestamp = number;
3
- type JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome';
3
+ type JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome' | 'Conjunction';
4
4
  export type JsonResultUnknown = {
5
5
  status: 'UNKNOWN';
6
6
  };
@@ -50,10 +50,18 @@ type JsonCommand = {
50
50
  result: JsonCommandResult;
51
51
  };
52
52
  export type JsonStep = {
53
+ keyword: string;
53
54
  type: JsonStepType;
54
55
  text: string;
55
56
  commands: JsonCommand[];
56
57
  result: JsonStepResult;
58
+ data?: any;
59
+ };
60
+ export type RetrainStats = {
61
+ result: JsonTestResult;
62
+ totalSteps: number;
63
+ upload_id: string;
64
+ local_id: number;
57
65
  };
58
66
  export type JsonTestProgress = {
59
67
  id: string;
@@ -63,19 +71,27 @@ export type JsonTestProgress = {
63
71
  parameters: Record<string, string>;
64
72
  steps: JsonStep[];
65
73
  result: JsonTestResult;
74
+ retrainStats?: RetrainStats;
75
+ webLog: any;
66
76
  };
67
77
  export type JsonReport = {
68
78
  testCases: JsonTestProgress[];
69
79
  result: JsonReportResult;
80
+ env: {
81
+ name: string;
82
+ baseUrl: string;
83
+ };
70
84
  };
71
85
  export default class ReportGenerator {
72
86
  private report;
73
87
  private gherkinDocumentMap;
88
+ private stepMap;
74
89
  private pickleMap;
75
90
  private testCaseMap;
76
91
  private testStepMap;
77
- private stepProgressMap;
78
- private testProgressMap;
92
+ private stepReportMap;
93
+ private testCaseReportMap;
94
+ private scenarioIterationCountMap;
79
95
  reportFolder: null | string;
80
96
  handleMessage(envelope: messages.Envelope): void;
81
97
  getReport(): JsonReport;
@@ -85,10 +101,13 @@ export default class ReportGenerator {
85
101
  private getTimeStamp;
86
102
  private onTestRunStarted;
87
103
  private onTestCase;
104
+ private _findScenario;
105
+ private _getParameters;
88
106
  private onTestCaseStarted;
89
107
  private onTestStepStarted;
90
108
  private onAttachment;
91
109
  private onTestStepFinished;
110
+ getLogFileContent(): any;
92
111
  private getTestCaseResult;
93
112
  private onTestCaseFinished;
94
113
  private onTestRunFinished;