@dev-blinq/cucumber_client 1.0.1400-dev → 1.0.1400-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 (50) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +105 -105
  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 +163 -44
  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 +1 -1
  17. package/bin/client/code_cleanup/find_step_definition_references.js +0 -1
  18. package/bin/client/code_cleanup/utils.js +5 -1
  19. package/bin/client/code_gen/api_codegen.js +2 -2
  20. package/bin/client/code_gen/code_inversion.js +63 -2
  21. package/bin/client/code_gen/function_signature.js +4 -0
  22. package/bin/client/code_gen/page_reflection.js +846 -906
  23. package/bin/client/code_gen/playwright_codeget.js +27 -3
  24. package/bin/client/cucumber/feature.js +4 -0
  25. package/bin/client/cucumber/feature_data.js +2 -2
  26. package/bin/client/cucumber/project_to_document.js +8 -2
  27. package/bin/client/cucumber/steps_definitions.js +6 -3
  28. package/bin/client/cucumber_selector.js +17 -1
  29. package/bin/client/local_agent.js +3 -2
  30. package/bin/client/parse_feature_file.js +23 -26
  31. package/bin/client/playground/projects/env.json +2 -2
  32. package/bin/client/project.js +186 -202
  33. package/bin/client/recorderv3/bvt_init.js +349 -0
  34. package/bin/client/recorderv3/bvt_recorder.js +1068 -104
  35. package/bin/client/recorderv3/implemented_steps.js +2 -0
  36. package/bin/client/recorderv3/index.js +4 -303
  37. package/bin/client/recorderv3/scriptTest.js +1 -1
  38. package/bin/client/recorderv3/services.js +814 -154
  39. package/bin/client/recorderv3/step_runner.js +315 -206
  40. package/bin/client/recorderv3/step_utils.js +473 -25
  41. package/bin/client/recorderv3/update_feature.js +9 -5
  42. package/bin/client/recorderv3/wbr_entry.js +61 -0
  43. package/bin/client/recording.js +1 -0
  44. package/bin/client/upload-service.js +3 -2
  45. package/bin/client/utils/socket_logger.js +132 -0
  46. package/bin/index.js +4 -1
  47. package/bin/logger.js +3 -2
  48. package/bin/min/consoleApi.min.cjs +2 -3
  49. package/bin/min/injectedScript.min.cjs +16 -16
  50. package/package.json +19 -9
@@ -150,6 +150,7 @@ class LocatorGenerator {
150
150
  }
