@dev-blinq/cucumber_client 1.0.1466-dev → 1.0.1466-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 (36) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +73 -73
  2. package/bin/assets/scripts/recorder.js +87 -49
  3. package/bin/assets/scripts/snapshot_capturer.js +10 -17
  4. package/bin/assets/scripts/unique_locators.js +169 -47
  5. package/bin/assets/templates/_hooks_template.txt +6 -2
  6. package/bin/assets/templates/utils_template.txt +16 -16
  7. package/bin/client/code_cleanup/utils.js +16 -7
  8. package/bin/client/code_gen/code_inversion.js +127 -2
  9. package/bin/client/code_gen/duplication_analysis.js +2 -1
  10. package/bin/client/code_gen/function_signature.js +8 -0
  11. package/bin/client/code_gen/index.js +4 -0
  12. package/bin/client/code_gen/page_reflection.js +95 -10
  13. package/bin/client/code_gen/playwright_codeget.js +173 -77
  14. package/bin/client/cucumber/feature.js +4 -17
  15. package/bin/client/cucumber/steps_definitions.js +13 -0
  16. package/bin/client/recorderv3/bvt_init.js +310 -0
  17. package/bin/client/recorderv3/bvt_recorder.js +1560 -1183
  18. package/bin/client/recorderv3/implemented_steps.js +2 -0
  19. package/bin/client/recorderv3/index.js +3 -293
  20. package/bin/client/recorderv3/mixpanel.js +41 -0
  21. package/bin/client/recorderv3/services.js +838 -142
  22. package/bin/client/recorderv3/step_runner.js +36 -7
  23. package/bin/client/recorderv3/step_utils.js +171 -95
  24. package/bin/client/recorderv3/update_feature.js +87 -39
  25. package/bin/client/recorderv3/wbr_entry.js +61 -0
  26. package/bin/client/recording.js +1 -0
  27. package/bin/client/types/locators.js +2 -0
  28. package/bin/client/upload-service.js +2 -0
  29. package/bin/client/utils/app_dir.js +21 -0
  30. package/bin/client/utils/socket_logger.js +100 -125
  31. package/bin/index.js +4 -1
  32. package/package.json +12 -5
  33. package/bin/client/recorderv3/app_dir.js +0 -23
  34. package/bin/client/recorderv3/network.js +0 -299
  35. package/bin/client/recorderv3/scriptTest.js +0 -5
  36. package/bin/client/recorderv3/ws_server.js +0 -72
@@ -170,7 +170,7 @@ export class CodePage {
170
170
  this.generateModel(fileContentNew);
171
171
  }
172
172
  catch (e) {
173
- logger.info("failed to format the code");
173
+ logger.error("failed to format the code");
174
174
  logger.debug(e);
175
175
  }
176
176
  if (!existsSync(this.sourceFileName)) {
@@ -288,6 +288,11 @@ export class CodePage {
288
288
  codePart.name = node.id.name;
289
289
  }
290
290
  }
