@dev-blinq/cucumber_client 1.0.1173-dev → 1.0.1173-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 (47) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +220 -0
  2. package/bin/assets/preload/accessibility.js +1 -1
  3. package/bin/assets/preload/find_context.js +1 -1
  4. package/bin/assets/preload/generateSelector.js +24 -0
  5. package/bin/assets/preload/locators.js +18 -0
  6. package/bin/assets/preload/recorderv3.js +85 -11
  7. package/bin/assets/preload/unique_locators.js +24 -3
  8. package/bin/assets/scripts/aria_snapshot.js +235 -0
  9. package/bin/assets/scripts/dom_attr.js +372 -0
  10. package/bin/assets/scripts/dom_element.js +0 -0
  11. package/bin/assets/scripts/dom_parent.js +185 -0
  12. package/bin/assets/scripts/event_utils.js +105 -0
  13. package/bin/assets/scripts/pw.js +7886 -0
  14. package/bin/assets/scripts/recorder.js +1147 -0
  15. package/bin/assets/scripts/snapshot_capturer.js +155 -0
  16. package/bin/assets/scripts/unique_locators.js +844 -0
  17. package/bin/assets/scripts/yaml.js +4770 -0
  18. package/bin/assets/templates/page_template.txt +2 -16
  19. package/bin/assets/templates/utils_template.txt +65 -12
  20. package/bin/client/cli_helpers.js +0 -1
  21. package/bin/client/code_cleanup/utils.js +43 -14
  22. package/bin/client/code_gen/code_inversion.js +112 -18
  23. package/bin/client/code_gen/index.js +3 -0
  24. package/bin/client/code_gen/page_reflection.js +37 -20
  25. package/bin/client/code_gen/playwright_codeget.js +152 -48
  26. package/bin/client/cucumber/feature.js +96 -42
  27. package/bin/client/cucumber/project_to_document.js +8 -7
  28. package/bin/client/cucumber/steps_definitions.js +59 -16
  29. package/bin/client/local_agent.js +9 -7
  30. package/bin/client/operations/dump_tree.js +159 -8
  31. package/bin/client/playground/playground.js +1 -1
  32. package/bin/client/project.js +6 -2
  33. package/bin/client/recorderv3/bvt_recorder.js +236 -79
  34. package/bin/client/recorderv3/cli.js +1 -0
  35. package/bin/client/recorderv3/implemented_steps.js +111 -11
  36. package/bin/client/recorderv3/index.js +45 -4
  37. package/bin/client/recorderv3/network.js +299 -0
  38. package/bin/client/recorderv3/step_runner.js +179 -13
  39. package/bin/client/recorderv3/step_utils.js +159 -14
  40. package/bin/client/recorderv3/update_feature.js +55 -30
  41. package/bin/client/recording.js +8 -0
  42. package/bin/client/run_cucumber.js +116 -4
  43. package/bin/client/scenario_report.js +112 -50
  44. package/bin/client/test_scenario.js +0 -1
  45. package/bin/index.js +1 -0
  46. package/package.json +15 -8
  47. package/bin/client/code_gen/get_implemented_steps.js +0 -27
@@ -32,7 +32,6 @@ const MAX_SIZE_LIMIT = 1e7 * 3;
32
32
 
33
33
  import { getJsonReport } from "./bvt_json_report.js";
34
34
  import { profile } from "./profiler.js";
35
- import { getDocumentAndPickel } from "./cucumber/feature.js";
36
35
  winCA({});
37
36
 
38
37
  class Client {
@@ -383,7 +382,7 @@ class LocalAgent {
383
382
  error: command.data.errorMessage,
384
383
  });
385
384
  agent.stepFailResolve(command.data.errorMessage);
