@dev-blinq/cucumber_client 1.0.1330-dev → 1.0.1330-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.
- package/bin/assets/bundled_scripts/recorder.js +110 -110
- package/bin/assets/preload/css_gen.js +10 -10
- package/bin/assets/preload/recorderv3.js +3 -1
- package/bin/assets/preload/toolbar.js +27 -29
- package/bin/assets/preload/unique_locators.js +1 -1
- package/bin/assets/preload/yaml.js +288 -275
- package/bin/assets/scripts/aria_snapshot.js +223 -220
- package/bin/assets/scripts/dom_attr.js +329 -329
- package/bin/assets/scripts/dom_parent.js +169 -174
- package/bin/assets/scripts/event_utils.js +94 -94
- package/bin/assets/scripts/pw.js +2050 -1949
- package/bin/assets/scripts/recorder.js +5 -17
- package/bin/assets/scripts/snapshot_capturer.js +153 -146
- package/bin/assets/scripts/unique_locators.js +173 -48
- package/bin/assets/scripts/yaml.js +796 -783
- package/bin/assets/templates/_hooks_template.txt +41 -0
- package/bin/assets/templates/utils_template.txt +1 -44
- package/bin/client/apiTest/apiTest.js +6 -0
- package/bin/client/cli_helpers.js +11 -13
- package/bin/client/code_cleanup/utils.js +5 -1
- package/bin/client/code_gen/api_codegen.js +2 -2
- package/bin/client/code_gen/code_inversion.js +112 -4
- package/bin/client/code_gen/page_reflection.js +839 -906
- package/bin/client/code_gen/playwright_codeget.js +26 -18
- package/bin/client/cucumber/feature.js +89 -27
- package/bin/client/cucumber/feature_data.js +2 -2
- package/bin/client/cucumber/project_to_document.js +9 -3
- package/bin/client/cucumber/steps_definitions.js +6 -3
- package/bin/client/cucumber_selector.js +17 -1
- package/bin/client/local_agent.js +6 -5
- package/bin/client/parse_feature_file.js +23 -26
- package/bin/client/playground/projects/env.json +2 -2
- package/bin/client/project.js +186 -196
- package/bin/client/recorderv3/bvt_recorder.js +181 -78
- package/bin/client/recorderv3/implemented_steps.js +24 -14
- package/bin/client/recorderv3/index.js +68 -54
- package/bin/client/recorderv3/network.js +22 -5
- package/bin/client/recorderv3/scriptTest.js +1 -1
- package/bin/client/recorderv3/services.js +4 -16
- package/bin/client/recorderv3/step_runner.js +303 -205
- package/bin/client/recorderv3/step_utils.js +476 -17
- package/bin/client/recorderv3/update_feature.js +32 -30
- package/bin/client/recording.js +1 -0
- package/bin/client/run_cucumber.js +5 -1
- package/bin/client/scenario_report.js +0 -5
- package/bin/client/test_scenario.js +0 -1
- package/bin/client/upload-service.js +3 -2
- package/bin/client/utils/socket_logger.js +132 -0
- package/bin/index.js +1 -0
- package/bin/logger.js +3 -2
- package/bin/min/consoleApi.min.cjs +2 -3
- package/bin/min/injectedScript.min.cjs +16 -16
- package/package.json +21 -12
|
@@ -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,52 @@ class LocatorGenerator {
|
|
|
213
217
|
}
|
|
214
218
|
return result;
|
|
215
219
|
}
|
|
220
|
+
toContextLocators(element, contextElement) {
|
|
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
|
+
});
|
|
235
|
+
|
|
236
|
+
const attachContextToLocators = (locs) => {
|
|
237
|
+
locs.forEach((loc) => {
|
|
238
|
+
loc.climb = climb;
|
|
239
|
+
loc.text = text;
|
|
240
|
+
});
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const allStrategyLocators = result.allStrategyLocators;
|
|
244
|
+
const locators = result.locators;
|
|
245
|
+
if (allStrategyLocators) {
|
|
246
|
+
const allLocators = [];
|
|
247
|
+
for (const strategy in allStrategyLocators) {
|
|
248
|
+
if (strategy === "strategy") continue;
|
|
249
|
+
const locators = allStrategyLocators[strategy];
|
|
250
|
+
if (locators.length === 0) continue;
|
|
251
|
+
allLocators.push(...locators);
|
|
252
|
+
allStrategyLocators[strategy] = [];
|
|
253
|
+
}
|
|
254
|
+
attachContextToLocators(allLocators);
|
|
255
|
+
allStrategyLocators[this.locatorStrategies.context] = allLocators;
|
|
256
|
+
allStrategyLocators.strategy = this.locatorStrategies.context;
|
|
257
|
+
result.locators = allLocators;
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
if (locators) {
|
|
261
|
+
attachContextToLocators(locators);
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
216
266
|
getContextLocators(element, locators) {
|
|
217
267
|
if (!locators || !Array.isArray(locators)) {
|
|
218
268
|
console.error("Locators must be an array");
|
|
@@ -283,7 +333,7 @@ class LocatorGenerator {
|
|
|
283
333
|
}
|
|
284
334
|
const textElement = elements[0];
|
|
285
335
|
// const text = this.PW.selectorUtils.elementText(textElement);
|
|
286
|
-
const text = this.injectedScript.utils.elementText(new Map(), textElement).full;
|
|
336
|
+
const text = this.injectedScript.utils.elementText(new Map(), textElement).full.trim();
|
|
287
337
|
|
|
288
338
|
const fullSelector = `${textLocator} >> xpath=${xpath} >> ${restOfSelector}`;
|
|
289
339
|
const fullElements = this.getMatchingElements(fullSelector, {});
|
|
@@ -361,7 +411,7 @@ class LocatorGenerator {
|
|
|
361
411
|
hasDigitsInText = digitsRegex.test(text);
|
|
362
412
|
|
|
363
413
|
let pattern = this.PW.stringUtils.escapeRegExp(text.substring(1, text.length - 2));
|
|
364
|
-
const re = new RegExp(
|
|
414
|
+
const re = new RegExp(pattern);
|
|
365
415
|
|
|
366
416
|
finalSelector += `internal:text=${escapeRegexForSelector(re).replace(digitsRegex, "\\d+")} >> `;
|
|
367
417
|
}
|
|
@@ -437,8 +487,16 @@ class LocatorGenerator {
|
|
|
437
487
|
categorizeLocators(element, locators, options) {
|
|
438
488
|
const unique = [];
|
|
439
489
|
const nonUnique = [];
|
|
490
|
+
const visible = options?.visible ?? true;
|
|
440
491
|
try {
|
|
441
492
|
for (const locator of locators) {
|
|
493
|
+
if (!locator || !locator.css || typeof locator.css !== "string") {
|
|
494
|
+
console.error("Locator must have a valid css selector found: ", locator);
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (visible === false) {
|
|
498
|
+
locator.visible = false;
|
|
499
|
+
}
|
|
442
500
|
const elements = this.getMatchingElements(locator.css, options);
|
|
443
501
|
if (elements.length === 0) {
|
|
444
502
|
console.warn(`No elements found for locator: ${locator.css}`);
|
|
@@ -617,7 +675,7 @@ class LocatorGenerator {
|
|
|
617
675
|
|
|
618
676
|
getUniqueLocators2(element, locatorGenerator = this.getNoTextLocators, options = {}) {
|
|
619
677
|
try {
|
|
620
|
-
const { maxLocators = 5, root = window.document.body } = options;
|
|
678
|
+
const { maxLocators = 5, root = window.document.body, prefix } = options;
|
|
621
679
|
|
|
622
680
|
if (!element) {
|
|
623
681
|
return [];
|
|
@@ -637,13 +695,7 @@ class LocatorGenerator {
|
|
|
637
695
|
},
|
|
638
696
|
];
|
|
639
697
|
} else {
|
|
640
|
-
return [
|
|
641
|
-
{
|
|
642
|
-
css: ":root",
|
|
643
|
-
score: 1,
|
|
644
|
-
priority: 1,
|
|
645
|
-
},
|
|
646
|
-
];
|
|
698
|
+
return [];
|
|
647
699
|
}
|
|
648
700
|
}
|
|
649
701
|
|
|
@@ -670,12 +722,15 @@ class LocatorGenerator {
|
|
|
670
722
|
|
|
671
723
|
const elementsCache = new Map();
|
|
672
724
|
|
|
673
|
-
const allAncestors = this.dom_Parent.getFullAncestorChainToRoot(element, root);
|
|
725
|
+
const allAncestors = prefix ? [element] : this.dom_Parent.getFullAncestorChainToRoot(element, root);
|
|
674
726
|
allAncestors.shift(); // remove the element itself from the ancestors
|
|
675
727
|
|
|
728
|
+
const cache = new Map();
|
|
729
|
+
const textToIgnore = this.PW.selectorUtils.elementText(cache, element).full.trim();
|
|
676
730
|
const ancestorLocators = [];
|
|
731
|
+
let uniqueAncestor = null;
|
|
677
732
|
for (const ancestor of allAncestors) {
|
|
678
|
-
const _locators = locatorGenerator(ancestor, options);
|
|
733
|
+
const _locators = locatorGenerator(ancestor, { ...options, textToIgnore });
|
|
679
734
|
if (!_locators || !Array.isArray(_locators) || _locators.length === 0) {
|
|
680
735
|
continue;
|
|
681
736
|
}
|
|
@@ -686,11 +741,15 @@ class LocatorGenerator {
|
|
|
686
741
|
});
|
|
687
742
|
elementsCache.set(ancestor, _categorized);
|
|
688
743
|
if (_categorized.unique.length > 0) {
|
|
744
|
+
uniqueAncestor = {
|
|
745
|
+
element: ancestor,
|
|
746
|
+
locators: _categorized,
|
|
747
|
+
};
|
|
689
748
|
break;
|
|
690
749
|
}
|
|
691
750
|
}
|
|
692
751
|
|
|
693
|
-
const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
|
|
752
|
+
// const uniqueAncestor = ancestorLocators[ancestorLocators.length - 1];
|
|
694
753
|
|
|
695
754
|
for (const locator of nonUnique) {
|
|
696
755
|
const selector = locator.css ?? locator.selector;
|
|
@@ -699,6 +758,27 @@ class LocatorGenerator {
|
|
|
699
758
|
console.warn(`No elements found for locator: ${selector}`);
|
|
700
759
|
continue;
|
|
701
760
|
}
|
|
761
|
+
if (!uniqueAncestor) {
|
|
762
|
+
const elements = this.getMatchingElements(selector, options);
|
|
763
|
+
if (elements.length === 1 && elements[0] === element) {
|
|
764
|
+
result.push({
|
|
765
|
+
css: selector,
|
|
766
|
+
score: locator.score,
|
|
767
|
+
priority: 1,
|
|
768
|
+
});
|
|
769
|
+
} else {
|
|
770
|
+
const index = elements.indexOf(element);
|
|
771
|
+
if (index !== -1) {
|
|
772
|
+
result.push({
|
|
773
|
+
css: selector,
|
|
774
|
+
index,
|
|
775
|
+
score: locator.score + 200,
|
|
776
|
+
priority: 2,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
702
782
|
|
|
703
783
|
for (const unique_locator of uniqueAncestor.locators.unique) {
|
|
704
784
|
const fullSelector = `${unique_locator.css} >> ${selector}`;
|
|
@@ -737,12 +817,47 @@ class LocatorGenerator {
|
|
|
737
817
|
return [];
|
|
738
818
|
}
|
|
739
819
|
}
|
|
820
|
+
isElementVisible(element) {
|
|
821
|
+
if (!(element instanceof Element)) return false;
|
|
822
|
+
const style = window.getComputedStyle(element);
|
|
823
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
|
|
824
|
+
const rect = element.getBoundingClientRect();
|
|
825
|
+
if (rect.width === 0 || rect.height === 0) return false;
|
|
826
|
+
return true;
|
|
827
|
+
}
|
|
740
828
|
getElementLocators(element, options = {}) {
|
|
829
|
+
const isVisible = this.isElementVisible(element);
|
|
830
|
+
if (isVisible === false) {
|
|
831
|
+
console.warn("Element is not visible: ", element);
|
|
832
|
+
options.visible = isVisible;
|
|
833
|
+
}
|
|
741
834
|
try {
|
|
742
|
-
const {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
835
|
+
const {
|
|
836
|
+
excludeText = false,
|
|
837
|
+
strategies = {
|
|
838
|
+
[this.locatorStrategies.custom]: true,
|
|
839
|
+
[this.locatorStrategies.context]: true,
|
|
840
|
+
[this.locatorStrategies.text]: true,
|
|
841
|
+
[this.locatorStrategies.text_with_index]: true,
|
|
842
|
+
[this.locatorStrategies.digitIgnore]: true,
|
|
843
|
+
[this.locatorStrategies.no_text]: true,
|
|
844
|
+
},
|
|
845
|
+
} = options;
|
|
846
|
+
|
|
847
|
+
const allStrategyLocators = {
|
|
848
|
+
[this.locatorStrategies.custom]: [],
|
|
849
|
+
[this.locatorStrategies.context]: [],
|
|
850
|
+
[this.locatorStrategies.text]: [],
|
|
851
|
+
[this.locatorStrategies.text_with_index]: [],
|
|
852
|
+
[this.locatorStrategies.digitIgnore]: [],
|
|
853
|
+
[this.locatorStrategies.no_text]: [],
|
|
854
|
+
};
|
|
855
|
+
if (
|
|
856
|
+
strategies[this.locatorStrategies.custom] &&
|
|
857
|
+
this.options?.customAttributes &&
|
|
858
|
+
Array.isArray(this.options.customAttributes) &&
|
|
859
|
+
this.options.customAttributes.length > 0
|
|
860
|
+
) {
|
|
746
861
|
console.groupCollapsed("Generating Custom locators for element:", element);
|
|
747
862
|
const customLocators = this.getUniqueLocators(element, this.getCustomLocators.bind(this), options);
|
|
748
863
|
if (customLocators.length > 0) {
|
|
@@ -751,43 +866,53 @@ class LocatorGenerator {
|
|
|
751
866
|
}
|
|
752
867
|
console.groupEnd();
|
|
753
868
|
if (!excludeText) {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
console.groupEnd();
|
|
757
|
-
if (basicLocators.length > 0) {
|
|
758
|
-
allStrategyLocators[this.locatorStrategies.text] = basicLocators;
|
|
759
|
-
}
|
|
869
|
+
if (strategies[this.locatorStrategies.text]) {
|
|
870
|
+
console.groupCollapsed("Generating Text locators for element:", element);
|
|
760
871
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
872
|
+
const basicLocators = this.getUniqueLocators(element, this.getTextLocators.bind(this), options);
|
|
873
|
+
console.groupEnd();
|
|
874
|
+
if (basicLocators.length > 0) {
|
|
875
|
+
allStrategyLocators[this.locatorStrategies.text] = basicLocators;
|
|
876
|
+
}
|
|
877
|
+
if (strategies[this.locatorStrategies.text_with_index]) {
|
|
878
|
+
const textWithIndexLocators = this.getTextwithIndexLocators(basicLocators);
|
|
879
|
+
if (textWithIndexLocators.length > 0) {
|
|
880
|
+
allStrategyLocators[this.locatorStrategies.text_with_index] = textWithIndexLocators;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
if (strategies[this.locatorStrategies.digitIgnore]) {
|
|
884
|
+
const digitIgnoreLocators = this.getDigitIgnoreLocators(element, basicLocators);
|
|
885
|
+
if (digitIgnoreLocators.length > 0) {
|
|
886
|
+
allStrategyLocators[this.locatorStrategies.digitIgnore] = digitIgnoreLocators;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
if (strategies[this.locatorStrategies.context]) {
|
|
890
|
+
const contextLocators = this.getContextLocators(element, basicLocators);
|
|
891
|
+
if (contextLocators.length > 0) {
|
|
892
|
+
allStrategyLocators[this.locatorStrategies.context] = contextLocators;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
772
895
|
}
|
|
773
896
|
}
|
|
774
|
-
|
|
775
|
-
|
|
897
|
+
if (strategies[this.locatorStrategies.no_text]) {
|
|
898
|
+
console.groupCollapsed("Generating No Text locators for element:", element);
|
|
899
|
+
const noTextLocators = this.getUniqueLocators(element, this.getNoTextLocators.bind(this), options);
|
|
776
900
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
901
|
+
if (noTextLocators.length > 0) {
|
|
902
|
+
allStrategyLocators[this.locatorStrategies.no_text] = noTextLocators;
|
|
903
|
+
} else {
|
|
904
|
+
const _locators = [];
|
|
905
|
+
_locators.push({
|
|
906
|
+
css: this.generateUniqueCSSSelector(element, options),
|
|
907
|
+
score: 500,
|
|
908
|
+
priority: 3,
|
|
909
|
+
});
|
|
910
|
+
if (_locators.length > 0) {
|
|
911
|
+
allStrategyLocators[this.locatorStrategies.no_text] = _locators;
|
|
912
|
+
}
|
|
788
913
|
}
|
|
914
|
+
console.groupEnd();
|
|
789
915
|
}
|
|
790
|
-
console.groupEnd();
|
|
791
916
|
|
|
792
917
|
let bestStrategy = this.getBestStrategy(allStrategyLocators);
|
|
793
918
|
if (!bestStrategy) {
|