151
151
  getTextLocators(element, options) {
152
152
  const injectedScript = this.injectedScript;
153
+ const { textToIgnore = null } = options;
153
154
  const selectorPartLists = this.PW.selectorGenerator.buildTextCandidates(injectedScript, element, options);
154
155
  const result = [];
155
156
  for (const selectorPartList of selectorPartLists) {
@@ -157,6 +158,9 @@ class LocatorGenerator {
157
158
  const tSelectorList = [];
158
159
  for (const selectorPart of selectorPartList) {
159
160
  const { engine, selector } = selectorPart;
161
+ if (textToIgnore && selector.includes(textToIgnore)) {
162
+ continue;
163
+ }
160
164
  if (engine === "css") {
161
165
  tSelectorList.push(selector);
162
166
  } else {
@@ -213,6 +217,53 @@ class LocatorGenerator {
213
217
  }
214
218
  return result;
215
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
+ }
216
267
  getContextLocators(element, locators) {
217
268
  if (!locators || !Array.isArray(locators)) {
218
269
  console.error("Locators must be an array");
@@ -437,8 +488,16 @@ class LocatorGenerator {
437
488
  categorizeLocators(element, locators, options) {
438
489
  const unique = [];
439
490
  const nonUnique = [];
491
+ const visible = options?.visible ?? true;
440
492
  try {
441
493
  for (const locator of locators) {
494
+ if (!locator || !locator.css || typeof locator.css !== "string") {
495
+ console.error("Locator must have a valid css selector found: ", locator);
496
+ continue;
497
+ }
498
+ if (visible === false) {
499
+ locator.visible = false;
500
+ }
442
501
  const elements = this.getMatchingElements(locator.css, options);
443
502
  if (elements.length === 0) {
444
503
  console.warn(`No elements found for locator: ${locator.css}`);
@@ -617,7 +676,7 @@ class LocatorGenerator {
617
676
 
618
677
  getUniqueLocators2(element, locatorGenerator = this.getNoTextLocators, options = {}) {
619
678
  try {
620
- const { maxLocators = 5, root = window.document.body } = options;
679
+ const { maxLocators = 5, root = window.document.body, prefix } = options;
621
680
 
622
681
  if (!element) {
623
682
  return [];
@@ -637,13 +696,7 @@ class LocatorGenerator {
637
696
  },
638
697
  ];
639
698
  } else {
640
- return [
641
- {
642
- css: ":root",
643
- score: 1,
644
- priority: 1,
645
- },
646
- ];
699
+ return [];
647
700
  }
648
701
  }
649
702
 
@@ -670,12 +723,15 @@ class LocatorGenerator {
670
723
 
671
724
  const elementsCache = new Map();
672
725
 
673
- const allAncestors = this.dom_Parent.getFullAncestorChainToRoot(element, root);
726
+ const allAncestors = prefix ? [element] : this.dom_Parent.getFullAncestorChainToRoot(element, root);
674
727
  allAncestors.shift(); // remove the element itself from the ancestors
675
728
 
729
+ const cache = new Map();
730
+ const textToIgnore = this.PW.selectorUtils.elementText(cache, element).full.trim();
676
731
  const ancestorLocators = [];
732
+ let uniqueAncestor = null;
677
733
  for (const ancestor of allAncestors) {
678
- const _locators = locatorGenerator(ancestor, options);
734
+ const _locators = locatorGenerator(ancestor, { ...options, textToIgnore });
679
735
  if (!_locators || !Array.isArray(_locators) || _locators.length === 0) {
680
736
  continue;
681
737
  }
@@ -686,11 +742,15 @@ class LocatorGenerator {
686
742
  });
687
743
  elementsCache.set(ancestor, _categorized);
688
744
  if (_categorized.unique.length > 0) {
745
+ uniqueAncestor = {
746
+ element: ancestor,
747
+ locators: _categorized,
748
+ };
689
749
  break;
690
750
  }
691
751
  }
692
752
 
693
- const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
753
+ // const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
694
754
 
695
755
  for (const locator of nonUnique) {
696
756
  const selector = locator.css ?? locator.selector;
@@ -699,6 +759,27 @@ class LocatorGenerator {
699
759
  console.warn(`No elements found for locator: ${selector}`);
700
760
  continue;
701
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
+ }
702
783
 
703
784
  for (const unique_locator of uniqueAncestor.locators.unique) {
704
785
  const fullSelector = `${unique_locator.css} >> ${selector}`;
@@ -737,9 +818,32 @@ class LocatorGenerator {
737
818
  return [];
738
819
  }
739
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
+ }
740
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
+ }
741
835
  try {
742
- 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;
743
847
 
744
848
  const allStrategyLocators = {
745
849
  [this.locatorStrategies.custom]: [],
@@ -749,7 +853,12 @@ class LocatorGenerator {
749
853
  [this.locatorStrategies.digitIgnore]: [],
750
854
  [this.locatorStrategies.no_text]: [],
751
855
  };
752
- 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
+ ) {
753
862
  console.groupCollapsed("Generating Custom locators for element:", element);
754
863
  const customLocators = this.getUniqueLocators(element, this.getCustomLocators.bind(this), options);
755
864
  if (customLocators.length > 0) {
@@ -758,43 +867,53 @@ class LocatorGenerator {
758
867
  }
759
868
  console.groupEnd();
760
869
  if (!excludeText) {
761
- console.groupCollapsed("Generating Text locators for element:", element);
762
- const basicLocators = this.getUniqueLocators(element, this.getTextLocators.bind(this), options);
763
- console.groupEnd();
764
- if (basicLocators.length > 0) {
765
- allStrategyLocators[this.locatorStrategies.text] = basicLocators;
766
- }
870
+ if (strategies[this.locatorStrategies.text]) {
871
+ console.groupCollapsed("Generating Text locators for element:", element);
767
872
 
768
- const textWithIndexLocators = this.getTextwithIndexLocators(basicLocators);
769
- if (textWithIndexLocators.length > 0) {
770
- allStrategyLocators[this.locatorStrategies.text_with_index] = textWithIndexLocators;
771
- }
772
- const digitIgnoreLocators = this.getDigitIgnoreLocators(element, basicLocators);
773
- if (digitIgnoreLocators.length > 0) {
774
- allStrategyLocators[this.locatorStrategies.digitIgnore] = digitIgnoreLocators;
775
- }
776
- const contextLocators = this.getContextLocators(element, basicLocators);
777
- if (contextLocators.length > 0) {
778
- 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
+ }
779
896
  }
780
897
  }
781
- console.groupCollapsed("Generating No Text locators for element:", element);
782
- 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);
783
901
 
784
- if (noTextLocators.length > 0) {
785
- allStrategyLocators[this.locatorStrategies.no_text] = noTextLocators;
786
- } else {
787
- const _locators = [];
788
- _locators.push({
789
- css: this.generateUniqueCSSSelector(element, options),
790
- score: 500,
791
- priority: 3,
792
- });
793
- if (_locators.length > 0) {
794
- 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
+ }
795
914
  }
915
+ console.groupEnd();
796
916
  }
797
- console.groupEnd();
798
917
 
799
918
  let bestStrategy = this.getBestStrategy(allStrategyLocators);
800
919
  if (!bestStrategy) {