@dev-blinq/cucumber_client 1.0.1426-dev → 1.0.1426-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 +153 -45
  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 +1008 -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 +31 -8
  36. package/bin/client/recorderv3/step_utils.js +510 -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
@@ -158,8 +158,7 @@ class LocatorGenerator {
158
158
  const tSelectorList = [];
159
159
  for (const selectorPart of selectorPartList) {
160
160
  const { engine, selector } = selectorPart;
161
- if (textToIgnore && selector.includes(textToIgnore)
162
- ) {
161
+ if (textToIgnore && selector.includes(textToIgnore)) {
163
162
  continue;
164
163
  }
165
164
  if (engine === "css") {
@@ -218,6 +217,53 @@ class LocatorGenerator {
218
217
  }
219
218
  return result;
220
219
  }
220
+ toContextLocators(element, contextElement, options = {}) {
221
+ const commonParent = this.dom_Parent.findLowestCommonAncestor([contextElement, element]);
222
+ const climb = this.dom_Parent.getClimbCountToParent(contextElement, commonParent);
223
+ const text = contextElement.innerText.trim();
224
+
225
+ const prefix = `internal:text="${text}" >> ${this.getXPathSelector(climb)}`;
226
+ const result = this.getElementLocators(element, {
227
+ root: commonParent,
228
+ strategies: {
229
+ [this.locatorStrategies.custom]: true,
230
+ [this.locatorStrategies.text]: true,
231
+ [this.locatorStrategies.no_text]: true,
232
+ },
233
+ prefix,
234
+ ...options,
235
+ });
236
+
237
+ const attachContextToLocators = (locs) => {
238
+ locs.forEach((loc) => {
239
+ loc.climb = climb;
240
+ loc.text = text;
241
+ });
242
+ };
243
+
244
+ const allStrategyLocators = result.allStrategyLocators;
245
+ const locators = result.locators;
246
+ if (allStrategyLocators) {
247
+ const allLocators = [];
248
+ for (const strategy in allStrategyLocators) {
249
+ if (strategy === "strategy") continue;
250
+ const locators = allStrategyLocators[strategy];
251
+ if (locators.length === 0) continue;
252
+ allLocators.push(...locators);
253
+ allStrategyLocators[strategy] = [];
254
+ }
255
+ attachContextToLocators(allLocators);
256
+ allStrategyLocators[this.locatorStrategies.context] = allLocators;
257
+ allStrategyLocators.strategy = this.locatorStrategies.context;
258
+ result.locators = allLocators;
259
+ return result;
260
+ }
261
+ if (locators) {
262
+ attachContextToLocators(locators);
263
+ return result;
264
+ }
265
+ return result;
266
+ }
221
267
  getContextLocators(element, locators) {
222
268
  if (!locators || !Array.isArray(locators)) {
223
269
  console.error("Locators must be an array");
@@ -442,12 +488,16 @@ class LocatorGenerator {
442
488
  categorizeLocators(element, locators, options) {
443
489
  const unique = [];
444
490
  const nonUnique = [];
491
+ const visible = options?.visible ?? true;
445
492
  try {
446
493
  for (const locator of locators) {
447
494
  if (!locator || !locator.css || typeof locator.css !== "string") {
448
495
  console.error("Locator must have a valid css selector found: ", locator);
449
496
  continue;
450
497
  }
498
+ if (visible === false) {
499
+ locator.visible = false;
500
+ }
451
501
  const elements = this.getMatchingElements(locator.css, options);
452
502
  if (elements.length === 0) {
453
503
  console.warn(`No elements found for locator: ${locator.css}`);
@@ -626,7 +676,7 @@ class LocatorGenerator {
626
676
 
627
677
  getUniqueLocators2(element, locatorGenerator = this.getNoTextLocators, options = {}) {
628
678
  try {
629
- const { maxLocators = 5, root = window.document.body } = options;
679
+ const { maxLocators = 5, root = window.document.body, prefix } = options;
630
680
 
631
681
  if (!element) {
632
682
  return [];
@@ -646,13 +696,7 @@ class LocatorGenerator {
646
696
  },
647
697
  ];
648
698
  } else {
649
- return [
650
- {
651
- css: ":root",
652
- score: 1,
653
- priority: 1,
654
- },
655
- ];
699
+ return [];
656
700
  }
657
701
  }
658
702
 
@@ -679,12 +723,13 @@ class LocatorGenerator {
679
723
 
680
724
  const elementsCache = new Map();
681
725
 
682
- const allAncestors = this.dom_Parent.getFullAncestorChainToRoot(element, root);
726
+ const allAncestors = prefix ? [element] : this.dom_Parent.getFullAncestorChainToRoot(element, root);
683
727
  allAncestors.shift(); // remove the element itself from the ancestors
684
728
 
685
729
  const cache = new Map();
686
730
  const textToIgnore = this.PW.selectorUtils.elementText(cache, element).full.trim();
687
731
  const ancestorLocators = [];
732
+ let uniqueAncestor = null;
688
733
  for (const ancestor of allAncestors) {
689
734
  const _locators = locatorGenerator(ancestor, { ...options, textToIgnore });
690
735
  if (!_locators || !Array.isArray(_locators) || _locators.length === 0) {
@@ -697,11 +742,15 @@ class LocatorGenerator {
697
742
  });
698
743
  elementsCache.set(ancestor, _categorized);
699
744
  if (_categorized.unique.length > 0) {
745
+ uniqueAncestor = {
746
+ element: ancestor,
747
+ locators: _categorized,
748
+ };
700
749
  break;
701
750
  }
702
751
  }
703
752
 
704
- const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
753
+ // const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
705
754
 
706
755
  for (const locator of nonUnique) {
707
756
  const selector = locator.css ?? locator.selector;
@@ -710,6 +759,27 @@ class LocatorGenerator {
710
759
  console.warn(`No elements found for locator: ${selector}`);
711
760
  continue;
712
761
  }
762
+ if (!uniqueAncestor) {
763
+ const elements = this.getMatchingElements(selector, options);
764
+ if (elements.length === 1 && elements[0] === element) {
765
+ result.push({
766
+ css: selector,
767
+ score: locator.score,
768
+ priority: 1,
769
+ });
770
+ } else {
771
+ const index = elements.indexOf(element);
772
+ if (index !== -1) {
773
+ result.push({
774
+ css: selector,
775
+ index,
776
+ score: locator.score + 200,
777
+ priority: 2,
778
+ });
779
+ }
780
+ }
781
+ continue;
782
+ }
713
783
 
714
784
  for (const unique_locator of uniqueAncestor.locators.unique) {
715
785
  const fullSelector = `${unique_locator.css} >> ${selector}`;
@@ -748,9 +818,32 @@ class LocatorGenerator {
748
818
  return [];
749
819
  }
750
820
  }
821
+ isElementVisible(element) {
822
+ if (!(element instanceof Element)) return false;
823
+ const style = window.getComputedStyle(element);
824
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
825
+ const rect = element.getBoundingClientRect();
826
+ if (rect.width === 0 || rect.height === 0) return false;
827
+ return true;
828
+ }
751
829
  getElementLocators(element, options = {}) {
830
+ const isVisible = this.isElementVisible(element);
831
+ if (isVisible === false) {
832
+ console.warn("Element is not visible: ", element);
833
+ options.visible = isVisible;
834
+ }
752
835
  try {
753
- const { excludeText = false } = options;
836
+ const {
837
+ excludeText = false,
838
+ strategies = {
839
+ [this.locatorStrategies.custom]: true,
840
+ [this.locatorStrategies.context]: true,
841
+ [this.locatorStrategies.text]: true,
842
+ [this.locatorStrategies.text_with_index]: true,
843
+ [this.locatorStrategies.digitIgnore]: true,
844
+ [this.locatorStrategies.no_text]: true,
845
+ },
846
+ } = options;
754
847
 
755
848
  const allStrategyLocators = {
756
849
  [this.locatorStrategies.custom]: [],
@@ -760,7 +853,12 @@ class LocatorGenerator {
760
853
  [this.locatorStrategies.digitIgnore]: [],
761
854
  [this.locatorStrategies.no_text]: [],
762
855
  };
763
- if (this.options?.customAttributes) {
856
+ if (
857
+ strategies[this.locatorStrategies.custom] &&
858
+ this.options?.customAttributes &&
859
+ Array.isArray(this.options.customAttributes) &&
860
+ this.options.customAttributes.length > 0
861
+ ) {
764
862
  console.groupCollapsed("Generating Custom locators for element:", element);
765
863
  const customLocators = this.getUniqueLocators(element, this.getCustomLocators.bind(this), options);
766
864
  if (customLocators.length > 0) {
@@ -769,43 +867,53 @@ class LocatorGenerator {
769
867
  }
770
868
  console.groupEnd();
771
869
  if (!excludeText) {
772
- console.groupCollapsed("Generating Text locators for element:", element);
773
- const basicLocators = this.getUniqueLocators(element, this.getTextLocators.bind(this), options);
774
- console.groupEnd();
775
- if (basicLocators.length > 0) {
776
- allStrategyLocators[this.locatorStrategies.text] = basicLocators;
777
- }
870
+ if (strategies[this.locatorStrategies.text]) {
871
+ console.groupCollapsed("Generating Text locators for element:", element);
778
872
 
779
- const textWithIndexLocators = this.getTextwithIndexLocators(basicLocators);
780
- if (textWithIndexLocators.length > 0) {
781
- allStrategyLocators[this.locatorStrategies.text_with_index] = textWithIndexLocators;
782
- }
783
- const digitIgnoreLocators = this.getDigitIgnoreLocators(element, basicLocators);
784
- if (digitIgnoreLocators.length > 0) {
785
- allStrategyLocators[this.locatorStrategies.digitIgnore] = digitIgnoreLocators;
786
- }
787
- const contextLocators = this.getContextLocators(element, basicLocators);
788
- if (contextLocators.length > 0) {
789
- allStrategyLocators[this.locatorStrategies.context] = contextLocators;
873
+ const basicLocators = this.getUniqueLocators(element, this.getTextLocators.bind(this), options);
874
+ console.groupEnd();
875
+ if (basicLocators.length > 0) {
876
+ allStrategyLocators[this.locatorStrategies.text] = basicLocators;
877
+ }
878
+ if (strategies[this.locatorStrategies.text_with_index]) {
879
+ const textWithIndexLocators = this.getTextwithIndexLocators(basicLocators);
880
+ if (textWithIndexLocators.length > 0) {
881
+ allStrategyLocators[this.locatorStrategies.text_with_index] = textWithIndexLocators;
882
+ }
883
+ }
884
+ if (strategies[this.locatorStrategies.digitIgnore]) {
885
+ const digitIgnoreLocators = this.getDigitIgnoreLocators(element, basicLocators);
886
+ if (digitIgnoreLocators.length > 0) {
887
+ allStrategyLocators[this.locatorStrategies.digitIgnore] = digitIgnoreLocators;
888
+ }
889
+ }
890
+ if (strategies[this.locatorStrategies.context]) {
891
+ const contextLocators = this.getContextLocators(element, basicLocators);
892
+ if (contextLocators.length > 0) {
893
+ allStrategyLocators[this.locatorStrategies.context] = contextLocators;
894
+ }
895
+ }
790
896
  }
791
897
  }
792
- console.groupCollapsed("Generating No Text locators for element:", element);
793
- const noTextLocators = this.getUniqueLocators(element, this.getNoTextLocators.bind(this), options);
898
+ if (strategies[this.locatorStrategies.no_text]) {
899
+ console.groupCollapsed("Generating No Text locators for element:", element);
900
+ const noTextLocators = this.getUniqueLocators(element, this.getNoTextLocators.bind(this), options);
794
901
 
795
- if (noTextLocators.length > 0) {
796
- allStrategyLocators[this.locatorStrategies.no_text] = noTextLocators;
797
- } else {
798
- const _locators = [];
799
- _locators.push({
800
- css: this.generateUniqueCSSSelector(element, options),
801
- score: 500,
802
- priority: 3,
803
- });
804
- if (_locators.length > 0) {
805
- allStrategyLocators[this.locatorStrategies.no_text] = _locators;
902
+ if (noTextLocators.length > 0) {
903
+ allStrategyLocators[this.locatorStrategies.no_text] = noTextLocators;
904
+ } else {
905
+ const _locators = [];
906
+ _locators.push({
907
+ css: this.generateUniqueCSSSelector(element, options),
908
+ score: 500,
909
+ priority: 3,
910
+ });
911
+ if (_locators.length > 0) {
912
+ allStrategyLocators[this.locatorStrategies.no_text] = _locators;
913
+ }
806
914
  }
915
+ console.groupEnd();
807
916
  }
808
- console.groupEnd();
809
917
 
810
918
  let bestStrategy = this.getBestStrategy(allStrategyLocators);
811
919
  if (!bestStrategy) {