291
+ findKey(funcString, key) {
292
+ const sourceRegex = new RegExp(`${key}:\\s*(.*)`);
293
+ const match = funcString.match(sourceRegex);
294
+ return match ? match[1] : null;
295
+ }
291
296
  collectAllTemplates() {
292
297
  const templates = [];
293
298
  if (this.cucumberCalls.length > 0) {
@@ -300,10 +305,12 @@ export class CodePage {
300
305
  const stepType = cucumberCall["stepType"];
301
306
  let firstFind = true;
302
307
  const stepPaths = [];
308
+ let source = null;
303
309
  for (let j = 0; j < this.methods.length; j++) {
304
310
  const method = this.methods[j];
305
311
  if (method.name === methodName) {
306
312
  if (firstFind) {
313
+ source = this.findKey(method.codePart, "source");
307
314
  foundMethod = true;
308
315
  const paramsObj = (method.node?.params ?? []);
309
316
  if (paramsObj && paramsObj.length > 0) {
@@ -315,7 +322,7 @@ export class CodePage {
315
322
  }
316
323
  }
317
324
  if (foundMethod) {
318
- templates.push({ pattern, methodName, params, stepType, paths: stepPaths });
325
+ templates.push({ pattern, methodName, params, stepType, paths: stepPaths, source });
319
326
  }
320
327
  }
321
328
  }
@@ -363,6 +370,39 @@ export class CodePage {
363
370
  return result;
364
371
  }
365
372
  }
373
+ addInfraCommandUtil(methodName, description, stepVariables, stepCodeLines, renamedText, previousText, parametersMap, protectStep = false, source = null, codePath = "") {
374
+ let code = "\n";
375
+ code += "/**\n";
376
+ code += ` * ${description}\n`;
377
+ const tags = [];
378
+ if (protectStep)
379
+ tags.push("@protect");
380
+ if (source)
381
+ tags.push(`@${source}`);
382
+ if (tags.length > 0)
383
+ code += ` * ${tags.join(" ")}\n`;
384
+ if (codePath !== null)
385
+ code += ` * @path=${escapeForComment(codePath)}\n`;
386
+ const matches = previousText.match(/"[^"]*"/g);
387
+ const countInMethodName = matches ? matches.length : 0;
388
+ code += " */\n";
389
+ code += `async function ${methodName} (${new Array(countInMethodName)
390
+ .fill(0)
391
+ .map((v, index) => `param${index}`)
392
+ .join(", ")}){\n`;
393
+ code += `// source: ${source}\n`;
394
+ code += `// implemented_at: ${new Date().toISOString()}\n`;
395
+ stepCodeLines.forEach((line) => (code += ` ${line}\n`));
396
+ if (renamedText === "verify_page_title" || renamedText === "verify_page_url") {
397
+ const parameters = stepVariables.map((v) => parametersMap[v.text.replace(/[<>]/g, "")]);
398
+ code += `await ${renamedText}(${parameters.map((v) => (isNaN(Number(v)) ? `"${v}"` : Number(v))).join(", ")});\n`;
399
+ }
400
+ else {
401
+ code += `await ${renamedText}(${stepVariables.map((v) => (isNaN(Number(v.text)) ? `"${v.text}"` : Number(v.text))).join(", ")});\n`;
402
+ }
403
+ code += "}\n";
404
+ return this._injectMethod(methodName, code);
405
+ }
366
406
  addInfraCommand(methodName, description, stepVarables, stepCodeLines, protectStep = false, source = null, codePath = "") {
367
407
  let code = "\n";
368
408
  code += "/**\n";
@@ -415,6 +455,46 @@ export class CodePage {
415
455
  code += "}\n";
416
456
  return this._injectMethod(methodName, code);
417
457
  }
458
+ _replaceSelectedCode(code, injectIndexEnd) {
459
+ const newFileContent = this.fileContent.substring(0, injectIndexEnd - 2) +
460
+ "\n " +
461
+ code +
462
+ "\n}\n" +
463
+ this.fileContent.substring(injectIndexEnd);
464
+ this._init();
465
+ this.generateModel(newFileContent);
466
+ }
467
+ _injectOneCommand(methodName, code) {
468
+ const result = { methodName };
469
+ code = code.trim();
470
+ const existMethod = this.methods.find((m) => m.name === methodName);
471
+ if (!existMethod) {
472
+ throw new Error(`method ${methodName} not found for injection`);
473
+ }
474
+ const oldCode = existMethod.codePart.trim();
475
+ this._replaceSelectedCode(code, existMethod.end);
476
+ result.status = CodeStatus.UPDATED;
477
+ result.oldCode = oldCode;
478
+ result.newCode = code;
479
+ return result;
480
+ }
481
+ _removeSelectedCode(commands, injectIndexStart, injectIndexEnd) {
482
+ let newFileContent = this.fileContent.substring(injectIndexStart, injectIndexEnd);
483
+ commands.forEach((cmd) => {
484
+ newFileContent = newFileContent.replace(cmd, "");
485
+ });
486
+ newFileContent =
487
+ this.fileContent.substring(0, injectIndexStart) + newFileContent + this.fileContent.substring(injectIndexEnd);
488
+ this._init();
489
+ this.generateModel(newFileContent);
490
+ }
491
+ _removeCommands(methodName, commands) {
492
+ const existMethod = this.methods.find((m) => m.name === methodName);
493
+ if (!existMethod) {
494
+ throw new Error(`method ${methodName} not found for removal`);
495
+ }
496
+ this._removeSelectedCode(commands, existMethod.start, existMethod.end);
497
+ }
418
498
  _injectMethod(methodName, code) {
419
499
  const result = { methodName };
420
500
  code = code.trim();
@@ -487,11 +567,16 @@ export class CodePage {
487
567
  if (!element || !element.locators)
488
568
  return element;
489
569
  const clone = JSON.parse(JSON.stringify(element));
490
- for (let i = 0; i < (clone.locators?.length ?? 0); i++) {
491
- const locator = clone.locators[i];
492
- if (locator.score)
493
- delete locator.score;
494
- }
570
+ const locatorsArray = Array.isArray(clone.locators)
571
+ ? clone.locators
572
+ : (clone.locators.locators ?? []);
573
+ for (let i = 0; i < locatorsArray.length; i++) {
574
+ if (locatorsArray[i].score)
575
+ delete locatorsArray[i].score;
576
+ }
577
+ clone.locators = Array.isArray(clone.locators)
578
+ ? locatorsArray
579
+ : { ...clone.locators, locators: locatorsArray };
495
580
  return clone;
496
581
  }
497
582
  insertElements(elements) {
@@ -621,7 +706,7 @@ export class CodePage {
621
706
  let locatorsMetadataFileName = this.sourceFileName.replace(".mjs", ".json");
622
707
  const config = getAiConfig();
623
708
  if (config && config.locatorsMetadataDir) {
624
- locatorsMetadataFileName = path.join(config.locatorsMetadataDir, path.basename(locatorsMetadataFileName));
709
+ locatorsMetadataFileName = locatorsMetadataFileName.replace(path.join("features", "step_definitions"), path.join(config.locatorsMetadataDir));
625
710
  if (!existsSync(path.dirname(locatorsMetadataFileName))) {
626
711
  mkdirSync(path.dirname(locatorsMetadataFileName), { recursive: true });
627
712
  }
@@ -633,7 +718,7 @@ export class CodePage {
633
718
  }
634
719
  }
635
720
  catch {
636
- logger.info("failed to read locators metadata file", locatorsMetadataFileName);
721
+ logger.error("failed to read locators metadata file", locatorsMetadataFileName);
637
722
  }
638
723
  const keys = Object.keys(locatorsMetadata);
639
724
  keys.forEach((key) => {
@@ -643,7 +728,7 @@ export class CodePage {
643
728
  writeFileSync(locatorsMetadataFileName, JSON.stringify(metadata, null, 2), "utf8");
644
729
  }
645
730
  catch {
646
- logger.info("failed to write locators metadata file", locatorsMetadataFileName);
731
+ logger.error("failed to write locators metadata file", locatorsMetadataFileName);
647
732
  }
648
733
  }
649
734
  _getVariableStartEnd(variableName) {