@dev-blinq/cucumber_client 1.0.1427-dev → 1.0.1427-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 +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,59 @@ class LocatorGenerator {
218
217
  }
219
218
  return result;
220
219
  }
220
+ getMixedLocators(element, options) {
221
+ const noTextLocators = this.getNoTextLocators(element, options);
222
+ const textLocators = this.getTextLocators(element, options);
223
+ const customLocators = this.getCustomLocators(element, options);
224
+ return [...customLocators, ...textLocators, ...noTextLocators];
225
+ }
226
+ toContextLocators(element, contextElement, options = {}) {
227
+ const commonParent = this.dom_Parent.findLowestCommonAncestor([contextElement, element]);
228
+ const climb = this.dom_Parent.getClimbCountToParent(contextElement, commonParent);
229
+ const text = contextElement.innerText.trim();
230
+
231
+ const prefix = `internal:text="${text}" >> ${this.getXPathSelector(climb)}`;
232
+ const result = this.getElementLocators(element, {
233
+ root: commonParent,
234
+ strategies: {
235
+ [this.locatorStrategies.custom]: true,
236
+ [this.locatorStrategies.text]: true,
237
+ [this.locatorStrategies.no_text]: true,
238
+ },
239
+ prefix,
240
+ ...options,
241
+ });
242
+
243
+ const attachContextToLocators = (locs) => {
244
+ locs.forEach((loc) => {
245
+ loc.climb = climb;
246
+ loc.text = text;
247
+ });
248
+ };
249
+
250
+ const allStrategyLocators = result.allStrategyLocators;
251
+ const locators = result.locators;
252
+ if (allStrategyLocators) {
253
+ const allLocators = [];
254
+ for (const strategy in allStrategyLocators) {
255
+ if (strategy === "strategy") continue;
256
+ const locators = allStrategyLocators[strategy];
257
+ if (locators.length === 0) continue;
258
+ allLocators.push(...locators);
259
+ allStrategyLocators[strategy] = [];
260
+ }
261
+ attachContextToLocators(allLocators);
262
+ allStrategyLocators[this.locatorStrategies.context] = allLocators;
263
+ allStrategyLocators.strategy = this.locatorStrategies.context;
264
+ result.locators = allLocators;
265
+ return result;
266
+ }
267
+ if (locators) {
268
+ attachContextToLocators(locators);
269
+ return result;
270
+ }
271
+ return result;
272
+ }
221
273
  getContextLocators(element, locators) {
222
274
  if (!locators || !Array.isArray(locators)) {
223
275
  console.error("Locators must be an array");
@@ -442,12 +494,16 @@ class LocatorGenerator {
442
494
  categorizeLocators(element, locators, options) {
443
495
  const unique = [];
444
496
  const nonUnique = [];
497
+ const visible = options?.visible ?? true;
445
498
  try {
446
499
  for (const locator of locators) {
447
500
  if (!locator || !locator.css || typeof locator.css !== "string") {
448
501
  console.error("Locator must have a valid css selector found: ", locator);
449
502
  continue;
450
503
  }
504
+ if (visible === false) {
505
+ locator.visible = false;
506
+ }
451
507
  const elements = this.getMatchingElements(locator.css, options);
452
508
  if (elements.length === 0) {
453
509
  console.warn(`No elements found for locator: ${locator.css}`);
@@ -572,7 +628,7 @@ class LocatorGenerator {
572
628
  result.push(_locator);
573
629
  } else {
574
630
  const index = _elements.indexOf(element);
575
- if (index !== -1 && index < 5) {
631
+ if (index !== -1 && index < 10) {
576
632
  // _locator.selector = fullSelector;
577
633
  _locator.css = fullSelector;
578
634
  _locator.index = index;
@@ -584,7 +640,7 @@ class LocatorGenerator {
584
640
  }
585
641
  } else {
586
642
  const index = elements.indexOf(element);
587
- if (index !== -1 && index < 5) {
643
+ if (index !== -1 && index < 10) {
588
644
  locator.index = index;
589
645
  locator.priority = 2; // non-unique locators have lower priority
590
646
  result.push(locator);
@@ -592,7 +648,7 @@ class LocatorGenerator {
592
648
  }
593
649
  } else {
594
650
  const index = elements.indexOf(element);
595
- if (index !== -1 && index < 5) {
651
+ if (index !== -1 && index < 10) {
596
652
  locator.index = index;
597
653
  locator.priority = 2; // non-unique locators have lower priority
598
654
  result.push(locator);
@@ -626,7 +682,7 @@ class LocatorGenerator {
626
682
 
627
683
  getUniqueLocators2(element, locatorGenerator = this.getNoTextLocators, options = {}) {
628
684
  try {
629
- const { maxLocators = 5, root = window.document.body } = options;
685
+ const { maxLocators = 5, root = window.document.body, prefix } = options;
630
686
 
631
687
  if (!element) {
632
688
  return [];
@@ -646,13 +702,7 @@ class LocatorGenerator {
646
702
  },
647
703
  ];
648
704
  } else {
649
- return [
650
- {
651
- css: ":root",
652
- score: 1,
653
- priority: 1,
654
- },
655
- ];
705
+ return [];
656
706
  }
657
707
  }
658
708
 
@@ -679,12 +729,13 @@ class LocatorGenerator {
679
729
 
680
730
  const elementsCache = new Map();
681
731
 
682
- const allAncestors = this.dom_Parent.getFullAncestorChainToRoot(element, root);
732
+ const allAncestors = prefix ? [element] : this.dom_Parent.getFullAncestorChainToRoot(element, root);
683
733
  allAncestors.shift(); // remove the element itself from the ancestors
684
734
 
685
735
  const cache = new Map();
686
736
  const textToIgnore = this.PW.selectorUtils.elementText(cache, element).full.trim();
687
737
  const ancestorLocators = [];
738
+ let uniqueAncestor = null;
688
739
  for (const ancestor of allAncestors) {
689
740
  const _locators = locatorGenerator(ancestor, { ...options, textToIgnore });
690
741
  if (!_locators || !Array.isArray(_locators) || _locators.length === 0) {
@@ -697,11 +748,15 @@ class LocatorGenerator {
697
748
  });
698
749
  elementsCache.set(ancestor, _categorized);
699
750
  if (_categorized.unique.length > 0) {
751
+ uniqueAncestor = {
752
+ element: ancestor,
753
+ locators: _categorized,
754
+ };
700
755
  break;
701
756
  }
702
757
  }
703
758
 
704
- const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
759
+ // const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
705
760
 
706
761
  for (const locator of nonUnique) {
707
762
  const selector = locator.css ?? locator.selector;
@@ -710,6 +765,27 @@ class LocatorGenerator {
710
765
  console.warn(`No elements found for locator: ${selector}`);
711
766
  continue;
712
767
  }
768
+ if (!uniqueAncestor) {
769
+ const elements = this.getMatchingElements(selector, options);
770
+ if (elements.length === 1 && elements[0] === element) {
771
+ result.push({
772
+ css: selector,
773
+ score: locator.score,
774
+ priority: 1,
775
+ });
776
+ } else {
777
+ const index = elements.indexOf(element);
778
+ if (index !== -1) {
779
+ result.push({
780
+ css: selector,
781
+ index,
782
+ score: locator.score + 200,
783
+ priority: 2,
784
+ });
785
+ }
786
+ }
787
+ continue;
788
+ }
713
789
 
714
790
  for (const unique_locator of uniqueAncestor.locators.unique) {
715
791
  const fullSelector = `${unique_locator.css} >> ${selector}`;
@@ -725,7 +801,7 @@ class LocatorGenerator {
725
801
  result.push(newLocator);
726
802
  } else {
727
803
  const index = elements.indexOf(element);
728
- if (index !== -1 && index < 5) {
804
+ if (index !== -1 && index < 10) {
729
805
  const effectiveScore = (unique_locator.score + locator.score) / 2;
730
806
  const newLocator = {
731
807
  ...unique_locator,
@@ -748,9 +824,32 @@ class LocatorGenerator {
748
824
  return [];
749
825
  }
750
826
  }
827
+ isElementVisible(element) {
828
+ if (!(element instanceof Element)) return false;
829
+ const style = window.getComputedStyle(element);
830
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
831
+ const rect = element.getBoundingClientRect();
832
+ if (rect.width === 0 || rect.height === 0) return false;
833
+ return true;
834
+ }
751
835
  getElementLocators(element, options = {}) {
836
+ const isVisible = this.isElementVisible(element);
837
+ if (isVisible === false) {
838
+ console.warn("Element is not visible: ", element);
839
+ options.visible = isVisible;
840
+ }
752
841
  try {
753
- const { excludeText = false } = options;
842
+ const {
843
+ excludeText = false,
844
+ strategies = {
845
+ [this.locatorStrategies.custom]: true,
846
+ [this.locatorStrategies.context]: true,
847
+ [this.locatorStrategies.text]: true,
848
+ [this.locatorStrategies.text_with_index]: true,
849
+ [this.locatorStrategies.digitIgnore]: true,
850
+ [this.locatorStrategies.no_text]: true,
851
+ },
852
+ } = options;
754
853
 
755
854
  const allStrategyLocators = {
756
855
  [this.locatorStrategies.custom]: [],
@@ -760,7 +859,12 @@ class LocatorGenerator {
760
859
  [this.locatorStrategies.digitIgnore]: [],
761
860
  [this.locatorStrategies.no_text]: [],
762
861
  };
763
- if (this.options?.customAttributes) {
862
+ if (
863
+ strategies[this.locatorStrategies.custom] &&
864
+ this.options?.customAttributes &&
865
+ Array.isArray(this.options.customAttributes) &&
866
+ this.options.customAttributes.length > 0
867
+ ) {
764
868
  console.groupCollapsed("Generating Custom locators for element:", element);
765
869
  const customLocators = this.getUniqueLocators(element, this.getCustomLocators.bind(this), options);
766
870
  if (customLocators.length > 0) {
@@ -769,43 +873,60 @@ class LocatorGenerator {
769
873
  }
770
874
  console.groupEnd();
771
875
  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
- }
876
+ if (strategies[this.locatorStrategies.text]) {
877
+ console.groupCollapsed("Generating Text locators for element:", element);
778
878
 
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;
879
+ const basicLocators = this.getUniqueLocators(element, this.getTextLocators.bind(this), options);
880
+ console.groupEnd();
881
+ if (basicLocators.length > 0) {
882
+ allStrategyLocators[this.locatorStrategies.text] = basicLocators;
883
+ }
884
+ if (strategies[this.locatorStrategies.text_with_index]) {
885
+ const textWithIndexLocators = this.getTextwithIndexLocators(basicLocators);
886
+ if (textWithIndexLocators.length > 0) {
887
+ allStrategyLocators[this.locatorStrategies.text_with_index] = textWithIndexLocators;
888
+ }
889
+ }
890
+ if (strategies[this.locatorStrategies.digitIgnore]) {
891
+ const digitIgnoreLocators = this.getDigitIgnoreLocators(element, basicLocators);
892
+ if (digitIgnoreLocators.length > 0) {
893
+ allStrategyLocators[this.locatorStrategies.digitIgnore] = digitIgnoreLocators;
894
+ }
895
+ }
896
+ if (strategies[this.locatorStrategies.context]) {
897
+ const contextLocators = this.getContextLocators(element, basicLocators);
898
+ if (contextLocators.length > 0) {
899
+ allStrategyLocators[this.locatorStrategies.context] = contextLocators;
900
+ }
901
+ }
790
902
  }
791
903
  }
792
- console.groupCollapsed("Generating No Text locators for element:", element);
793
- const noTextLocators = this.getUniqueLocators(element, this.getNoTextLocators.bind(this), options);
904
+ if (strategies[this.locatorStrategies.no_text]) {
905
+ console.groupCollapsed("Generating No Text locators for element:", element);
906
+ const noTextLocators = this.getUniqueLocators(element, this.getNoTextLocators.bind(this), options);
794
907
 
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;
908
+ if (noTextLocators.length > 0) {
909
+ allStrategyLocators[this.locatorStrategies.no_text] = noTextLocators;
910
+ } else {
911
+
912
+ // try mixed locator strategy as last resort
913
+ const mixedLocators = this.getUniqueLocators(element, this.getMixedLocators.bind(this), options);
914
+ if (mixedLocators.length > 0) {
915
+ allStrategyLocators[this.locatorStrategies.no_text] = mixedLocators;
916
+ } else {
917
+ const _locators = [];
918
+ _locators.push({
919
+ css: this.generateUniqueCSSSelector(element, options),
920
+ score: 500,
921
+ priority: 3,
922
+ });
923
+ if (_locators.length > 0) {
924
+ allStrategyLocators[this.locatorStrategies.no_text] = _locators;
925
+ }
926
+ }
806
927
  }
928
+ console.groupEnd();
807
929
  }
808
- console.groupEnd();
809
930
 
810
931
  let bestStrategy = this.getBestStrategy(allStrategyLocators);
811
932
  if (!bestStrategy) {