@dev-blinq/cucumber_client 1.0.1322-dev → 1.0.1322-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 (52) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +108 -108
  2. package/bin/assets/preload/css_gen.js +10 -10
  3. package/bin/assets/preload/recorderv3.js +3 -1
  4. package/bin/assets/preload/toolbar.js +27 -29
  5. package/bin/assets/preload/unique_locators.js +1 -1
  6. package/bin/assets/preload/yaml.js +288 -275
  7. package/bin/assets/scripts/aria_snapshot.js +223 -220
  8. package/bin/assets/scripts/dom_attr.js +329 -329
  9. package/bin/assets/scripts/dom_parent.js +169 -174
  10. package/bin/assets/scripts/event_utils.js +94 -94
  11. package/bin/assets/scripts/pw.js +2050 -1949
  12. package/bin/assets/scripts/recorder.js +5 -17
  13. package/bin/assets/scripts/snapshot_capturer.js +153 -146
  14. package/bin/assets/scripts/unique_locators.js +156 -48
  15. package/bin/assets/scripts/yaml.js +796 -783
  16. package/bin/assets/templates/_hooks_template.txt +41 -0
  17. package/bin/assets/templates/utils_template.txt +1 -44
  18. package/bin/client/apiTest/apiTest.js +6 -0
  19. package/bin/client/cli_helpers.js +11 -13
  20. package/bin/client/code_cleanup/utils.js +5 -1
  21. package/bin/client/code_gen/api_codegen.js +2 -2
  22. package/bin/client/code_gen/code_inversion.js +53 -4
  23. package/bin/client/code_gen/page_reflection.js +839 -906
  24. package/bin/client/code_gen/playwright_codeget.js +26 -18
  25. package/bin/client/cucumber/feature.js +89 -27
  26. package/bin/client/cucumber/feature_data.js +2 -2
  27. package/bin/client/cucumber/project_to_document.js +9 -3
  28. package/bin/client/cucumber/steps_definitions.js +90 -87
  29. package/bin/client/cucumber_selector.js +17 -1
  30. package/bin/client/local_agent.js +6 -5
  31. package/bin/client/parse_feature_file.js +23 -26
  32. package/bin/client/playground/projects/env.json +2 -2
  33. package/bin/client/project.js +186 -196
  34. package/bin/client/recorderv3/bvt_recorder.js +190 -127
  35. package/bin/client/recorderv3/implemented_steps.js +74 -16
  36. package/bin/client/recorderv3/index.js +68 -54
  37. package/bin/client/recorderv3/network.js +22 -5
  38. package/bin/client/recorderv3/scriptTest.js +1 -1
  39. package/bin/client/recorderv3/services.js +4 -16
  40. package/bin/client/recorderv3/step_runner.js +303 -218
  41. package/bin/client/recorderv3/step_utils.js +484 -7
  42. package/bin/client/recorderv3/update_feature.js +32 -30
  43. package/bin/client/run_cucumber.js +5 -1
  44. package/bin/client/scenario_report.js +0 -5
  45. package/bin/client/test_scenario.js +0 -1
  46. package/bin/client/upload-service.js +2 -2
  47. package/bin/client/utils/socket_logger.js +132 -0
  48. package/bin/index.js +1 -0
  49. package/bin/logger.js +3 -2
  50. package/bin/min/consoleApi.min.cjs +2 -3
  51. package/bin/min/injectedScript.min.cjs +16 -16
  52. package/package.json +21 -12
@@ -1,9 +1,9 @@
1
1
  import { AstBuilder, GherkinClassicTokenMatcher, Parser } from "@cucumber/gherkin";
2
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
2
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs";
3
3
  import path from "path";
4
4
  import url from "url";
5
5
  import { findFilesWithExtension, StepsDefinitions } from "../cucumber/steps_definitions.js";
6
- import { Feature } from "../cucumber/feature.js";
6
+ import { Feature, Step } from "../cucumber/feature.js";
7
7
  import { CodePage } from "../code_gen/page_reflection.js";
8
8
  import { getCommandsForImplementedStep, loadStepDefinitions } from "./step_utils.js";
9
9
  import { parseStepTextParameters } from "../cucumber/utils.js";
