@dev-blinq/cucumber-js 1.0.84-main → 1.0.84-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 (32) hide show
  1. package/bin/download-install.js +31 -19
  2. package/lib/formatter/api.d.ts +2 -0
  3. package/lib/formatter/api.js +59 -0
  4. package/lib/formatter/api.js.map +1 -0
  5. package/lib/formatter/bvt_analysis_formatter.d.ts +13 -1
  6. package/lib/formatter/bvt_analysis_formatter.js +197 -71
  7. package/lib/formatter/bvt_analysis_formatter.js.map +1 -1
  8. package/lib/formatter/feature_data_format.js +14 -1
  9. package/lib/formatter/feature_data_format.js.map +1 -1
  10. package/lib/formatter/helpers/constants.d.ts +50 -0
  11. package/lib/formatter/helpers/constants.js +60 -0
  12. package/lib/formatter/helpers/constants.js.map +1 -0
  13. package/lib/formatter/helpers/report_generator.d.ts +40 -13
  14. package/lib/formatter/helpers/report_generator.js +348 -57
  15. package/lib/formatter/helpers/report_generator.js.map +1 -1
  16. package/lib/formatter/helpers/test_case_attempt_formatter.js +1 -1
  17. package/lib/formatter/helpers/test_case_attempt_formatter.js.map +1 -1
  18. package/lib/formatter/helpers/upload_serivce.d.ts +16 -3
  19. package/lib/formatter/helpers/upload_serivce.js +176 -34
  20. package/lib/formatter/helpers/upload_serivce.js.map +1 -1
  21. package/lib/formatter/helpers/uploader.d.ts +2 -1
  22. package/lib/formatter/helpers/uploader.js +63 -18
  23. package/lib/formatter/helpers/uploader.js.map +1 -1
  24. package/lib/formatter/summary_formatter.js +4 -0
  25. package/lib/formatter/summary_formatter.js.map +1 -1
  26. package/lib/runtime/test_case_runner.d.ts +1 -0
  27. package/lib/runtime/test_case_runner.js +10 -1
  28. package/lib/runtime/test_case_runner.js.map +1 -1
  29. package/lib/version.d.ts +1 -1
  30. package/lib/version.js +1 -1
  31. package/lib/version.js.map +1 -1
  32. package/package.json +4 -2
@@ -17,10 +17,16 @@ const getSSoUrl = () => {
17
17
  return 'http://localhost:5000/api/auth'
18
18
  case 'dev':
19
19
  return 'https://dev.api.blinq.io/api/auth'
20
- case "stage":
20
+ case 'stage':
21
21
  return 'https://stage.api.blinq.io/api/auth'
22
- default:
22
+ case 'prod':
23
+ return 'https://api.blinq.io/api/auth'
24
+ case null:
23
25
  return 'https://api.blinq.io/api/auth'
26
+ case undefined:
27
+ return 'https://api.blinq.io/api/auth'
28
+ default:
29
+ return `${process.env.NODE_ENV_BLINQ}/api/auth`
24
30
  }
25
31
  }
26
32
 
@@ -51,8 +57,14 @@ const getWorkSpaceUrl = () => {
51
57
  return 'https://dev.api.blinq.io/api/workspace'
52
58
  case "stage":
53
59
  return 'https://stage.api.blinq.io/api/workspace'
54
- default:
60
+ case 'prod':
61
+ return 'https://api.blinq.io/api/workspace'
62
+ case null:
55
63
  return 'https://api.blinq.io/api/workspace'
64
+ case undefined:
65
+ return 'https://api.blinq.io/api/workspace'
66
+ default:
67
+ return `${process.env.NODE_ENV_BLINQ}/api/workspace`
56
68
  }
57
69
  }
58
70
 
@@ -105,31 +117,31 @@ const dirExists = (path) => {
105
117
  }
106
118
  const ssoUrl = getSSoUrl()
107
119
 
