@dev-blinq/cucumber_client 1.0.1428-dev → 1.0.1428-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 (43) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +73 -73
  2. package/bin/assets/preload/css_gen.js +10 -10
  3. package/bin/assets/preload/toolbar.js +27 -29
  4. package/bin/assets/preload/unique_locators.js +1 -1
  5. package/bin/assets/preload/yaml.js +288 -275
  6. package/bin/assets/scripts/aria_snapshot.js +223 -220
  7. package/bin/assets/scripts/dom_attr.js +329 -329
  8. package/bin/assets/scripts/dom_parent.js +169 -174
  9. package/bin/assets/scripts/event_utils.js +94 -94
  10. package/bin/assets/scripts/pw.js +2050 -1949
  11. package/bin/assets/scripts/recorder.js +70 -45
  12. package/bin/assets/scripts/snapshot_capturer.js +147 -147
  13. package/bin/assets/scripts/unique_locators.js +170 -49
  14. package/bin/assets/scripts/yaml.js +796 -783
  15. package/bin/assets/templates/_hooks_template.txt +6 -2
  16. package/bin/assets/templates/utils_template.txt +16 -16
  17. package/bin/client/code_cleanup/find_step_definition_references.js +0 -1
  18. package/bin/client/code_gen/api_codegen.js +2 -2
  19. package/bin/client/code_gen/code_inversion.js +63 -2
  20. package/bin/client/code_gen/function_signature.js +4 -0
  21. package/bin/client/code_gen/page_reflection.js +52 -11
  22. package/bin/client/code_gen/playwright_codeget.js +25 -3
  23. package/bin/client/cucumber/feature_data.js +2 -2
  24. package/bin/client/cucumber/project_to_document.js +8 -2
  25. package/bin/client/cucumber/steps_definitions.js +19 -3
  26. package/bin/client/local_agent.js +3 -2
  27. package/bin/client/parse_feature_file.js +23 -26
  28. package/bin/client/playground/projects/env.json +2 -2
  29. package/bin/client/recorderv3/bvt_init.js +363 -0
  30. package/bin/client/recorderv3/bvt_recorder.js +1009 -47
  31. package/bin/client/recorderv3/implemented_steps.js +2 -0
  32. package/bin/client/recorderv3/index.js +3 -283
  33. package/bin/client/recorderv3/scriptTest.js +1 -1
  34. package/bin/client/recorderv3/services.js +818 -142
  35. package/bin/client/recorderv3/step_runner.js +28 -8
  36. package/bin/client/recorderv3/step_utils.js +511 -39
  37. package/bin/client/recorderv3/update_feature.js +32 -13
  38. package/bin/client/recorderv3/wbr_entry.js +61 -0
  39. package/bin/client/recording.js +1 -0
  40. package/bin/client/upload-service.js +4 -2
  41. package/bin/client/utils/socket_logger.js +1 -1
  42. package/bin/index.js +4 -1
  43. package/package.json +6 -4
@@ -14,6 +14,428 @@ import { createHash } from "crypto";
14
14
 
15
15
  const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
16
16
 