386
- logger.info("Step fail, " + command.data.errorMessage);
385
+ logger.error("Step fail, " + command.data.errorMessage);
387
386
  } else {
388
387
  agent.stepEndResolve();
389
388
  logger.info("Step end");
@@ -655,6 +654,7 @@ class LocalAgent {
655
654
 
656
655
  let page = agent.project.getPage(agent.pageName, true);
657
656
  const generateCodeResult = generateCode(recording, page, userData, agent.project.rootFolder, methodName);
657
+
658
658
  if (generateCodeResult.simple === true) {
659
659
  agent.sendDone("generateStepCode", null);
660
660
  break;
@@ -707,6 +707,9 @@ class LocalAgent {
707
707
  cucumberStep: agent.cucumberStep,
708
708
  },
709
709
  });
710
+ if (generateCodeResult.locatorsMetadata) {
711
+ page.addLocatorsMetadata(generateCodeResult.locatorsMetadata);
712
+ }
710
713
  await page.save();
711
714
  agent.scenarioReport.updateLastStep({
712
715
  recording: command.data.recording,
@@ -967,7 +970,7 @@ class LocalAgent {
967
970
  async createNewStepLocal(
968
971
  featureName,
969
972
  cucumberStep,
970
- feature,
973
+ comments,
971
974
  userData,
972
975
  firstStep,
973
976
  previousTasks,
@@ -1056,9 +1059,8 @@ class LocalAgent {
1056
1059
  //stepText = _replaceWithLocalData(stepText, testData);
1057
1060
 
1058
1061
  logger.info("\x1b[38;5;208mCreate new step:\x1b[0m " + stepText);
1059
- const stepObject = getDocumentAndPickel(featureName, featureFileText, scenarioDocument.name);
1060
- if (this.context && this.context.web) {
1061
- await this.context.web.beforeStep(null, stepObject);
1062
+ if (this.context && this.context.stable) {
1063
+ await this.context.stable.beforeStep(null, cucumberStep);
1062
1064
  }
1063
1065
  //this.pageName = pageName;
1064
1066
  this.cucumberStep = cucumberStep;
@@ -1083,7 +1085,7 @@ class LocalAgent {
1083
1085
  previousTasks,
1084
1086
  scenarioDocument,
1085
1087
  scenarioStepIndex,
1086
- comments: feature.comments,
1088
+ comments,
1087
1089
  featureFileText,
1088
1090
  recover,
1089
1091
  dumpConfig: this.dumpConfig,
@@ -48,18 +48,13 @@ const _openCDP = async (context) => {
48
48
  // let result = await cdp.send("DOM.getDocument", { depth: -1, pierce: true });
49
49
  // console.log("result", JSON.stringify(result, null, 2));
50
50
  };
51
+
51
52
  const getAccessibilityTree = async (context, dumpConfig) => {
52
53
  for (let i = 0; i < 3; i++) {
53
54
  await _closeCDP();
54
55
  try {
55
56
  await _openCDP(context);
56
- if (dumpConfig && dumpConfig.supress_errors === true) {
57
- process.env.SUPRESS_ERRORS = "true";
58
- }
59
57
  //wait for 2 seconds
60
- // if (dumpConfig && dumpConfig.independentThought === true) {
61
- // context.INDEPENDENT_THOUGHT = "true";
62
- // }
63
58
  if (dumpConfig && dumpConfig.load_all_lazy === true) {
64
59
  await context.page.evaluate(() => {
65
60
  // document.addEventListener("load", () => {
@@ -86,6 +81,7 @@ const getAccessibilityTree = async (context, dumpConfig) => {
86
81
  break;
87
82
  }
88
83
  }
84
+
89
85
  await context.page.evaluate(() => {
90
86
  const { top, left } = window.originalScroll || { top: 0, left: 0 };
91
87
  window.scrollTo(left, top);
@@ -381,6 +377,81 @@ const findLocatorByText = async (context, texts, backendNodeId) => {
381
377
  await _closeCDP();
382
378
  }
383
379
  };
380
+ function classifyLocatorsByStrategy(locators) {
381
+ const locs = [];
382
+
383
+ const allStrategyLocators = {
384
+ basic: [],
385
+ no_text: [],
386
+ ignore_digit: [],
387
+ context: [],
388
+ strategy: "basic",
389
+ };
390
+
391
+ const regexRegex = /\/.*\\[d][+].*\//;
392
+ for (const locator of locators) {
393
+ if (locator.mode) {
394
+ const { mode, ...rest } = locator;
395
+ locs.push(rest);
396
+ allStrategyLocators[locator.mode.toLowerCase()].push(rest);
397
+ } else if (locator.text && locator.text.length > 0) {
398
+ locs.push({
399
+ ...locator,
400
+ mode: "CONTEXT",
401
+ });
402
+ allStrategyLocators["context"].push(locator);
403
+ } else if (regexRegex.test(locator.css)) {
404
+ locs.push({
405
+ ...locator,
406
+ mode: "IGNORE_DIGIT",
407
+ });
408
+ allStrategyLocators["ignore_digit"].push(locator);
409
+ } else if (locator.css.includes("text=") || locator.css.includes("[name=") || locator.css.includes("label=")) {
410
+ locs.push(locator);
411
+ allStrategyLocators["basic"].push(locator);
412
+ } else {
413
+ locs.push({
414
+ ...locator,
415
+ mode: "NO_TEXT",
416
+ });
417
+ allStrategyLocators["no_text"].push(locator);
418
+ }
419
+ }
420
+ if (allStrategyLocators["context"].length > 0) {
421
+ allStrategyLocators["strategy"] = "context";
422
+ } else if (allStrategyLocators["basic"].length === 0 && allStrategyLocators["no_text"].length > 0) {
423
+ allStrategyLocators["strategy"] = "no_text";
424
+ }
425
+
426
+ return {
427
+ locators: locs,
428
+ allStrategyLocators,
429
+ };
430
+ }
431
+
432
+ async function filterLocators(cssLocators, elObjectId) {
433
+ const kept = [];
434
+ for (const selector of cssLocators) {
435
+ // call window.findElement(selector) === el
436
+ const { result } = await cdp.send("Runtime.callFunctionOn", {
437
+ functionDeclaration: `
438
+ function(element,selector) {
439
+ console.log("filterLocators in progress");
440
+ console.log(element,selector);
441
+ return window.findElement(selector) === element;
442
+ }
443
+ `,
444
+ objectId: elObjectId,
445
+ arguments: [{ objectId: elObjectId }, { value: selector }],
446
+ returnByValue: true,
447
+ });
448
+
449
+ if (result.value) {
450
+ kept.push(selector);
451
+ }
452
+ }
453
+ return kept;
454
+ }
384
455
 
385
456
  async function getRecorderLocators(context, backendNodeId) {
386
457
  if (!cdp) {
@@ -391,7 +462,8 @@ async function getRecorderLocators(context, backendNodeId) {
391
462
  backendNodeId: backendNodeId,
392
463
  });
393
464
  const objectId = domNode.object.objectId;
394
- let res = await cdp.send("Runtime.callFunctionOn", {
465
+ let locators = [];
466
+ locators = await cdp.send("Runtime.callFunctionOn", {
395
467
  functionDeclaration:
396
468
  "function(element,options) { console.log(element,options); return window.getPWLocators(element,options); }",
397
469
  objectId: objectId,
@@ -408,8 +480,87 @@ async function getRecorderLocators(context, backendNodeId) {
408
480
  ],
409
481
  returnByValue: true,
410
482
  });
483
+ if (!locators || !locators.result || !locators.result.value) {
484
+ locators = [];
485
+ } else {
486
+ locators = locators.result?.value;
487
+ }
488
+ let cssLocators = [];
489
+ try {
490
+ let origenCss = await cdp.send("Runtime.callFunctionOn", {
491
+ functionDeclaration:
492
+ "function(element) { console.log(element); return window.generateUniqueCSSSelector(element); }",
493
+ objectId: objectId,
494
+ arguments: [
495
+ {
496
+ objectId: objectId,
497
+ },
498
+ ],
499
+ returnByValue: true,
500
+ });
501
+ origenCss = origenCss.result?.value;
502
+ if (origenCss) {
503
+ cssLocators.push(origenCss);
504
+ }
505
+ let noClasses = await cdp.send("Runtime.callFunctionOn", {
506
+ functionDeclaration:
507
+ "function(element,options) { console.log(element,options); return window.CssSelectorGenerator.getCssSelector(element,options); }",
508
+ objectId: objectId,
509
+ arguments: [
510
+ {
511
+ objectId: objectId,
512
+ },
513
+ {
514
+ value: {
515
+ blacklist: [/^(?!.*h\d).*?\d.*/, /\[style/, /\[data-input-id/, /\[blinq-container/],
516
+ combineWithinSelector: true,
517
+ combineBetweenSelectors: true,
518
+ selectors: ["id", "attribute", "tag", "nthchild", "nthoftype"],
519
+ maxCombinations: 100,
520
+ },
521
+ },
522
+ ],
523
+ returnByValue: true,
524
+ });
525
+ noClasses = noClasses.result?.value;
526
+ if (!cssLocators.includes(noClasses)) {
527
+ cssLocators.push(noClasses);
528
+ }
529
+ let withClasses = await cdp.send("Runtime.callFunctionOn", {
530
+ functionDeclaration:
531
+ "function(element,options) { console.log(element,options); return window.CssSelectorGenerator.getCssSelector(element,options); }",
532
+ objectId: objectId,
533
+ arguments: [
534
+ {
535
+ objectId: objectId,
536
+ },
537
+ {
538
+ value: {
539
+ blacklist: [/^(?!.*h\d).*?\d.*/, /\[style/, /\[data-input-id/, /\[blinq-container/],
540
+ combineWithinSelector: true,
541
+ combineBetweenSelectors: true,
542
+ selectors: ["id", "attribute", "tag", "nthchild", "nthoftype", "class"],
543
+ maxCombinations: 100,
544
+ },
545
+ },
546
+ ],
547
+ returnByValue: true,
548
+ });
549
+ withClasses = withClasses.result?.value;
550
+ if (!cssLocators.includes(withClasses)) {
551
+ cssLocators.push(withClasses);
552
+ }
553
+ cssLocators.sort((a, b) => a.length - b.length);
554
+
555
+ cssLocators = await filterLocators(cssLocators, objectId);
556
+ } catch (err) {
557
+ console.error("Error in generateUniqueCSSSelector", error);
558
+ }
559
+ locators?.push(...cssLocators.map((css) => ({ mode: "NO_TEXT", css })));
560
+
561
+ const result = classifyLocatorsByStrategy(locators);
411
562
 
412
- return res.result;
563
+ return { ...result, element_name: "" };
413
564
  } finally {
414
565
  await _closeCDP();
415
566
  }
@@ -190,7 +190,7 @@ class Playground {
190
190
  .createNewStepLocal(
191
191
  "untitled",
192
192
  cucumberStep,
193
- this.feature,
193
+ this.feature.comments,
194
194
  userData,
195
195
  false,
196
196
  this.previousTasks,
@@ -4,6 +4,7 @@ import { CodePage } from "./code_gen/page_reflection.js";
4
4
  import logger from "../logger.js";
5
5
  import path from "path";
6
6
  import { fileURLToPath } from "url";
7
+ import { findFilesWithExtension } from "./cucumber/steps_definitions.js";
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = path.dirname(__filename);
9
10
 
@@ -85,7 +86,10 @@ class Project {
85
86
  logger.error("Error loading utils_template");
86
87
  }
87
88
 
88
- let files = readdirSync(this.stepsFolder);
89
+ const files = findFilesWithExtension(this.stepsFolder, "mjs");
90
+
91
+ //let files = readdirSync(this.stepsFolder);
92
+
89
93
  for (let i = 0; i < files.length; i++) {
90
94
  let file = files[i];
91
95
  if (file.startsWith("_")) {
@@ -100,7 +104,7 @@ class Project {
100
104
  this.pages.push(page);
101
105
  }
102
106
  }
103
- return envFile;
107
+ return this.environment.name;
104
108
  }
105
109
  getPagesNames() {
106
110
  let result = [];