120
+ const getProjectByAccessKey = async (access_key) => {
121
+ const accessKeyUrl = `${ssoUrl}/getProjectByAccessKey`
122
+ const response = await axios.post(accessKeyUrl, {
123
+ access_key,
124
+ httpAgent: getProxy(),
125
+ proxy: false,
126
+ })
127
+ if (response.status !== 200) {
128
+ console.error('Error: Invalid access key')
129
+ process.exit(1)
130
+ }
131
+ return response.data
132
+ };
133
+
108
134
  const downloadAndInstall = async (extractPath, token) => {
109
135
  if (!dirExists(extractPath)) {
110
136
  fs.mkdirSync(extractPath, { recursive: true })
111
137
  }
112
138
  try {
113
- const accessKeyUrl = `${ssoUrl}/getProjectByAccessKey`
114
- const response = await axios.post(accessKeyUrl, {
115
- access_key: token,
116
- httpAgent: getProxy(),
117
- proxy: false,
118
- })
119
- if (response.status !== 200) {
120
- console.error('Error: Unable to fetch project')
121
- process.exit(1)
122
- }
123
- const data = response.data
124
- if (!data.status) {
125
- console.error('Error: Invalid access key')
126
- process.exit(1)
127
- }
139
+ const data = await getProjectByAccessKey(token)
128
140
 
129
141
  const workspaceUrl = getWorkSpaceUrl() + '/pull-workspace'
130
142
  const res = await axios.get(workspaceUrl, {
131
143
  params: {
132
- projectId: response.data.project._id,
144
+ projectId: data.project._id,
133
145
  },
134
146
  httpAgent: getProxy(),
135
147
  proxy: false,
@@ -0,0 +1,2 @@
1
+ declare const getProjectByAccessKey: (access_key: string) => Promise<any>;
2
+ export { getProjectByAccessKey };
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getProjectByAccessKey = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const tunnel_1 = __importDefault(require("tunnel"));
9
+ const getSSoUrl = () => {
10
+ switch (process.env.NODE_ENV_BLINQ) {
11
+ case 'local':
12
+ return 'http://localhost:5000/api/auth';
13
+ case 'dev':
14
+ return 'https://dev.api.blinq.io/api/auth';
15
+ case 'stage':
16
+ return 'https://stage.api.blinq.io/api/auth';
17
+ case 'prod':
18
+ return 'https://api.blinq.io/api/auth';
19
+ case null:
20
+ return 'https://api.blinq.io/api/auth';
21
+ case undefined:
22
+ return 'https://api.blinq.io/api/auth';
23
+ default:
24
+ return `${process.env.NODE_ENV_BLINQ}/api/auth`;
25
+ }
26
+ };
27
+ const getProxy = () => {
28
+ if (!process.env.PROXY) {
29
+ return null;
30
+ }
31
+ const proxy = process.env.PROXY;
32
+ const url = new URL(proxy);
33
+ const proxyObject = {
34
+ host: url.hostname,
35
+ port: Number(url.port),
36
+ };
37
+ const { username, password } = url;
38
+ if (username && password) {
39
+ //@ts-ignore
40
+ proxyObject.proxyAuth = `${username}:${password}`;
41
+ }
42
+ return tunnel_1.default.httpsOverHttp({ proxy: proxyObject });
43
+ };
44
+ const getProjectByAccessKey = async (access_key) => {
45
+ const ssoUrl = getSSoUrl();
46
+ const accessKeyUrl = `${ssoUrl}/getProjectByAccessKey`;
47
+ const response = await axios_1.default.post(accessKeyUrl, {
48
+ access_key,
49
+ httpAgent: getProxy(),
50
+ proxy: false,
51
+ });
52
+ if (response.status !== 200) {
53
+ console.error('Error: Invalid access key');
54
+ process.exit(1);
55
+ }
56
+ return response.data;
57
+ };
58
+ exports.getProjectByAccessKey = getProjectByAccessKey;
59
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/formatter/api.ts"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB,oDAA2B;AAE3B,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,QAAQ,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;QAClC,KAAK,OAAO;YACV,OAAO,gCAAgC,CAAA;QACzC,KAAK,KAAK;YACR,OAAO,mCAAmC,CAAA;QAC5C,KAAK,OAAO;YACV,OAAO,qCAAqC,CAAA;QAC9C,KAAK,MAAM;YACT,OAAO,+BAA+B,CAAA;QACxC,KAAK,IAAI;YACP,OAAO,+BAA+B,CAAA;QACxC,KAAK,SAAS;YACZ,OAAO,+BAA+B,CAAA;QACxC;YACE,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW,CAAA;KAClD;AACH,CAAC,CAAA;AACD,MAAM,QAAQ,GAAG,GAAG,EAAE;IACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE;QACtB,OAAO,IAAI,CAAA;KACZ;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAA;IAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IAC1B,MAAM,WAAW,GAAG;QAClB,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;KACvB,CAAA;IAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAA;IAElC,IAAI,QAAQ,IAAI,QAAQ,EAAE;QACxB,YAAY;QACZ,WAAW,CAAC,SAAS,GAAG,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAA;KAClD;IACD,OAAO,gBAAM,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;AACrD,CAAC,CAAA;AAED,MAAM,qBAAqB,GAAG,KAAK,EAAE,UAAkB,EAAE,EAAE;IACzD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,YAAY,GAAG,GAAG,MAAM,wBAAwB,CAAA;IACtD,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAAC,YAAY,EAAE;QAC9C,UAAU;QACV,SAAS,EAAE,QAAQ,EAAE;QACrB,KAAK,EAAE,KAAK;KACb,CAAC,CAAA;IACF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;QAC3B,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;KAChB;IACD,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC,CAAA;AAEQ,sDAAqB","sourcesContent":["import axios from 'axios'\nimport tunnel from 'tunnel'\n\nconst getSSoUrl = () => {\n switch (process.env.NODE_ENV_BLINQ) {\n case 'local':\n return 'http://localhost:5000/api/auth'\n case 'dev':\n return 'https://dev.api.blinq.io/api/auth'\n case 'stage':\n return 'https://stage.api.blinq.io/api/auth'\n case 'prod':\n return 'https://api.blinq.io/api/auth'\n case null:\n return 'https://api.blinq.io/api/auth'\n case undefined:\n return 'https://api.blinq.io/api/auth'\n default:\n return `${process.env.NODE_ENV_BLINQ}/api/auth`\n }\n}\nconst getProxy = () => {\n if (!process.env.PROXY) {\n return null\n }\n\n const proxy = process.env.PROXY\n const url = new URL(proxy)\n const proxyObject = {\n host: url.hostname,\n port: Number(url.port),\n }\n\n const { username, password } = url\n\n if (username && password) {\n //@ts-ignore\n proxyObject.proxyAuth = `${username}:${password}`\n }\n return tunnel.httpsOverHttp({ proxy: proxyObject })\n}\n\nconst getProjectByAccessKey = async (access_key: string) => {\n const ssoUrl = getSSoUrl()\n const accessKeyUrl = `${ssoUrl}/getProjectByAccessKey`\n const response = await axios.post(accessKeyUrl, {\n access_key,\n httpAgent: getProxy(),\n proxy: false,\n })\n if (response.status !== 200) {\n console.error('Error: Invalid access key')\n process.exit(1)\n }\n return response.data\n}\n\nexport { getProjectByAccessKey }\n"]}
@@ -1,11 +1,22 @@
1
1
  import Formatter, { IFormatterOptions } from '.';
2
+ import ReportGenerator, { JsonTestResult } from './helpers/report_generator';
3
+ export declare let globalReportLink: string;
2
4
  export default class BVTAnalysisFormatter extends Formatter {
5
+ static reportGenerator: ReportGenerator;
6
+ static reRunFailedStepsIndex: {
7
+ testCaseId: string;
8
+ failedStepIndex: number;
9
+ }[] | null;
3
10
  private reportGenerator;
4
11
  private uploader;
5
12
  private exit;
6
13
  private START;
7
14
  private runName;
15
+ private failedStepsIndex;
16
+ private summaryFormatter;
17
+ private rootCauseArray;
8
18
  constructor(options: IFormatterOptions);
19
+ private sendEvent;
9
20
  private uploadReport;
10
21
  finished(): Promise<any>;
11
22
  private analyzeReport;
@@ -13,7 +24,8 @@ export default class BVTAnalysisFormatter extends Formatter {
13
24
  private processTestCase;
14
25
  private uploadFinalReport;
15
26
  private retrain;
27
+ private rerun;
16
28
  private call_cucumber_client;
17
- private logReportLink;
18
29
  private getAppDataDir;
19
30
  }
31
+ export declare function logReportLink(runId: string, projectId: string, status: JsonTestResult): string;
@@ -3,6 +3,7 @@ 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 = exports.globalReportLink = void 0;
6
7
  const child_process_1 = require("child_process");
7
8
  const fs_1 = require("fs");
8
9
  const promises_1 = require("fs/promises");
@@ -13,36 +14,77 @@ const value_checker_1 = require("../value_checker");
13
14
  const report_generator_1 = __importDefault(require("./helpers/report_generator"));
14
15
  const uploader_1 = __importDefault(require("./helpers/uploader"));
15
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");
16
23
  //User token
17
24
  const TOKEN = process.env.TOKEN;
25
+ exports.globalReportLink = '';
18
26
  class BVTAnalysisFormatter extends _1.default {
19
27
  constructor(options) {
20
28
  super(options);
21
29
  this.reportGenerator = new report_generator_1.default();
22
30
  this.uploader = new uploader_1.default(this.reportGenerator);
23
31
  this.exit = false;
32
+ this.rootCauseArray = [];
33
+ this.summaryFormatter = new summary_formatter_1.default(options);
34
+ BVTAnalysisFormatter.reportGenerator = this.reportGenerator;
35
+ this.rootCauseArray = [];
36
+ this.failedStepsIndex = [];
37
+ BVTAnalysisFormatter.reRunFailedStepsIndex = process.env.RERUN
38
+ ? JSON.parse(process.env.RERUN)
39
+ : null;
24
40
  if (!TOKEN && process.env.BVT_FORMATTER === 'ANALYSIS') {
25
41
  throw new Error('TOKEN must be set');
26
42
  }
27
- options.eventBroadcaster.on('envelope', async (envelope) => {
28
- this.reportGenerator.handleMessage(envelope);
43
+ this.sendEvent(constants_1.ActionEvents.cli_run_tests);
44
+ options.eventBroadcaster.on('envelope', async (envelope, data) => {
45
+ if ((0, value_checker_1.doesHaveValue)(envelope.testCaseFinished) && data) {
46
+ const { rootCause, report } = data;
47
+ if (!rootCause.status) {
48
+ console.error(`Root cause: ${rootCause.failClass}\n, ${rootCause.analysis}\nfailing step: ${rootCause.failedStep}`);
49
+ this.rootCauseArray.push({ rootCause, report });
50
+ this.failedStepsIndex.push({
51
+ testCaseId: report.id,
52
+ failedStepIndex: rootCause.failedStep,
53
+ });
54
+ }
55
+ return;
56
+ }
57
+ await this.reportGenerator.handleMessage(envelope);
29
58
  if ((0, value_checker_1.doesHaveValue)(envelope.meta) &&
30
59
  (0, value_checker_1.doesHaveValue)(envelope.meta.runName)) {
31
60
  this.runName = envelope.meta.runName;
32
61
  }
33
62
  if ((0, value_checker_1.doesHaveValue)(envelope.testRunFinished)) {
34
- const report = this.reportGenerator.getReport();
35
63
  this.START = Date.now();
36
64
  if (process.env.BVT_FORMATTER === 'ANALYSIS') {
37
- await this.analyzeReport(report);
65
+ await this.analyzeReport();
38
66
  }
39
67
  else {
40
- await this.uploadReport(report);
68
+ // await this.uploadReport(report)
41
69
  }
42
70
  this.exit = true;
43
71
  }
44
72
  });
45
73
  }
74
+ sendEvent(event) {
75
+ axios_client_1.axiosClient
76
+ .post(`${constants_1.SERVICES_URI.STORAGE}/event`, {
77
+ event,
78
+ }, {
79
+ headers: {
80
+ Authorization: `Bearer ${TOKEN}`,
81
+ 'x-source': 'cucumber_js',
82
+ },
83
+ })
84
+ .catch((err) => {
85
+ // Error with events, ignoring
86
+ });
87
+ }
46
88
  async uploadReport(report) {
47
89
  const uploadSuccessful = await this.uploadFinalReport(report);
48
90
  if (uploadSuccessful && report.result.status !== 'FAILED') {
@@ -53,77 +95,80 @@ class BVTAnalysisFormatter extends _1.default {
53
95
  async finished() {
54
96
  await new Promise((resolve) => {
55
97
  const checkInterval = setInterval(() => {
56
- if (this.exit) {
57
- clearInterval(checkInterval);
58
- resolve(null);
98
+ let anyRem;
99
+ if (process.env.UPLOADING_TEST_CASE) {
100
+ anyRem = JSON.parse(process.env.UPLOADING_TEST_CASE);
101
+ }
102
+ else {
103
+ anyRem = undefined;
104
+ }
105
+ if (this.exit && (!anyRem || anyRem.length === 0)) {
106
+ // clearInterval(checkInterval)
107
+ // resolve(null)
108
+ if (this.reportGenerator.getReport().result.status === 'FAILED') {
109
+ process.exit(1);
110
+ }
111
+ else {
112
+ process.exit(0);
113
+ }
59
114
  }
60
115
  }, 100); // check every 100ms
61
116
  });
62
117
  }
63
- async analyzeReport(report) {
64
- if (report.result.status === 'PASSED') {
65
- this.log('No test failed. No need to retrain\n');
66
- const uploadSuccessful = await this.uploadFinalReport(report);
67
- if (uploadSuccessful) {
68
- process.exit(0);
118
+ async analyzeReport() {
119
+ if (this.rootCauseArray.length === 0 ||
120
+ process.env.NO_RETRAIN === 'false') {
121
+ if (this.rootCauseArray.length === 0) {
122
+ this.log('No test failed. No need to retrain\n');
69
123
  }
70
- process.exit(1);
124
+ if (process.env.NO_RETRAIN === 'false') {
125
+ this.log('Retraining is skipped since the failed step contains an API request\n');
126
+ }
127
+ // const uploadSuccessful = await this.uploadFinalReport(report)
128
+ // process.exit(0)
129
+ this.exit = true;
130
+ return;
71
131
  }
72
132
  //checking if the type of report.result is JsonResultFailed or not
73
133
  this.log('Some tests failed, starting the retraining...\n');
74
- if (!('startTime' in report.result) || !('endTime' in report.result)) {
75
- this.log('Unknown error occured,not retraining\n');
76
- await this.uploadFinalReport(report);
77
- return;
78
- }
79
- const finalReport = await this.processTestCases(report);
80
- const uploadSuccessful = await this.uploadFinalReport(finalReport);
81
- if (finalReport.result.status !== 'FAILED' && uploadSuccessful) {
82
- process.exit(0);
83
- }
84
- else {
134
+ await this.processTestCases();
135
+ if (this.reportGenerator.getReport().result.status === 'FAILED') {
85
136
  process.exit(1);
86
137
  }
138
+ process.exit(0);
87
139
  }
88
- async processTestCases(report) {
89
- const finalTestCases = [];
90
- for (const testCase of report.testCases) {
91
- const modifiedTestCase = await this.processTestCase(testCase, report);
92
- finalTestCases.push(modifiedTestCase);
140
+ async processTestCases() {
141
+ for (const { rootCause, report } of this.rootCauseArray) {
142
+ await this.processTestCase(rootCause, report);
93
143
  }
94
- const finalResult = finalTestCases.some((tc) => tc.result.status !== 'PASSED')
95
- ? report.result
96
- : {
97
- ...report.result,
98
- status: 'PASSED',
99
- };
100
- return {
101
- result: finalResult,
102
- testCases: finalTestCases,
103
- env: report.env,
104
- };
105
- }
106
- async processTestCase(testCase, report) {
107
- if (testCase.result.status === 'PASSED') {
108
- return testCase;
144
+ }
145
+ async processTestCase(rootCause, report) {
146
+ const failedTestSteps = rootCause.failedStep;
147
+ if (BVTAnalysisFormatter.reRunFailedStepsIndex &&
148
+ BVTAnalysisFormatter.reRunFailedStepsIndex.length > 0) {
149
+ const previousRun = BVTAnalysisFormatter.reRunFailedStepsIndex[0];
150
+ if (previousRun.failedStepIndex === failedTestSteps) {
151
+ console.log('Same step has failed again, skipping retraining');
152
+ BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
153
+ return;
154
+ }
155
+ BVTAnalysisFormatter.reRunFailedStepsIndex.shift();
109
156
  }
110
- const failedTestSteps = testCase.steps
111
- .map((step, i) => (step.result.status === 'FAILED' ? i : null))
112
- .filter((i) => i !== null);
113
- const retrainStats = await this.retrain(failedTestSteps, testCase);
157
+ const retrainStats = await this.retrain(failedTestSteps, report);
114
158
  if (!retrainStats) {
115
- return testCase;
159
+ return;
116
160
  }
117
- return {
118
- ...testCase,
161
+ await this.uploader.modifyTestCase({
162
+ ...report,
119
163
  retrainStats,
120
- };
164
+ });
165
+ await this.rerun(report);
121
166
  }
122
167
  async uploadFinalReport(finalReport) {
123
168
  let success = true;
124
169
  try {
125
170
  const { projectId, runId } = await this.uploader.uploadRun(finalReport, this.runName);
126
- this.logReportLink(runId, projectId);
171
+ logReportLink(runId, projectId, finalReport.result);
127
172
  }
128
173
  catch (err) {
129
174
  this.log('Error uploading report\n');
@@ -132,12 +177,57 @@ class BVTAnalysisFormatter extends _1.default {
132
177
  }
133
178
  success = false;
134
179
  }
180
+ finally {
181
+ try {
182
+ (0, fs_1.writeFileSync)(path_1.default.join(this.reportGenerator.reportFolder, 'report.json'), JSON.stringify(finalReport, null, 2), 'utf-8');
183
+ }
184
+ catch (e) {
185
+ console.error('failed to write report.json to local disk');
186
+ }
187
+ }
135
188
  //this.log(JSON.stringify(finalReport, null, 2))
136
189
  return success;
137
190
  }
138
191
  async retrain(failedTestCases, testCase) {
192
+ const data = await (0, api_1.getProjectByAccessKey)(TOKEN);
193
+ const currentTimestampInSeconds = Math.floor(Date.now() / 1000);
194
+ if (data.project.expriration_date < currentTimestampInSeconds) {
195
+ console.log('Warning: Your project has expired, retraining is restricted. Please contact sales.');
196
+ process.exit(1);
197
+ }
139
198
  return await this.call_cucumber_client(failedTestCases, testCase);
140
199
  }
200
+ async rerun(report) {
201
+ await new Promise((resolve) => {
202
+ const node_path = process.argv.shift();
203
+ const args = [
204
+ path_1.default.join(process.cwd(), 'node_modules', '@dev-blinq', 'cucumber-js', 'bin', 'cucumber.js'),
205
+ '--name',
206
+ `^${report.scenarioName}$`,
207
+ '--exit',
208
+ '--format',
209
+ 'bvt',
210
+ '--run-name',
211
+ `${report.scenarioName}@debug`,
212
+ path_1.default.join(process.cwd(), 'features', `${report.featureName}.feature`),
213
+ ];
214
+ const cucumberClient = (0, child_process_1.spawn)(node_path, args, {
215
+ env: {
216
+ ...process.env,
217
+ RERUN: JSON.stringify(this.failedStepsIndex),
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', () => {
227
+ resolve();
228
+ });
229
+ });
230
+ }
141
231
  async call_cucumber_client(stepsToRetrain, testCase) {
142
232
  return new Promise((resolve, reject) => {
143
233
  const cucumber_client_path = path_1.default.resolve(process.cwd(), 'node_modules', '@dev-blinq', 'cucumber_client', 'bin', 'client', 'cucumber.js');
@@ -146,7 +236,7 @@ class BVTAnalysisFormatter extends _1.default {
146
236
  path_1.default.join(process.cwd(), testCase.uri),
147
237
  `${testCase.scenarioName}`,
148
238
  'undefined',
149
- `${stepsToRetrain.join(',')}`,
239
+ `${stepsToRetrain},`,
150
240
  ];
151
241
  if (process.env.BLINQ_ENV) {
152
242
  args.push(`--env=${process.env.BLINQ_ENV}`);
@@ -159,6 +249,10 @@ class BVTAnalysisFormatter extends _1.default {
159
249
  (0, tmp_1.tmpName)(async (err, name) => {
160
250
  const tempFile = path_1.default.join(this.getAppDataDir(), 'blinq.io', '.temp', path_1.default.basename(name));
161
251
  console.log('File path: ', tempFile);
252
+ // check if the file directory exists, if not create it
253
+ if (!(0, fs_1.existsSync)(path_1.default.dirname(tempFile))) {
254
+ await (0, promises_1.mkdir)(path_1.default.dirname(tempFile), { recursive: true });
255
+ }
162
256
  await (0, promises_1.writeFile)(tempFile, '', 'utf-8');
163
257
  args.push(`--temp-file=${tempFile}`);
164
258
  const cucumberClient = (0, child_process_1.spawn)('node', [cucumber_client_path, ...args], {
@@ -181,26 +275,21 @@ class BVTAnalysisFormatter extends _1.default {
181
275
  }
182
276
  else {
183
277
  this.log('Error retraining\n');
184
- resolve(null);
278
+ try {
279
+ const reportData = (0, fs_1.readFileSync)(tempFile, 'utf-8');
280
+ const retrainStats = JSON.parse(reportData);
281
+ await (0, promises_1.unlink)(tempFile);
282
+ resolve(retrainStats);
283
+ }
284
+ catch (e) {
285
+ this.log('Error reading scenario report\n ' + e);
286
+ resolve(null);
287
+ }
185
288
  }
186
289
  });
187
290
  });
188
291
  });
189
292
  }
190
- logReportLink(runId, projectId) {
191
- let reportLinkBaseUrl = 'https://www.app.blinq.io';
192
- if (process.env.NODE_ENV_BLINQ === 'local') {
193
- reportLinkBaseUrl = 'http://localhost:3000';
194
- }
195
- else if (process.env.NODE_ENV_BLINQ === 'dev') {
196
- reportLinkBaseUrl = 'https://dev.app.blinq.io';
197
- }
198
- else if (process.env.NODE_ENV_BLINQ === 'stage') {
199
- reportLinkBaseUrl = 'https://stage.app.blinq.io';
200
- }
201
- const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
202
- this.log(`Report link: ${reportLink}\n`);
203
- }
204
293
  getAppDataDir() {
205
294
  if (process.env.BLINQ_APPDATA_DIR) {
206
295
  return process.env.BLINQ_APPDATA_DIR;
@@ -221,4 +310,41 @@ class BVTAnalysisFormatter extends _1.default {
221
310
  }
222
311
  }
223
312
  exports.default = BVTAnalysisFormatter;
313
+ function logReportLink(runId, projectId, status) {
314
+ let reportLinkBaseUrl = 'https://app.blinq.io';
315
+ if (process.env.NODE_ENV_BLINQ === 'local') {
316
+ reportLinkBaseUrl = 'http://localhost:3000';
317
+ }
318
+ else if (process.env.NODE_ENV_BLINQ === 'dev') {
319
+ reportLinkBaseUrl = 'https://dev.app.blinq.io';
320
+ }
321
+ else if (process.env.NODE_ENV_BLINQ === 'stage') {
322
+ reportLinkBaseUrl = 'https://stage.app.blinq.io';
323
+ }
324
+ else if (process.env.NODE_ENV_BLINQ === 'prod') {
325
+ reportLinkBaseUrl = 'https://app.blinq.io';
326
+ }
327
+ else if (!process.env.NODE_ENV_BLINQ) {
328
+ reportLinkBaseUrl = 'https://app.blinq.io';
329
+ }
330
+ else {
331
+ reportLinkBaseUrl = process.env.NODE_ENV_BLINQ.replace('api', 'app');
332
+ }
333
+ const reportLink = `${reportLinkBaseUrl}/${projectId}/run-report/${runId}`;
334
+ exports.globalReportLink = reportLink;
335
+ try {
336
+ publishReportLinkToGuacServer(reportLink, status.status === "PASSED");
337
+ }
338
+ catch (err) {
339
+ // Error with events, ignoring
340
+ }
341
+ return reportLink;
342
+ }
343
+ exports.logReportLink = logReportLink;
344
+ function publishReportLinkToGuacServer(reportLink, result) {
345
+ if ((0, fs_1.existsSync)('/tmp/report_publish.sh')) {
346
+ const execAsync = (0, util_1.promisify)(child_process_2.exec);
347
+ execAsync('sh /tmp/report_publish.sh ' + reportLink + ' ' + result);
348
+ }
349
+ }
224
350
  //# sourceMappingURL=bvt_analysis_formatter.js.map