ff-automationv2 2.2.29 → 2.2.31

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 (113) hide show
  1. package/dist/ai/llmcalls/llmAction.js +49 -13
  2. package/dist/ai/llmcalls/parseLlmOputput.js +5 -5
  3. package/dist/ai/llmprompts/promptRegistry.js +4 -0
  4. package/dist/ai/llmprompts/systemPrompts/actionExtractorPrompt.js +39 -11
  5. package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtactors.js +6 -6
  6. package/dist/ai/llmprompts/systemPrompts/fireflinkElementIndexExtractor_Mob.js +32 -0
  7. package/dist/ai/llmprompts/systemPrompts/mobileKeywordExtractor.js +17 -8
  8. package/dist/ai/llmprompts/systemPrompts/otpExtractorPrompt.d.ts +1 -0
  9. package/dist/ai/llmprompts/systemPrompts/otpExtractorPrompt.js +22 -0
  10. package/dist/ai/llmprompts/systemPrompts/verifyActionExtractorPrompt.js +3 -1
  11. package/dist/ai/llmprompts/systemPrompts/visionPrompt.js +14 -6
  12. package/dist/ai/llmprompts/systemPrompts/visionPromptMobile.js +3 -0
  13. package/dist/ai/llmprompts/userPrompts/userPrompt.js +1 -0
  14. package/dist/automation/actions/executor.d.ts +4 -0
  15. package/dist/automation/actions/executor.js +20 -0
  16. package/dist/automation/actions/interaction/clear/clear.js +1 -1
  17. package/dist/automation/actions/interaction/clear/clearAndEnter.js +1 -1
  18. package/dist/automation/actions/interaction/click/click.js +10 -3
  19. package/dist/automation/actions/interaction/click/clickNtimes.js +1 -1
  20. package/dist/automation/actions/interaction/click/doubleClick.js +1 -1
  21. package/dist/automation/actions/interaction/click/rightClick.js +1 -1
  22. package/dist/automation/actions/interaction/elementlessActions/getOtp.d.ts +2 -0
  23. package/dist/automation/actions/interaction/elementlessActions/getOtp.js +101 -0
  24. package/dist/automation/actions/interaction/enterActions/enterInput.js +11 -6
  25. package/dist/automation/actions/interaction/enterActions/enterInputAndPress.js +2 -2
  26. package/dist/automation/actions/interaction/enterActions/enterusingJs.js +2 -2
  27. package/dist/automation/actions/interaction/enterActions/waitAndEnter.js +1 -1
  28. package/dist/automation/actions/interaction/upload/uploadfile.js +1 -1
  29. package/dist/automation/actions/interaction/verify/VerifyNavigateURL.js +38 -11
  30. package/dist/automation/actions/interface/FireFlinkResponseSchema.d.ts +12 -0
  31. package/dist/automation/actions/interface/FireFlinkResponseSchema.js +19 -3
  32. package/dist/automation/actions/interface/getOtpInterface.d.ts +15 -0
  33. package/dist/automation/actions/interface/getOtpInterface.js +2 -0
  34. package/dist/automation/browserSession/initiateBrowserSession.d.ts +1 -1
  35. package/dist/automation/browserSession/initiateBrowserSession.js +15 -7
  36. package/dist/automation/driverState.d.ts +2 -0
  37. package/dist/automation/driverState.js +4 -0
  38. package/dist/automation/mobileSession/initiateMobileSession.d.ts +4 -5
  39. package/dist/automation/mobileSession/initiateMobileSession.js +83 -19
  40. package/dist/core/constants/allAction.js +5 -1
  41. package/dist/core/constants/supportedActions.js +5 -2
  42. package/dist/core/interfaces/actionInterface.d.ts +4 -0
  43. package/dist/core/interfaces/browserConfigurationInterface.d.ts +0 -4
  44. package/dist/core/interfaces/browserConfigurationInterface.js +0 -1
  45. package/dist/core/interfaces/executionDetails.d.ts +6 -3
  46. package/dist/core/interfaces/fireflinkScriptPayloadInterface.d.ts +22 -16
  47. package/dist/core/interfaces/llmResponseInterface.d.ts +1 -0
  48. package/dist/core/interfaces/promptInterface.d.ts +1 -0
  49. package/dist/core/main/SessionManager.d.ts +9 -0
  50. package/dist/core/main/SessionManager.js +23 -0
  51. package/dist/core/main/actionHandlerFactory.js +261 -64
  52. package/dist/core/main/executionContext.d.ts +7 -1
  53. package/dist/core/main/executionContext.js +94 -3
  54. package/dist/core/main/runAutomationScript.d.ts +1 -0
  55. package/dist/core/main/runAutomationScript.js +912 -304
  56. package/dist/core/main/stepProcessor.js +7 -2
  57. package/dist/core/types/browserType.d.ts +3 -3
  58. package/dist/core/types/browserType.js +2 -2
  59. package/dist/core/types/messageType.d.ts +13 -0
  60. package/dist/core/types/messageType.js +15 -0
  61. package/dist/core/types/promptType.d.ts +2 -1
  62. package/dist/core/types/promptType.js +1 -0
  63. package/dist/domAnalysis/searchBest.js +15 -16
  64. package/dist/domAnalysis/simplifyAndFlatten.js +6 -4
  65. package/dist/fireflinkData/fireflinkLocators/getListOfLocators.d.ts +3 -0
  66. package/dist/fireflinkData/fireflinkLocators/getListOfLocators.js +23 -15
  67. package/dist/fireflinkData/fireflinkLocators/parser/getElementsFromHTML.d.ts +3 -3
  68. package/dist/fireflinkData/fireflinkLocators/parser/getElementsFromHTML.js +134 -118
  69. package/dist/fireflinkData/fireflinkLocators/types/locator.d.ts +11 -1
  70. package/dist/fireflinkData/fireflinkLocators/utils/androidSelector.d.ts +1 -1
  71. package/dist/fireflinkData/fireflinkLocators/utils/androidSelector.js +35 -9
  72. package/dist/fireflinkData/fireflinkLocators/utils/cssSelector.d.ts +10 -10
  73. package/dist/fireflinkData/fireflinkLocators/utils/cssSelector.js +56 -59
  74. package/dist/fireflinkData/fireflinkLocators/utils/iosSelector.d.ts +1 -1
  75. package/dist/fireflinkData/fireflinkLocators/utils/iosSelector.js +53 -29
  76. package/dist/fireflinkData/fireflinkLocators/utils/referenceXpath.d.ts +8 -8
  77. package/dist/fireflinkData/fireflinkLocators/utils/referenceXpath.js +113 -190
  78. package/dist/fireflinkData/fireflinkLocators/utils/xpath.d.ts +17 -26
  79. package/dist/fireflinkData/fireflinkLocators/utils/xpath.js +314 -786
  80. package/dist/fireflinkData/fireflinkLocators/utils/xpathHelpers.d.ts +68 -70
  81. package/dist/fireflinkData/fireflinkLocators/utils/xpathHelpers.js +498 -517
  82. package/dist/fireflinkData/fireflinkScript/appendScriptData.d.ts +1 -1
  83. package/dist/fireflinkData/fireflinkScript/appendScriptData.js +5 -8
  84. package/dist/fireflinkData/fireflinkScript/scriptGenrationData.d.ts +2 -2
  85. package/dist/fireflinkData/fireflinkScript/scriptGenrationData.js +17 -27
  86. package/dist/llmConfig/llmConfiguration.js +13 -6
  87. package/dist/service/api/fireflinkApi.service.d.ts +1 -1
  88. package/dist/service/api/fireflinkApi.service.js +1 -2
  89. package/dist/service/fireflink.service.d.ts +3 -3
  90. package/dist/service/fireflink.service.js +23 -21
  91. package/dist/service/kafka/fireflinkKafka.service.d.ts +1 -2
  92. package/dist/service/kafka/fireflinkKafka.service.js +6 -4
  93. package/dist/tests/test12.d.ts +0 -1
  94. package/dist/tests/test12.js +65 -78
  95. package/dist/tests/testkaf.d.ts +0 -1
  96. package/dist/tests/testkaf.js +51 -55
  97. package/dist/utils/InstancesDetails/getInstancesInfo.js +1 -1
  98. package/dist/utils/browserCap/capability.d.ts +5 -1
  99. package/dist/utils/browserCap/capability.js +91 -15
  100. package/dist/utils/helpers/domSanitizer.d.ts +1 -0
  101. package/dist/utils/helpers/domSanitizer.js +9 -0
  102. package/dist/utils/helpers/enterActionHelper.js +23 -4
  103. package/dist/utils/helpers/xpathcreation.js +2 -2
  104. package/dist/utils/javascript/jsFindElement.d.ts +1 -1
  105. package/dist/utils/javascript/jsFindElement.js +2 -2
  106. package/dist/utils/newTab/newTabTracker.js +18 -6
  107. package/dist/utils/workers/LocatorWorkerInterface.d.ts +22 -0
  108. package/dist/utils/workers/LocatorWorkerInterface.js +2 -0
  109. package/dist/utils/workers/LocatorWorkerPool.d.ts +13 -0
  110. package/dist/utils/workers/LocatorWorkerPool.js +89 -0
  111. package/dist/utils/workers/locatorWorker.d.ts +1 -0
  112. package/dist/utils/workers/locatorWorker.js +44 -0
  113. package/package.json +3 -1
@@ -1,439 +1,68 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseDOM = exports.getTextXPath = exports.getUniqueClassName = exports.attributesBasedXPath = exports.generateIndexedXpaths = void 0;
3
+ exports.aiParseDOM = exports.getAiTextXPath = exports.getAiUniqueClassName = exports.attributesAiBasedXPath = void 0;
4
4
  const logData_js_1 = require("../../../utils/logger/logData.js");
5
5
  const xpathHelpers_js_1 = require("./xpathHelpers.js");
6
6
  const androidSelector_js_1 = require("./androidSelector.js");
7
7
  const iosSelector_js_1 = require("./iosSelector.js");