@@ -13,7 +13,6 @@ const uuidFn = () => (++id).toString(16);
13
13
  const builder = new AstBuilder(uuidFn);
14
14
  const matcher = new GherkinClassicTokenMatcher();
15
15
  const parser = new Parser(builder, matcher);
16
-
17
16
  let i = 0;
18
17
  const getImplId = () => {
19
18
  return `I-${i++}`;
@@ -57,6 +56,53 @@ function memorySizeOf(obj) {
57
56
  return sizeOf(obj);
58
57
  }
59
58
 
59
+ export function parseRouteFiles(projectDir, step) {
60
+ const routeFolder = path.join(projectDir, "data", "routes");
61
+ const templateRouteMap = new Map();
62
+
63
+ if (!existsSync(routeFolder)) {
64
+ step.routeItems = null;
65
+ return;
66
+ }
67
+
68
+ // Go over all the files in the route folder and parse them
69
+ const routeFiles = readdirSync(routeFolder).filter((file) => file.endsWith(".json"));
70
+ for (const file of routeFiles) {
71
+ const filePath = path.join(routeFolder, file);
72
+ const routeData = JSON.parse(readFileSync(filePath, "utf8"));
73
+ if (routeData && routeData.template) {
74
+ const template = routeData.template;
75
+ const routes = routeData.routes;
76
+
77
+ templateRouteMap.set(template, routes);
78
+ }
79
+ }
80
+
81
+ if (!existsSync(routeFolder)) {
82
+ return null;
83
+ } else if (step && step.text) {
84
+ // Convert the step text to cucumber template
85
+ const cucumberStep = new Step();
86
+ cucumberStep.text = step.text;
87
+ const template = cucumberStep.getTemplate();
88
+ if (templateRouteMap.has(template)) {
89
+ const routeItems = templateRouteMap.get(template);
90
+ routeItems.forEach((item) => {
91
+ const filters = item.filters || {};
92
+ const queryParams = filters?.queryParams || {};
93
+ const queryParamsArray = Object.keys(queryParams).map((key) => ({
94
+ key: key,
95
+ value: queryParams[key],
96
+ }));
97
+ filters.queryParams = queryParamsArray || [];
98
+ });
99
+ step.routeItems = routeItems;
100
+ } else {
101
+ step.routeItems = null;
102
+ }
103
+ }
104
+ }
105
+
60
106
  export const getImplementedSteps = async (projectDir) => {
61
107
  const foundErrors = [];
62
108
  try {
@@ -70,6 +116,12 @@ export const getImplementedSteps = async (projectDir) => {
70
116
  const utilsContent = readFileSync(utilsTemplateFilePath, "utf8");
71
117
  //console.log({ utilsContent });
72
118
  writeFileSync(utilsFilePath, utilsContent, "utf8");
119
+ const hooksTemplateFilePath = path.join(__dirname, "../../assets", "templates", "_hooks_template.txt");
120
+ if (existsSync(hooksTemplateFilePath)) {
121
+ const hooksFilePath = path.join(stepDefinitionFolderPath, "_hooks.mjs");
122
+ const hooksContent = readFileSync(hooksTemplateFilePath, "utf8");
123
+ writeFileSync(hooksFilePath, hooksContent, "utf8");
124
+ }
73
125
  } catch (error) {
74
126
  foundErrors.push({ error });
75
127
  }
@@ -168,7 +220,10 @@ export const getImplementedSteps = async (projectDir) => {
168
220
  }
169
221
  stepLineSet.add(stepLine);
170
222
  step.templateIndex = implementedSteps.length;
171
- implementedSteps.push({
223
+
224
+ parseRouteFiles(projectDir, step);
225
+
226
+ const implementedStep = {
172
227
  keyword: step.keyword.trim(),
173
228
  keywordAlias: step.keywordAlias?.trim(),
174
229
  text: updateStepText(template.pattern, step.parameters),
@@ -179,7 +234,10 @@ export const getImplementedSteps = async (projectDir) => {
179
234
  templateIndex: step.templateIndex,
180
235
  pattern: template.pattern,
181
236
  paths: template.paths,
182
- });
237
+ routeItems: step.routeItems,
238
+ };
239
+
240
+ implementedSteps.push(implementedStep);
183
241
  }
184
242
  }
185
243
 
@@ -236,17 +294,17 @@ export const getImplementedSteps = async (projectDir) => {
236
294
  for (const tag of scenario.tags) {
237
295
  delete tag.location;
238
296
  }
239
- // for (const scenario of scenarios) {
240
- // for (const step of scenario.steps) {
241
- // if (step.templateIndex === undefined) {
242
- // const cleanStepName = stepsDefinitions._stepNameToTemplate(step.text);
243
- // const index = implementedSteps.findIndex((istep) => {
244
- // return cleanStepName === istep.pattern;
245
- // });
246
- // step.templateIndex = index;
247
- // }
248
- // }
249
- // }
297
+ for (const scenario of scenarios) {
298
+ for (const step of scenario.steps) {
299
+ if (step.templateIndex === undefined) {
300
+ const cleanStepName = stepsDefinitions._stepNameToTemplate(step.text);
301
+ const index = implementedSteps.findIndex((istep) => {
302
+ return cleanStepName === istep.pattern;
303
+ });
304
+ step.templateIndex = index;
305
+ }
306
+ }
307
+ }
250
308
  }
251
309
  if (foundErrors.length > 0) {
252
310
  console.log("foundErrors", foundErrors);
@@ -4,10 +4,23 @@ import { BVTRecorder } from "./bvt_recorder.js";
4
4
  import { compareWithScenario } from "../code_gen/duplication_analysis.js";
5
5
  import { getAppDataDir } from "./app_dir.js";
6
6
  import { readdir } from "fs/promises";
7
+ import socketLogger from "../utils/socket_logger.js";
7
8
 
8
9
  let port = process.env.EDITOR_PORT || 3003;
9
10
  const WS_URL = "http://localhost:" + port;
10
11
 
12
+ const responseSize = (response) => {
13
+ try {
14
+ if (typeof response !== "string") {
15
+ return new Blob([JSON.stringify(response)]).size;
16
+ } else {
17
+ return new Blob([response]).size;
18
+ }
19
+ } catch {
20
+ return -1;
21
+ }
22
+ };
23
+
11
24
  class PromisifiedSocketServer {
12
25
  constructor(socket, routes) {
13
26
  this.socket = socket;
@@ -16,7 +29,9 @@ class PromisifiedSocketServer {
16
29
  init() {
17
30
  this.socket.on("request", async (data) => {
18
31
  const { event, input, id, roomId, socketId } = data;
19
- console.log("request", { event, input, id, roomId, socketId });
32
+ if (event !== "recorderWindow.getCurrentChromiumPath") {
33
+ socketLogger.info("Received request", { event, input, id, roomId, socketId });
34
+ }
20
35
  try {
21
36
  const handler = this.routes[event];
22
37
  if (!handler) {
@@ -24,17 +39,19 @@ class PromisifiedSocketServer {
24
39
  return;
25
40
  }
26
41
  const response = await handler(input);
27
- // console.log("response", { id, value: response, roomId, socketId });
42
+ if (event !== "recorderWindow.getCurrentChromiumPath") {
43
+ socketLogger.info(`Sending response for ${event}, ${responseSize(response)} bytes`);
44
+ }
28
45
  this.socket.emit("response", { id, value: response, roomId, socketId });
29
46
  } catch (error) {
30
- console.log("request", JSON.stringify({ event, input, id, roomId, socketId }));
31
- console.error("response", { id, error, roomId, socketId });
32
- // console.error({
33
- // message: error?.message,
34
- // code: error?.code,
35
- // info: error?.info,
36
- // stack: error?.stack,
37
- // })
47
+ socketLogger.error("Error handling request", {
48
+ event,
49
+ input,
50
+ id,
51
+ roomId,
52
+ socketId,
53
+ error: error instanceof Error ? `${error.message}\n${error.stack}` : error,
54
+ });
38
55
  this.socket.emit("response", {
39
56
  id,
40
57
  error: {
@@ -51,45 +68,17 @@ class PromisifiedSocketServer {
51
68
  }
52
69
  }
53
70
 
54
- function memorySizeOf(obj) {
55
- var bytes = 0;
56
-
57
- function sizeOf(obj) {
58
- if (obj !== null && obj !== undefined) {
59
- switch (typeof obj) {
60
- case "number":
61
- bytes += 8;
62
- break;
63
- case "string":
64
- bytes += obj.length * 2;
65
- break;
66
- case "boolean":
67
- bytes += 4;
68
- break;
69
- case "object":
70
- var objClass = Object.prototype.toString.call(obj).slice(8, -1);
71
- if (objClass === "Object" || objClass === "Array") {
72
- for (var key in obj) {
73
- if (!obj.hasOwnProperty(key)) continue;
74
- sizeOf(obj[key]);
75
- }
76
- } else bytes += obj.toString().length * 2;
77
- break;
78
- }
79
- }
80
- return bytes;
81
- }
82
- return sizeOf(obj);
83
- }
84
-
85
71
  const init = ({ envName, projectDir, roomId, TOKEN }) => {
86
- console.log("connecting to " + WS_URL);
72
+ console.log("Connecting to " + WS_URL);
87
73
  const socket = io(WS_URL);
74
+ socketLogger.init(socket, { context: "BVTRecorder", eventName: "BVTRecorder.log" });
88
75
  socket.on("connect", () => {
89
- console.log("connected to server");
76
+ socketLogger.info("Connected to BVTRecorder server");
77
+ console.log("Connected to BVTRecorder server");
90
78
  });
91
79
  socket.on("disconnect", () => {
92
- console.log("disconnected from server");
80
+ socketLogger.info("Disconnected from server");
81
+ console.log("Disconnected from server");
93
82
  });
94
83
  socket.emit("joinRoom", { id: roomId, window: "cucumber_client/bvt_recorder" });
95
84
  const recorder = new BVTRecorder({
@@ -97,19 +86,19 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
97
86
  projectDir,
98
87
  TOKEN,
99
88
  sendEvent: (event, data) => {
100
- console.log("Size of data", memorySizeOf(data), "bytes");
101
- console.log("----", event, data, "roomId", roomId);
89
+ socketLogger.info("Sending event", { event, data, roomId });
102
90
  socket.emit(event, data, roomId);
103
- console.log("Successfully sent event", event, "to room", roomId);
104
91
  },
92
+ logger: socketLogger,
105
93
  });
106
94
  recorder
107
95
  .openBrowser()
108
96
  .then(() => {
109
- // console.log("BVTRecorder.browserOpened");
97
+ socketLogger.info("BVTRecorder.browserOpened");
110
98
  socket.emit("BVTRecorder.browserOpened", null, roomId);
111
99
  })
112
100
  .catch((e) => {
101
+ socketLogger.error("BVTRecorder.browserLaunchFailed", e);
113
102
  socket.emit("BVTRecorder.browserLaunchFailed", e, roomId);
114
103
  });
115
104
  const timeOutForFunction = async (promise, timeout = 5000) => {
@@ -120,6 +109,7 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
120
109
  return res;
121
110
  } catch (error) {
122
111
  console.error(error);
112
+ socketLogger.error(error);
123
113
  throw error;
124
114
  }
125
115
  };
@@ -129,10 +119,13 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
129
119
  return recorder
130
120
  .openBrowser(input)
131
121
  .then(() => {
122
+ socketLogger.info("BVTRecorder.browserOpened");
123
+ console.info("BVTRecorder.browserOpened");
132
124
  socket.emit("BVTRecorder.browserOpened", { roomId, window: "cucumber_client/bvt_recorder" });
133
125
  })
134
126
  .catch((e) => {
135
- console.error(e);
127
+ socketLogger.error("Error opening browser", e);
128
+ console.error("BVTRecorder.browserLaunchFailed", e);
136
129
  socket.emit("BVTRecorder.browserLaunchFailed", { roomId, window: "cucumber_client/bvt_recorder" });
137
130
  });
138
131
  },
@@ -143,10 +136,13 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
143
136
  return recorder
144
137
  .reOpenBrowser(input)
145
138
  .then(() => {
146
- // console.log("BVTRecorder.browserOpened");
139
+ socketLogger.info("BVTRecorder.browserOpened");
140
+ console.log("BVTRecorder.browserOpened");
147
141
  socket.emit("BVTRecorder.browserOpened", null, roomId);
148
142
  })
149
- .catch(() => {
143
+ .catch((e) => {
144
+ socketLogger.info("BVTRecorder.browserLaunchFailed");
145
+ console.error("BVTRecorder.browserLaunchFailed", e);
150
146
  socket.emit("BVTRecorder.browserLaunchFailed", null, roomId);
151
147
  });
152
148
  },
@@ -224,9 +220,18 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
224
220
  "recorderWindow.getNumberOfOccurrences": async (input) => {
225
221
  return recorder.getNumberOfOccurrences(input);
226
222
  },
223
+ "recorderWindow.getFakeParams": async ({ parametersMap }) => {
224
+ return recorder.fakeParams(parametersMap);
225
+ },
227
226
  "recorderWindow.abortExecution": async (input) => {
228
227
  return recorder.abortExecution(input);
229
228
  },
229
+ "recorderWindow.pauseExecution": async (input) => {
230
+ return recorder.pauseExecution(input);
231
+ },
232
+ "recorderWindow.resumeExecution": async (input) => {
233
+ return recorder.resumeExecution(input);
234
+ },
230
235
  "recorderWindow.loadExistingScenario": async (input) => {
231
236
  return recorder.loadExistingScenario(input);
232
237
  },
@@ -239,9 +244,7 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
239
244
  "recorderWindow.getSnapshotFiles": async (input) => {
240
245
  const snapshotFolder = recorder.getSnapshotFolder();
241
246
  if (snapshotFolder) {
242
- // Get the list of filenames in the snapshot folder
243
247
  const files = await readdir(snapshotFolder);
244
- // Filter the files to only include .png files
245
248
  const ymlFiles = files.filter((file) => file.endsWith(".yml") || file.endsWith(".yaml"));
246
249
  return { folder: snapshotFolder, files: ymlFiles };
247
250
  } else return { folder: null, files: [] };
@@ -275,6 +278,18 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
275
278
  "recorderWindow.getNetworkEvents": async (input) => {
276
279
  return await recorder.getNetworkEvents(input);
277
280
  },
281
+ "recorderWindow.initExecution": async (input) => {
282
+ return await recorder.initExecution(input);
283
+ },
284
+ "recorderWindow.cleanupExecution": async (input) => {
285
+ return await recorder.cleanupExecution(input);
286
+ },
287
+ "recorderWindow.resetExecution": async (input) => {
288
+ return await recorder.resetExecution(input);
289
+ },
290
+ "recorderWindow.stopRecordingNetwork": async (input) => {
291
+ return recorder.stopRecordingNetwork(input);
292
+ },
278
293
  });
279
294
  socket.on("targetBrowser.command.event", async (input) => {
280
295
  return recorder.onAction(input);
@@ -301,7 +316,6 @@ try {
301
316
  showUsage(error, usage);
302
317
  }
303
318
  try {
304
- // console.log({ envName, projectDir, featureName, scenarioName, stepIndex, roomId })
305
319
  init({
306
320
  envName,
307
321
  projectDir,
@@ -1,8 +1,18 @@
1
+ /**
2
+ * @typedef {Object} NetworkEvent
3
+ * @property {import('playwright').Request} request
4
+ * @property {import('playwright').Response|null} response
5
+ * @property {string} id
6
+ * @property {number} timestamp
7
+ * @property {string} status - 'completed', 'failed'
8
+ */
9
+
1
10
  class NetworkMonitor {
2
11
  constructor() {
3
12
  this.networkId = 0;
4
- this.networkEvents = new Map();
13
+ /** @type {Map<string, NetworkEvent>} */
5
14
  this.requestIdMap = new Map();
15
+ this.networkEvents = new Map();
6
16
  /** @type {Map<import('playwright').Page, {responseListener: Function, requestFailedListener: Function}>} */
7
17
  this.pageListeners = new Map();
8
18
  }
@@ -12,7 +22,6 @@ class NetworkMonitor {
12
22
  * @param {import('playwright').Page} page
13
23
  */
14
24
  addNetworkEventListener(page) {
15
-
16
25
  // Create the listener functions
17
26
  const responseListener = async (response) => {
18
27
  const request = response.request();
@@ -201,7 +210,6 @@ class NetworkMonitor {
201
210
  // Try to get response body safely (only for successful responses)
202
211
  if (response && networkEvent.status === "completed") {
203
212
  try {
204
-
205
213
  const isBinary =
206
214
  !response.headers()["content-type"]?.includes("application/json") &&
207
215
  !response.headers()["content-type"]?.includes("text");
@@ -229,7 +237,6 @@ class NetworkMonitor {
229
237
  marshalledEvent.failureReason = request.failure()?.errorText || "Unknown error";
230
238
  }
231
239
 
232
-
233
240
  console.log("Marshalled network event:", marshalledEvent);
234
241
 
235
242
  return marshalledEvent;
@@ -246,7 +253,18 @@ class NetworkMonitor {
246
253
  }
247
254
  }
248
255
 
256
+ /**
257
+ *@returns {Promise<Object[]>}
258
+ * Get all marshalled network events
259
+ * This is useful for sending to the server or saving to a file.
260
+ * */
261
+ async getAllMarshalledNetworkEvents() {
262
+ const events = this.getAllNetworkEvents();
263
+ const marshalledEvents = await Promise.all(events.map((event) => this.marshallNetworkEvent(event)));
264
+ return marshalledEvents;
265
+ }
249
266
 
267
+ /**
250
268
  * Get marshalled network events since this ID
251
269
  * @returns {Promise<Object[]>}
252
270
  * @param {number} sinceId
@@ -263,7 +281,6 @@ class NetworkMonitor {
263
281
  * @param {number} endId
264
282
  * @returns {Promise<Object[]>}
265
283
  */
266
-
267
284
  async getMarshalledNetworkEventsInRange(startId, endId) {
268
285
  const events = this.getNetworkEventsInRange(startId, endId);
269
286
  const marshalledEvents = await Promise.all(events.map((event) => this.marshallNetworkEvent(event)));
@@ -2,4 +2,4 @@
2
2
 
3
3
  // getImplementedSteps('/Users/yash/Library/Application Support/blinq.io/67d7c7ffb099a8da65d7e204').then((implementedSteps) => {
4
4
  // console.log(JSON.stringify(implementedSteps, null, 2));
5
- // });
5
+ // });
@@ -15,20 +15,7 @@ export class NamesService {
15
15
  if (!screenshot && commands.length > 1) {
16
16
  screenshot = this.screenshotMap.get(commands[commands.length - 2].inputID);
17
17
  }
18
- this.logger.info(
19
- "data: " +
20
- JSON.stringify(
21
- {
22
- commands,
23
- stepsNames,
24
- parameters,
25
- map,
26
- },
27
- null,
28
- 2
29
- )
30
- );
31
- // get screenshot for the last command
18
+
32
19
  const url = `${getRunsServiceBaseURL()}/generate-step-information/generate`;
33
20
  const TIMEOUT = 120; // 2 minutes
34
21
  const { data } = await axiosClient({
@@ -38,7 +25,7 @@ export class NamesService {
38
25
  commands,
39
26
  stepsNames,
40
27
  parameters,
41
- screenshot,
28
+ //screenshot,
42
29
  map,
43
30
  },
44
31
  headers: {
@@ -65,6 +52,7 @@ export class NamesService {
65
52
  }
66
53
  } catch (error) {
67
54
  if (i === TIMEOUT - 1) {
55
+ this.logger.error("Timeout while generating step details: ", error);
68
56
  console.error("Timeout while generating step details: ", error);
69
57
  }
70
58
  }
@@ -96,7 +84,6 @@ export class NamesService {
96
84
  scenario: scenarioAsText,
97
85
  };
98
86
 
99
- this.logger.info("data: " + JSON.stringify(genObject, null, 2));
100
87
  // get screenshot for the last command
101
88
  const url = `${getRunsServiceBaseURL()}/generate-step-information/generate_scenario_feature`;
102
89
  const TIMEOUT = 120; // 2 minutes
@@ -140,6 +127,7 @@ export class NamesService {
140
127
  if (result.status !== 200) {
141
128
  return { success: false, message: "Error while generating step details" };
142
129
  }
130
+
143
131
  return result.data;
144
132
  }
145
133