17
+ const convertToIdentifier = (text) => {
18
+ // replace all invalid characters with _
19
+ return text.replace(/[^a-zA-Z0-9_]/g, "_");
20
+ };
21
+
22
+ export const isVariable = (text) => {
23
+ if (typeof text !== "string") return false;
24
+ const isParametric = text.startsWith("<") && text.endsWith(">");
25
+ if (!isParametric) return false;
26
+ const l = text.length;
27
+ if (l < 2) return false;
28
+ const leftindex = text.indexOf("<");
29
+ const rightindex = text.indexOf(">");
30
+ return leftindex === 0 && rightindex === l - 1;
31
+ };
32
+
33
+ export const extractQuotes = (text) => {
34
+ const stringRegex = /"([^"]*)"/g;
35
+ const matches = text.match(stringRegex);
36
+ if (!matches) return [];
37
+ const quotes = [];
38
+ for (const match of matches) {
39
+ const value = match.slice(1, -1);
40
+ quotes.push(value);
41
+ }
42
+ return quotes;
43
+ };
44
+
45
+ const replaceLastOccurence = (str, search, replacement) => {
46
+ const lastIndex = str.lastIndexOf(search);
47
+ if (lastIndex === -1) return str;
48
+ return str.substring(0, lastIndex) + replacement + str.substring(lastIndex + search.length);
49
+ };
50
+
51
+ const _toRecordingStep = (cmd) => {
52
+ switch (cmd.type) {
53
+ case "hover_element": {
54
+ return {
55
+ type: "hover_element",
56
+ element: {
57
+ role: cmd.role,
58
+ name: cmd.label,
59
+ },
60
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
61
+ };
62
+ }
63
+ case "click_element": {
64
+ return {
65
+ type: "click_element",
66
+ element: {
67
+ role: cmd.role,
68
+ name: cmd.label,
69
+ },
70
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
71
+ count: cmd.count ?? 1,
72
+ };
73
+ }
74
+ case "context_click": {
75
+ return {
76
+ type: "context_click",
77
+ element: {
78
+ role: cmd.role,
79
+ name: cmd.label,
80
+ },
81
+ label: cmd.label,
82
+ value: cmd.value,
83
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
84
+ text: cmd.text,
85
+ count: cmd.count ?? 1,
86
+ };
87
+ }
88
+ case "parameterized_click": {
89
+ return {
90
+ type: "parameterized_click",
91
+ element: {
92
+ role: cmd.role,
93
+ name: cmd.label,
94
+ },
95
+ label: cmd.label,
96
+ value: cmd.value,
97
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
98
+ count: cmd.count ?? 1,
99
+ };
100
+ }
101
+ case "fill_element": {
102
+ return {
103
+ type: "fill_element",
104
+ element: {
105
+ role: cmd.role,
106
+ name: cmd.label,
107
+ },
108
+ parameters: [cmd.value, cmd.enter ?? false],
109
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
110
+ };
111
+ }
112
+ case "select_combobox": {
113
+ return {
114
+ type: "select_combobox",
115
+ element: {
116
+ role: "combobox",
117
+ name: cmd.label,
118
+ },
119
+ selectMode: "select",
120
+ parameters: [cmd.value],
121
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
122
+ };
123
+ }
124
+ case "verify_page_contains_text": {
125
+ return {
126
+ type: "verify_page_contains_text",
127
+ parameters: [cmd.value, cmd.isRegex],
128
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
129
+ };
130
+ }
131
+ case "verify_element_contains_text": {
132
+ return {
133
+ type: "verify_element_contains_text",
134
+ element: {
135
+ role: cmd.role,
136
+ name: cmd.label,
137
+ },
138
+ parameters: [cmd.value, cmd.climb],
139
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
140
+ };
141
+ }
142
+ case "close_page": {
143
+ return {
144
+ type: "close_page",
145
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
146
+ };
147
+ }
148
+ case "check_element": {
149
+ return {
150
+ type: "check_element",
151
+ element: {
152
+ role: cmd.role,
153
+ name: cmd.label,
154
+ },
155
+ check: cmd.check,
156
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
157
+ };
158
+ }
159
+ case "press_key": {
160
+ return {
161
+ type: "press_key",
162
+ element: {
163
+ role: cmd.role,
164
+ name: cmd.label,
165
+ },
166
+ key: cmd.value,
167
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
168
+ };
169
+ }
170
+ case "load_user": {
171
+ return {
172
+ type: "load_data",
173
+ parameters: ["users", cmd.value],
174
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
175
+ };
176
+ }
177
+ case "load_csv": {
178
+ return {
179
+ type: "load_data",
180
+ parameters: ["csv", `${cmd.label}:${cmd.value}`],
181
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
182
+ };
183
+ }
184
+ case "set_date_time": {
185
+ return {
186
+ type: "set_date_time",
187
+ element: {
188
+ role: cmd.role,
189
+ name: cmd.label,
190
+ },
191
+ parameters: [cmd.value],
192
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
193
+ };
194
+ }
195
+ case "set_input": {
196
+ return {
197
+ type: "set_input",
198
+ element: {
199
+ role: cmd.role,
200
+ name: cmd.label,
201
+ },
202
+ value: cmd.value,
203
+ parameters: [cmd.value],
204
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
205
+ };
206
+ }
207
+ case "extract_attribute": {
208
+ return {
209
+ type: "extract_attribute",
210
+ element: {
211
+ role: cmd.role,
212
+ name: cmd.label,
213
+ },
214
+ parameters: [cmd.selectedField, cmd.variableName],
215
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
216
+ regex: cmd.regex,
217
+ trimSpaces: cmd.trimSpaces,
218
+ };
219
+ }
220
+ case "extract_property": {
221
+ return {
222
+ type: "extract_property",
223
+ element: {
224
+ role: cmd.role,
225
+ name: cmd.label,
226
+ },
227
+ parameters: [cmd.selectedField, cmd.variableName],
228
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
229
+ regex: cmd.regex,
230
+ trimSpaces: cmd.trimSpaces,
231
+ };
232
+ }
233
+ case "verify_element_attribute": {
234
+ return {
235
+ type: "verify_element_attribute",
236
+ element: {
237
+ role: cmd.role,
238
+ name: cmd.label,
239
+ },
240
+ parameters: [cmd.selectedField, cmd.value],
241
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
242
+ };
243
+ }
244
+ case "verify_element_property": {
245
+ return {
246
+ type: "verify_element_property",
247
+ element: {
248
+ role: cmd.role,
249
+ name: cmd.label,
250
+ },
251
+ parameters: [cmd.selectedField, cmd.value],
252
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
253
+ };
254
+ }
255
+ case "conditional_wait": {
256
+ return {
257
+ type: "conditional_wait",
258
+ element: {
259
+ role: cmd.role,
260
+ name: cmd.label,
261
+ },
262
+ parameters: [cmd.timeout, cmd.selectedField, cmd.value],
263
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
264
+ };
265
+ }
266
+ case "navigate": {
267
+ return {
268
+ type: "navigate",
269
+ parameters: [cmd.value],
270
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
271
+ };
272
+ }
273
+ case "browser_go_back": {
274
+ return {
275
+ type: "browser_go_back",
276
+ };
277
+ }
278
+ case "browser_go_forward": {
279
+ return {
280
+ type: "browser_go_forward",
281
+ };
282
+ }
283
+ case "set_input_files": {
284
+ return {
285
+ type: "set_input_files",
286
+ element: {
287
+ role: cmd.role,
288
+ name: cmd.label,
289
+ },
290
+ parameters: [cmd.files],
291
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
292
+ };
293
+ }
294
+ case "verify_page_snapshot": {
295
+ return {
296
+ type: "verify_page_snapshot",
297
+ parameters: [cmd.value],
298
+ selectors: cmd.selectors,
299
+ data: cmd.data,
300
+ };
301
+ }
302
+ default: {
303
+ return {
304
+ type: cmd.type,
305
+ parameters: [cmd.value],
306
+ lastKnownUrlPath: cmd.lastKnownUrlPath,
307
+ };
308
+ }
309
+ }
310
+ };
311
+
312
+ function getBestStrategy(allStrategyLocators) {
313
+ const orderedPriorities = ["custom", "context", "basic", "text_with_index", "ignore_digit", "no_text"];
314
+ for (const strategy of orderedPriorities) {
315
+ if (allStrategyLocators[strategy] && allStrategyLocators[strategy].length > 0) {
316
+ return strategy;
317
+ }
318
+ }
319
+ return null;
320
+ }
321
+
322
+ const _parameterizeLocators = (locators, replacementFromValue, replacementToValue) => {
323
+ for (const loc of locators) {
324
+ if (loc?.css?.includes(replacementFromValue)) {
325
+ loc.css = loc.css.replaceAll(replacementFromValue, replacementToValue);
326
+ }
327
+ if (loc?.text?.includes(replacementFromValue)) {
328
+ loc.text = loc.text.replaceAll(replacementFromValue, replacementToValue);
329
+ }
330
+ if (loc?.climb && typeof loc.climb === "string" && loc.climb?.includes(replacementFromValue)) {
331
+ loc.climb = loc.climb.replaceAll(replacementFromValue, replacementToValue);
332
+ }
333
+ }
334
+ return locators;
335
+ };
336
+ const parameterizeLocators = ({ cmd, locs, isValueVariable, isTargetValueVariable, parametersMap }) => {
337
+ if (isValueVariable) {
338
+ const variable = cmd.value.slice(1, -1);
339
+ // const val = parametersMap[variable];
340
+ if (typeof cmd.text === "string") {
341
+ const replacementFromValue = cmd.text.trim().replace(/\s+/g, " ") ?? ""; // val.trim();
342
+ if (replacementFromValue.length > 0) {
343
+ const replacementToValue = `{${variable}}`;
344
+ locs = _parameterizeLocators(locs, replacementFromValue, replacementToValue);
345
+ }
346
+ }
347
+ }
348
+ if (isTargetValueVariable) {
349
+ const variable = cmd.targetValue.slice(1, -1);
350
+ // const val = parametersMap[variable];
351
+ if (typeof cmd.targetText === "string") {
352
+ const replacementFromValue = cmd.targetText.trim().replace(/\s+/g, " ") ?? ""; // val.trim();
353
+ if (replacementFromValue.length > 0) {
354
+ const replacementToValue = `{${variable}}`;
355
+ locs = _parameterizeLocators(locs, replacementFromValue, replacementToValue);
356
+ }
357
+ }
358
+ }
359
+ return locs;
360
+ };
361
+
362
+ //TODO: IMPORTAN
363
+ export const toRecordingStep = (cmd, parametersMap) => {
364
+ if (cmd.type === "api") {
365
+ return {
366
+ type: "api",
367
+ value: cmd.value,
368
+ };
369
+ }
370
+ const step = _toRecordingStep(cmd);
371
+ const cmdID = {
372
+ cmdId: cmd.id,
373
+ };
374
+ Object.assign(step, cmdID);
375
+
376
+ const locatorsObject = JSON.parse(JSON.stringify(cmd.locators ?? null));
377
+
378
+ if (!locatorsObject) return step;
379
+
380
+ const element_name = cmd?.locators?.element_name ?? `${cmd.label} ${cmd.role ?? "Text"}`;
381
+ locatorsObject.element_name = element_name;
382
+
383
+ const isValueVariable = isVariable(cmd.value);
384
+ const isTargetValueVariable = isVariable(cmd.targetValue);
385
+ const allStrategyLocators = JSON.parse(JSON.stringify(cmd?.allStrategyLocators ?? null));
386
+ step.locators = locatorsObject;
387
+ step.allStrategyLocators = allStrategyLocators;
388
+ step.isLocatorsAssigned = true;
389
+
390
+ if (!isValueVariable && !isTargetValueVariable) {
391
+ return step;
392
+ }
393
+
394
+ if (isValueVariable) {
395
+ step.dataSource = "parameters";
396
+ step.dataKey = convertToIdentifier(cmd.value.slice(1, -1));
397
+ }
398
+
399
+ if (!allStrategyLocators) {
400
+ let locs = locatorsObject.locators;
401
+ locs = parameterizeLocators({
402
+ cmd,
403
+ locs,
404
+ isValueVariable,
405
+ isTargetValueVariable,
406
+ parametersMap,
407
+ });
408
+ locatorsObject.locators = locs;
409
+ return {
410
+ ...step,
411
+ locators: locatorsObject,
412
+ };
413
+ }
414
+
415
+ for (const key in allStrategyLocators) {
416
+ if (key === "strategy") continue;
417
+ if (key === "no_text" || key === "custom") continue;
418
+ const locators = allStrategyLocators[key];
419
+ if (locators.length === 0) continue;
420
+ parameterizeLocators({
421
+ cmd,
422
+ locs: locators,
423
+ isValueVariable,
424
+ isTargetValueVariable,
425
+ parametersMap,
426
+ });
427
+ }
428
+
429
+ locatorsObject.locators = allStrategyLocators[allStrategyLocators.strategy] ?? locatorsObject.locators;
430
+
431
+ return {
432
+ ...step,
433
+ locators: locatorsObject,
434
+ allStrategyLocators,
435
+ isLocatorsAssigned: true,
436
+ };
437
+ };
438
+
17
439
  export const toMethodName = (str) => {
18
440
  // Remove any non-word characters (excluding underscore) and trim spaces
19
441
  let cleanStr = str.trim().replace(/[^\w\s]/gi, "");
@@ -36,7 +458,7 @@ export function getCodePage(stepDefsFilePath) {
36
458
  export function getCucumberStep({ step }) {
37
459
  const cucumberStep = new Step();
38
460
  cucumberStep.loadFromJson({
39
- text: step.text,
461
+ text: step.renamedText ? step.renamedText : step.text,
40
462
  keyword: step.keyword,
41
463
  keywordType: step.keywordType,
42
464
  parameters: [],
@@ -54,7 +476,7 @@ export function getCucumberStep({ step }) {
54
476
 
55
477
  function makeStepTextUnique(step, stepsDefinitions) {
56
478
  // const utilsFilePath = path.join("features", "step_definitions", "utils.mjs");
57
- let stepText = step.text;
479
+ let stepText = step.renamedText ? step.renamedText : step.text;
58
480
  let stepIndex = 1;
59
481
  // console.log("makeStepTextUnique", step.text);
60
482
  let stepDef = stepsDefinitions.findMatchingStep(stepText);
@@ -70,10 +492,13 @@ function makeStepTextUnique(step, stepsDefinitions) {
70
492
  step.text = stepText;
71
493
  }
72
494
 
73
- export async function saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions }) {
495
+ export async function saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions, parametersMap }) {
496
+ if (step.commands && Array.isArray(step.commands)) {
497
+ step.commands = step.commands.map((cmd) => toRecordingStep(cmd, parametersMap));
498
+ }
74
499
  let routesPath = path.join(tmpdir(), "blinq_temp_routes");
75
500
 
76
- if (process.env.TEMP_RUN) {
501
+ if (process.env.TEMP_RUN === "true") {
77
502
  if (existsSync(routesPath)) {
78
503
  rmSync(routesPath, { recursive: true });
79
504
  }
@@ -84,9 +509,9 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
84
509
  // remove the folder
85
510
  try {
86
511
  rmSync(routesPath, { recursive: true });
87
- console.log("Removed temp_routes_folder:", routesPath);
512
+ //
88
513
  } catch (error) {
89
- console.error("Error removing temp_routes folder", error);
514
+ //
90
515
  }
91
516
  routesPath = path.join(projectDir, "data", "routes");
92
517
  if (!existsSync(routesPath)) {
@@ -107,32 +532,37 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
107
532
  const isUtilStep = makeStepTextUnique(step, stepsDefinitions);
108
533
 
109
534
  if (isUtilStep) {
110
- return;
535
+ if (!step.renamedText) {
536
+ return;
537
+ }
538
+ step.text = step.text.trim();
539
+ const { functionName } = stepsDefinitions.findMatchingStep(step.renamedText);
540
+ step.renamedText = functionName;
541
+ const newImportLine = `import { ${functionName} } from "./utils.mjs";\n`;
542
+
543
+ if (!codePage.fileContent.includes(newImportLine)) {
544
+ codePage.fileContent = newImportLine + codePage.fileContent;
545
+ }
111
546
  }
112
547
  }
113
548
 
549
+ routesPath = path.join(tmpdir(), "blinq_temp_routes");
114
550
  if (process.env.TEMP_RUN === "true") {
115
- console.log("Save routes in temp folder for running:", routesPath);
116
551
  if (existsSync(routesPath)) {
117
- console.log("Removing existing temp_routes_folder:", routesPath);
118
552
  rmSync(routesPath, { recursive: true });
119
553
  }
120
554
  mkdirSync(routesPath, { recursive: true });
121
- console.log("Created temp_routes_folder:", routesPath);
122
555
  saveRoutes({ step, folderPath: routesPath });
123
556
  } else {
124
- console.log("Saving routes in project directory:", projectDir);
125
557
  if (existsSync(routesPath)) {
126
558
  // remove the folder
127
559
  try {
128
560
  rmSync(routesPath, { recursive: true });
129
- console.log("Removed temp_routes_folder:", routesPath);
130
561
  } catch (error) {
131
- console.error("Error removing temp_routes folder", error);
562
+ //
132
563
  }
133
564
  }
134
565
  routesPath = path.join(projectDir, "data", "routes");
135
- console.log("Saving routes to:", routesPath);
136
566
  if (!existsSync(routesPath)) {
137
567
  mkdirSync(routesPath, { recursive: true });
138
568
  }
@@ -141,6 +571,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
141
571
 
142
572
  cucumberStep.text = step.text;
143
573
  const recording = new Recording();
574
+
144
575
  const steps = step.commands;
145
576
 
146
577
  recording.loadFromObject({ steps, step: cucumberStep });
@@ -191,7 +622,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
191
622
  stepsDefinitions
192
623
  );
193
624
 
194
- if (!step.isImplemented) {
625
+ if (!step.renamedText) {
195
626
  stepsDefinitions.addStep({
196
627
  name: step.text,
197
628
  file: result.codePage.sourceFileName,
@@ -209,7 +640,10 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
209
640
  }
210
641
  codePage = generateCodeResult.page;
211
642
  methodName = generateCodeResult.methodName;
212
- codePage.insertElements(generateCodeResult.elements);
643
+
644
+ if (!step.renamedText) {
645
+ codePage.insertElements(generateCodeResult.elements);
646
+ }
213
647
 
214
648
  const description = cucumberStep.text;
215
649
  let path = null;
@@ -222,15 +656,32 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
222
656
  protect = true;
223
657
  }
224
658
  }
225
- const infraResult = codePage.addInfraCommand(
226
- methodName,
227
- description,
228
- cucumberStep.getVariablesList(),
229
- generateCodeResult.codeLines,
230
- protect,
231
- "recorder",
232
- path
233
- );
659
+
660
+ if (step.renamedText) {
661
+ codePage.addInfraCommandUtil(
662
+ methodName,
663
+ description,
664
+ cucumberStep.parameters,
665
+ generateCodeResult.codeLines,
666
+ step.renamedText,
667
+ step.text,
668
+ parametersMap,
669
+ protect,
670
+ "recorder",
671
+ path
672
+ );
673
+ } else {
674
+ codePage.addInfraCommand(
675
+ methodName,
676
+ description,
677
+ cucumberStep.getVariablesList(),
678
+ generateCodeResult.codeLines,
679
+ protect,
680
+ "recorder",
681
+ path
682
+ );
683
+ }
684
+
234
685
  const keyword = (cucumberStep.keywordAlias ?? cucumberStep.keyword).trim();
235
686
  const stepResult = codePage.addCucumberStep(
236
687
  keyword,
@@ -240,7 +691,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
240
691
  step.finalTimeout
241
692
  );
242
693
 
243
- if (!step.isImplemented) {
694
+ if (!step.renamedText && !(step.isImplemented && step.shouldOverride)) {
244
695
  stepsDefinitions.addStep({
245
696
  name: step.text,
246
697
  file: codePage.sourceFileName,
@@ -249,6 +700,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
249
700
  }
250
701
 
251
702
  codePage.removeUnusedElements();
703
+ codePage.mergeSimilarElements();
252
704
  cucumberStep.methodName = methodName;
253
705
  if (generateCodeResult.locatorsMetadata) {
254
706
  codePage.addLocatorsMetadata(generateCodeResult.locatorsMetadata);
@@ -300,26 +752,35 @@ export const getCommandsForImplementedStep = (stepName, stepsDefinitions, stepPa
300
752
  if (error) {
301
753
  throw new Error(error);
302
754
  }
755
+ isUtilStep = codePage.sourceFileName.endsWith("utils.mjs");
303
756
 
304
757
  if (parametersNames.length !== stepParams.length) {
305
758
  // console.log("Parameters mismatch", parametersNames, stepParams);
306
759
  throw new Error("Parameters mismatch");
307
760
  }
308
- for (let i = 0; i < parametersNames.length; i++) {
309
- stepParams[i].argumentName = parametersNames[i];
310
- }
311
761
 
312
- isUtilStep = codePage.sourceFileName.endsWith("utils.mjs");
313
- for (const { code } of codeCommands) {
314
- const command = invertCodeToCommand(code, elements, stepParams, stepsDefinitions, codePage, stepName)[0];
315
- if (command === undefined || command.type === null) continue;
316
- if (command.element) {
317
- const key = command.element.key;
318
- if (key && locatorsJson[key]) {
319
- command.allStrategyLocators = locatorsJson[key];
762
+ const pattern = step.name;
763
+ if (isUtilStep && pattern === "Verify the file {string} exists") {
764
+ commands.push({
765
+ type: "verify_file_exists",
766
+ parameters: [stepParams[0].text],
767
+ });
768
+ } else {
769
+ for (let i = 0; i < parametersNames.length; i++) {
770
+ stepParams[i].argumentName = parametersNames[i];
771
+ }
772
+
773
+ for (const { code } of codeCommands) {
774
+ const command = invertCodeToCommand(code, elements, stepParams, stepsDefinitions, codePage, stepName)[0];
775
+ if (command === undefined || command.type === null) continue;
776
+ if (command.element) {
777
+ const key = command.element.key;
778
+ if (key && locatorsJson[key]) {
779
+ command.allStrategyLocators = locatorsJson[key];
780
+ }
320
781
  }
782
+ commands.push(command);
321
783
  }
322
- commands.push(command);
323
784
  }
324
785
  } catch (error) {
325
786
  console.error(error);
@@ -404,6 +865,7 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
404
865
  console.log("Save routes in temp folder for running:", routesPath);
405
866
  if (existsSync(routesPath)) {
406
867
  console.log("Removing existing temp_routes_folder:", routesPath);
868
+ routesPath = path.join(tmpdir(), `blinq_temp_routes`);
407
869
  rmSync(routesPath, { recursive: true });
408
870
  }
409
871
  mkdirSync(routesPath, { recursive: true });
@@ -427,6 +889,9 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
427
889
  }
428
890
  saveRoutes({ step, folderPath: routesPath });
429
891
  }
892
+ if (step.commands && Array.isArray(step.commands)) {
893
+ step.commands = step.commands.map((cmd) => toRecordingStep(cmd, scenario.parametersMap));
894
+ }
430
895
  continue;
431
896
  }
432
897
  const cucumberStep = getCucumberStep({ step });
@@ -434,7 +899,14 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
434
899
  const stepDefsFilePath = locateDefinitionPath(featureFolder, pageName);
435
900
  // path.join(stepDefinitionFolderPath, pageName + "_page.mjs");
436
901
  let codePage = getCodePage(stepDefsFilePath);
437
- codePage = await saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions });
902
+ codePage = await saveRecording({
903
+ step,
904
+ cucumberStep,
905
+ codePage,
906
+ projectDir,
907
+ stepsDefinitions,
908
+ parametersMap: scenario.parametersMap,
909
+ });
438
910
  if (!codePage) {
439
911
  continue;
440
912
  }