8
8
  let xpathData = [];
9
- const xpathDataWithIndex = [];
9
+ const xpathValues = new Set();
10
+ const MAX_XPATH_RESULTS = 5;
10
11
  const referenceElementMode = false;
11
12
  const xpathCache = new Map();
12
13
  const cache = new Map();
14
+ const parentRelativeCache = new WeakMap();
13
15
  const parentXpathCache = new Map();
14
- const STRATEGY_MAP = {
15
- andConditions: "and",
16
- orConditions: "or",
17
- contains: "contains",
18
- startsWith: "startsWith",
19
- normalizeSpace: "normalizeSpace",
20
- axes: "axes",
21
- index: "index",
22
- hardCodedText: "text",
23
- tillTag: "tag"
24
- };
25
- const getStrategyName = (strategy) => {
26
- return STRATEGY_MAP[strategy] || strategy;
27
- };
28
- const withStrategyKey = (strategy, entries) => {
29
- return entries.map((entry) => ({
30
- ...entry,
31
- key: entry?.key?.includes(strategy)
32
- ? entry.key
33
- : `${strategy} ${entry.key}`.trim()
34
- }));
35
- };
36
- const getUniqueXpathEntries = (entries) => {
37
- const seen = new Set();
38
- return entries.filter((entry) => {
39
- if (!entry?.value || seen.has(entry.value)) {
40
- return false;
41
- }
42
- seen.add(entry.value);
16
+ const filteredTextCache = new WeakMap();
17
+ const textContentCache = new WeakMap();
18
+ const appendXPath = (target, xpath) => {
19
+ if (!xpath.value)
20
+ return false;
21
+ if (xpathValues.has(xpath.value))
43
22
  return true;
44
- });
23
+ if (target.length >= MAX_XPATH_RESULTS)
24
+ return false;
25
+ target.push(xpath);
26
+ xpathValues.add(xpath.value);
27
+ return target.length < MAX_XPATH_RESULTS;
45
28
  };
46
- const getNormalizedText = (element) => {
47
- return element?.textContent?.replace(/\s+/g, " ")?.trim() || "";
29
+ const hasReachedRelativeXpathLimit = () => {
30
+ return xpathData.length >= MAX_XPATH_RESULTS;
48
31
  };
49
- const buildTextStrategyXpaths = (element, docmt, strategy, platform) => {
50
- const text = getNormalizedText(element);
51
- if (!text) {
52
- return [];
53
- }
54
- if (strategy === "text") {
55
- const textXpath = (0, xpathHelpers_js_1.getFilteredTextXPath)(element) ||
56
- (0, exports.getTextXPath)(element, docmt, false, false, platform);
57
- return textXpath ? [{ key: "xpath by text", value: textXpath }] : [];
58
- }
59
- return [];
60
- };
61
- const buildPropertyStrategyXpaths = (element, isTarget, strategy, platform) => {
62
- const xpaths = [];
63
- const attributes = Array.from(element.attributes || []).filter((attribute) => attribute?.value && (0, xpathHelpers_js_1.checkBlockedAttributes)(attribute, element, isTarget));
64
- const text = getNormalizedText(element);
65
- const getStrategyXPath = strategy === "contains"
66
- ? xpathHelpers_js_1.getContainsPropertyXPath
67
- : strategy === "startsWith"
68
- ? xpathHelpers_js_1.getStartsWithPropertyXPath
69
- : strategy === "normalizeSpace"
70
- ? xpathHelpers_js_1.getNormalizedPropertyXPath
71
- : null;
72
- if (!getStrategyXPath) {
73
- return xpaths;
74
- }
75
- attributes.forEach((attribute) => {
76
- const xpath = getStrategyXPath(element, `@${attribute.name}`, attribute.value, platform);
77
- if (xpath) {
78
- xpaths.push({
79
- key: `xpath by ${strategy} ${attribute.name}`,
80
- value: xpath
81
- });
82
- }
83
- });
84
- if (text) {
85
- const xpath = getStrategyXPath(element, ".", text, platform);
86
- if (xpath) {
87
- xpaths.push({
88
- key: `xpath by ${strategy} text`,
89
- value: xpath
90
- });
32
+ const getCachedXPathCount = (xpath, element, doc) => {
33
+ try {
34
+ const cached = xpathCache.get(xpath);
35
+ if (cached !== undefined) {
36
+ return cached;
91
37
  }
38
+ const count = (0, xpathHelpers_js_1.getAiCountOfXPath)(xpath, element, doc);
39
+ xpathCache.set(xpath, count);
40
+ return count;
92
41
  }
93
- return xpaths;
94
- };
95
- const buildConditionStrategyXpaths = (element, docmt, isTarget, strategy, platform) => {
96
- const attributes = Array.from(element.attributes || []).filter((attribute) => attribute?.value && (0, xpathHelpers_js_1.checkBlockedAttributes)(attribute, element, isTarget));
97
- if (strategy === "and") {
98
- const combinationXpath = (0, xpathHelpers_js_1.getAttributeCombinationXpath)(element, docmt, attributes, isTarget, platform);
99
- return combinationXpath
100
- ? [{ key: "xpath by combination", value: combinationXpath }]
101
- : [];
102
- }
103
- if (strategy === "or" && attributes.length >= 1) {
104
- const xpath = (0, xpathHelpers_js_1.getOrAttributesXPath)(element, attributes, platform);
105
- return xpath ? [{ key: "xpath by or", value: xpath }] : [];
42
+ catch {
43
+ return 0;
106
44
  }
107
- return [];
108
45
  };
109
- const collectSubtreeElements = (root) => {
110
- const view = root?.ownerDocument?.defaultView;
111
- if (!root || !view || !(root instanceof view.Element))
112
- return [];
113
- const nodes = [];
114
- const queue = Array.from(root.children || []);
115
- while (queue.length) {
116
- const currentNode = queue.shift();
117
- if (currentNode.classList?.contains("flntooltip")) {
118
- continue;
119
- }
120
- nodes.push(currentNode);
121
- queue.push(...Array.from(currentNode.children || []));
122
- }
123
- return nodes;
46
+ const getCachedTextContent = (element) => {
47
+ const cached = textContentCache.get(element);
48
+ if (cached !== undefined)
49
+ return cached;
50
+ const value = (0, xpathHelpers_js_1.getAiTextContent)(element);
51
+ textContentCache.set(element, value);
52
+ return value;
124
53
  };
125
- const getSiblingNodes = (element, direction) => {
126
- const nodes = [];
127
- let currentNode = direction === "previous"
128
- ? element.previousElementSibling
129
- : element.nextElementSibling;
130
- while (currentNode) {
131
- if (!currentNode.classList?.contains("flntooltip")) {
132
- nodes.push(currentNode);
133
- }
134
- currentNode =
135
- direction === "previous"
136
- ? currentNode.previousElementSibling
137
- : currentNode.nextElementSibling;
138
- }
139
- return nodes;
140
- };
141
- const getDirectionalAxisSeedNodes = (element, direction) => {
142
- const nodes = [];
143
- for (let currentNode = element; currentNode?.parentElement; currentNode = currentNode.parentElement) {
144
- let sibling = direction === "previous"
145
- ? currentNode.previousElementSibling
146
- : currentNode.nextElementSibling;
147
- while (sibling) {
148
- if (!sibling.classList?.contains("flntooltip")) {
149
- nodes.push(sibling);
150
- nodes.push({
151
- node: sibling,
152
- expand: () => collectSubtreeElements(sibling)
153
- });
154
- }
155
- sibling =
156
- direction === "previous"
157
- ? sibling.previousElementSibling
158
- : sibling.nextElementSibling;
159
- }
160
- }
161
- return nodes;
54
+ const getCachedFilteredText = (element) => {
55
+ const cached = filteredTextCache.get(element);
56
+ if (cached !== undefined)
57
+ return cached;
58
+ const value = (0, xpathHelpers_js_1.getAiFilteredText)(element);
59
+ filteredTextCache.set(element, value);
60
+ return value;
162
61
  };
163
- const isLowQualityNode = (node) => {
164
- const view = node?.ownerDocument?.defaultView;
165
- if (!view || !(node instanceof view.Element))
166
- return true;
167
- const text = node.textContent?.trim();
168
- return (!node.id &&
169
- !node.className &&
170
- node.attributes.length === 0 &&
171
- (!text || text.length > 60) &&
172
- node.children.length > 2);
173
- };
174
- const buildAxisXpathsForNodes = (nodes, axis, targetElement, docmt, isTarget, key, isIndex, platform) => {
175
- const targetNodeTest = (0, xpathHelpers_js_1.getAxisNodeTest)(targetElement, platform);
176
- const MAX_INDEX_TRY = 3;
177
- const MAX_CANDIDATES = 5;
178
- const candidates = [];
179
- let processed = 0;
180
- const MAX_PROCESS = axis.includes("descendant") ? 10 : 20;
181
- for (const nodeItem of nodes) {
182
- if (processed++ > MAX_PROCESS)
183
- break;
184
- if (candidates.length >= MAX_CANDIDATES)
185
- break;
186
- const node = "node" in nodeItem ? nodeItem.node : nodeItem;
187
- const view = node.ownerDocument?.defaultView;
188
- if (!view || !(node instanceof view.Element))
189
- continue;
190
- if (isLowQualityNode(node))
191
- continue;
192
- const anchorStages = [
193
- () => (0, xpathHelpers_js_1.getUniqueNodeAnchorXpaths)(node, docmt, isTarget, platform),
194
- () => {
195
- const anchors = [];
196
- const element = node;
197
- const attributes = Array.from(element.attributes || []).filter((attr) => attr.value &&
198
- !/\d/.test(attr.value) &&
199
- (0, xpathHelpers_js_1.checkBlockedAttributes)(attr, element, isTarget));
200
- for (const attr of attributes) {
201
- const value = attr.value;
202
- if (!value)
203
- continue;
204
- const containsXpath = (0, xpathHelpers_js_1.getContainsPropertyXPath)(node, `@${attr.name}`, value, platform);
205
- if (containsXpath) {
206
- anchors.push({ key: "contains", value: containsXpath });
207
- }
208
- const startsWithXpath = (0, xpathHelpers_js_1.getStartsWithPropertyXPath)(node, `@${attr.name}`, value, platform);
209
- if (startsWithXpath) {
210
- anchors.push({ key: "starts-with", value: startsWithXpath });
211
- }
212
- }
213
- return anchors;
214
- },
215
- () => [{ key: "tag", value: (0, xpathHelpers_js_1.getTagOnlyXPath)(node, platform, docmt) }]
216
- ];
217
- for (let stageIndex = 0; stageIndex < anchorStages.length; stageIndex++) {
218
- let anchors = anchorStages[stageIndex]();
219
- if (!anchors.length)
220
- continue;
221
- if (!isIndex) {
222
- anchors = anchors.filter((a) => !/\[\d+\]/.test(a.value));
223
- }
224
- const seen = new Set();
225
- anchors = anchors.filter((a) => {
226
- if (seen.has(a.value))
227
- return false;
228
- seen.add(a.value);
229
- return true;
230
- });
231
- anchors = anchors.slice(0, 5);
232
- for (const anchor of anchors) {
233
- const xpath = `${anchor.value}/${axis}::${targetNodeTest}`;
234
- if ((0, xpathHelpers_js_1.isExactUniqueXpath)(xpath, targetElement, docmt)) {
235
- candidates.push({ key, value: xpath });
236
- if (candidates.length >= 2) {
237
- return candidates;
238
- }
239
- if (candidates.length >= MAX_CANDIDATES) {
240
- return candidates;
241
- }
242
- }
243
- }
244
- if (isIndex && stageIndex === anchorStages.length - 1) {
245
- for (const anchor of anchors) {
246
- const count = (0, xpathHelpers_js_1.getCountOfXPath)(anchor.value, node, docmt);
247
- for (let i = 1; i <= Math.min(count, MAX_INDEX_TRY); i++) {
248
- const xpath = `(${anchor.value})[${i}]/${axis}::${targetNodeTest}`;
249
- if ((0, xpathHelpers_js_1.isExactUniqueXpath)(xpath, targetElement, docmt)) {
250
- candidates.push({ key, value: xpath });
251
- if (candidates.length >= 2) {
252
- return candidates;
253
- }
254
- if (candidates.length >= MAX_CANDIDATES) {
255
- return candidates;
256
- }
257
- }
258
- }
259
- }
260
- }
261
- }
262
- if ("expand" in nodeItem && nodeItem.expand) {
263
- const expanded = nodeItem.expand();
264
- let childCount = 0;
265
- for (const child of expanded) {
266
- if (childCount++ > 15)
267
- break;
268
- if (candidates.length >= MAX_CANDIDATES)
269
- break;
270
- const view = child.ownerDocument?.defaultView;
271
- if (!view || !(child instanceof view.Element))
272
- continue;
273
- if (isLowQualityNode(child))
274
- continue;
275
- const anchors = (0, xpathHelpers_js_1.getUniqueNodeAnchorXpaths)(child, docmt, isTarget, platform);
276
- for (const anchor of anchors.slice(0, 5)) {
277
- const xpath = `${anchor.value}/${axis}::${targetNodeTest}`;
278
- if ((0, xpathHelpers_js_1.isExactUniqueXpath)(xpath, targetElement, docmt)) {
279
- candidates.push({ key, value: xpath });
280
- if (candidates.length >= 2) {
281
- return candidates;
282
- }
283
- if (candidates.length >= MAX_CANDIDATES) {
284
- return candidates;
285
- }
286
- }
287
- }
288
- }
289
- }
290
- }
291
- return candidates;
292
- };
293
- const buildAxesStrategyXpaths = (element, docmt, isTarget, isIndex, platform) => {
294
- const ancestors = [];
295
- for (let currentNode = element.parentElement; currentNode; currentNode = currentNode.parentElement) {
296
- ancestors.push(currentNode);
297
- }
298
- const descendants = collectSubtreeElements(element);
299
- const previousSiblings = getSiblingNodes(element, "previous");
300
- const nextSiblings = getSiblingNodes(element, "next");
301
- const precedingSeeds = getDirectionalAxisSeedNodes(element, "previous");
302
- const followingSeeds = getDirectionalAxisSeedNodes(element, "next");
303
- const limitNodes = (nodes, limit = 20) => {
304
- return nodes.length > limit ? nodes.slice(0, limit) : nodes;
305
- };
306
- const tiers = [
307
- [
308
- {
309
- nodes: limitNodes(nextSiblings),
310
- axis: "preceding-sibling",
311
- key: "preceding-sibling"
312
- },
313
- {
314
- nodes: limitNodes(previousSiblings),
315
- axis: "following-sibling",
316
- key: "following-sibling"
317
- }
318
- ],
319
- [
320
- { nodes: limitNodes(ancestors), axis: "child", key: "child" },
321
- {
322
- nodes: limitNodes(descendants, 15),
323
- axis: "parent",
324
- key: "parent"
325
- }
326
- ],
327
- [
328
- { nodes: limitNodes(ancestors), axis: "descendant", key: "descendant" },
329
- {
330
- nodes: limitNodes(ancestors),
331
- axis: "descendant-or-self",
332
- key: "descendant-or-self"
333
- },
334
- {
335
- nodes: limitNodes(descendants, 10),
336
- axis: "ancestor",
337
- key: "ancestor"
338
- },
339
- {
340
- nodes: limitNodes(descendants, 10),
341
- axis: "ancestor-or-self",
342
- key: "ancestor-or-self"
343
- }
344
- ],
345
- [
346
- {
347
- nodes: limitNodes(precedingSeeds),
348
- axis: "following",
349
- key: "following"
350
- },
351
- { nodes: limitNodes(followingSeeds), axis: "preceding", key: "preceding" }
352
- ]
353
- ];
354
- for (const tier of tiers) {
355
- for (const strategy of tier) {
356
- const results = buildAxisXpathsForNodes(strategy.nodes, strategy.axis, element, docmt, isTarget, strategy.key, isIndex, platform);
357
- if (results.length > 0) {
358
- return results;
359
- }
360
- }
361
- }
362
- return [];
363
- };
364
- const generateIndexedXpaths = (element, docmt, platform) => {
365
- const results = [];
366
- const tag = platform === "web"
367
- ? element.tagName.toLowerCase()
368
- : element.tagName;
369
- const globalList = Array.from(docmt.querySelectorAll(tag));
370
- const idx = globalList.indexOf(element) + 1;
371
- if (idx <= 0)
372
- return [];
373
- results.push({
374
- key: "xpath by index",
375
- value: `(//${tag})[${idx}]`
376
- });
377
- let current = element.parentElement;
378
- while (current && current !== docmt.body) {
379
- if (current.id || current.className) {
380
- const cls = current.className
381
- ?.toString()
382
- .split(" ")
383
- .map((name) => name.trim())
384
- .find(Boolean);
385
- const tagName = platform === "web"
386
- ? current.tagName.toLowerCase()
387
- : current.tagName;
388
- const scopeXpath = current.id
389
- ? `//${tagName}[@id='${current.id}']`
390
- : cls
391
- ? `//${tagName}[contains(@class,'${cls}')]`
392
- : "";
393
- if (!scopeXpath) {
394
- current = current.parentElement;
395
- continue;
396
- }
397
- const scopedDescendants = Array.from(current.querySelectorAll(tag));
398
- const scopedIdx = scopedDescendants.indexOf(element) + 1;
399
- if (scopedIdx > 0) {
400
- results.push({
401
- key: "xpath by index",
402
- value: `(${scopeXpath}//${tag})[${scopedIdx}]`
403
- });
404
- break;
405
- }
406
- }
407
- current = current.parentElement;
408
- }
409
- return results;
410
- };
411
- exports.generateIndexedXpaths = generateIndexedXpaths;
412
- const buildStrategyXpaths = (element, docmt, isTarget, strategy, platform) => {
413
- const strategyName = getStrategyName(strategy);
414
- if (strategyName === "text") {
415
- return withStrategyKey(strategy, buildTextStrategyXpaths(element, docmt, strategyName, platform));
416
- }
417
- if (["contains", "startsWith", "normalizeSpace"].includes(strategyName)) {
418
- return withStrategyKey(strategy, buildPropertyStrategyXpaths(element, isTarget, strategyName, platform));
419
- }
420
- if (["and", "or"].includes(strategyName)) {
421
- return withStrategyKey(strategy, buildConditionStrategyXpaths(element, docmt, isTarget, strategyName, platform));
422
- }
423
- if (strategyName === "axes") {
424
- return withStrategyKey(strategy, buildAxesStrategyXpaths(element, docmt, isTarget, false, platform));
425
- }
426
- if (strategyName === "index") {
427
- return withStrategyKey(strategy, (0, exports.generateIndexedXpaths)(element, docmt, platform));
428
- }
429
- if (strategyName === "tag") {
430
- return withStrategyKey(strategy, [
431
- { key: "xpath till tag", value: (0, xpathHelpers_js_1.getTagOnlyXPath)(element, platform, docmt) }
432
- ]);
62
+ const checkAiRelativeXpathRelation = (nodeXpath1, nodeXpath2, targetElemt, docmt, relationType) => {
63
+ if (hasReachedRelativeXpathLimit()) {
64
+ return;
433
65
  }
434
- return [];
435
- };
436
- const checkRelativeXpathRelation = (nodeXpath1, nodeXpath2, targetElemt, docmt, isIndex, relationType) => {
437
66
  if (nodeXpath1 && !referenceElementMode) {
438
67
  let xpaths;
439
68
  if (relationType === "parent") {
@@ -453,49 +82,18 @@ const checkRelativeXpathRelation = (nodeXpath1, nodeXpath2, targetElemt, docmt,
453
82
  // Check if result is already cached to avoid recomputation
454
83
  if (!xpathCache?.get(xpath)) {
455
84
  // Compute and store result in cache
456
- xpathCache.set(xpath, (0, xpathHelpers_js_1.getCountOfXPath)(xpath, targetElemt, docmt));
85
+ xpathCache.set(xpath, getCachedXPathCount(xpath, targetElemt, docmt));
457
86
  }
458
87
  const count = xpathCache?.get(xpath);
459
88
  // Short-circuit: Return the first valid XPath result found
460
89
  if (count === 1) {
461
90
  return xpath;
462
91
  }
463
- if (count > 1) {
464
- if (xpathDataWithIndex.length) {
465
- if (count < xpathDataWithIndex[0].count) {
466
- xpathDataWithIndex.pop();
467
- xpathDataWithIndex.push({
468
- key: `relative xpath by unique parent ${isIndex ? "index" : ""}`,
469
- value: xpath,
470
- count
471
- });
472
- }
473
- }
474
- else {
475
- xpathDataWithIndex.push({
476
- key: `relative xpath by unique parent ${isIndex ? "index" : ""}`,
477
- value: xpath,
478
- count
479
- });
480
- }
481
- }
482
- if (count > 1 && isIndex && !xpathData.length) {
483
- // Try finding XPath with index if count is greater than 1
484
- const indexedXpath = (0, xpathHelpers_js_1.findXpathWithIndex)(xpath, targetElemt, docmt, count);
485
- // Cache the indexed XPath result
486
- if (indexedXpath &&
487
- (0, xpathHelpers_js_1.getCountOfXPath)(indexedXpath, targetElemt, docmt) === 1) {
488
- xpathData.push({
489
- key: `relative xpath by unique parent ${isIndex ? "index" : ""}`,
490
- value: indexedXpath
491
- });
492
- }
493
- }
494
92
  }
495
93
  }
496
94
  return null;
497
95
  };
498
- const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex, platform) => {
96
+ const getAiUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, _platform) => {
499
97
  try {
500
98
  if (parentXpathCache.has(domNode)) {
501
99
  return parentXpathCache.get(domNode);
@@ -504,19 +102,38 @@ const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex
504
102
  const xpathParts = [];
505
103
  let currentNode = domNode;
506
104
  while (currentNode && currentNode.nodeType === 1) {
507
- const hasUniqueAttr = false;
508
- for (const attrName of Array.from(currentNode.attributes)) {
509
- if ((0, xpathHelpers_js_1.checkBlockedAttributes)(attrName, currentNode, isTarget)) {
510
- const attrValue = (0, xpathHelpers_js_1.sanitizeAttributeValue)(attrName.name, attrName.nodeValue);
105
+ if (hasReachedRelativeXpathLimit()) {
106
+ return null;
107
+ }
108
+ const PRIORITY = [
109
+ "id",
110
+ "name",
111
+ "data-testid",
112
+ "data-test",
113
+ "aria-label",
114
+ "placeholder",
115
+ "class"
116
+ ];
117
+ const attrs = Array
118
+ .from(currentNode.attributes)
119
+ .sort((a, b) => {
120
+ const ai = PRIORITY.indexOf(a.name);
121
+ const bi = PRIORITY.indexOf(b.name);
122
+ return (ai == -1 ? 999 : ai) - (bi == -1 ? 999 : bi);
123
+ })
124
+ .slice(0, 3);
125
+ for (const attrName of attrs) {
126
+ if ((0, xpathHelpers_js_1.checkAiBlockedAttributes)(attrName, currentNode, isTarget)) {
127
+ const attrValue = (0, xpathHelpers_js_1.sanitizeAiAttributeValue)(attrName.name, attrName.nodeValue);
511
128
  const elementName = attrName.name;
512
- const xpathe = (0, xpathHelpers_js_1.getXpathString)(currentNode, elementName, attrValue);
129
+ const xpathe = (0, xpathHelpers_js_1.getAiXpathString)(currentNode, elementName, attrValue);
513
130
  let othersWithAttr;
514
131
  // If the XPath does not parse, move to the next unique attribute
515
132
  try {
516
- othersWithAttr = checkRelativeXpathRelation(xpathe, nodeXpath, node, docmt, isIndex, "parent");
133
+ othersWithAttr = checkAiRelativeXpathRelation(xpathe, nodeXpath, node, docmt, "parent");
517
134
  }
518
135
  catch (ign) {
519
- logData_js_1.logger.error("error in getUniqueParentXpath", ign);
136
+ logData_js_1.logger.error("error in getAiUniqueParentXpath", ign);
520
137
  continue;
521
138
  }
522
139
  // If the attribute isn't actually unique, get it's index too
@@ -525,21 +142,22 @@ const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex
525
142
  }
526
143
  }
527
144
  }
528
- if (currentNode.textContent && !currentNode.textContent) {
145
+ const text = getCachedFilteredText(currentNode);
146
+ if (text) {
529
147
  if (!isTarget ||
530
- (isTarget && !(0, xpathHelpers_js_1.isNumberExist)(currentNode.textContent))) {
148
+ (isTarget && !(0, xpathHelpers_js_1.isAiNumberExist)(text))) {
531
149
  let xpathe;
532
150
  if (!xpathHelpers_js_1.reWhiteSpace.test(currentNode.textContent)) {
533
- xpathe = (0, xpathHelpers_js_1.isSvg)(currentNode)
534
- ? `//*[local-name()='${currentNode.tagName}' and normalize-space(.)=${(0, xpathHelpers_js_1.escapeCharacters)((0, xpathHelpers_js_1.getFilteredText)(currentNode))}]`
535
- : `//${currentNode.tagName || "*"}[normalize-space(.)=${(0, xpathHelpers_js_1.escapeCharacters)((0, xpathHelpers_js_1.getFilteredText)(currentNode))}]`;
151
+ xpathe = (0, xpathHelpers_js_1.isAiSvg)(currentNode)
152
+ ? `//*[local-name()='${currentNode.tagName}' and normalize-space(.)=${(0, xpathHelpers_js_1.escapeAiCharacters)(getCachedFilteredText(currentNode))}]`
153
+ : `//${currentNode.tagName || "*"}[normalize-space(.)=${(0, xpathHelpers_js_1.escapeAiCharacters)(getCachedFilteredText(currentNode))}]`;
536
154
  }
537
155
  else {
538
- xpathe = (0, xpathHelpers_js_1.isSvg)(currentNode)
539
- ? `//*[local-name()='${currentNode.tagName}' and .=${(0, xpathHelpers_js_1.escapeCharacters)((0, xpathHelpers_js_1.getFilteredText)(currentNode))}]`
540
- : `//${currentNode.tagName || "*"}[.=${(0, xpathHelpers_js_1.escapeCharacters)((0, xpathHelpers_js_1.getFilteredText)(currentNode))}]`;
156
+ xpathe = (0, xpathHelpers_js_1.isAiSvg)(currentNode)
157
+ ? `//*[local-name()='${currentNode.tagName}' and .=${(0, xpathHelpers_js_1.escapeAiCharacters)(getCachedFilteredText(currentNode))}]`
158
+ : `//${currentNode.tagName || "*"}[.=${(0, xpathHelpers_js_1.escapeAiCharacters)(getCachedFilteredText(currentNode))}]`;
541
159
  }
542
- const othersWithAttr = checkRelativeXpathRelation(xpathe, nodeXpath, node, docmt, isIndex, "parent");
160
+ const othersWithAttr = checkAiRelativeXpathRelation(xpathe, nodeXpath, node, docmt, "parent");
543
161
  if (othersWithAttr) {
544
162
  return othersWithAttr;
545
163
  }
@@ -547,26 +165,26 @@ const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex
547
165
  else {
548
166
  const combinePattern = [];
549
167
  const contentRes = [
550
- ...new Set((0, xpathHelpers_js_1.getFilteredText)(currentNode).match(/([^0-9]+)/g))
168
+ ...new Set(getCachedFilteredText(currentNode).match(/([^0-9]+)/g))
551
169
  ];
552
170
  const reWhiteSpace = new RegExp(/^[\S]+( [\S]+)*$/gi);
553
171
  if (contentRes?.length) {
554
172
  for (let i = 0; i < contentRes?.length; i++) {
555
- if (contentRes[i] && (0, xpathHelpers_js_1.replaceWhiteSpaces)(contentRes[i].trim())) {
173
+ if (contentRes[i] && (0, xpathHelpers_js_1.aiReplaceWhiteSpaces)(contentRes[i].trim())) {
556
174
  if (!reWhiteSpace.test(contentRes[i])) {
557
- combinePattern.push(`contains(.,${(0, xpathHelpers_js_1.escapeCharacters)((0, xpathHelpers_js_1.replaceWhiteSpaces)(contentRes[i])).trim()})`);
175
+ combinePattern.push(`contains(.,${(0, xpathHelpers_js_1.escapeAiCharacters)((0, xpathHelpers_js_1.aiReplaceWhiteSpaces)(contentRes[i])).trim()})`);
558
176
  }
559
177
  else {
560
- combinePattern.push(`contains(.,${(0, xpathHelpers_js_1.escapeCharacters)(contentRes[i].trim()).trim()})`);
178
+ combinePattern.push(`contains(.,${(0, xpathHelpers_js_1.escapeAiCharacters)(contentRes[i].trim()).trim()})`);
561
179
  }
562
180
  }
563
181
  }
564
182
  }
565
183
  if (combinePattern?.length) {
566
- const xpathe = (0, xpathHelpers_js_1.isSvg)(currentNode)
184
+ const xpathe = (0, xpathHelpers_js_1.isAiSvg)(currentNode)
567
185
  ? `//*[local-name()='${currentNode.tagName}' and ${combinePattern.join(" and ")}]`
568
186
  : `//${currentNode.tagName || "*"}[${combinePattern.join(" and ")}]`;
569
- const othersWithAttr = checkRelativeXpathRelation(xpathe, nodeXpath, node, docmt, isIndex, "parent");
187
+ const othersWithAttr = checkAiRelativeXpathRelation(xpathe, nodeXpath, node, docmt, "parent");
570
188
  if (othersWithAttr) {
571
189
  return othersWithAttr;
572
190
  }
@@ -574,28 +192,16 @@ const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex
574
192
  }
575
193
  }
576
194
  // Construct the XPath based on the tag name
577
- if (!hasUniqueAttr) {
578
- const fallback = (0, xpathHelpers_js_1.getPlatformFallbackXpath)(currentNode, platform);
579
- if (fallback) {
580
- const xpath = checkRelativeXpathRelation(fallback, nodeXpath, node, docmt, isIndex, "parent");
581
- if (xpath) {
582
- return xpath;
583
- }
584
- }
585
- const xpathe = (0, xpathHelpers_js_1.isSvg)(currentNode)
586
- ? `/*[local-name()='${currentNode.tagName}']`
587
- : `/${currentNode.tagName}`;
588
- xpathParts.unshift(xpathe);
589
- }
590
- else {
591
- break;
592
- }
195
+ const xpathe = (0, xpathHelpers_js_1.isAiSvg)(currentNode)
196
+ ? `/*[local-name()='${currentNode.tagName}']`
197
+ : `/${currentNode.tagName}`;
198
+ xpathParts.unshift(xpathe);
593
199
  // Move to the parent node for the next iteration
594
200
  currentNode = currentNode.parentElement;
595
201
  }
596
202
  // Final constructed XPath
597
203
  const finalXPath = xpathParts.join("") + nodeXpath;
598
- const count = (0, xpathHelpers_js_1.getCountOfXPath)(finalXPath, domNode, docmt);
204
+ const count = getCachedXPathCount(finalXPath, domNode, docmt);
599
205
  if (count === 1) {
600
206
  parentXpathCache.set(domNode, finalXPath); // Cache final result
601
207
  return finalXPath;
@@ -606,33 +212,52 @@ const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex
606
212
  return null;
607
213
  }
608
214
  };
609
- const getParentRelativeXpath = (domNode, docmt, node, isTarget, platform) => {
610
- const cache = new Map(); // Cache to store computed results
611
- if (cache.has(domNode)) {
612
- return cache.get(domNode); // Return cached result if available
215
+ const getAiParentRelativeXpath = (domNode, docmt, node, isTarget, _platform) => {
216
+ if (parentRelativeCache.has(domNode)) {
217
+ return parentRelativeCache.get(domNode); // Return cached result if available
613
218
  }
614
219
  const xpathParts = []; // Initialize an array to hold parts of the XPath
615
220
  let currentNode = domNode; // Start with the provided DOM node
616
221
  try {
617
222
  while (currentNode && currentNode.nodeType === 1) {
223
+ if (hasReachedRelativeXpathLimit()) {
224
+ return null;
225
+ }
618
226
  // BASE CASE #1: If this isn't an element, we're above the root, return empty string
619
227
  if (!currentNode.tagName) {
620
228
  return "";
621
229
  }
622
230
  // BASE CASE #2: Check for unique attributes
623
231
  let uniqueAttrFound = false;
624
- for (const attr of Array.from(currentNode.attributes)) {
625
- if ((0, xpathHelpers_js_1.checkBlockedAttributes)(attr, currentNode, isTarget)) {
626
- const attrValue = (0, xpathHelpers_js_1.sanitizeAttributeValue)(attr.name, attr.nodeValue);
232
+ const PRIORITY = [
233
+ "id",
234
+ "name",
235
+ "data-testid",
236
+ "data-test",
237
+ "aria-label",
238
+ "placeholder",
239
+ "class"
240
+ ];
241
+ const attrs = Array
242
+ .from(currentNode.attributes)
243
+ .sort((a, b) => {
244
+ const ai = PRIORITY.indexOf(a.name);
245
+ const bi = PRIORITY.indexOf(b.name);
246
+ return (ai == -1 ? 999 : ai) - (bi == -1 ? 999 : bi);
247
+ })
248
+ .slice(0, 3);
249
+ for (const attr of attrs) {
250
+ if ((0, xpathHelpers_js_1.checkAiBlockedAttributes)(attr, currentNode, isTarget)) {
251
+ const attrValue = (0, xpathHelpers_js_1.sanitizeAiAttributeValue)(attr.name, attr.nodeValue);
627
252
  const elementName = attr.name;
628
- const xpathe = (0, xpathHelpers_js_1.getXpathString)(currentNode, elementName, attrValue);
253
+ const xpathe = (0, xpathHelpers_js_1.getAiXpathString)(currentNode, elementName, attrValue);
629
254
  let othersWithAttr;
630
255
  // If the XPath does not parse, move to the next unique attribute
631
256
  try {
632
- othersWithAttr = (0, xpathHelpers_js_1.getCountOfXPath)(xpathe, currentNode, docmt);
257
+ othersWithAttr = getCachedXPathCount(xpathe, currentNode, docmt);
633
258
  }
634
259
  catch (ign) {
635
- logData_js_1.logger.error("error in getParentRelativeXpath", ign);
260
+ logData_js_1.logger.error("error in getAiParentRelativeXpath", ign);
636
261
  continue;
637
262
  }
638
263
  // If the attribute is unique, return its XPath
@@ -644,10 +269,10 @@ const getParentRelativeXpath = (domNode, docmt, node, isTarget, platform) => {
644
269
  }
645
270
  }
646
271
  // If no unique attributes, check for text content
647
- if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {
648
- const textXPath = (0, xpathHelpers_js_1.getFilteredTextXPath)(currentNode);
272
+ if (!uniqueAttrFound && !currentNode.textContent && !node.textContent) {
273
+ const textXPath = (0, xpathHelpers_js_1.getAiFilteredTextXPath)(currentNode);
649
274
  if (textXPath) {
650
- const othersWithAttr = (0, xpathHelpers_js_1.getCountOfXPath)(textXPath, currentNode, docmt);
275
+ const othersWithAttr = getCachedXPathCount(textXPath, currentNode, docmt);
651
276
  if (othersWithAttr === 1) {
652
277
  uniqueAttrFound = true; // Mark that we found at least one unique attribute
653
278
  xpathParts.unshift(textXPath);
@@ -656,14 +281,8 @@ const getParentRelativeXpath = (domNode, docmt, node, isTarget, platform) => {
656
281
  }
657
282
  }
658
283
  if (!uniqueAttrFound) {
659
- const fallback = (0, xpathHelpers_js_1.getPlatformFallbackXpath)(currentNode, platform);
660
- if (fallback) {
661
- xpathParts.push(fallback);
662
- uniqueAttrFound = true;
663
- break;
664
- }
665
284
  // Construct the XPath based on the tag name
666
- const xpathe = (0, xpathHelpers_js_1.isSvg)(currentNode)
285
+ const xpathe = (0, xpathHelpers_js_1.isAiSvg)(currentNode)
667
286
  ? `/*[local-name()='${currentNode.tagName}']`
668
287
  : `/${currentNode.tagName}`;
669
288
  // Prepend the current XPath part to the array
@@ -685,7 +304,7 @@ const getParentRelativeXpath = (domNode, docmt, node, isTarget, platform) => {
685
304
  return null;
686
305
  }
687
306
  };
688
- const getChildRelativeXpath = (domNode, docmt, node) => {
307
+ const getAiChildRelativeXpath = (domNode, docmt, node) => {
689
308
  const xpathParts = []; // Initialize an array to hold parts of the XPath.
690
309
  let currentNode;
691
310
  const st = [];
@@ -700,21 +319,45 @@ const getChildRelativeXpath = (domNode, docmt, node) => {
700
319
  st.unshift(m.nextElementSibling);
701
320
  }
702
321
  try {
322
+ let processedNodes = 0;
703
323
  do {
704
324
  let uniqueAttrFound = false;
705
325
  for (currentNode = st.pop(); currentNode !== null;) {
706
- for (const attr of Array.from(currentNode.attributes)) {
707
- if ((0, xpathHelpers_js_1.checkBlockedAttributes)(attr, currentNode, true)) {
708
- const attrValue = (0, xpathHelpers_js_1.sanitizeAttributeValue)(attr.name, attr.nodeValue);
326
+ if (++processedNodes > 30) {
327
+ return null;
328
+ }
329
+ if (hasReachedRelativeXpathLimit()) {
330
+ return null;
331
+ }
332
+ const PRIORITY = [
333
+ "id",
334
+ "name",
335
+ "data-testid",
336
+ "data-test",
337
+ "aria-label",
338
+ "placeholder",
339
+ "class"
340
+ ];
341
+ const attrs = Array
342
+ .from(currentNode.attributes)
343
+ .sort((a, b) => {
344
+ const ai = PRIORITY.indexOf(a.name);
345
+ const bi = PRIORITY.indexOf(b.name);
346
+ return (ai == -1 ? 999 : ai) - (bi == -1 ? 999 : bi);
347
+ })
348
+ .slice(0, 3);
349
+ for (const attr of attrs) {
350
+ if ((0, xpathHelpers_js_1.checkAiBlockedAttributes)(attr, currentNode, true)) {
351
+ const attrValue = (0, xpathHelpers_js_1.sanitizeAiAttributeValue)(attr.name, attr.nodeValue);
709
352
  const elementName = attr.name;
710
- const xpathe = (0, xpathHelpers_js_1.getXpathString)(currentNode, elementName, attrValue);
353
+ const xpathe = (0, xpathHelpers_js_1.getAiXpathString)(currentNode, elementName, attrValue);
711
354
  let othersWithAttr;
712
355
  // If the XPath does not parse, move to the next unique attribute
713
356
  try {
714
- othersWithAttr = (0, xpathHelpers_js_1.getCountOfXPath)(xpathe, currentNode, docmt);
357
+ othersWithAttr = getCachedXPathCount(xpathe, currentNode, docmt);
715
358
  }
716
359
  catch (ign) {
717
- logData_js_1.logger.error("error in getChildRelativeXpath", ign);
360
+ logData_js_1.logger.error("error in getAiChildRelativeXpath", ign);
718
361
  continue;
719
362
  }
720
363
  // If the attribute is unique, return its XPath
@@ -727,9 +370,9 @@ const getChildRelativeXpath = (domNode, docmt, node) => {
727
370
  }
728
371
  // If no unique attributes, check for text content
729
372
  if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {
730
- const textXPath = (0, xpathHelpers_js_1.getFilteredTextXPath)(currentNode);
373
+ const textXPath = (0, xpathHelpers_js_1.getAiFilteredTextXPath)(currentNode);
731
374
  if (textXPath) {
732
- const othersWithAttr = (0, xpathHelpers_js_1.getCountOfXPath)(textXPath, currentNode, docmt);
375
+ const othersWithAttr = getCachedXPathCount(textXPath, currentNode, docmt);
733
376
  if (othersWithAttr === 1) {
734
377
  uniqueAttrFound = true; // Mark that we found at least one unique attribute
735
378
  xpathParts.push(textXPath);
@@ -739,7 +382,7 @@ const getChildRelativeXpath = (domNode, docmt, node) => {
739
382
  }
740
383
  if (!uniqueAttrFound) {
741
384
  // Construct the XPath based on the tag name
742
- const xpathe = (0, xpathHelpers_js_1.isSvg)(currentNode)
385
+ const xpathe = (0, xpathHelpers_js_1.isAiSvg)(currentNode)
743
386
  ? `/*[local-name()='${currentNode.tagName}']`
744
387
  : `/${currentNode.tagName}`;
745
388
  // Prepend the current XPath part to the array
@@ -763,121 +406,114 @@ const getChildRelativeXpath = (domNode, docmt, node) => {
763
406
  return finalXpath;
764
407
  }
765
408
  catch (error) {
766
- logData_js_1.logger.error("error in getChildRelativeXpath", error);
409
+ logData_js_1.logger.error("error in getAiChildRelativeXpath", error);
767
410
  return null;
768
411
  }
769
412
  };
770
- const getSiblingRelativeXPath = (domNode, docmt, isTarget, nodeXpath, platform) => {
413
+ const getAiSiblingRelativeXPath = (domNode, docmt, isTarget, nodeXpath, platform) => {
771
414
  try {
772
- const markedSpan = document.querySelector(".flntooltip");
415
+ const markedSpan = domNode.ownerDocument?.querySelector(".flntooltip");
773
416
  for (let m = domNode.nextElementSibling; m !== null && m !== markedSpan; m = m.nextElementSibling) {
774
- processSibling(m, domNode, docmt, nodeXpath, "preceding-sibling", isTarget, platform);
417
+ if (hasReachedRelativeXpathLimit()) {
418
+ return xpathData;
419
+ }
420
+ processAiSibling(m, domNode, docmt, nodeXpath, "preceding-sibling", isTarget, platform);
775
421
  }
776
422
  for (let n = domNode.previousElementSibling; n !== null && n !== markedSpan; n = n.previousElementSibling) {
777
- processSibling(n, domNode, docmt, nodeXpath, "following-sibling", isTarget, platform);
423
+ if (hasReachedRelativeXpathLimit()) {
424
+ return;
425
+ }
426
+ processAiSibling(n, domNode, docmt, nodeXpath, "following-sibling", isTarget, platform);
778
427
  }
779
428
  }
780
- catch (error) {
781
- console.error("sibling error", error);
429
+ catch {
782
430
  return null;
783
431
  }
784
432
  };
785
- const processSibling = (sibling, domNode, docmt, nodeXpath, axis, isTarget, platform) => {
433
+ const processAiSibling = (sibling, domNode, docmt, nodeXpath, axis, isTarget, _platform) => {
786
434
  try {
435
+ if (hasReachedRelativeXpathLimit()) {
436
+ return;
437
+ }
787
438
  if (sibling.hasAttributes()) {
788
- for (const attr of Array.from(sibling.attributes)) {
789
- let xpathe = (0, xpathHelpers_js_1.intermediateXpathStep)(sibling, {
439
+ const PRIORITY = [
440
+ "id",
441
+ "name",
442
+ "data-testid",
443
+ "data-test",
444
+ "aria-label",
445
+ "placeholder",
446
+ "class"
447
+ ];
448
+ const attrs = Array
449
+ .from(sibling.attributes)
450
+ .sort((a, b) => {
451
+ const ai = PRIORITY.indexOf(a.name);
452
+ const bi = PRIORITY.indexOf(b.name);
453
+ return (ai == -1 ? 999 : ai) - (bi == -1 ? 999 : bi);
454
+ })
455
+ .slice(0, 3);
456
+ for (const attr of attrs) {
457
+ if (hasReachedRelativeXpathLimit()) {
458
+ return;
459
+ }
460
+ let xpathe = (0, xpathHelpers_js_1.intermediateAiXpathStep)(sibling, {
790
461
  name: attr.name,
791
462
  value: attr.value
792
463
  }, isTarget);
793
- if (!xpathe) {
794
- xpathe = (0, xpathHelpers_js_1.getPlatformFallbackXpath)(sibling, platform);
795
- }
796
464
  if (xpathe) {
797
465
  xpathe += `/${axis}::${nodeXpath}`;
798
- const count = (0, xpathHelpers_js_1.getCountOfXPath)(xpathe, sibling, docmt);
466
+ const count = getCachedXPathCount(xpathe, sibling, docmt);
799
467
  if (count === 1) {
800
- xpathData.push({
468
+ if (!appendXPath(xpathData, {
801
469
  key: `xpath by ${axis}`,
802
470
  value: xpathe
803
- });
804
- return;
805
- }
806
- else if (count > 1) {
807
- if (xpathDataWithIndex.length) {
808
- if (count < xpathDataWithIndex[0].count) {
809
- xpathDataWithIndex.pop();
810
- xpathDataWithIndex.push({
811
- key: `relative xpath by ${axis}`,
812
- value: xpathe,
813
- count
814
- });
815
- }
471
+ })) {
472
+ return;
816
473
  }
817
- else {
818
- xpathDataWithIndex.push({
819
- key: `relative xpath by ${axis}`,
820
- value: xpathe,
821
- count
822
- });
474
+ if (hasReachedRelativeXpathLimit()) {
475
+ return;
823
476
  }
824
477
  }
825
478
  }
826
479
  }
827
480
  }
828
481
  if (!isTarget) {
829
- const xpathe = (0, xpathHelpers_js_1.intermediateXpathStep)(sibling, {
482
+ const xpathe = (0, xpathHelpers_js_1.intermediateAiXpathStep)(sibling, {
830
483
  name: "text",
831
- value: sibling.textContent
484
+ value: getCachedTextContent(sibling)
832
485
  }, isTarget);
833
486
  if (xpathe) {
834
- const count = (0, xpathHelpers_js_1.getCountOfXPath)(xpathe, sibling, docmt);
487
+ const count = getCachedXPathCount(xpathe, sibling, docmt);
835
488
  if (count === 1) {
836
- xpathData.push({
489
+ if (!appendXPath(xpathData, {
837
490
  key: `xpath by ${axis}`,
838
491
  value: xpathe
839
- });
840
- return;
841
- }
842
- else if (count > 1) {
843
- if (xpathDataWithIndex.length) {
844
- if (count < xpathDataWithIndex[0].count) {
845
- xpathDataWithIndex.pop();
846
- xpathDataWithIndex.push({
847
- key: `relative xpath by ${axis}`,
848
- value: xpathe,
849
- count
850
- });
851
- }
852
- }
853
- else {
854
- xpathDataWithIndex.push({
855
- key: `relative xpath by ${axis}`,
856
- value: xpathe,
857
- count
858
- });
492
+ })) {
493
+ return;
859
494
  }
495
+ return;
860
496
  }
861
497
  }
862
498
  }
863
499
  }
864
500
  catch (error) {
865
- logData_js_1.logger.error(`${axis} xpath-error`, error);
501
+ logData_js_1.logger.error(`${axis} xpath-error`, error.message);
866
502
  }
867
503
  };
868
- function getXPathUsingAttributeAndText(attributes, targetElemt, docmt, isTarget) {
504
+ function getAiXPathUsingAttributeAndText(attributes, targetElemt, docmt, isTarget) {
869
505
  const { tagName } = targetElemt;
870
- const textContent = targetElemt.textContent.trim();
506
+ const textContent = getCachedTextContent(targetElemt);
871
507
  if (!textContent) {
872
508
  return;
873
509
  }
874
510
  for (const attrName of attributes) {
875
- if ((0, xpathHelpers_js_1.checkBlockedAttributes)(attrName, targetElemt, isTarget)) {
876
- const attrValue = (0, xpathHelpers_js_1.sanitizeAttributeValue)(attrName.name, attrName.nodeValue);
511
+ if ((0, xpathHelpers_js_1.checkAiBlockedAttributes)(attrName, targetElemt, isTarget)) {
512
+ const attrValue = (0, xpathHelpers_js_1.sanitizeAiAttributeValue)(attrName.name, attrName.nodeValue);
877
513
  const elementName = attrName.name;
878
514
  const xpath = `//${tagName}[@${elementName}='${attrValue}' and text()='${textContent}']`;
879
515
  if (xpath) {
880
- const count = (0, xpathHelpers_js_1.getCountOfXPath)(xpath, targetElemt, docmt);
516
+ const count = getCachedXPathCount(xpath, targetElemt, docmt);
881
517
  if (count == 1) {
882
518
  return xpath;
883
519
  }
@@ -885,225 +521,124 @@ function getXPathUsingAttributeAndText(attributes, targetElemt, docmt, isTarget)
885
521
  }
886
522
  }
887
523
  }
888
- const addRelativeXpaths = (targetElemt, docmt, isIndex, isTarget, attribute, platform) => {
889
- try {
890
- const nodeXpath = [];
891
- let relativeXpath, relativeChildXpath;
892
- xpathData = [];
893
- if (attribute) {
894
- for (const attrName of attribute) {
895
- const expression = (0, xpathHelpers_js_1.intermediateXpathStep)(targetElemt, {
896
- name: attrName.name,
897
- value: attrName.value
898
- }, isTarget);
899
- if (expression) {
900
- nodeXpath.push(expression);
901
- }
902
- }
903
- }
904
- if (targetElemt.textContent) {
905
- const expression = (0, xpathHelpers_js_1.intermediateXpathStep)(targetElemt, {
906
- name: "text",
907
- value: targetElemt.textContent
908
- }, isTarget);
909
- // console.log(expression);
910
- if (expression) {
911
- nodeXpath.push(expression);
912
- }
913
- }
914
- nodeXpath.push(targetElemt.tagName);
915
- if (nodeXpath?.length) {
916
- for (let i = 0; i < nodeXpath.length; i++) {
917
- if (!xpathData.length) {
918
- getSiblingRelativeXPath(targetElemt, docmt, isTarget, nodeXpath[i], platform);
919
- if (!xpathData.length) {
920
- if (!relativeXpath) {
921
- relativeXpath = getParentRelativeXpath(targetElemt.parentElement, docmt, targetElemt, isTarget, platform);
922
- }
923
- if (relativeXpath &&
924
- (relativeXpath.includes("@") ||
925
- relativeXpath.includes("text()") ||
926
- relativeXpath.includes(".=")) &&
927
- relativeXpath.match(/\//g)?.length - 2 < 5) {
928
- const fullRelativeXpath = relativeXpath + `/${nodeXpath[i]}`;
929
- const count = (0, xpathHelpers_js_1.getCountOfXPath)(fullRelativeXpath, targetElemt, docmt);
930
- if (count === 1) {
931
- xpathData.push({
932
- key: "relative xpath by relative parent",
933
- value: fullRelativeXpath
934
- });
935
- }
936
- else if (count > 1 && isIndex) {
937
- const relativeXpathIndex = (0, xpathHelpers_js_1.findXpathWithIndex)(fullRelativeXpath, targetElemt, docmt, count);
938
- if (relativeXpathIndex &&
939
- (0, xpathHelpers_js_1.getCountOfXPath)(relativeXpathIndex, targetElemt, docmt) === 1) {
940
- xpathData.push({
941
- key: `relative xpath by relative parent ${isIndex ? "index" : ""}`,
942
- value: relativeXpathIndex
943
- });
944
- }
945
- }
946
- }
947
- }
948
- if (xpathData.length <= 1) {
949
- if (!relativeChildXpath) {
950
- relativeChildXpath = getChildRelativeXpath(targetElemt, docmt, targetElemt);
951
- }
952
- if (relativeChildXpath &&
953
- (relativeChildXpath.includes("@") ||
954
- relativeChildXpath.includes("text()") ||
955
- relativeChildXpath.includes(".="))) {
956
- const fullRelativeXpath = `/${nodeXpath[i] + relativeChildXpath.substring(1)}`;
957
- const count = (0, xpathHelpers_js_1.getCountOfXPath)(fullRelativeXpath, targetElemt, docmt);
958
- if (count === 1) {
959
- xpathData.push({
960
- key: "relative xpath by relative child",
961
- value: fullRelativeXpath
962
- });
963
- }
964
- else if (count > 1 && isIndex) {
965
- const relativeXpathIndex = (0, xpathHelpers_js_1.findXpathWithIndex)(fullRelativeXpath, targetElemt, docmt, count);
966
- if (relativeXpathIndex &&
967
- (0, xpathHelpers_js_1.getCountOfXPath)(relativeXpathIndex, targetElemt, docmt) === 1) {
968
- xpathData.push({
969
- key: `relative xpath by relative parent ${isIndex ? "index" : ""}`,
970
- value: relativeXpathIndex
971
- });
972
- }
973
- }
974
- }
975
- }
976
- if (xpathData?.length === 1 &&
977
- (xpathData?.[0]?.value?.match(/\[([0-9]+)\]/gm)?.length || 0) > 3 &&
978
- !referenceElementMode) {
979
- if (targetElemt.textContent) {
980
- const txtXpath = (0, exports.getTextXPath)(targetElemt, docmt, isIndex, false, platform);
981
- if (txtXpath) {
982
- xpathData.unshift({
983
- key: `xpath by text${isIndex ? "index" : ""}`,
984
- value: txtXpath
985
- });
986
- }
987
- }
988
- }
989
- if (!xpathData.length) {
990
- const tempRelativeXpath = getUniqueParentXpath(targetElemt.parentElement, docmt, targetElemt, isTarget, nodeXpath[i], isIndex, platform);
991
- if (tempRelativeXpath) {
992
- xpathData.push({
993
- key: "xpath by unique parent",
994
- value: tempRelativeXpath
995
- });
996
- }
997
- }
998
- }
999
- }
1000
- }
1001
- return xpathData;
1002
- }
1003
- catch (error) {
1004
- logData_js_1.logger.error("Error in addRelativeXpaths:", error);
1005
- }
1006
- };
1007
- const attributesBasedXPath = (attr, targetElemt, docmt, isIndex, isTarget, platform) => {
524
+ const attributesAiBasedXPath = (attr, targetElemt, docmt, isTarget, platform) => {
1008
525
  const attrName = attr.name;
1009
- const xpath = (0, xpathHelpers_js_1.getPropertyXPath)(targetElemt, docmt, `@${attrName}`, attr.value, isIndex, isTarget, platform);
526
+ const xpath = (0, xpathHelpers_js_1.getAiPropertyXPath)(targetElemt, docmt, `@${attrName}`, attr.value, isTarget, platform);
1010
527
  return xpath;
1011
528
  };
1012
- exports.attributesBasedXPath = attributesBasedXPath;
1013
- const getUniqueClassName = (element, docmt, isIndex, isTarget, platform) => {
529
+ exports.attributesAiBasedXPath = attributesAiBasedXPath;
530
+ const getAiUniqueClassName = (element, docmt, isTarget, platform) => {
1014
531
  let value = element.className;
1015
532
  if (typeof value !== "string") {
1016
533
  value = "";
1017
534
  }
1018
535
  value = value?.replace("flndisabled", "disabled");
1019
- value = (0, xpathHelpers_js_1.sanitizeAttributeValue)("class", value);
536
+ value = (0, xpathHelpers_js_1.sanitizeAiAttributeValue)("class", value);
1020
537
  value = value?.trim();
1021
538
  if (value) {
1022
- return (0, xpathHelpers_js_1.getPropertyXPath)(element, docmt, `@class`, value, isIndex, isTarget, platform);
539
+ return (0, xpathHelpers_js_1.getAiPropertyXPath)(element, docmt, `@class`, value, isTarget, platform);
1023
540
  }
1024
541
  };
1025
- exports.getUniqueClassName = getUniqueClassName;
1026
- const getTextXPath = (element, docmt, isIndex, isTarget, platform) => {
542
+ exports.getAiUniqueClassName = getAiUniqueClassName;
543
+ const getAiTextXPath = (element, docmt, isTarget, platform) => {
1027
544
  if ((element.textContent ?? "").trim() != "") {
1028
- const text = (0, xpathHelpers_js_1.getTextContent)(element);
545
+ const text = getCachedTextContent(element);
1029
546
  if (text) {
1030
- return (0, xpathHelpers_js_1.getPropertyXPath)(element, docmt, ".", text, isIndex, isTarget, platform);
547
+ return (0, xpathHelpers_js_1.getAiPropertyXPath)(element, docmt, ".", text, isTarget, platform);
1031
548
  }
1032
549
  }
1033
550
  };
1034
- exports.getTextXPath = getTextXPath;
1035
- const addAllXPathAttributes = (attributes, targetElemt, docmt, isIndex, isTarget, platform) => {
551
+ exports.getAiTextXPath = getAiTextXPath;
552
+ const addAiAllXPathAttributes = (attributes, targetElemt, docmt, isTarget, platform) => {
1036
553
  const attributesArray = attributes;
1037
554
  try {
1038
555
  attributesArray.map((attr) => {
1039
556
  if (!(attr.name === "className" || attr.name === "class")) {
1040
- if ((0, xpathHelpers_js_1.checkBlockedAttributes)(attr, targetElemt, isTarget)) {
1041
- const xpth = (0, exports.attributesBasedXPath)(attr, targetElemt, docmt, isIndex, isTarget, platform);
557
+ if ((0, xpathHelpers_js_1.checkAiBlockedAttributes)(attr, targetElemt, isTarget)) {
558
+ const xpth = (0, exports.attributesAiBasedXPath)(attr, targetElemt, docmt, isTarget, platform);
1042
559
  if (xpth) {
1043
- xpathData.push({
1044
- key: `xpath by ${attr.name}${isIndex ? " index" : ""}`,
560
+ if (!appendXPath(xpathData, {
561
+ key: `xpath by ${attr.name}`,
1045
562
  value: xpth
1046
- });
563
+ })) {
564
+ return;
565
+ }
1047
566
  }
1048
- const containsXpath = (0, xpathHelpers_js_1.getContainsPropertyXPath)(targetElemt, `@${attr.name}`, attr.value, platform);
567
+ const containsXpath = (0, xpathHelpers_js_1.getAiContainsPropertyXPath)(targetElemt, `@${attr.name}`, attr.value, platform);
1049
568
  if (containsXpath &&
1050
- (0, xpathHelpers_js_1.getCountOfXPath)(containsXpath, targetElemt, docmt) === 1) {
1051
- xpathData.push({
569
+ getCachedXPathCount(containsXpath, targetElemt, docmt) === 1) {
570
+ if (!appendXPath(xpathData, {
1052
571
  key: `xpath by contains ${attr.name}`,
1053
572
  value: containsXpath
1054
- });
573
+ })) {
574
+ return;
575
+ }
1055
576
  }
1056
- const startsWithXpath = (0, xpathHelpers_js_1.getStartsWithPropertyXPath)(targetElemt, `@${attr.name}`, attr.value, platform);
577
+ const startsWithXpath = (0, xpathHelpers_js_1.getAiStartsWithPropertyXPath)(targetElemt, `@${attr.name}`, attr.value, platform);
1057
578
  if (startsWithXpath &&
1058
- (0, xpathHelpers_js_1.getCountOfXPath)(startsWithXpath, targetElemt, docmt) === 1) {
1059
- xpathData.push({
579
+ getCachedXPathCount(startsWithXpath, targetElemt, docmt) === 1) {
580
+ if (!appendXPath(xpathData, {
1060
581
  key: `xpath by startsWith ${attr.name}`,
1061
582
  value: startsWithXpath
1062
- });
583
+ })) {
584
+ return;
585
+ }
1063
586
  }
1064
587
  }
1065
588
  }
1066
589
  });
1067
- const txtXpath = (0, exports.getTextXPath)(targetElemt, docmt, isIndex, isTarget, platform);
590
+ const txtXpath = (0, exports.getAiTextXPath)(targetElemt, docmt, isTarget, platform);
1068
591
  if (txtXpath) {
1069
- xpathData.push({
1070
- key: `xpath by text${isIndex ? " index" : ""}`,
592
+ if (!appendXPath(xpathData, {
593
+ key: "xpath by text",
1071
594
  value: txtXpath
1072
- });
595
+ })) {
596
+ return;
597
+ }
1073
598
  }
1074
599
  const classNameAttr = attributesArray.find((element) => element.name === "className");
1075
- if (classNameAttr && (0, xpathHelpers_js_1.checkBlockedAttributes)(classNameAttr, targetElemt, isTarget)) {
1076
- const xpath = (0, exports.getUniqueClassName)(targetElemt, docmt, isIndex, isTarget, platform);
600
+ if (classNameAttr && (0, xpathHelpers_js_1.checkAiBlockedAttributes)(classNameAttr, targetElemt, isTarget)) {
601
+ const xpath = (0, exports.getAiUniqueClassName)(targetElemt, docmt, isTarget, platform);
1077
602
  if (xpath) {
1078
- xpathData.push({
603
+ if (!appendXPath(xpathData, {
1079
604
  key: "xpath by class",
1080
605
  value: xpath
1081
- });
606
+ })) {
607
+ return;
608
+ }
1082
609
  }
1083
610
  }
1084
611
  if (!xpathData.length && attributesArray.length > 1) {
1085
- const combinationXpath = (0, xpathHelpers_js_1.getAttributeCombinationXpath)(targetElemt, docmt, attributesArray, isTarget, platform);
1086
- if (combinationXpath)
1087
- xpathData.push({
612
+ const combinationXpath = (0, xpathHelpers_js_1.getAiAttributeCombinationXpath)(targetElemt, docmt, attributesArray, isTarget, platform);
613
+ if (combinationXpath) {
614
+ if (!appendXPath(xpathData, {
1088
615
  key: "xpath by combination",
1089
616
  value: combinationXpath
1090
- });
617
+ })) {
618
+ return;
619
+ }
620
+ }
1091
621
  }
1092
622
  if (!xpathData.length) {
1093
- const textAttribute = getXPathUsingAttributeAndText(attributes, targetElemt, docmt, isTarget);
1094
- if (textAttribute)
1095
- xpathData.push({
623
+ const textAttribute = getAiXPathUsingAttributeAndText(attributes, targetElemt, docmt, isTarget);
624
+ if (textAttribute) {
625
+ if (!appendXPath(xpathData, {
1096
626
  key: "xpath by textAttribute",
1097
627
  value: textAttribute
1098
- });
628
+ })) {
629
+ return;
630
+ }
631
+ }
1099
632
  }
1100
633
  }
1101
634
  catch (error) {
1102
- logData_js_1.logger.error("Error in addAllXPathAttributes:", error);
635
+ logData_js_1.logger.error("Error in addAiAllXPathAttributes:", error);
1103
636
  }
1104
637
  };
1105
- const parseDOM = (element, doc, isIndex, isTarget, includedAttributes = [], strategies = [], platform) => {
638
+ const aiParseDOM = (element, doc, isTarget, includedAttributes = [], platform) => {
1106
639
  xpathData = [];
640
+ xpathValues.clear();
641
+ xpathCache.clear();
1107
642
  const targetElemt = element;
1108
643
  const rootNode = targetElemt?.getRootNode?.();
1109
644
  const DOCUMENT_FRAGMENT_NODE = 11;
@@ -1112,28 +647,29 @@ const parseDOM = (element, doc, isIndex, isTarget, includedAttributes = [], stra
1112
647
  const tag = targetElemt.tagName;
1113
648
  const { attributes } = targetElemt;
1114
649
  const attributesToUse = includedAttributes.length > 0 ? includedAttributes : Array.from(attributes);
1115
- addAllXPathAttributes(attributesToUse, targetElemt, docmt, isIndex, isTarget, platform);
650
+ addAiAllXPathAttributes(attributesToUse, targetElemt, docmt, isTarget, platform);
651
+ if (xpathData.length >= MAX_XPATH_RESULTS) {
652
+ return xpathData;
653
+ }
1116
654
  if (platform === "android") {
1117
- xpathData.push(...(0, androidSelector_js_1.generateAndroidLocators)(targetElemt, docmt, isTarget));
655
+ xpathData.push(...(0, androidSelector_js_1.generateAiAndroidLocators)(targetElemt, docmt, isTarget));
1118
656
  }
1119
657
  else if (platform === "ios") {
1120
- xpathData.push(...(0, iosSelector_js_1.generateIOSLocators)(targetElemt, docmt, isTarget));
658
+ xpathData.push(...(0, iosSelector_js_1.generateAiIOSLocators)(targetElemt, docmt, isTarget));
659
+ }
660
+ if (xpathData.length >= MAX_XPATH_RESULTS) {
661
+ return xpathData;
1121
662
  }
1122
- if (xpathData.length < 2) {
1123
- const fallback = (0, xpathHelpers_js_1.getPlatformFallbackXpath)(targetElemt, platform);
1124
- if (fallback) {
1125
- xpathData.push({
1126
- key: "platform fallback",
1127
- value: fallback
663
+ if (platform === "android" && !xpathData.length) {
664
+ const relativeXpath = (0, xpathHelpers_js_1.getAIRelativeXPath)(targetElemt, docmt, isTarget, attributesToUse, platform);
665
+ if (relativeXpath && getCachedXPathCount(relativeXpath, targetElemt, docmt) === 1) {
666
+ appendXPath(xpathData, {
667
+ key: "Relative xpath",
668
+ value: relativeXpath
1128
669
  });
1129
670
  }
1130
671
  }
1131
- if (strategies.length) {
1132
- const strategyXpaths = strategies.flatMap((strategy) => buildStrategyXpaths(targetElemt, docmt, isTarget, strategy, platform));
1133
- xpathData = getUniqueXpathEntries(strategyXpaths.filter((xpath) => (0, xpathHelpers_js_1.getCountOfXPath)(xpath.value, targetElemt, docmt) === 1));
1134
- return xpathData;
1135
- }
1136
- if (!referenceElementMode) {
672
+ if (!referenceElementMode && xpathData.length < MAX_XPATH_RESULTS) {
1137
673
  if (xpathData.length) {
1138
674
  const len = xpathData.length;
1139
675
  for (let i = 0; i < len; i++) {
@@ -1141,42 +677,34 @@ const parseDOM = (element, doc, isIndex, isTarget, includedAttributes = [], stra
1141
677
  if (xpth.startsWith(`//${tag}`)) {
1142
678
  xpth = "//*" + xpth.substring(2 + tag.length);
1143
679
  }
1144
- if ((0, xpathHelpers_js_1.getCountOfXPath)(xpth, element, docmt) === 1 &&
1145
- !xpathData.some(x => x.value === xpth)) {
1146
- xpathData.push({
680
+ if (getCachedXPathCount(xpth, element, docmt) === 1) {
681
+ if (!appendXPath(xpathData, {
1147
682
  key: `${xpathData[i].key} regex`,
1148
683
  value: xpth
1149
- });
684
+ })) {
685
+ return xpathData;
686
+ }
687
+ if (xpathData.length >= MAX_XPATH_RESULTS) {
688
+ return xpathData;
689
+ }
1150
690
  }
1151
- // const count = getCountOfXPath(xpth, element, docmt);
1152
- // if (count === 1) {
1153
- // xpathData.push({
1154
- // key: `${xpathData[i].key} regex`,
1155
- // value: xpth
1156
- // });
1157
- // }
1158
691
  }
1159
692
  }
1160
693
  }
1161
- if (!xpathData.length && !isShadowScoped) {
1162
- xpathData = buildAxesStrategyXpaths(targetElemt, docmt, isTarget, isIndex, platform);
1163
- }
1164
694
  return xpathData;
1165
695
  };
1166
- exports.parseDOM = parseDOM;
696
+ exports.aiParseDOM = aiParseDOM;
1167
697
  const xpath = {
1168
- parseDOM: exports.parseDOM,
1169
- getTextXPath: exports.getTextXPath,
1170
- getUniqueClassName: exports.getUniqueClassName,
1171
- attributesBasedXPath: exports.attributesBasedXPath,
1172
- addAllXPathAttributes,
1173
- addRelativeXpaths,
1174
- getXPathUsingAttributeAndText,
1175
- getSiblingRelativeXPath,
1176
- getChildRelativeXpath,
1177
- getParentRelativeXpath,
1178
- getUniqueParentXpath,
1179
- checkRelativeXpathRelation,
1180
- buildAxesStrategyXpaths
698
+ aiParseDOM: exports.aiParseDOM,
699
+ getAiTextXPath: exports.getAiTextXPath,
700
+ getAiUniqueClassName: exports.getAiUniqueClassName,
701
+ attributesAiBasedXPath: exports.attributesAiBasedXPath,
702
+ addAiAllXPathAttributes,
703
+ getAiXPathUsingAttributeAndText,
704
+ getAiSiblingRelativeXPath,
705
+ getAiChildRelativeXpath,
706
+ getAiParentRelativeXpath,
707
+ getAiUniqueParentXpath,
708
+ checkAiRelativeXpathRelation
1181
709
  };
1182
710
  exports.default = xpath;