ff-dom 2.0.4 → 2.0.6
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/dist/index.browser.cjs +1 -1
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cdn.js +1 -1
- package/dist/types/browser/browser/xpath.d.ts +5 -5
- package/dist/types/browser/utils/cssSelector.d.ts +10 -10
- package/dist/xpath.mjs +1 -1
- package/dist/xpath.mjs.map +1 -1
- package/package.json +1 -1
- package/tsconfig.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.cjs","sources":["../src/utils/xpathHelpers.ts","../src/utils/xpath.ts","../src/utils/referenceXpath.ts","../src/utils/getElementsFromHTML.ts","../src/utils/cssSelector.ts","../src/browser/xpath.ts"],"sourcesContent":["export const reWhiteSpace = /^[\\S]+( [\\S]+)*$/gi;\r\nexport let cspEnabled: boolean = false;\r\nconst xpathCache: { [x: string]: number } = {};\r\nlet relativeXPathCache = new Map();\r\nexport let modifiedElementAttributes: {\r\n url: string | null;\r\n attributeName: string | null;\r\n element: HTMLElement | Element;\r\n doc: Document;\r\n}[] = [];\r\nlet mutationObserver: MutationObserver;\r\n\r\nexport const createObserver = (addedNodeCallBack: Function) => {\r\n mutationObserver = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation?.addedNodes?.length) {\r\n addedNodeCallBack(mutation?.addedNodes);\r\n }\r\n\r\n if (mutation.target instanceof HTMLElement) {\r\n if (\r\n mutation?.type === \"attributes\" &&\r\n mutation.attributeName === \"class\" &&\r\n ((isSvg(mutation.target) &&\r\n mutation.oldValue?.trim() ===\r\n mutation.target.classList.value?.trim()) ||\r\n mutation.target.classList?.value\r\n ?.replace(mutation.oldValue!, \"\")\r\n .trim() === \"marked-element-temp\" ||\r\n mutation?.oldValue\r\n ?.replace(mutation.target.classList?.value, \"\")\r\n .trim() === \"marked-element-temp\")\r\n ) {\r\n } else if (\r\n mutation?.type === \"attributes\" &&\r\n ![\"flndisabled\"].includes(mutation.attributeName!)\r\n ) {\r\n modifiedElementAttributes.push({\r\n url: mutation.target.baseURI,\r\n attributeName: mutation.attributeName,\r\n element: mutation.target,\r\n doc: mutation.target.ownerDocument\r\n });\r\n }\r\n }\r\n });\r\n });\r\n};\r\nexport const startObserver = (\r\n target: Node,\r\n options: MutationObserverInit | undefined\r\n) => {\r\n mutationObserver?.observe(target, options);\r\n};\r\n\r\nexport const stopObserver = () => {\r\n mutationObserver?.disconnect();\r\n};\r\n\r\nexport const isNumberExist = (str: string): boolean => {\r\n const hasNumber = /\\d/;\r\n return hasNumber.test(str);\r\n};\r\n\r\nexport const buildPattern = (\r\n pattern: string,\r\n isSvg: boolean,\r\n tagName: string\r\n): string => {\r\n return isSvg\r\n ? `//*[local-name()='${tagName}' and ${pattern}]`\r\n : `//${tagName}[${pattern}]`;\r\n};\r\n\r\nexport const getTextContent = (\r\n targetElement: HTMLElement | Element\r\n): string => {\r\n const textContent = targetElement?.textContent;\r\n if (cspEnabled) {\r\n if (textContent) {\r\n const tooltip = document.querySelector(\".flntooltip\") as HTMLElement;\r\n if (tooltip) {\r\n const lastIndex = textContent.lastIndexOf(tooltip.innerText);\r\n if (\r\n lastIndex &&\r\n textContent.length === lastIndex + tooltip.innerText.length\r\n ) {\r\n return textContent.substring(0, lastIndex);\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nexport const getFilteredText = (element: Node): string => {\r\n return element?.childNodes[0]?.nodeValue || \"\";\r\n};\r\n\r\nexport const getCountOfXPath = (\r\n xpath: string,\r\n element: HTMLElement | Element,\r\n docmt: Node,\r\n multiElementReferenceMode: boolean = false\r\n): number => {\r\n try {\r\n let count;\r\n // Check if result is cached\r\n if (xpathCache[xpath] !== undefined) {\r\n count = xpathCache[xpath];\r\n } else {\r\n const owner =\r\n docmt.nodeType === 9 // DOCUMENT_NODE\r\n ? (docmt as Document)\r\n : docmt.ownerDocument!;\r\n\r\n count = owner.evaluate(\r\n `count(${xpath})`,\r\n docmt,\r\n null,\r\n XPathResult.NUMBER_TYPE,\r\n null\r\n ).numberValue;\r\n xpathCache[xpath] = count;\r\n }\r\n\r\n if (multiElementReferenceMode && Array.isArray(element)) {\r\n if (count > 1) {\r\n const elementsFromXpath = getElementFromXpath(xpath, docmt, true);\r\n let nodex,\r\n matchedCount = 0;\r\n if (elementsFromXpath instanceof XPathResult) {\r\n while ((nodex = elementsFromXpath?.iterateNext())) {\r\n if (element.includes(nodex)) {\r\n matchedCount += 1;\r\n\r\n if (matchedCount === 2) break;\r\n }\r\n }\r\n }\r\n\r\n if (matchedCount !== 2) return 0;\r\n }\r\n } else {\r\n // Short-circuit if we only need to match one element\r\n if (count === 1) {\r\n const elementFromXpath = getElementFromXpath(xpath, docmt);\r\n return elementFromXpath === element ? count : 0; // Return 0 if no match\r\n }\r\n }\r\n return count; // Return the count\r\n } catch (error) {\r\n console.error(`Error evaluating XPath: ${xpath}`, error);\r\n return 0; // Return 0 on error to avoid re-processing\r\n }\r\n};\r\n\r\nexport const escapeCharacters = (text: string): string => {\r\n if (text) {\r\n if (!(text.indexOf('\"') === -1)) {\r\n return `'${text}'`;\r\n }\r\n if (!(text.indexOf(\"'\") === -1)) {\r\n return `\"${text}\"`;\r\n }\r\n }\r\n return `'${text}'`;\r\n};\r\n\r\nexport const removeParenthesis = (xpath: string): string => {\r\n const charArr = xpath.split(\"\");\r\n\r\n let count = charArr.length;\r\n const indexArray = [];\r\n\r\n while (charArr[count - 2] !== \"[\") {\r\n indexArray.push(charArr[count - 2]);\r\n count--;\r\n }\r\n\r\n indexArray.reverse();\r\n let finalStr = \"\";\r\n for (let i = 0; i < indexArray.length; i++) {\r\n finalStr += indexArray[i];\r\n }\r\n\r\n const endBracketLength = finalStr.length + 2;\r\n let firstpart = xpath.slice(0, xpath.length - endBracketLength);\r\n\r\n if (firstpart.startsWith(\"(\") && firstpart.endsWith(\")\")) {\r\n firstpart = firstpart.slice(1, -1);\r\n } else {\r\n firstpart = xpath;\r\n }\r\n\r\n return firstpart;\r\n};\r\n\r\nexport const findXpathWithIndex = (\r\n val: string,\r\n node: HTMLElement | Element,\r\n docmt: Node,\r\n count: number\r\n) => {\r\n try {\r\n const owner =\r\n docmt.nodeType === 9 // DOCUMENT_NODE\r\n ? (docmt as Document)\r\n : docmt.ownerDocument!;\r\n\r\n let index = 0;\r\n if (count) {\r\n if (getCountOfXPath(`${val}[${count}]`, node, docmt) === 1) {\r\n return `${val}[${count}]`;\r\n }\r\n\r\n if (getCountOfXPath(`(${val})[${count}]`, node, docmt) === 1) {\r\n return `(${val})[${count}]`;\r\n }\r\n }\r\n\r\n const nodes = owner.evaluate(val, docmt, null, XPathResult.ANY_TYPE, null);\r\n let nodex;\r\n while ((nodex = nodes.iterateNext())) {\r\n index++;\r\n if (nodex.isSameNode(node)) {\r\n if (getCountOfXPath(`${val}[${index}]`, node, docmt) === 1) {\r\n return `${val}[${index}]`;\r\n }\r\n if (getCountOfXPath(`(${val})[${index}]`, node, docmt) === 1) {\r\n return `(${val})[${index}]`;\r\n }\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nconst deleteLineGap = (a: string): string => {\r\n a &&= a.split(\"\\n\")[0].length > 0 ? a.split(\"\\n\")[0] : a.split(\"\\n\")[1];\r\n return a;\r\n};\r\n\r\nconst deleteGarbageFromInnerText = (a: string): string => {\r\n a = deleteLineGap(a);\r\n a = a\r\n .split(/[^\\u0000-\\u00ff]/)\r\n .reduce((b, c) => {\r\n return b.length > c.length ? b : c;\r\n }, \"\")\r\n .trim();\r\n return (a = a.split(\"/\")[0].trim());\r\n};\r\n\r\nexport const replaceWhiteSpaces = (str: string): string => {\r\n if (str) {\r\n return str.replace(/\\s\\s+/g, \" \").trim();\r\n }\r\n\r\n return str;\r\n};\r\n\r\nexport const getShadowRoot = (el: HTMLElement | Element): Element | null => {\r\n if (!el || !el?.getRootNode) return null;\r\n\r\n const root = el.getRootNode() as ShadowRoot;\r\n return root && root?.host ? (root as unknown as Element) : null;\r\n};\r\n\r\nexport const checkBlockedAttributes = (\r\n attribute: {\r\n name: string;\r\n value: string;\r\n },\r\n targetElement: HTMLElement | Element,\r\n isTarget: boolean\r\n): boolean => {\r\n if (\r\n !attribute?.value ||\r\n typeof attribute?.value === \"boolean\" ||\r\n [\"true\", \"false\", \"on\", \"off\", \"flntooltip\"].some(\r\n (x) => x === attribute.value\r\n ) ||\r\n [\"type\", \"style\", \"locator-data-tooltip\", \"value\"].some(\r\n (x) => x === attribute.name\r\n ) ||\r\n modifiedElementAttributes?.find(\r\n (x) =>\r\n x.doc === targetElement.ownerDocument &&\r\n x.element === targetElement &&\r\n x.attributeName === attribute.name\r\n ) ||\r\n (attribute?.name?.indexOf(\"on\") === 0 && attribute?.name?.length > 3) ||\r\n typeof attribute.value === \"function\" ||\r\n (isTarget && isNumberExist(attribute.value))\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\nexport const getRelationship = (a: HTMLElement, b: HTMLElement): string => {\r\n let pos = a.compareDocumentPosition(b);\r\n return pos === 2\r\n ? \"preceding\"\r\n : pos === 4\r\n ? \"following\"\r\n : pos === 8\r\n ? \"ancestor\"\r\n : pos === 16\r\n ? \"descendant\"\r\n : pos === 32\r\n ? \"self\"\r\n : \"\";\r\n};\r\n\r\nexport const isSvg = (element: HTMLElement | Element) => {\r\n return element instanceof SVGElement;\r\n};\r\n\r\nexport const replaceTempAttributes = (str: string): string => {\r\n if (!str) return str;\r\n\r\n return str.replace(/\\b[a-zA-Z_]*disabled\\b/gi, \"disabled\");\r\n};\r\n\r\nconst getElementFromXpath = (xpath: string, docmt: Node, multi = false) => {\r\n let contextNode: Node = docmt;\r\n\r\n // XPath does NOT support DocumentFragment / ShadowRoot\r\n if (docmt.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\r\n contextNode = (docmt as ShadowRoot).host ?? docmt;\r\n }\r\n\r\n const owner =\r\n contextNode.nodeType === Node.DOCUMENT_NODE\r\n ? (contextNode as Document)\r\n : contextNode.ownerDocument!;\r\n\r\n if (multi) {\r\n return owner.evaluate(xpath, contextNode, null, XPathResult.ANY_TYPE, null);\r\n }\r\n\r\n return owner.evaluate(\r\n xpath,\r\n contextNode,\r\n null,\r\n XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n ).singleNodeValue;\r\n};\r\n\r\nexport const getPropertyXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n prop: string,\r\n value: string,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if (value) {\r\n const { tagName } = element;\r\n let count;\r\n let combinePattern = \"\";\r\n const mergePattern = [];\r\n let pattern;\r\n\r\n if (value && (!isTarget || !isNumberExist(value))) {\r\n if (!reWhiteSpace.test(value)) {\r\n pattern = buildPattern(\r\n `normalize-space(${prop})=${escapeCharacters(\r\n replaceWhiteSpaces(value)\r\n ).trim()}`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n } else {\r\n pattern = `//${tagName}[${prop}=${escapeCharacters(value)}]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n if (value && isTarget) {\r\n const splitText = value.split(\" \");\r\n if (splitText?.length) {\r\n if (splitText.length === 1) {\r\n const contentRes = [...new Set(splitText[0].match(/([^0-9]+)/g))];\r\n if (contentRes?.length >= 1) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 1\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (contentRes?.length > 1) {\r\n if (\r\n contentRes[contentRes.length - 1] &&\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1].trim())\r\n ?.length > 1\r\n ) {\r\n if (value.endsWith(contentRes[contentRes.length - 1])) {\r\n if (!reWhiteSpace.test(contentRes[contentRes.length - 1])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[contentRes.length - 1]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n } else {\r\n const endIndex =\r\n splitText.length % 2 === 0\r\n ? splitText.length / 2\r\n : splitText.length % 2;\r\n const startIndexString = splitText.slice(0, endIndex).join(\" \");\r\n let contentRes = [...new Set(startIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n const endIndexString = splitText\r\n .slice(endIndex, splitText.length - 1)\r\n .join(\" \");\r\n contentRes = [...new Set(endIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 3\r\n ) {\r\n if (value.endsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (value && isTarget && isNumberExist(value)) {\r\n const contentRes = [...new Set(value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (mergePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${mergePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tagName}[${mergePattern.join(\" and \")}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and text()]`;\r\n } else {\r\n pattern = `//${tagName}[text()]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAbsoluteXPath = (\r\n domNode: HTMLElement | Element | null,\r\n docmt: Document\r\n): string => {\r\n try {\r\n if (!domNode) {\r\n return \"\";\r\n }\r\n\r\n let xpathe = isSvg(domNode)\r\n ? `/*[local-name()='${domNode.tagName}']`\r\n : `/${domNode.tagName}`;\r\n\r\n // // If this node has siblings of the same tagName, get the index of this node\r\n if (domNode.parentElement) {\r\n // Get the siblings\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.parentElement.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n } else if (domNode instanceof HTMLElement) {\r\n if (domNode.offsetParent) {\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.offsetParent.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n }\r\n }\r\n\r\n // // Make a recursive call to this nodes parents and prepend it to this xpath\r\n return getAbsoluteXPath(domNode?.parentElement, docmt) + xpathe;\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(\"xpath\", error);\r\n\r\n return \"\";\r\n }\r\n};\r\n\r\nexport const getRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean = false,\r\n attributesArray: Attr[]\r\n) => {\r\n try {\r\n // Generate a cache key based on the node's identifier, index, and target flag\r\n // Check if the result for this node is already cached\r\n if (relativeXPathCache.has(domNode)) {\r\n return relativeXPathCache.get(domNode);\r\n }\r\n\r\n // Initialize an array to hold parts of the XPath\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n // Traverse up the DOM tree iteratively instead of using recursion\r\n while (currentNode) {\r\n let xpathe: string | undefined = \"\";\r\n let hasUniqueAttr = false;\r\n let attributes =\r\n domNode === currentNode\r\n ? (attributesArray ?? currentNode.attributes)\r\n : currentNode.attributes;\r\n\r\n // Loop through attributes to check for unique identifiers\r\n for (const attrName of Array.from(attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n // Clean up attribute value\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n\r\n const elementName = attrName.name;\r\n\r\n // Construct an XPath based on attribute\r\n xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr: number = 0;\r\n if (xpathe) {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n if (xpathe) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n // return replaceTempAttributes(xpathe);\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${\r\n currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n } else {\r\n let combinePattern: string[] = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g))\r\n ];\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces((contentRes[i] as string).trim())\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i] as string)) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n (contentRes[i] as string).trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If no unique attribute was found, construct XPath by tag name\r\n if (!hasUniqueAttr) {\r\n let tagBasedXPath = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Handle sibling nodes\r\n if (currentNode.parentElement) {\r\n const siblings = Array.from(\r\n currentNode.parentElement.children\r\n ).filter((childNode) => childNode.tagName === currentNode.tagName);\r\n\r\n // Append index to distinguish between siblings\r\n if (siblings.length > 1) {\r\n const index = siblings.indexOf(currentNode);\r\n tagBasedXPath += `[${index + 1}]`;\r\n }\r\n }\r\n\r\n // Add the constructed tag-based XPath to the parts array\r\n xpathParts.unshift(tagBasedXPath);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move up to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXPath = `${xpathParts.join(\"\")}`;\r\n\r\n // Cache the final XPath for this node\r\n relativeXPathCache.set(domNode, finalXPath);\r\n return finalXPath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nexport const getCombinationXpath = (\r\n attribute: Attr,\r\n domNode: HTMLElement | Element\r\n) => {\r\n const combinePattern = [];\r\n let pattern: string = \"\";\r\n\r\n if (\r\n attribute &&\r\n !isNumberExist(attribute.value) &&\r\n typeof attribute.nodeValue !== \"function\" // &&\r\n // !modifiedElementAttributes?.find(\r\n // (x) => x.element === domNode && x.attributeName === attribute.name\r\n // )\r\n ) {\r\n const contentRes = [...new Set(attribute.value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 2\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n contentRes[i].trim()\r\n )})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n pattern = isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`\r\n : `//${domNode.tagName}[${combinePattern.join(\" and \")}]`;\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAttributeCombinationXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n uniqueAttributes: Attr[],\r\n isTarget: boolean\r\n): string | undefined => {\r\n try {\r\n const xpathAttributes = [];\r\n\r\n if (uniqueAttributes.length > 1) {\r\n for (const attrName of uniqueAttributes) {\r\n if (checkBlockedAttributes(attrName, domNode, isTarget)) {\r\n const attrValue = attrName.nodeValue;\r\n\r\n if (!reWhiteSpace.test(attrValue!)) {\r\n xpathAttributes.push(\r\n `normalize-space(@${attrName.nodeName})=\"${attrValue}\"`\r\n );\r\n } else if (attrName.nodeName === \"class\") {\r\n xpathAttributes.push(\r\n `contains(@${attrName.nodeName},\"${attrValue}\")`\r\n );\r\n } else {\r\n xpathAttributes.push(`@${attrName.nodeName}=\"${attrValue}\"`);\r\n }\r\n\r\n const xpathe = isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${xpathAttributes.join(\r\n \" and \"\r\n )}]`\r\n : `//${domNode.tagName}[${xpathAttributes.join(\" and \")}]`;\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, domNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n if (othersWithAttr === 1 && !xpathe.includes(\"and\")) {\r\n return \"\";\r\n }\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr === 1 && xpathe.includes(\"and\")) {\r\n return xpathe;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(`'${JSON.stringify(error, null, 2)}'`);\r\n }\r\n};\r\n\r\nexport const intermediateXpathStep = (\r\n targetElemt: HTMLElement | Element,\r\n attr: { name: string; value: string },\r\n isTarget: boolean\r\n): string => {\r\n let isSvgElement = isSvg(targetElemt);\r\n let expression: string = \"\";\r\n\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n let attrValue = attr.value;\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attr.name;\r\n\r\n if (!reWhiteSpace.test(attrValue)) {\r\n expression = isSvgElement\r\n ? `*[local-name()='${\r\n targetElemt.tagName\r\n }' and normalize-space(@${elementName})=${escapeCharacters(\r\n attrValue\r\n )}]`\r\n : `${\r\n targetElemt.tagName || \"*\"\r\n }[normalize-space(@${elementName})=${escapeCharacters(attrValue)}]`;\r\n } else {\r\n expression = isSvgElement\r\n ? `*[local-name()='${\r\n targetElemt.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${targetElemt.tagName || \"*\"}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return expression;\r\n};\r\n\r\nexport const getFilteredTextXPath = (\r\n node: HTMLElement | Element,\r\n docmt: Document\r\n): string => {\r\n if (!node.textContent) return \"\";\r\n\r\n const filteredText = getFilteredText(node);\r\n\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(filteredText)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and normalize-space(.)=${escapeCharacters(filteredText)}]`\r\n : `//${node.tagName || \"*\"}[normalize-space(.)=${escapeCharacters(\r\n filteredText\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName}' and .=${escapeCharacters(\r\n filteredText\r\n )}]`\r\n : `//${node.tagName || \"*\"}[.=${escapeCharacters(filteredText)}]`;\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const getTextXpathFunction = (\r\n domNode: HTMLElement | Element\r\n): string | undefined => {\r\n const trimmedText = getTextContent(domNode)?.trim();\r\n const filteredText = trimmedText\r\n ? escapeCharacters(deleteGarbageFromInnerText(trimmedText))\r\n : trimmedText;\r\n if (filteredText) {\r\n if (filteredText !== `'${trimmedText}'`) {\r\n return `contains(.,${filteredText})`;\r\n }\r\n return `normalize-space(.)='${trimmedText}'`;\r\n }\r\n};\r\n\r\nexport const getXpathString = (\r\n node: HTMLElement | Element,\r\n attrName: string,\r\n attrValue: string\r\n): string => {\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n let xpathe: string = \"\";\r\n\r\n if (attrValue) {\r\n if (!reWhiteSpace.test(attrValue)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else if (attrName === \"class\") {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and @${attrName}=${escapeCharacters(attrValue)}]`\r\n : `//${node.tagName || \"*\"}[@${attrName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const replaceActualAttributes = (\r\n str: string,\r\n element: { attributes: any }\r\n): string => {\r\n if (str) {\r\n return str.replace(/\\bdisabled\\b/gi, \"flndisabled\");\r\n }\r\n return str;\r\n};\r\n\r\nconst addAttributeSplitCombineXpaths = (\r\n attributes: NamedNodeMap,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n const attributesArray = Array.prototype.slice.call(attributes);\r\n const xpaths: { key: string; value: string }[] = [];\r\n try {\r\n attributesArray.map((element) => {\r\n if (checkBlockedAttributes(element, targetElemt, isTarget)) {\r\n const xpth = getCombinationXpath(element, targetElemt);\r\n if (xpth) {\r\n xpaths.push({\r\n key: `split xpath by ${element.name}`,\r\n value: xpth\r\n });\r\n }\r\n }\r\n });\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return xpaths;\r\n};\r\n\r\nexport const getReferenceElementsXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n let nodeXpath1;\r\n const xpaths1 = [];\r\n if (\r\n domNode.textContent &&\r\n (!isTarget || (isTarget && !isNumberExist(domNode.textContent)))\r\n ) {\r\n if (!reWhiteSpace.test(domNode.textContent)) {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and ${getTextXpathFunction(\r\n domNode\r\n )})]`\r\n : `${domNode.tagName}[${getTextXpathFunction(domNode)}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and .=${escapeCharacters(\r\n getTextContent(domNode)\r\n )}]`\r\n : `${domNode.tagName}[.=${escapeCharacters(getTextContent(domNode))}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n }\r\n }\r\n\r\n if (domNode.attributes) {\r\n for (const attrName of Array.from(domNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, domNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attrName.name;\r\n\r\n if (elementName === \"class\") {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${\r\n domNode.tagName\r\n }' and contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`\r\n : `${domNode.tagName}[contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${\r\n domNode.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${domNode.tagName}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n\r\n if (nodeXpath1) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: nodeXpath1\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const attributesArray = Array.prototype.slice.call(domNode.attributes);\r\n if (attributesArray?.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n domNode,\r\n docmt,\r\n Array.prototype.slice.call(domNode.attributes),\r\n isTarget\r\n );\r\n if (combinationXpath) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: combinationXpath\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const combinePattern = [];\r\n let pattern;\r\n const tag = isSvg(domNode);\r\n if (domNode.textContent && isTarget && isNumberExist(domNode.textContent)) {\r\n const contentRes = [...new Set(domNode.textContent.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(contentRes[i]).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (tag) {\r\n pattern = `//*[local-name()='${tag}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tag}[${combinePattern.join(\" and \")}]`;\r\n }\r\n\r\n if (pattern)\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: pattern });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const xpaths = addAttributeSplitCombineXpaths(\r\n domNode.attributes,\r\n domNode,\r\n docmt,\r\n isTarget\r\n );\r\n if (xpaths?.length) {\r\n xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n return xpaths1;\r\n};\r\n\r\nexport const parseXml = (\r\n xmlStr: string,\r\n type: DOMParserSupportedType\r\n): Document | null => {\r\n if (window.DOMParser) {\r\n return new window.DOMParser().parseFromString(xmlStr, type);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const normalizeXPath = (xpath: string): string => {\r\n // Replace text() = \"value\" or text()='value'\r\n xpath = xpath.replace(\r\n /text\\(\\)\\s*=\\s*(['\"])(.*?)\\1/g,\r\n \"normalize-space(.)=$1$2$1\"\r\n );\r\n\r\n // Replace . = \"value\" or .='value'\r\n xpath = xpath.replace(/\\.\\s*=\\s*(['\"])(.*?)\\1/g, \"normalize-space(.)=$1$2$1\");\r\n\r\n return xpath;\r\n};\r\n\r\nexport const findMatchingParenthesis = (\r\n text: string,\r\n openPos: number\r\n): number => {\r\n let closePos = openPos;\r\n let counter = 1;\r\n while (counter > 0) {\r\n const c = text[++closePos];\r\n if (c == \"(\") {\r\n counter++;\r\n } else if (c == \")\") {\r\n counter--;\r\n }\r\n }\r\n return closePos;\r\n};\r\n\r\nexport function canonicalizeXPath(xpath: string): string {\r\n return (\r\n xpath\r\n .toLowerCase()\r\n // replace quoted values\r\n .replace(/'[^']*'/g, \"?\")\r\n .replace(/\"[^\"]*\"/g, \"?\")\r\n // replace numbers in predicates\r\n .replace(/\\[\\d+\\]/g, \"[?]\")\r\n // normalize node names\r\n .replace(/\\/\\/[a-z0-9_-]+/g, \"//node\")\r\n .replace(/\\/[a-z0-9_-]+/g, \"/node\")\r\n );\r\n}\r\n\r\nexport function extractXPathSignatureParts(xpath: string) {\r\n const xp = xpath.toLowerCase();\r\n\r\n const axisMatch = xp.match(\r\n /(ancestor-or-self|ancestor|descendant-or-self|descendant|following-sibling|preceding-sibling|following|preceding|parent|child|self)::/\r\n );\r\n const axis = axisMatch?.[1] ?? \"none\";\r\n\r\n const attrMatch = xp.match(/@([a-z0-9:-]+)/);\r\n const attribute = attrMatch?.[1] ?? \"none\";\r\n\r\n const usesNormalize = xp.includes(\"normalize-space\");\r\n\r\n return { axis, attribute, usesNormalize };\r\n}\r\n\r\nexport function getXPathPattern(xpath: string): string {\r\n const canonical = canonicalizeXPath(xpath);\r\n const parts = extractXPathSignatureParts(xpath);\r\n\r\n return [\r\n \"XPATH\",\r\n `axis:${parts.axis}`,\r\n `attr:${parts.attribute}`,\r\n `normalize:${parts.usesNormalize}`,\r\n `shape:${canonical}`\r\n ].join(\"|\");\r\n}\r\n\r\nexport function escapeAttrValue(value: string): string {\r\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\r\n}\r\n\r\nexport function isUniqueInDOM(\r\n docmt: Document,\r\n name: string,\r\n value: string\r\n): boolean {\r\n try {\r\n switch (name) {\r\n case \"id\":\r\n return (\r\n docmt.getElementById(value) !== null &&\r\n docmt.querySelectorAll(`#${value}`).length === 1\r\n );\r\n\r\n case \"name\":\r\n return (\r\n docmt.querySelectorAll(`[name=\"${escapeAttrValue(value)}\"]`)\r\n .length === 1\r\n );\r\n\r\n case \"className\":\r\n return docmt.getElementsByClassName(value).length === 1;\r\n\r\n case \"tagName\":\r\n return docmt.getElementsByTagName(value).length === 1;\r\n\r\n case \"linkText\":\r\n return (\r\n Array.from(docmt.querySelectorAll(\"a\")).filter(\r\n (a) => a.textContent?.trim() === value\r\n ).length === 1\r\n );\r\n case \"partialLinkText\":\r\n return (\r\n Array.from(docmt.querySelectorAll(\"a\")).filter((a) =>\r\n a.textContent?.includes(value)\r\n ).length === 1\r\n );\r\n default:\r\n return false;\r\n }\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport const xpathUtils = {\r\n parseXml,\r\n getReferenceElementsXpath,\r\n getAbsoluteXPath,\r\n getRelativeXPath,\r\n getCombinationXpath,\r\n getAttributeCombinationXpath,\r\n getElementFromXpath,\r\n isSvg,\r\n findXpathWithIndex,\r\n isNumberExist,\r\n getTextContent,\r\n getCountOfXPath,\r\n normalizeXPath,\r\n getShadowRoot,\r\n escapeCharacters,\r\n removeParenthesis,\r\n checkBlockedAttributes,\r\n getRelationship,\r\n findMatchingParenthesis,\r\n deleteGarbageFromInnerText,\r\n replaceTempAttributes,\r\n createObserver,\r\n startObserver,\r\n stopObserver,\r\n modifiedElementAttributes,\r\n cspEnabled,\r\n getXPathPattern,\r\n escapeAttrValue,\r\n isUniqueInDOM\r\n};\r\n","import {\r\n isNumberExist,\r\n getCountOfXPath,\r\n escapeCharacters,\r\n checkBlockedAttributes,\r\n replaceWhiteSpaces,\r\n getTextContent,\r\n getPropertyXPath,\r\n findXpathWithIndex,\r\n getFilteredText,\r\n intermediateXpathStep,\r\n getAttributeCombinationXpath,\r\n getFilteredTextXPath,\r\n isSvg,\r\n getXpathString,\r\n reWhiteSpace,\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathData: { key: string; value: string }[] = [];\r\nlet xpathDataWithIndex: { key: string; value: string; count: number }[] = [];\r\nlet referenceElementMode: boolean = false;\r\nlet xpathCache = new Map();\r\nlet cache = new Map();\r\n\r\nconst parentXpathCache = new Map(); // Cache for parent XPaths\r\n\r\nconst checkRelativeXpathRelation = (\r\n nodeXpath1: string,\r\n nodeXpath2: string,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n relationType: string\r\n) => {\r\n if (nodeXpath1 && !referenceElementMode) {\r\n let xpaths;\r\n\r\n if (relationType === \"parent\") {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/descendant-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/following::${nodeXpath2}`,\r\n ];\r\n } else {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/ancestor-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/preceding::${nodeXpath2}`,\r\n ];\r\n }\r\n\r\n // Iterate through XPath patterns\r\n for (const xpath of xpaths) {\r\n // Check if result is already cached to avoid recomputation\r\n if (!xpathCache?.get(xpath)) {\r\n // Compute and store result in cache\r\n xpathCache.set(xpath, getCountOfXPath(xpath, targetElemt, docmt));\r\n }\r\n\r\n const count = xpathCache?.get(xpath);\r\n\r\n // Short-circuit: Return the first valid XPath result found\r\n if (count === 1) {\r\n return xpath;\r\n }\r\n if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count,\r\n });\r\n }\r\n }\r\n\r\n if (count > 1 && isIndex && !xpathData.length) {\r\n // Try finding XPath with index if count is greater than 1\r\n const indexedXpath = findXpathWithIndex(\r\n xpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n\r\n // Cache the indexed XPath result\r\n if (\r\n indexedXpath &&\r\n getCountOfXPath(indexedXpath, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: indexedXpath,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nconst getUniqueParentXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean,\r\n nodeXpath: string,\r\n isIndex: boolean\r\n) => {\r\n try {\r\n if (parentXpathCache.has(domNode)) {\r\n return parentXpathCache.get(domNode);\r\n }\r\n\r\n // Direct XPath construction without loops\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n while (currentNode && currentNode.nodeType === 1) {\r\n const hasUniqueAttr = false;\r\n for (const attrName of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attrName.name;\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent && !currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${\r\n currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n } else {\r\n const combinePattern = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g)),\r\n ];\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (contentRes[i] && replaceWhiteSpaces(contentRes[i].trim())) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n const xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Construct the XPath based on the tag name\r\n if (!hasUniqueAttr) {\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Final constructed XPath\r\n const finalXPath = xpathParts.join(\"\") + nodeXpath;\r\n let count = getCountOfXPath(finalXPath, domNode, docmt);\r\n if (count === 1) {\r\n parentXpathCache.set(domNode, finalXPath); // Cache final result\r\n return finalXPath;\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getParentRelativeXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean\r\n) => {\r\n const cache = new Map(); // Cache to store computed results\r\n\r\n if (cache.has(domNode)) {\r\n return cache.get(domNode); // Return cached result if available\r\n }\r\n\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath\r\n let currentNode = domNode; // Start with the provided DOM node\r\n\r\n try {\r\n while (currentNode && currentNode.nodeType === 1) {\r\n // BASE CASE #1: If this isn't an element, we're above the root, return empty string\r\n if (!currentNode.tagName) {\r\n return \"\";\r\n }\r\n\r\n // BASE CASE #2: Check for unique attributes\r\n let uniqueAttrFound = false;\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, isTarget)) {\r\n let attrValue = attr.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(xpathe);\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(textXPath, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.unshift(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getChildRelativeXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n node: HTMLElement | Element\r\n) => {\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath.\r\n let currentNode: HTMLElement | Element | null;\r\n\r\n const st = [];\r\n if (\r\n domNode.firstElementChild != null &&\r\n domNode.firstElementChild.classList.contains(\"flntooltip\")\r\n ) {\r\n st.unshift(domNode.firstElementChild);\r\n } else if (domNode.nextElementSibling != null)\r\n st.unshift(domNode.nextElementSibling);\r\n\r\n for (\r\n let m = domNode.parentElement;\r\n m != null && m.nodeType === 1;\r\n m = m.parentElement\r\n ) {\r\n if (m.nextElementSibling) st.unshift(m.nextElementSibling);\r\n }\r\n\r\n try {\r\n do {\r\n let uniqueAttrFound = false;\r\n for (currentNode = st.pop()!; currentNode !== null; ) {\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, true)) {\r\n let attrValue = attr.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(xpathe);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(\r\n textXPath,\r\n currentNode,\r\n docmt\r\n );\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.push(xpathe);\r\n\r\n if (currentNode.firstElementChild != null) {\r\n st.push(currentNode.nextElementSibling);\r\n currentNode = currentNode.firstElementChild;\r\n } else {\r\n currentNode = currentNode.nextElementSibling;\r\n }\r\n } else {\r\n break;\r\n }\r\n }\r\n } while (st.length > 0);\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getSiblingRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n nodeXpath: string\r\n) => {\r\n try {\r\n const markedSpan = document.querySelector(\".flntooltip\");\r\n\r\n for (\r\n let m = domNode.nextElementSibling;\r\n m !== null && m !== markedSpan;\r\n m = m.nextElementSibling\r\n ) {\r\n processSibling(\r\n m,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"preceding-sibling\",\r\n isTarget\r\n );\r\n }\r\n\r\n for (\r\n let n = domNode.previousElementSibling;\r\n n !== null && n !== markedSpan;\r\n n = n.previousElementSibling\r\n ) {\r\n processSibling(\r\n n,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"following-sibling\",\r\n isTarget\r\n );\r\n }\r\n } catch (error) {\r\n console.error(\"sibling error\", error);\r\n return null;\r\n }\r\n};\r\n\r\nconst processSibling = (\r\n sibling: Element,\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n nodeXpath: string,\r\n axis: string,\r\n isTarget: boolean\r\n) => {\r\n try {\r\n if (sibling.hasAttributes()) {\r\n for (const attr of Array.from(sibling.attributes)) {\r\n let xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: attr.name,\r\n value: attr.value,\r\n },\r\n isTarget\r\n );\r\n if (xpathe) {\r\n xpathe += `/${axis}::${nodeXpath}`;\r\n\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe,\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!isTarget) {\r\n let xpathe;\r\n xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: \"text\",\r\n value: sibling.textContent,\r\n },\r\n isTarget\r\n );\r\n\r\n if (xpathe) {\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe,\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(`${axis} xpath-error`, error);\r\n }\r\n};\r\n\r\nfunction getXPathUsingAttributeAndText(\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n) {\r\n const { tagName } = targetElemt;\r\n const textContent = targetElemt.textContent.trim();\r\n for (const attrName of attributes) {\r\n if (checkBlockedAttributes(attrName, targetElemt, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attrName.name;\r\n const xpath = `//${tagName}[@${elementName}='${attrValue}' and text()='${textContent}']`;\r\n if (xpath) {\r\n const count = getCountOfXPath(xpath, targetElemt, docmt);\r\n if (count == 1) {\r\n return xpath;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nconst addRelativeXpaths = (\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n attribute: Attr[]\r\n) => {\r\n try {\r\n let nodeXpath: string[] = [];\r\n let relativeXpath, relativeChildXpath;\r\n xpathData = [];\r\n\r\n console.log(attribute);\r\n if (attribute) {\r\n for (const attrName of attribute) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: attrName.name,\r\n value: attrName.value,\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n }\r\n\r\n if (targetElemt.textContent) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: \"text\",\r\n value: targetElemt.textContent,\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n\r\n nodeXpath.push(targetElemt.tagName);\r\n\r\n if (nodeXpath?.length) {\r\n for (let i = 0; i < nodeXpath.length; i++) {\r\n if (!xpathData.length) {\r\n getSiblingRelativeXPath(targetElemt, docmt, isTarget, nodeXpath[i]);\r\n\r\n if (!xpathData.length) {\r\n if (!relativeXpath) {\r\n relativeXpath = getParentRelativeXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget\r\n );\r\n }\r\n\r\n console.log(relativeXpath);\r\n\r\n if (\r\n relativeXpath &&\r\n (relativeXpath.includes(\"@\") ||\r\n relativeXpath.includes(\"text()\") ||\r\n relativeXpath.includes(\".=\")) &&\r\n relativeXpath.match(/\\//g)?.length - 2 < 5\r\n ) {\r\n const fullRelativeXpath = relativeXpath + `/${nodeXpath[i]}`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative parent\",\r\n value: fullRelativeXpath,\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n if (!relativeChildXpath) {\r\n relativeChildXpath = getChildRelativeXpath(\r\n targetElemt,\r\n docmt,\r\n targetElemt\r\n );\r\n }\r\n\r\n if (\r\n relativeChildXpath &&\r\n (relativeChildXpath.includes(\"@\") ||\r\n relativeChildXpath.includes(\"text()\") ||\r\n relativeChildXpath.includes(\".=\"))\r\n ) {\r\n const fullRelativeXpath = `/${\r\n nodeXpath[i] + relativeChildXpath.substring(1)\r\n }`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative child\",\r\n value: fullRelativeXpath,\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (\r\n xpathData?.length === 1 &&\r\n xpathData?.[0]?.value?.match(/\\[([0-9]+)\\]/gm)?.length! > 3 &&\r\n !referenceElementMode\r\n ) {\r\n if (targetElemt.textContent) {\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, false);\r\n if (txtXpath) {\r\n xpathData.unshift({\r\n key: `xpath by text${isIndex ? \"index\" : \"\"}`,\r\n value: txtXpath,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n let tempRelativeXpath = getUniqueParentXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget,\r\n nodeXpath[i],\r\n isIndex\r\n );\r\n\r\n if (tempRelativeXpath) {\r\n xpathData.push({\r\n key: \"xpath by unique parent\",\r\n value: tempRelativeXpath,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return xpathData;\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const attributesBasedXPath = (\r\n attr: Attr,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let attrName;\r\n\r\n attrName = attr.name;\r\n let xpath = getPropertyXPath(\r\n targetElemt,\r\n docmt,\r\n `@${attrName}`,\r\n attr.value,\r\n isIndex,\r\n isTarget\r\n );\r\n\r\n return xpath;\r\n};\r\n\r\nexport const getUniqueClassName = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let value = element.className;\r\n if (typeof value !== \"string\") {\r\n value = \"\";\r\n }\r\n value = value?.replace(\"flndisabled\", \"disabled\");\r\n value = value?.replace(\"removePointers\", \"\");\r\n value = value?.trim();\r\n\r\n if (value) {\r\n return getPropertyXPath(element, docmt, `@class`, value, isIndex, isTarget);\r\n }\r\n};\r\n\r\nexport const getTextXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if (element.textContent != \"\") {\r\n const text = getTextContent(element);\r\n\r\n if (text) {\r\n return getPropertyXPath(element, docmt, \".\", text, isIndex, isTarget);\r\n }\r\n }\r\n};\r\n\r\nconst addAllXPathAttributes = (\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n const attributesArray = attributes;\r\n try {\r\n attributesArray.map((attr) => {\r\n if (!(attr.name === \"className\" || attr.name === \"class\")) {\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n const xpth = attributesBasedXPath(\r\n attr,\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget\r\n );\r\n if (xpth) {\r\n xpathData.push({\r\n key: `xpath by ${attr.name}${isIndex ? \" index\" : \"\"}`,\r\n value: xpth,\r\n });\r\n }\r\n }\r\n }\r\n });\r\n\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, isTarget);\r\n if (txtXpath) {\r\n xpathData.push({\r\n key: `xpath by text${isIndex ? \" index\" : \"\"}`,\r\n value: txtXpath,\r\n });\r\n }\r\n\r\n if (\r\n attributesArray.find((element) => element.name === \"className\") &&\r\n checkBlockedAttributes(\r\n attributesArray?.find((element) => element.name === \"className\")!,\r\n targetElemt,\r\n isTarget\r\n )\r\n ) {\r\n let xpath = getUniqueClassName(targetElemt, docmt, isIndex, isTarget);\r\n if (xpath) {\r\n xpathData.push({\r\n key: \"xpath by class\",\r\n value: xpath,\r\n });\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n const textAttribute = getXPathUsingAttributeAndText(\r\n attributes,\r\n targetElemt,\r\n docmt,\r\n isTarget\r\n );\r\n if (textAttribute)\r\n xpathData.push({\r\n key: \"xpath by textAttribute\",\r\n value: textAttribute,\r\n });\r\n }\r\n\r\n if (!xpathData.length && attributesArray.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n targetElemt,\r\n docmt,\r\n attributesArray,\r\n isTarget\r\n );\r\n if (combinationXpath)\r\n xpathData.push({\r\n key: \"xpath by combination\",\r\n value: combinationXpath,\r\n });\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const parseDOM = (\r\n element: HTMLElement | Element,\r\n doc: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n includedAttributes: Attr[] = []\r\n) => {\r\n xpathData = [];\r\n console.log(element);\r\n const targetElemt = element;\r\n const docmt = targetElemt?.ownerDocument || doc;\r\n const tag = targetElemt.tagName;\r\n const { attributes } = targetElemt;\r\n const attributesToUse =\r\n includedAttributes.length > 0 ? includedAttributes : Array.from(attributes);\r\n addAllXPathAttributes(\r\n attributesToUse,\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget\r\n );\r\n if (!referenceElementMode) {\r\n if (xpathData.length) {\r\n const len = xpathData.length;\r\n for (let i = 0; i < len; i++) {\r\n let xpth = xpathData[i].value;\r\n xpth = \"//*\" + xpth.substring(xpth.indexOf(\"//\") + 2 + tag.length);\r\n const count = getCountOfXPath(xpth, element, docmt);\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `${xpathData[i].key} regex`,\r\n value: xpth,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n console.log(xpathData);\r\n if (!xpathData.length) {\r\n addRelativeXpaths(\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget,\r\n Array.from(targetElemt.attributes)\r\n );\r\n }\r\n\r\n return xpathData;\r\n};\r\n\r\nconst xpath = {\r\n parseDOM,\r\n getTextXPath,\r\n getUniqueClassName,\r\n attributesBasedXPath,\r\n addAllXPathAttributes,\r\n addRelativeXpaths,\r\n getXPathUsingAttributeAndText,\r\n getSiblingRelativeXPath,\r\n getChildRelativeXpath,\r\n getParentRelativeXpath,\r\n getUniqueParentXpath,\r\n checkRelativeXpathRelation,\r\n};\r\n\r\nexport default xpath;\r\n","import { parseDOM } from \"./xpath.ts\";\r\nimport {\r\n findXpathWithIndex,\r\n getShadowRoot,\r\n getTextContent,\r\n escapeCharacters,\r\n getCountOfXPath,\r\n checkBlockedAttributes,\r\n getAbsoluteXPath,\r\n isSvg,\r\n getCombinationXpath,\r\n getTextXpathFunction,\r\n replaceTempAttributes,\r\n replaceActualAttributes,\r\n getReferenceElementsXpath,\r\n getRelativeXPath,\r\n findMatchingParenthesis,\r\n removeParenthesis\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathDataWithIndex: any[] = [];\r\nlet xpathData: { key: string; value: string }[] = [];\r\nconst reWhiteSpace = /^[\\S]+( [\\S]+)*$/gi;\r\n\r\nexport const findRelativeXpath = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n docmt: Document,\r\n xpaths1: any[],\r\n xpaths2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n // debugger;\r\n const par1 = element1.parentElement;\r\n const par2 = element2.parentElement;\r\n let rel_xpath: any[] = [];\r\n\r\n let tempElement;\r\n let finalXpaths: any[] = [];\r\n\r\n if (isIndex) {\r\n if (xpathDataWithIndex.length) {\r\n const xpathWithIndex = findXpathWithIndex(\r\n xpathDataWithIndex[0].value,\r\n element2,\r\n element2.ownerDocument,\r\n xpathDataWithIndex[0].count\r\n );\r\n if (xpathWithIndex) {\r\n finalXpaths = finalXpaths.concat({\r\n key: `${xpathDataWithIndex[0]?.key\r\n ? xpathDataWithIndex[0]?.key\r\n : \"xpath with \"\r\n } index`,\r\n value: xpathWithIndex,\r\n });\r\n xpathDataWithIndex.pop();\r\n }\r\n }\r\n }\r\n\r\n if (!finalXpaths.length) {\r\n // both are same\r\n if (element1.isSameNode(element2)) {\r\n // rel_xpath = xpath1 + \"/self::\" + element1.tagName;\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"self\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n // parent\r\n tempElement = element1.parentElement;\r\n\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"parent\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n // ancestor\r\n tempElement = element1.parentElement;\r\n\r\n while (tempElement !== null) {\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"ancestor\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n\r\n tempElement = tempElement.parentNode;\r\n }\r\n\r\n // ancestor-or-self\r\n tempElement = element1;\r\n do {\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"ancestor-or-self\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n\r\n tempElement = tempElement.parentNode;\r\n } while (tempElement !== null);\r\n\r\n // both has same parent\r\n if (par1?.isSameNode(par2)) {\r\n for (\r\n let m = element1.nextElementSibling;\r\n m != null;\r\n m = m.nextElementSibling\r\n ) {\r\n if (m != null && m.isSameNode(element2)) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"following-sibling\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n for (\r\n let n = element1.previousElementSibling;\r\n n != null;\r\n n = n.previousElementSibling\r\n ) {\r\n if (n != null && n.isSameNode(element2)) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"preceding-sibling\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // child\r\n if (element1?.children?.length) {\r\n for (let m = element1.children[0]; m !== null; m = m?.nextElementSibling!) {\r\n if (m === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"child\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // following\r\n const relation = element1.compareDocumentPosition(element2);\r\n if (relation === 2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"preceding\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n }\r\n\r\n if (relation === 4) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"following\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n }\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n const descendantXpath = getDescendantXpath(\r\n [element1, element2],\r\n docmt,\r\n xpaths1,\r\n xpaths2,\r\n \"descendant\",\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (descendantXpath) finalXpaths = finalXpaths.concat(descendantXpath);\r\n\r\n const descendantSelfXpath = getDescendantXpath(\r\n [element1, element2],\r\n docmt,\r\n xpaths1,\r\n xpaths2,\r\n \"descendant-or-self\",\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (descendantSelfXpath) {\r\n finalXpaths = finalXpaths.concat(descendantSelfXpath);\r\n }\r\n }\r\n\r\n if (finalXpaths.length) {\r\n if (finalXpaths.length > 1) {\r\n finalXpaths.sort(function (a, b) {\r\n return a.value.length - b.value.length;\r\n });\r\n }\r\n\r\n if (finalXpaths.filter((x) => !x.key?.includes(\"index\"))?.length) {\r\n return [finalXpaths.filter((x) => !x.key?.includes(\"index\"))[0]];\r\n }\r\n return [finalXpaths[0]];\r\n }\r\n};\r\n\r\nconst descendantExpression = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n xpath2: string,\r\n relation: string,\r\n docmt: Node,\r\n isIndex: any,\r\n expCommonParentXpathElements: string | any[],\r\n step4: string,\r\n refCommonParentXpathElementLength: number = 0,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n let finalExpectedElementXpath: string | undefined = \"\";\r\n\r\n if (\r\n xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g)?.length >=\r\n expCommonParentXpathElements.length\r\n ) {\r\n const xpaths2Els: string[] = [];\r\n const xpath2Elements = xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g);\r\n for (let x = 1; x <= expCommonParentXpathElements.length; x++) {\r\n xpaths2Els.unshift(\r\n x === expCommonParentXpathElements.length\r\n ? expCommonParentXpathElements[\r\n expCommonParentXpathElements.length - x\r\n ]\r\n : xpath2Elements[xpath2Elements.length - x]\r\n );\r\n }\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n xpaths2Els,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n } else {\r\n finalExpectedElementXpath = `//${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n refExpectElement[refExpectElement.length - 1]\r\n )}`;\r\n let rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation} ${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst getDescendantXpath = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Document,\r\n xpaths1: { key: string; value: string }[],\r\n xpaths2: { key: string; value: string }[],\r\n relation: \"descendant\" | \"descendant-or-self\",\r\n isIndex: boolean = false,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n const refElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 2];\r\n const expElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 1];\r\n const expElementDocmnt = getShadowRoot(expElement) ?? expElement.ownerDocument;\r\n\r\n const refAbsoluteXpath =\r\n xpaths1.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(refElement, refElement.ownerDocument);\r\n\r\n const refFullXpathElements: any[] = [];\r\n const refFullXpathElementsWithoutNumber: any[] = [];\r\n refAbsoluteXpath.split(\"/\").map((x) => refFullXpathElements.push(x));\r\n refFullXpathElements.map((x) =>\r\n refFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n const expAbsoluteXpath =\r\n xpaths2.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(expElement, expElement.ownerDocument);\r\n\r\n const expFullXpathElements: any[] = [];\r\n const expFullXpathElementsWithoutNumber: any[] = [];\r\n expAbsoluteXpath.split(\"/\").map((x) => expFullXpathElements.push(x));\r\n expFullXpathElements.map((x) =>\r\n expFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n for (\r\n var parentElementNumber = 0;\r\n parentElementNumber < refFullXpathElements.length;\r\n parentElementNumber++\r\n ) {\r\n if (\r\n refFullXpathElements[parentElementNumber] !=\r\n expFullXpathElements[parentElementNumber]\r\n ) {\r\n break;\r\n }\r\n }\r\n\r\n const refCommonParentXpathElements = [];\r\n for (let i = parentElementNumber - 1; i < refFullXpathElements.length; i++) {\r\n if (refFullXpathElements[i]) {\r\n refCommonParentXpathElements.push(refFullXpathElementsWithoutNumber[i]);\r\n }\r\n }\r\n\r\n const expCommonParentXpathElements: string[] = [];\r\n for (\r\n let j =\r\n relation === \"descendant\" ? parentElementNumber : parentElementNumber - 1;\r\n j < expFullXpathElements.length;\r\n j++\r\n ) {\r\n if (expFullXpathElements[j]) {\r\n if (expCommonParentXpathElements.length)\r\n expCommonParentXpathElements.push(expFullXpathElementsWithoutNumber[j]);\r\n else\r\n expCommonParentXpathElements.push(\r\n expFullXpathElementsWithoutNumber[j].replace(/\\[([0-9]+)\\]/gm, \"\")\r\n );\r\n }\r\n }\r\n\r\n xpathData = xpaths2;\r\n\r\n let nodeXpath2;\r\n if (refExpectElement[refExpectElement.length - 2].textContent) {\r\n if (\r\n !reWhiteSpace.test(\r\n refExpectElement[refExpectElement.length - 2].textContent\r\n )\r\n ) {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and ${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )})]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )}]`;\r\n } else {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and .=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[.=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`;\r\n }\r\n\r\n refCommonParentXpathElements[refCommonParentXpathElements.length - 1] =\r\n nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n if (xpath2) {\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (refExpectElement[refExpectElement.length - 2].attributes) {\r\n for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]\r\n .attributes)) {\r\n if (\r\n checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attrName.name;\r\n\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[@${elementName}=${escapeCharacters(attrValue)}]`;\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]\r\n .attributes)) {\r\n if (\r\n checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const combinationXpath = getCombinationXpath(\r\n attrName,\r\n refExpectElement[refExpectElement.length - 2]\r\n );\r\n if (combinationXpath) {\r\n if (combinationXpath.startsWith(\"//\")) {\r\n nodeXpath2 = combinationXpath.substring(\r\n combinationXpath.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n nodeXpath2 = combinationXpath; // No need to modify the value\r\n }\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n const step4 = refCommonParentXpath;\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n expCommonParentXpathElements,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n};\r\n\r\nconst getXpathRelationExpression = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n relation: string,\r\n xpath1: any[],\r\n xpath2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let xpaths1;\r\n let xpaths2;\r\n console.log('getXpathRelationExpression', relation)\r\n const finalXpaths: { key: string; value: any }[] = [];\r\n\r\n try {\r\n xpaths1 = xpath1.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n xpaths2 = xpath2.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n let rel_xpath: string | undefined = `//${xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(xpaths1[i].value.indexOf(\"//\") + 2),\r\n element1\r\n )\r\n }/${relation}::${xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths2[j].value, element2)\r\n : replaceActualAttributes(\r\n xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2),\r\n element2\r\n )\r\n }`;\r\n console.log('getXpathRelationExpression', rel_xpath)\r\n const rel_count = getCountOfXPath(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument\r\n );\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n rel_xpath = findXpathWithIndex(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument,\r\n rel_count\r\n );\r\n if (rel_xpath) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(rel_xpath),\r\n });\r\n return finalXpaths;\r\n }\r\n } else if (rel_count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (rel_count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count,\r\n });\r\n }\r\n }\r\n } else if (rel_count === 1) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(rel_xpath),\r\n });\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n if (!finalXpaths.length) {\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n const tempPath = `${xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? xpaths2[j].value\r\n : xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2)\r\n }`;\r\n const xpath2Elements: string[] = tempPath.split(\r\n /\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g\r\n );\r\n if (xpath2Elements.length > 1) {\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(\r\n xpaths1[i].value.indexOf(\"//\") + 2\r\n ),\r\n element1\r\n )\r\n }`,\r\n xpath2Elements,\r\n element2,\r\n [element1, element2],\r\n element2.ownerDocument,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n\r\n console.log('getXpathRelationExpression traverseXpath', traverseXpath)\r\n if (traverseXpath) {\r\n finalXpaths.concat(traverseXpath);\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return finalXpaths;\r\n};\r\n\r\nconst getReferenceElementXpath = (element: HTMLElement | Element) => {\r\n let xpaths1: {\r\n key: string;\r\n value: string;\r\n }[] = [];\r\n\r\n xpaths1 = parseDOM(element, element.ownerDocument, false, false);\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = parseDOM(element, element.ownerDocument, true, false);\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n } else {\r\n let xpaths = parseDOM(element, element.ownerDocument, true, false);\r\n if (xpaths?.length) {\r\n xpaths = xpaths?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(element, element.ownerDocument, false, false, Array.from(element.attributes)),\r\n },\r\n ];\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(element, element.ownerDocument, true, false, Array.from(element.attributes)),\r\n },\r\n ];\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = getReferenceElementsXpath(element, element.ownerDocument, false);\r\n } else {\r\n const xpaths = getReferenceElementsXpath(\r\n element,\r\n element.ownerDocument,\r\n false\r\n );\r\n if (xpaths?.length) {\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n const referenceXpathElement = getAbsoluteXPath(\r\n element,\r\n element.ownerDocument\r\n );\r\n xpaths1 = xpaths1.filter((x) => x.value !== referenceXpathElement);\r\n\r\n xpaths1.push({\r\n key: \"absolute xpath\",\r\n value: referenceXpathElement.slice(1),\r\n });\r\n\r\n return xpaths1;\r\n};\r\n\r\nconst getTraverseXpathExpression = (\r\n xpathe1: string,\r\n absoluteXpathElements: string[],\r\n element2: HTMLElement | Element,\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Node,\r\n relation: string,\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let finalExpectedElementXpath: string | undefined;\r\n if (!multiElementReferenceMode) {\r\n for (let x = 1; x <= absoluteXpathElements.length; x++) {\r\n const xpath2 = absoluteXpathElements\r\n .slice(absoluteXpathElements.length - x, absoluteXpathElements.length)\r\n .join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n const xpath2 = absoluteXpathElements.join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst referenceXpath = {\r\n findRelativeXpath,\r\n getDescendantXpath,\r\n getXpathRelationExpression,\r\n getTraverseXpathExpression,\r\n getReferenceElementXpath,\r\n};\r\n\r\nexport default referenceXpath;\r\n","import { ElementRecord, Locator } from \"../types/locator.ts\";\r\nimport { parseDOM } from \"./xpath.ts\";\r\nimport {\r\n isNumberExist,\r\n normalizeXPath,\r\n getXPathPattern,\r\n escapeAttrValue,\r\n isUniqueInDOM\r\n} from \"./xpathHelpers.ts\";\r\n\r\nconst isSameXPathStillValid = (\r\n xpath: string,\r\n docmt: Document,\r\n target: Element\r\n): boolean => {\r\n const found = getElementFromXPath(docmt, normalizeXPath(xpath));\r\n return found === target;\r\n};\r\n\r\nconst resolveIsSelfHealed = (\r\n locName: string,\r\n oldValue: string | null | undefined,\r\n newValue: string | null | undefined\r\n): \"Y\" | null => {\r\n if (!oldValue || !newValue) return \"Y\";\r\n return oldValue === newValue ? null : \"Y\";\r\n};\r\n\r\ntype ElementDetails = {\r\n id?: string | null;\r\n className?: string | null;\r\n xpathByText?: string | null;\r\n xpathById?: string | null;\r\n xpathByClass?: string | null;\r\n xpathAbsolute?: string | null;\r\n xpathByName?: string | null;\r\n xpathByPlaceholder?: string | null;\r\n xpathByType?: string | null;\r\n visibleText?: string | null;\r\n relativeXpath?: string | null;\r\n [key: string]: any;\r\n};\r\n\r\nconst getElementFromShadowRoot = (\r\n el: Element | ShadowRoot,\r\n selector: string\r\n): Element | null => {\r\n // const shadowRoot = (element as HTMLElement).shadowRoot;\r\n // if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n // return shadowRoot.querySelector(selector);\r\n // }\r\n\r\n const elements = Array.from(el.querySelectorAll(\"*\"));\r\n\r\n try {\r\n for (let i = 0; i < elements.length; i++) {\r\n if (elements[i].shadowRoot) {\r\n const { shadowRoot } = elements[i];\r\n if (shadowRoot) {\r\n getElementFromShadowRoot(shadowRoot, selector);\r\n if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n return shadowRoot.querySelector(selector);\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n return null;\r\n};\r\n\r\nconst getId = (element: Element | null): string | null => {\r\n return element?.id || null;\r\n};\r\n\r\nconst getClassName = (element: Element): string | null => {\r\n return (element as HTMLElement).className || null;\r\n};\r\n\r\nconst getVisibleText = (element: Element): string | null => {\r\n return element.textContent?.trim() || null;\r\n};\r\n\r\nconst getName = (element: Element): string | null => {\r\n const elementEl = element as HTMLElement;\r\n\r\n if (elementEl.hasAttribute(\"name\")) {\r\n const attrValue = elementEl.getAttribute(\"name\");\r\n const name = `${attrValue}`;\r\n return name || null;\r\n }\r\n return null;\r\n};\r\n\r\nconst relations: string[] = [\r\n \"/preceding-sibling\",\r\n \"/following-sibling\",\r\n \"/parent\",\r\n \"/descendant\",\r\n \"/ancestor\",\r\n \"/self\",\r\n \"/ancestor-or-self\",\r\n \"/child\",\r\n \"/preceding\",\r\n \"/following\"\r\n];\r\n\r\nfunction getElementFromXPath(docmt: Document, xpath: string): Element | null {\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n xpath,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n return xpathResult.singleNodeValue as Element | null;\r\n}\r\n\r\nfunction checkReferenceElementIsValid(\r\n locator: string,\r\n relation: string,\r\n docmt: Document\r\n): string | null {\r\n if (locator.includes(relation)) {\r\n const locatotSplitArray: string[] = locator.split(relation);\r\n const sourceLoc = locatotSplitArray[0].trim();\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n if (!locator.includes(\"dynamic\")) {\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n sourceLoc,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n\r\n const sourceElement = xpathResult.singleNodeValue;\r\n if (sourceElement) {\r\n const xpathResultComplete = xpathEvaluator.evaluate(\r\n locator,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n const completeElement = xpathResultComplete.singleNodeValue;\r\n let relativeXpath: string;\r\n if (completeElement) {\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n } else {\r\n console.error(\"Complete Locator is Invalid:\", locator);\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n }\r\n } else {\r\n console.error(\"Source Locator Not Found:\", sourceLoc);\r\n }\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nconst getElementsFromHTML = (\r\n record: ElementRecord,\r\n docmt: Document\r\n): ElementDetails | null => {\r\n const elementsToRemove = docmt.querySelectorAll(\r\n \"script, style, link[rel='stylesheet'], meta, noscript, embed, object, param, source, svg\"\r\n );\r\n\r\n if (elementsToRemove) {\r\n elementsToRemove.forEach((tag) => {\r\n (tag as Element).remove();\r\n });\r\n }\r\n\r\n const finalLocatorsSet: Set<string> = new Set();\r\n let finalLocators: any[] = [];\r\n\r\n function createLocator(base: any, overrides: Partial<any> = {}) {\r\n const oldValue = base?.value;\r\n const newValue = overrides.value ?? base?.value;\r\n const newLocator: any = {\r\n name: overrides.name ?? base?.name,\r\n type: overrides.type ?? base?.type,\r\n value: overrides.value ?? base?.value,\r\n reference: overrides.reference ?? base?.reference,\r\n status: overrides.status ?? base?.status,\r\n isRecorded: overrides.isRecorded ?? base?.isRecorded\r\n };\r\n\r\n const previousSelfHealed = base?.isSelfHealed === \"Y\";\r\n\r\n newLocator.isSelfHealed = previousSelfHealed\r\n ? \"Y\"\r\n : overrides.hasOwnProperty(\"isSelfHealed\")\r\n ? overrides.isSelfHealed\r\n : resolveIsSelfHealed(newLocator.name, oldValue, newValue);\r\n\r\n pushUniqueLocator(newLocator);\r\n }\r\n\r\n function pushUniqueLocator(obj: any) {\r\n const key = `${obj.name}:${obj.value}`;\r\n if (!finalLocatorsSet.has(key)) {\r\n finalLocatorsSet.add(key);\r\n finalLocators.push(obj);\r\n }\r\n }\r\n\r\n /** Locator Value Cleaner (Handles Special Scenarios) **/\r\n const cleanLocatorValue = (\r\n val: string | null | undefined,\r\n type?: string,\r\n isRecorded?: string\r\n ): string | null => {\r\n if (!val) return null;\r\n\r\n let cleaned = val.trim();\r\n\r\n // Return null for empty or literal \"null\"\r\n if (!cleaned || cleaned.toLowerCase() === \"null\") return null;\r\n\r\n // Unescape any escaped quotes\r\n cleaned = cleaned.replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\");\r\n\r\n // Remove surrounding single or double quotes\r\n cleaned = cleaned.replace(/^['\"](.+?)['\"]$/, \"$1\");\r\n\r\n // Replace double single quotes with a single quote inside XPath\r\n cleaned = cleaned.replace(/''/g, \"'\");\r\n\r\n // Normalize double quotes in XPath attribute selectors [@id=\"\" -> [@id='']\r\n cleaned = cleaned.replace(\r\n /\\[@(id|name)=['\"]{2}(.+?)['\"]{2}\\]/g,\r\n \"[@$1='$2']\"\r\n );\r\n\r\n // For DOM selectors (id or name), remove ALL quotes\r\n if (type === \"id\" || type === \"name\") {\r\n cleaned = cleaned.replace(/['\"]/g, \"\").trim();\r\n }\r\n\r\n if (type === \"xpath\" && isRecorded === \"Y\" && !val.startsWith(\"//\"))\r\n return null;\r\n\r\n // Final check for empty strings\r\n if (!cleaned || /^['\"]{2}$/.test(cleaned)) return null;\r\n\r\n return cleaned;\r\n };\r\n\r\n locators: for (const locator of record.locators) {\r\n try {\r\n const isRecorded = String(locator.isRecorded || \"\");\r\n const recordedNLocators = record.locators.filter(\r\n (l) => l.isRecorded === \"N\"\r\n );\r\n\r\n if (recordedNLocators.length > 0) {\r\n for (const locator of recordedNLocators) {\r\n createLocator(locator);\r\n }\r\n }\r\n\r\n const isDynamic = String(locator.value || locator.type || \"\");\r\n if (\r\n isDynamic.includes(\"dynamic\") ||\r\n isDynamic.match(\"dynamic\") ||\r\n isDynamic.includes(\"{\") ||\r\n isDynamic.includes(\"}\")\r\n ) {\r\n createLocator(locator);\r\n continue;\r\n }\r\n\r\n if (record.isShared.includes(\"Y\")) {\r\n break locators;\r\n }\r\n\r\n try {\r\n let targetElement: Element | null = null;\r\n if (locator.value.startsWith(\"iframe\")) {\r\n const iframe = docmt.querySelector(\r\n locator.value\r\n ) as HTMLIFrameElement;\r\n if (iframe) {\r\n const iframeDocument =\r\n iframe.contentDocument || iframe.contentWindow?.document;\r\n if (iframeDocument) {\r\n targetElement = iframeDocument.querySelector(\r\n locator.value.slice(6)\r\n );\r\n }\r\n }\r\n } else {\r\n const selectors = locator.value.split(\">>>\"); // Custom delimiter for shadow DOM\r\n\r\n for (const selector of selectors) {\r\n if (docmt) {\r\n const trimmedSelector = selector.trim();\r\n if (\r\n locator.name.includes(\"id\") ||\r\n trimmedSelector.startsWith(\"#\")\r\n ) {\r\n targetElement = docmt.querySelector(\"#\" + trimmedSelector);\r\n } else if (\r\n locator.name.includes(\"className\") ||\r\n trimmedSelector.startsWith(\".\")\r\n ) {\r\n targetElement = docmt.querySelector(\".\" + trimmedSelector);\r\n } else if (locator.name === \"name\") {\r\n const safeName = escapeAttrValue(trimmedSelector);\r\n targetElement = docmt.querySelector(`[name=\"${safeName}\"]`);\r\n } else if (locator.name === \"tagName\") {\r\n targetElement = docmt.querySelector(trimmedSelector);\r\n } else if (locator.name === \"linkText\") {\r\n targetElement =\r\n Array.from(docmt.querySelectorAll(\"a\")).find(\r\n (a) => a.textContent?.trim() === trimmedSelector\r\n ) || null;\r\n } else if (locator.name === \"partialLinkText\") {\r\n targetElement =\r\n Array.from(docmt.querySelectorAll(\"a\")).find((a) =>\r\n a.textContent?.includes(trimmedSelector)\r\n ) || null;\r\n } else if (\r\n (locator.name.includes(\"xpath\") ||\r\n trimmedSelector.startsWith(\"//\")) &&\r\n !locator.type.match(\"dynamic\")\r\n ) {\r\n const normalizedXPath = normalizeXPath(trimmedSelector);\r\n targetElement = getElementFromXPath(docmt, normalizedXPath);\r\n if (targetElement) {\r\n createLocator(locator, {\r\n value: trimmedSelector,\r\n isRecorded: String(locator.isRecorded).includes(\"N\")\r\n ? \"N\"\r\n : \"Y\"\r\n });\r\n }\r\n } else {\r\n targetElement = docmt.querySelector(trimmedSelector);\r\n if (!targetElement) {\r\n targetElement = getElementFromShadowRoot(\r\n docmt.body,\r\n trimmedSelector\r\n );\r\n }\r\n }\r\n } else {\r\n console.error(\"Element not found at:\", selector);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const locatorExists = (name: string, value: string): boolean => {\r\n const key = `${name}:${value}`;\r\n return finalLocatorsSet.has(key);\r\n };\r\n\r\n if (targetElement) {\r\n const payloadXPaths = record.locators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n\r\n for (const px of payloadXPaths) {\r\n if (isSameXPathStillValid(px.value, docmt, targetElement))\r\n createLocator(px, {\r\n isSelfHealed: null\r\n });\r\n }\r\n\r\n const existingXPaths = finalLocators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n\r\n // Track XPath patterns already used\r\n const usedXPathPatterns = new Set<string>(\r\n existingXPaths.map((x) => getXPathPattern(x.value))\r\n );\r\n\r\n const excludedAttributes: string[] = [];\r\n const idValue = getId(targetElement);\r\n if (\r\n idValue &&\r\n !locatorExists(\"id\", idValue) &&\r\n !isNumberExist(idValue)\r\n ) {\r\n const prevId = record.locators.find((l) => l.name === \"id\");\r\n if (isUniqueInDOM(docmt, \"id\", idValue)) {\r\n excludedAttributes.push(\"id\");\r\n createLocator(prevId, {\r\n name: \"id\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: idValue\r\n });\r\n }\r\n }\r\n\r\n const tagName = targetElement.tagName;\r\n if (tagName && !locatorExists(\"tagName\", tagName)) {\r\n const prevTag = record.locators.find((l) => l.name === \"tagName\");\r\n if (isUniqueInDOM(docmt, \"tagName\", tagName)) {\r\n excludedAttributes.push(\"tagName\");\r\n createLocator(prevTag, {\r\n name: \"tagName\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: tagName\r\n });\r\n }\r\n }\r\n\r\n const textValue = getVisibleText(targetElement);\r\n if (textValue && !isNumberExist(textValue)) {\r\n const prevLinkText = record.locators.find(\r\n (l) => l.name === \"linkText\"\r\n );\r\n if (isUniqueInDOM(docmt, \"linkText\", textValue)) {\r\n excludedAttributes.push(\"linkText\");\r\n createLocator(prevLinkText, {\r\n name: \"linkText\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: textValue\r\n });\r\n }\r\n }\r\n\r\n const nameLocator = getName(targetElement);\r\n if (\r\n nameLocator &&\r\n !locatorExists(\"name\", nameLocator) &&\r\n !isNumberExist(nameLocator)\r\n ) {\r\n const prevName = record.locators.find((l) => l.name === \"name\");\r\n if (isUniqueInDOM(docmt, \"name\", nameLocator)) {\r\n excludedAttributes.push(\"name\");\r\n createLocator(prevName, {\r\n name: \"name\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: nameLocator\r\n });\r\n }\r\n }\r\n\r\n const classValue = getClassName(targetElement);\r\n if (\r\n classValue &&\r\n classValue.trim() !== \"\" &&\r\n !locatorExists(\"className\", classValue) &&\r\n !isNumberExist(classValue)\r\n ) {\r\n const prevClassLocator = record.locators.find(\r\n (l) => l.name === \"className\"\r\n );\r\n if (isUniqueInDOM(docmt, \"className\", classValue)) {\r\n excludedAttributes.push(\"className\");\r\n createLocator(prevClassLocator, {\r\n name: \"className\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: classValue\r\n });\r\n }\r\n }\r\n\r\n const allAttributes = Array.from(targetElement.attributes);\r\n const includedAttributes = allAttributes.filter(\r\n (attr) => !excludedAttributes.includes(attr.name)\r\n );\r\n\r\n //If any direct locator is broken then we consider it as broken xpath\r\n\r\n const xpathResults = parseDOM(\r\n targetElement,\r\n docmt,\r\n false,\r\n true,\r\n includedAttributes\r\n );\r\n\r\n if (xpathResults?.length !== 0) {\r\n const brokenPayloadXPaths = payloadXPaths.filter(\r\n (px) => !isSameXPathStillValid(px.value, docmt, targetElement)\r\n );\r\n\r\n let xpathAdded = 0;\r\n\r\n for (const brokenPx of brokenPayloadXPaths) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n\r\n const originalPattern = getXPathPattern(brokenPx.value);\r\n if (usedXPathPatterns.has(originalPattern)) continue;\r\n\r\n const match = xpathResults.find(\r\n (r) => r.value && getXPathPattern(r.value) === originalPattern\r\n );\r\n\r\n if (match?.value) {\r\n createLocator(brokenPx, {\r\n name: \"xpath\",\r\n value: match.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(originalPattern);\r\n xpathAdded++;\r\n }\r\n }\r\n if (xpathAdded < brokenPayloadXPaths.length) {\r\n for (const result of xpathResults) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n if (!result.value) continue;\r\n\r\n const pattern = getXPathPattern(result.value);\r\n if (usedXPathPatterns.has(pattern)) continue;\r\n\r\n createLocator(result, {\r\n name: \"xpath\",\r\n value: result.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(pattern);\r\n xpathAdded++;\r\n }\r\n }\r\n }\r\n for (const locator of record.locators) {\r\n try {\r\n for (const loc of record.locators) {\r\n if (!loc.value) continue;\r\n\r\n for (const relation of relations) {\r\n if (loc.value.includes(relation)) {\r\n const relativeXpath = checkReferenceElementIsValid(\r\n loc.value,\r\n relation,\r\n docmt\r\n );\r\n if (relativeXpath) {\r\n createLocator(loc, {\r\n name: \"xpath\",\r\n value: relativeXpath,\r\n isRecorded:\r\n locator.isRecorded !== \"\" &&\r\n locator.isRecorded !== null\r\n ? locator.isRecorded\r\n : \"Y\"\r\n });\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n }\r\n }\r\n if (finalLocators.length < 5) {\r\n const fallbackCandidates = [\r\n { name: \"id\", value: getId(targetElement) },\r\n { name: \"name\", value: getName(targetElement) },\r\n { name: \"className\", value: getClassName(targetElement) },\r\n { name: \"tagName\", value: targetElement.tagName },\r\n { name: \"linkText\", value: getVisibleText(targetElement) }\r\n ];\r\n\r\n for (const candidate of fallbackCandidates) {\r\n if (finalLocators.length > 4) break;\r\n\r\n const { name, value } = candidate;\r\n if (!value) continue;\r\n if (isNumberExist(value)) continue;\r\n if (locatorExists(name, value)) continue;\r\n\r\n if (isUniqueInDOM(docmt, name, value)) {\r\n createLocator(undefined, {\r\n name,\r\n type: \"static\",\r\n value,\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n }\r\n }\r\n }\r\n\r\n const finalAutoHealedLocators = finalLocators.map((obj) => ({\r\n ...obj,\r\n value: cleanLocatorValue(obj.value, obj.name, obj.isRecorded)\r\n }));\r\n\r\n const jsonResult = [\r\n {\r\n name: `${record.name}`,\r\n desc: `${record.desc}`,\r\n type: `${record.type}`,\r\n locators: finalAutoHealedLocators.filter(\r\n (locator) => locator?.value != null && locator.value !== \"\"\r\n ),\r\n isShared: `${record.isShared}`,\r\n projectId: `${record.projectId}`,\r\n projectType: `${record.projectType}`,\r\n isRecorded: `${record.isRecorded}`,\r\n folder: `${record.folder}`,\r\n parentId: `${record.parentId}`,\r\n parentName: `${record.parentName}`,\r\n platform: `${record.platform}`,\r\n licenseId: `${record.licenseId}`,\r\n licenseType: `${record.licenseType}`,\r\n userId: `${record.userId}`\r\n }\r\n ];\r\n\r\n return jsonResult;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nexport { getElementsFromHTML };\r\n","import { isNumberExist } from \"./xpathHelpers.ts\";\r\n\r\nlet modifiedElementAttributes: [] = [];\r\n\r\nexport const parseCssSelectors = (el: HTMLElement | Element, docmt: Document) => {\r\n let cssSelector: { key: string, value: string }[] = [];\r\n\r\n try {\r\n let idCssSelector = getIdCssPath(el, docmt);\r\n\r\n if (\r\n idCssSelector &&\r\n idCssSelector.includes('#') &&\r\n docmt.querySelectorAll(idCssSelector)?.length === 1 &&\r\n !(\r\n idCssSelector.includes('body') ||\r\n idCssSelector.includes('head') ||\r\n idCssSelector.includes('html')\r\n )\r\n ) {\r\n cssSelector.push({ key: 'cssSelector by id', value: idCssSelector });\r\n } else {\r\n idCssSelector = '';\r\n }\r\n\r\n let nameCssSelector = getNameCssPath(el, docmt);\r\n\r\n if (\r\n nameCssSelector &&\r\n nameCssSelector !== idCssSelector &&\r\n nameCssSelector.includes('name') &&\r\n docmt.querySelectorAll(nameCssSelector)?.length === 1 &&\r\n !(\r\n nameCssSelector.includes('body') ||\r\n nameCssSelector.includes('head') ||\r\n nameCssSelector.includes('html')\r\n )\r\n ) {\r\n cssSelector.push({ key: 'cssSelector by name', value: nameCssSelector });\r\n } else {\r\n nameCssSelector = '';\r\n }\r\n\r\n let classCssSelector = getClassCssPath(el, docmt);\r\n\r\n if (\r\n classCssSelector &&\r\n classCssSelector !== idCssSelector &&\r\n nameCssSelector !== classCssSelector &&\r\n classCssSelector.includes('.') &&\r\n docmt.querySelectorAll(classCssSelector)?.length === 1 &&\r\n !(\r\n classCssSelector.includes('body') ||\r\n classCssSelector.includes('head') ||\r\n classCssSelector.includes('html')\r\n )\r\n ) {\r\n cssSelector.push({\r\n key: 'cssSelector by class',\r\n value: classCssSelector,\r\n });\r\n } else {\r\n classCssSelector = '';\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n if (!cssSelector.length) {\r\n let abSelector = getAbsoluteCssPath(el, docmt);\r\n if (\r\n abSelector &&\r\n docmt.querySelectorAll(abSelector)?.length === 1 &&\r\n !(\r\n abSelector.includes('body') ||\r\n abSelector.includes('head') ||\r\n abSelector.includes('html')\r\n )\r\n ) {\r\n cssSelector.push({\r\n key: 'Absolute cssSelector',\r\n value: abSelector,\r\n });\r\n } else {\r\n abSelector = '';\r\n }\r\n }\r\n\r\n return cssSelector;\r\n};\r\n\r\nexport const getIdCssPath = (el: HTMLElement | Element, docmt: Document) => {\r\n const tagName = el.tagName.toLowerCase();\r\n\r\n if (\r\n docmt?.defaultView?.Element &&\r\n !(el instanceof docmt?.defaultView?.Element)\r\n )\r\n return;\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n if (el.id && !isNumberExist(el.id)) {\r\n selector += `#${el.id}`;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nexport const getNameCssPath = (el: HTMLElement | Element, docmt: Document) => {\r\n const tagName = el.tagName.toLowerCase();\r\n\r\n if (\r\n docmt?.defaultView?.Element &&\r\n !(el instanceof docmt?.defaultView?.Element)\r\n )\r\n return;\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n let name = el.getAttribute('name');\r\n if (name && !isNumberExist(name)) {\r\n selector += `[name=${name}]`;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nexport const getClassCssPath = (el: HTMLElement | Element, docmt: Document) => {\r\n const tagName = el.tagName.toLowerCase();\r\n\r\n if (\r\n docmt?.defaultView?.Element &&\r\n !(el instanceof docmt?.defaultView?.Element)\r\n )\r\n return;\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n\r\n if (\r\n typeof el.className === 'string' &&\r\n el.className &&\r\n !isNumberExist(el.className) &&\r\n !modifiedElementAttributes?.find(\r\n (x: { element: HTMLElement | Element; attributeName: string; }) => x.element === el && x.attributeName === 'class'\r\n )\r\n ) {\r\n el.classList.remove('marked-element-temp');\r\n el.classList.remove('removePointers');\r\n if (el.className) {\r\n selector += `.${el.className.trim().replace(/\\s+/g, '.')}`;\r\n path.unshift(selector);\r\n break;\r\n }\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nexport const getAbsoluteCssPath = (el: HTMLElement | Element, docmt: Document) => {\r\n const tagName = el.tagName.toLowerCase();\r\n\r\n if (\r\n docmt?.defaultView?.Element &&\r\n !(el instanceof docmt?.defaultView?.Element)\r\n )\r\n return;\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n if (\r\n tagName.includes('body') ||\r\n tagName.includes('head') ||\r\n tagName.includes('html')\r\n ) {\r\n selector += tagName;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nexport const cssSelectors = {\r\n parseCssSelectors,\r\n getIdCssPath,\r\n getNameCssPath,\r\n getClassCssPath,\r\n getAbsoluteCssPath\r\n}","import xpath from '../utils/xpath.ts';\r\nimport referenceXpaths from '../utils/referenceXpath.ts';\r\nimport { xpathUtils } from '../utils/xpathHelpers.ts';\r\nimport { getElementsFromHTML } from '../utils/getElementsFromHTML.ts';\r\nimport { cssSelectors } from '../utils/cssSelector.ts';\r\n\r\nexport const createXPathAPI = () => ({\r\n xpath,\r\n referenceXpaths,\r\n xpathUtils,\r\n getElementsFromHTML,\r\n cssSelectors\r\n});\r\n\r\nexport default createXPathAPI;"],"names":["reWhiteSpace","xpathCache","mutationObserver","relativeXPathCache","Map","modifiedElementAttributes","isNumberExist","str","test","getTextContent","targetElement","textContent","getFilteredText","element","childNodes","nodeValue","getCountOfXPath","xpath","docmt","multiElementReferenceMode","count","undefined","nodeType","ownerDocument","evaluate","XPathResult","NUMBER_TYPE","numberValue","Array","isArray","elementsFromXpath","getElementFromXpath","nodex","matchedCount","iterateNext","includes","error","console","escapeCharacters","text","indexOf","removeParenthesis","charArr","split","length","indexArray","push","reverse","finalStr","i","endBracketLength","firstpart","slice","startsWith","endsWith","findXpathWithIndex","val","node","owner","index","nodes","ANY_TYPE","isSameNode","log","deleteGarbageFromInnerText","a","deleteLineGap","reduce","b","c","trim","replaceWhiteSpaces","replace","getShadowRoot","el","getRootNode","root","host","checkBlockedAttributes","attribute","isTarget","value","some","x","name","find","doc","attributeName","isSvg","SVGElement","replaceTempAttributes","multi","contextNode","Node","DOCUMENT_FRAGMENT_NODE","DOCUMENT_NODE","FIRST_ORDERED_NODE_TYPE","singleNodeValue","getPropertyXPath","prop","isIndex","tagName","combinePattern","mergePattern","pattern","buildPattern","toLowerCase","splitText","contentRes","Set","match","endIndex","startIndexString","join","endIndexString","getAbsoluteXPath","domNode","xpathe","parentElement","prototype","call","children","filter","childNode","HTMLElement","offsetParent","getRelativeXPath","attributesArray","has","get","xpathParts","currentNode","hasUniqueAttr","attributes","attrName","from","attrValue","elementName","getXpathString","othersWithAttr","unshift","RegExp","tagBasedXPath","siblings","finalXPath","set","getCombinationXpath","getAttributeCombinationXpath","uniqueAttributes","xpathAttributes","nodeName","ign","JSON","stringify","intermediateXpathStep","targetElemt","attr","isSvgElement","expression","getFilteredTextXPath","filteredText","getTextXpathFunction","trimmedText","replaceActualAttributes","getReferenceElementsXpath","nodeXpath1","xpaths1","key","combinationXpath","tag","xpaths","map","xpth","addAttributeSplitCombineXpaths","concat","normalizeXPath","findMatchingParenthesis","openPos","closePos","counter","getXPathPattern","canonical","canonicalizeXPath","parts","xp","axisMatch","axis","attrMatch","usesNormalize","extractXPathSignatureParts","escapeAttrValue","isUniqueInDOM","getElementById","querySelectorAll","getElementsByClassName","getElementsByTagName","xpathUtils","parseXml","xmlStr","type","window","DOMParser","parseFromString","getRelationship","pos","compareDocumentPosition","createObserver","addedNodeCallBack","MutationObserver","mutations","forEach","mutation","addedNodes","target","oldValue","classList","url","baseURI","startObserver","options","observe","stopObserver","disconnect","cspEnabled","xpathData","xpathDataWithIndex","cache","parentXpathCache","checkRelativeXpathRelation","nodeXpath2","relationType","pop","indexedXpath","getUniqueParentXpath","nodeXpath","getParentRelativeXpath","uniqueAttrFound","textXPath","finalXpath","getChildRelativeXpath","st","firstElementChild","contains","nextElementSibling","m","getSiblingRelativeXPath","markedSpan","document","querySelector","processSibling","n","previousElementSibling","sibling","hasAttributes","getXPathUsingAttributeAndText","addRelativeXpaths","relativeXpath","relativeChildXpath","fullRelativeXpath","relativeXpathIndex","substring","txtXpath","getTextXPath","tempRelativeXpath","attributesBasedXPath","getUniqueClassName","className","addAllXPathAttributes","textAttribute","parseDOM","includedAttributes","attributesToUse","len","descendantExpression","refExpectElement","xpath2","relation","expCommonParentXpathElements","step4","refCommonParentXpathElementLength","finalExpectedElementXpath","xpaths2Els","xpath2Elements","traverseXpath","getTraverseXpathExpression","repeat","rel_count","getDescendantXpath","xpaths2","refElement","expElement","expElementDocmnt","refAbsoluteXpath","refFullXpathElements","refFullXpathElementsWithoutNumber","expAbsoluteXpath","expFullXpathElements","expFullXpathElementsWithoutNumber","parentElementNumber","refCommonParentXpathElements","j","refCommonParentXpath","getXpathRelationExpression","element1","element2","xpath1","finalXpaths","rel_xpath","xpathe1","absoluteXpathElements","referenceXpath","findRelativeXpath","par1","par2","tempElement","xpathWithIndex","parentNode","descendantXpath","descendantSelfXpath","sort","getReferenceElementXpath","charAt","lastIndexOf","referenceXpathElement","isSameXPathStillValid","getElementFromXPath","getElementFromShadowRoot","selector","elements","shadowRoot","getId","id","getClassName","getVisibleText","getName","elementEl","hasAttribute","getAttribute","relations","defaultView","XPathEvaluator","checkReferenceElementIsValid","locator","sourceLoc","xpathEvaluator","getElementsFromHTML","record","elementsToRemove","remove","finalLocatorsSet","finalLocators","createLocator","base","overrides","newValue","newLocator","reference","status","isRecorded","previousSelfHealed","isSelfHealed","hasOwnProperty","locName","resolveIsSelfHealed","obj","add","pushUniqueLocator","cleanLocatorValue","cleaned","locators","String","recordedNLocators","l","isDynamic","isShared","iframe","iframeDocument","contentDocument","contentWindow","selectors","trimmedSelector","safeName","body","normalizedXPath","locatorExists","payloadXPaths","px","existingXPaths","usedXPathPatterns","excludedAttributes","idValue","prevId","prevTag","textValue","prevLinkText","nameLocator","prevName","classValue","prevClassLocator","xpathResults","brokenPayloadXPaths","xpathAdded","brokenPx","originalPattern","r","result","loc","fallbackCandidates","candidate","finalAutoHealedLocators","jsonResult","desc","projectId","projectType","folder","parentId","parentName","platform","licenseId","licenseType","userId","getIdCssPath","Element","path","ELEMENT_NODE","sib","nth","childElementCount","getNameCssPath","getClassCssPath","getAbsoluteCssPath","cssSelectors","parseCssSelectors","cssSelector","idCssSelector","nameCssSelector","classCssSelector","abSelector","createXPathAPI","referenceXpaths"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.browser.cjs","sources":["../src/utils/xpathHelpers.ts","../src/utils/xpath.ts","../src/utils/referenceXpath.ts","../src/utils/getElementsFromHTML.ts","../src/utils/cssSelector.ts","../src/browser/xpath.ts"],"sourcesContent":["export const reWhiteSpace = /^[\\S]+( [\\S]+)*$/i;\r\nexport let cspEnabled: boolean = false;\r\nconst xpathCache: { [x: string]: number } = {};\r\nlet relativeXPathCache = new Map();\r\nexport let modifiedElementAttributes: {\r\n url: string | null;\r\n attributeName: string | null;\r\n element: HTMLElement | Element;\r\n doc: Document;\r\n}[] = [];\r\nlet mutationObserver: MutationObserver;\r\n\r\nexport const createObserver = (addedNodeCallBack: Function) => {\r\n mutationObserver = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation?.addedNodes?.length) {\r\n addedNodeCallBack(mutation?.addedNodes);\r\n }\r\n\r\n if (mutation.target instanceof HTMLElement) {\r\n if (\r\n mutation?.type === \"attributes\" &&\r\n mutation.attributeName === \"class\" &&\r\n ((isSvg(mutation.target) &&\r\n mutation.oldValue?.trim() ===\r\n mutation.target.classList.value?.trim()) ||\r\n mutation.target.classList?.value\r\n ?.replace(mutation.oldValue!, \"\")\r\n .trim() === \"marked-element-temp\" ||\r\n mutation?.oldValue\r\n ?.replace(mutation.target.classList?.value, \"\")\r\n .trim() === \"marked-element-temp\")\r\n ) {\r\n } else if (\r\n mutation?.type === \"attributes\" &&\r\n ![\"flndisabled\"].includes(mutation.attributeName!)\r\n ) {\r\n modifiedElementAttributes.push({\r\n url: mutation.target.baseURI,\r\n attributeName: mutation.attributeName,\r\n element: mutation.target,\r\n doc: mutation.target.ownerDocument\r\n });\r\n }\r\n }\r\n });\r\n });\r\n};\r\nexport const startObserver = (\r\n target: Node,\r\n options: MutationObserverInit | undefined\r\n) => {\r\n mutationObserver?.observe(target, options);\r\n};\r\n\r\nexport const stopObserver = () => {\r\n mutationObserver?.disconnect();\r\n};\r\n\r\nexport const isNumberExist = (str: string): boolean => {\r\n const hasNumber = /\\d/;\r\n return hasNumber.test(str);\r\n};\r\n\r\nexport const buildPattern = (\r\n pattern: string,\r\n isSvg: boolean,\r\n tagName: string\r\n): string => {\r\n return isSvg\r\n ? `//*[local-name()='${tagName}' and ${pattern}]`\r\n : `//${tagName}[${pattern}]`;\r\n};\r\n\r\nexport const getTextContent = (\r\n targetElement: HTMLElement | Element\r\n): string => {\r\n const textContent = targetElement?.textContent;\r\n if (cspEnabled) {\r\n if (textContent) {\r\n const tooltip = document.querySelector(\".flntooltip\") as HTMLElement;\r\n if (tooltip) {\r\n const lastIndex = textContent.lastIndexOf(tooltip.innerText);\r\n if (\r\n lastIndex &&\r\n textContent.length === lastIndex + tooltip.innerText.length\r\n ) {\r\n return textContent.substring(0, lastIndex);\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nexport const getFilteredText = (element: Node): string => {\r\n return element?.childNodes[0]?.nodeValue || \"\";\r\n};\r\n\r\nexport const getCountOfXPath = (\r\n xpath: string,\r\n element: HTMLElement | Element,\r\n docmt: Node,\r\n multiElementReferenceMode: boolean = false\r\n): number => {\r\n try {\r\n let count;\r\n // Check if result is cached\r\n if (xpathCache[xpath] !== undefined) {\r\n count = xpathCache[xpath];\r\n } else {\r\n const owner =\r\n docmt.nodeType === 9 // DOCUMENT_NODE\r\n ? (docmt as Document)\r\n : docmt.ownerDocument!;\r\n\r\n count = owner.evaluate(\r\n `count(${xpath})`,\r\n docmt,\r\n null,\r\n XPathResult.NUMBER_TYPE,\r\n null\r\n ).numberValue;\r\n xpathCache[xpath] = count;\r\n }\r\n\r\n if (multiElementReferenceMode && Array.isArray(element)) {\r\n if (count > 1) {\r\n const elementsFromXpath = getElementFromXpath(xpath, docmt, true);\r\n let nodex,\r\n matchedCount = 0;\r\n if (elementsFromXpath instanceof XPathResult) {\r\n while ((nodex = elementsFromXpath?.iterateNext())) {\r\n if (element.includes(nodex)) {\r\n matchedCount += 1;\r\n\r\n if (matchedCount === 2) break;\r\n }\r\n }\r\n }\r\n\r\n if (matchedCount !== 2) return 0;\r\n }\r\n } else {\r\n // Short-circuit if we only need to match one element\r\n if (count === 1) {\r\n const elementFromXpath = getElementFromXpath(xpath, docmt);\r\n return elementFromXpath === element ? count : 0; // Return 0 if no match\r\n }\r\n }\r\n return count; // Return the count\r\n } catch (error) {\r\n console.error(`Error evaluating XPath: ${xpath}`, error);\r\n return 0; // Return 0 on error to avoid re-processing\r\n }\r\n};\r\n\r\nexport const escapeCharacters = (text: string): string => {\r\n if (text) {\r\n if (!(text.indexOf('\"') === -1)) {\r\n return `'${text}'`;\r\n }\r\n if (!(text.indexOf(\"'\") === -1)) {\r\n return `\"${text}\"`;\r\n }\r\n }\r\n return `'${text}'`;\r\n};\r\n\r\nexport const removeParenthesis = (xpath: string): string => {\r\n const charArr = xpath.split(\"\");\r\n\r\n let count = charArr.length;\r\n const indexArray = [];\r\n\r\n while (charArr[count - 2] !== \"[\") {\r\n indexArray.push(charArr[count - 2]);\r\n count--;\r\n }\r\n\r\n indexArray.reverse();\r\n let finalStr = \"\";\r\n for (let i = 0; i < indexArray.length; i++) {\r\n finalStr += indexArray[i];\r\n }\r\n\r\n const endBracketLength = finalStr.length + 2;\r\n let firstpart = xpath.slice(0, xpath.length - endBracketLength);\r\n\r\n if (firstpart.startsWith(\"(\") && firstpart.endsWith(\")\")) {\r\n firstpart = firstpart.slice(1, -1);\r\n } else {\r\n firstpart = xpath;\r\n }\r\n\r\n return firstpart;\r\n};\r\n\r\nexport const findXpathWithIndex = (\r\n val: string,\r\n node: HTMLElement | Element,\r\n docmt: Node,\r\n count: number\r\n) => {\r\n try {\r\n const owner =\r\n docmt.nodeType === 9 // DOCUMENT_NODE\r\n ? (docmt as Document)\r\n : docmt.ownerDocument!;\r\n\r\n let index = 0;\r\n if (count) {\r\n if (getCountOfXPath(`${val}[${count}]`, node, docmt) === 1) {\r\n return `${val}[${count}]`;\r\n }\r\n\r\n if (getCountOfXPath(`(${val})[${count}]`, node, docmt) === 1) {\r\n return `(${val})[${count}]`;\r\n }\r\n }\r\n\r\n const nodes = owner.evaluate(val, docmt, null, XPathResult.ANY_TYPE, null);\r\n let nodex;\r\n while ((nodex = nodes.iterateNext())) {\r\n index++;\r\n if (nodex.isSameNode(node)) {\r\n if (getCountOfXPath(`${val}[${index}]`, node, docmt) === 1) {\r\n return `${val}[${index}]`;\r\n }\r\n if (getCountOfXPath(`(${val})[${index}]`, node, docmt) === 1) {\r\n return `(${val})[${index}]`;\r\n }\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nconst deleteLineGap = (a: string): string => {\r\n a &&= a.split(\"\\n\")[0].length > 0 ? a.split(\"\\n\")[0] : a.split(\"\\n\")[1];\r\n return a;\r\n};\r\n\r\nconst deleteGarbageFromInnerText = (a: string): string => {\r\n a = deleteLineGap(a);\r\n a = a\r\n .split(/[^\\u0000-\\u00ff]/)\r\n .reduce((b, c) => {\r\n return b.length > c.length ? b : c;\r\n }, \"\")\r\n .trim();\r\n return (a = a.split(\"/\")[0].trim());\r\n};\r\n\r\nexport const replaceWhiteSpaces = (str: string): string => {\r\n if (str) {\r\n return str.replace(/\\s\\s+/g, \" \").trim();\r\n }\r\n\r\n return str;\r\n};\r\n\r\nexport const getShadowRoot = (el: HTMLElement | Element): Element | null => {\r\n if (!el || !el?.getRootNode) return null;\r\n\r\n const root = el.getRootNode() as ShadowRoot;\r\n return root && root?.host ? (root as unknown as Element) : null;\r\n};\r\n\r\nexport const checkBlockedAttributes = (\r\n attribute: {\r\n name: string;\r\n value: string;\r\n },\r\n targetElement: HTMLElement | Element,\r\n isTarget: boolean\r\n): boolean => {\r\n\r\n if (!attribute?.value || typeof attribute?.value === \"boolean\") {\r\n return false;\r\n }\r\n const blockedValues = [\"true\", \"false\", \"on\", \"off\", \"flntooltip\"];\r\n if (blockedValues.some((x) => x === attribute.value)) {\r\n return false;\r\n }\r\n const blockedNames = [\"type\", \"style\", \"locator-data-tooltip\", \"value\"];\r\n if (blockedNames.some((x) => x === attribute.name)) {\r\n return false;\r\n }\r\n\r\n const isModified = modifiedElementAttributes?.find(\r\n (x) =>\r\n x.doc === targetElement.ownerDocument &&\r\n x.element === targetElement &&\r\n x.attributeName === attribute.name\r\n );\r\n if (isModified) {\r\n return false;\r\n }\r\n\r\n if (attribute?.name?.indexOf(\"on\") === 0 && attribute?.name?.length > 3) {\r\n return false;\r\n }\r\n\r\n if (typeof attribute.value === \"function\") {\r\n return false;\r\n }\r\n\r\n if (isTarget && isNumberExist(attribute.value)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\n\r\nexport const getRelationship = (a: HTMLElement, b: HTMLElement): string => {\r\n let pos = a.compareDocumentPosition(b);\r\n return pos === 2\r\n ? \"preceding\"\r\n : pos === 4\r\n ? \"following\"\r\n : pos === 8\r\n ? \"ancestor\"\r\n : pos === 16\r\n ? \"descendant\"\r\n : pos === 32\r\n ? \"self\"\r\n : \"\";\r\n};\r\n\r\nexport const isSvg = (element: HTMLElement | Element) => {\r\n return element instanceof SVGElement;\r\n};\r\n\r\nexport const replaceTempAttributes = (str: string): string => {\r\n if (!str) return str;\r\n\r\n return str.replace(/\\b[a-zA-Z_]*disabled\\b/gi, \"disabled\");\r\n};\r\n\r\nconst getElementFromXpath = (xpath: string, docmt: Node, multi = false) => {\r\n let contextNode: Node = docmt;\r\n\r\n // XPath does NOT support DocumentFragment / ShadowRoot\r\n if (docmt.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\r\n contextNode = (docmt as ShadowRoot).host ?? docmt;\r\n }\r\n\r\n const owner =\r\n contextNode.nodeType === Node.DOCUMENT_NODE\r\n ? (contextNode as Document)\r\n : contextNode.ownerDocument!;\r\n\r\n if (multi) {\r\n return owner.evaluate(xpath, contextNode, null, XPathResult.ANY_TYPE, null);\r\n }\r\n\r\n return owner.evaluate(\r\n xpath,\r\n contextNode,\r\n null,\r\n XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n ).singleNodeValue;\r\n};\r\n\r\nexport const getPropertyXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n prop: string,\r\n value: string,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if (value) {\r\n const { tagName } = element;\r\n let count;\r\n let combinePattern = \"\";\r\n const mergePattern = [];\r\n let pattern;\r\n\r\n if (value && (!isTarget || !isNumberExist(value))) {\r\n if (!reWhiteSpace.test(value)) {\r\n pattern = buildPattern(\r\n `normalize-space(${prop})=${escapeCharacters(\r\n replaceWhiteSpaces(value)\r\n ).trim()}`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n } else {\r\n pattern = `//${tagName}[${prop}=${escapeCharacters(value)}]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n if (value && isTarget) {\r\n const splitText = value.split(\" \");\r\n if (splitText?.length) {\r\n if (splitText.length === 1) {\r\n const contentRes = [...new Set(splitText[0].match(/([^0-9]+)/g))];\r\n if (contentRes?.length >= 1) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 1\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (contentRes?.length > 1) {\r\n if (\r\n contentRes[contentRes.length - 1] &&\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1].trim())\r\n ?.length > 1\r\n ) {\r\n if (value.endsWith(contentRes[contentRes.length - 1])) {\r\n if (!reWhiteSpace.test(contentRes[contentRes.length - 1])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[contentRes.length - 1]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n } else {\r\n const endIndex =\r\n splitText.length % 2 === 0\r\n ? splitText.length / 2\r\n : splitText.length % 2;\r\n const startIndexString = splitText.slice(0, endIndex).join(\" \");\r\n let contentRes = [...new Set(startIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n const endIndexString = splitText\r\n .slice(endIndex, splitText.length - 1)\r\n .join(\" \");\r\n contentRes = [...new Set(endIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 3\r\n ) {\r\n if (value.endsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (value && isTarget && isNumberExist(value)) {\r\n const contentRes = [...new Set(value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (mergePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${mergePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tagName}[${mergePattern.join(\" and \")}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and text()]`;\r\n } else {\r\n pattern = `//${tagName}[text()]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAbsoluteXPath = (\r\n domNode: HTMLElement | Element | null,\r\n docmt: Document\r\n): string => {\r\n try {\r\n if (!domNode) {\r\n return \"\";\r\n }\r\n\r\n let xpathe = isSvg(domNode)\r\n ? `/*[local-name()='${domNode.tagName}']`\r\n : `/${domNode.tagName}`;\r\n\r\n // // If this node has siblings of the same tagName, get the index of this node\r\n if (domNode.parentElement) {\r\n // Get the siblings\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.parentElement.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n } else if (domNode instanceof HTMLElement) {\r\n if (domNode.offsetParent) {\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.offsetParent.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n }\r\n }\r\n\r\n // // Make a recursive call to this nodes parents and prepend it to this xpath\r\n return getAbsoluteXPath(domNode?.parentElement, docmt) + xpathe;\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(\"xpath\", error);\r\n\r\n return \"\";\r\n }\r\n};\r\n\r\nexport const getRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean = false,\r\n attributesArray: Attr[]\r\n) => {\r\n try {\r\n // Generate a cache key based on the node's identifier, index, and target flag\r\n // Check if the result for this node is already cached\r\n if (relativeXPathCache.has(domNode)) {\r\n return relativeXPathCache.get(domNode);\r\n }\r\n\r\n // Initialize an array to hold parts of the XPath\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n // Traverse up the DOM tree iteratively instead of using recursion\r\n while (currentNode) {\r\n let xpathe: string | undefined = \"\";\r\n let hasUniqueAttr = false;\r\n let attributes =\r\n domNode === currentNode\r\n ? (attributesArray ?? currentNode.attributes)\r\n : currentNode.attributes;\r\n\r\n // Loop through attributes to check for unique identifiers\r\n for (const attrName of Array.from(attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n // Clean up attribute value\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n\r\n const elementName = attrName.name;\r\n\r\n // Construct an XPath based on attribute\r\n xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr: number = 0;\r\n if (xpathe) {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n if (xpathe) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n // return replaceTempAttributes(xpathe);\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n } else {\r\n let combinePattern: string[] = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g))\r\n ];\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces((contentRes[i] as string).trim())\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i] as string)) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n (contentRes[i] as string).trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If no unique attribute was found, construct XPath by tag name\r\n if (!hasUniqueAttr) {\r\n let tagBasedXPath = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Handle sibling nodes\r\n if (currentNode.parentElement) {\r\n const siblings = Array.from(\r\n currentNode.parentElement.children\r\n ).filter((childNode) => childNode.tagName === currentNode.tagName);\r\n\r\n // Append index to distinguish between siblings\r\n if (siblings.length > 1) {\r\n const index = siblings.indexOf(currentNode);\r\n tagBasedXPath += `[${index + 1}]`;\r\n }\r\n }\r\n\r\n // Add the constructed tag-based XPath to the parts array\r\n xpathParts.unshift(tagBasedXPath);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move up to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXPath = `${xpathParts.join(\"\")}`;\r\n\r\n // Cache the final XPath for this node\r\n relativeXPathCache.set(domNode, finalXPath);\r\n return finalXPath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nexport const getCombinationXpath = (\r\n attribute: Attr,\r\n domNode: HTMLElement | Element\r\n) => {\r\n const combinePattern = [];\r\n let pattern: string = \"\";\r\n\r\n if (\r\n attribute &&\r\n !isNumberExist(attribute.value) &&\r\n typeof attribute.nodeValue !== \"function\" // &&\r\n // !modifiedElementAttributes?.find(\r\n // (x) => x.element === domNode && x.attributeName === attribute.name\r\n // )\r\n ) {\r\n const contentRes = [...new Set(attribute.value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 2\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n contentRes[i].trim()\r\n )})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n pattern = isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`\r\n : `//${domNode.tagName}[${combinePattern.join(\" and \")}]`;\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAttributeCombinationXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n uniqueAttributes: Attr[],\r\n isTarget: boolean\r\n): string | undefined => {\r\n try {\r\n const xpathAttributes = [];\r\n\r\n if (uniqueAttributes.length > 1) {\r\n for (const attrName of uniqueAttributes) {\r\n if (checkBlockedAttributes(attrName, domNode, isTarget)) {\r\n const attrValue = attrName.nodeValue;\r\n\r\n if (!reWhiteSpace.test(attrValue!)) {\r\n xpathAttributes.push(\r\n `normalize-space(@${attrName.nodeName})=\"${attrValue}\"`\r\n );\r\n } else if (attrName.nodeName === \"class\") {\r\n xpathAttributes.push(\r\n `contains(@${attrName.nodeName},\"${attrValue}\")`\r\n );\r\n } else {\r\n xpathAttributes.push(`@${attrName.nodeName}=\"${attrValue}\"`);\r\n }\r\n\r\n const xpathe = isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${xpathAttributes.join(\r\n \" and \"\r\n )}]`\r\n : `//${domNode.tagName}[${xpathAttributes.join(\" and \")}]`;\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, domNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n if (othersWithAttr === 1 && !xpathe.includes(\"and\")) {\r\n return \"\";\r\n }\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr === 1 && xpathe.includes(\"and\")) {\r\n return xpathe;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(`'${JSON.stringify(error, null, 2)}'`);\r\n }\r\n};\r\n\r\nexport const intermediateXpathStep = (\r\n targetElemt: HTMLElement | Element,\r\n attr: { name: string; value: string },\r\n isTarget: boolean\r\n): string => {\r\n let isSvgElement = isSvg(targetElemt);\r\n let expression: string = \"\";\r\n\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n let attrValue = attr.value;\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attr.name;\r\n\r\n if (!reWhiteSpace.test(attrValue)) {\r\n expression = isSvgElement\r\n ? `*[local-name()='${targetElemt.tagName\r\n }' and normalize-space(@${elementName})=${escapeCharacters(\r\n attrValue\r\n )}]`\r\n : `${targetElemt.tagName || \"*\"\r\n }[normalize-space(@${elementName})=${escapeCharacters(attrValue)}]`;\r\n } else {\r\n expression = isSvgElement\r\n ? `*[local-name()='${targetElemt.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${targetElemt.tagName || \"*\"}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return expression;\r\n};\r\n\r\nexport const getFilteredTextXPath = (\r\n node: HTMLElement | Element,\r\n docmt: Document\r\n): string => {\r\n if (!node.textContent) return \"\";\r\n\r\n const filteredText = getFilteredText(node);\r\n\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(filteredText)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and normalize-space(.)=${escapeCharacters(filteredText)}]`\r\n : `//${node.tagName || \"*\"}[normalize-space(.)=${escapeCharacters(\r\n filteredText\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName}' and .=${escapeCharacters(\r\n filteredText\r\n )}]`\r\n : `//${node.tagName || \"*\"}[.=${escapeCharacters(filteredText)}]`;\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const getTextXpathFunction = (\r\n domNode: HTMLElement | Element\r\n): string | undefined => {\r\n const trimmedText = getTextContent(domNode)?.trim();\r\n const filteredText = trimmedText\r\n ? escapeCharacters(deleteGarbageFromInnerText(trimmedText))\r\n : trimmedText;\r\n if (filteredText) {\r\n if (filteredText !== `'${trimmedText}'`) {\r\n return `contains(.,${filteredText})`;\r\n }\r\n return `normalize-space(.)='${trimmedText}'`;\r\n }\r\n};\r\n\r\nexport const getXpathString = (\r\n node: HTMLElement | Element,\r\n attrName: string,\r\n attrValue: string\r\n): string => {\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n let xpathe: string = \"\";\r\n\r\n if (attrValue) {\r\n if (!reWhiteSpace.test(attrValue)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else if (attrName === \"class\") {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and @${attrName}=${escapeCharacters(attrValue)}]`\r\n : `//${node.tagName || \"*\"}[@${attrName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const replaceActualAttributes = (\r\n str: string,\r\n element: { attributes: any }\r\n): string => {\r\n if (str) {\r\n return str.replace(/\\bdisabled\\b/gi, \"flndisabled\");\r\n }\r\n return str;\r\n};\r\n\r\nconst addAttributeSplitCombineXpaths = (\r\n attributes: NamedNodeMap,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n const attributesArray = Array.prototype.slice.call(attributes);\r\n const xpaths: { key: string; value: string }[] = [];\r\n try {\r\n attributesArray.map((element) => {\r\n if (checkBlockedAttributes(element, targetElemt, isTarget)) {\r\n const xpth = getCombinationXpath(element, targetElemt);\r\n if (xpth) {\r\n xpaths.push({\r\n key: `split xpath by ${element.name}`,\r\n value: xpth\r\n });\r\n }\r\n }\r\n });\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return xpaths;\r\n};\r\n\r\nexport const getReferenceElementsXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n let nodeXpath1;\r\n const xpaths1 = [];\r\n if (\r\n domNode.textContent &&\r\n (!isTarget || (isTarget && !isNumberExist(domNode.textContent)))\r\n ) {\r\n if (!reWhiteSpace.test(domNode.textContent)) {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and ${getTextXpathFunction(\r\n domNode\r\n )})]`\r\n : `${domNode.tagName}[${getTextXpathFunction(domNode)}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and .=${escapeCharacters(\r\n getTextContent(domNode)\r\n )}]`\r\n : `${domNode.tagName}[.=${escapeCharacters(getTextContent(domNode))}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n }\r\n }\r\n\r\n if (domNode.attributes) {\r\n for (const attrName of Array.from(domNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, domNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attrName.name;\r\n\r\n if (elementName === \"class\") {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName\r\n }' and contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`\r\n : `${domNode.tagName}[contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${domNode.tagName}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n\r\n if (nodeXpath1) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: nodeXpath1\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const attributesArray = Array.prototype.slice.call(domNode.attributes);\r\n if (attributesArray?.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n domNode,\r\n docmt,\r\n Array.prototype.slice.call(domNode.attributes),\r\n isTarget\r\n );\r\n if (combinationXpath) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: combinationXpath\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const combinePattern = [];\r\n let pattern;\r\n const tag = isSvg(domNode);\r\n if (domNode.textContent && isTarget && isNumberExist(domNode.textContent)) {\r\n const contentRes = [...new Set(domNode.textContent.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(contentRes[i]).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (tag) {\r\n pattern = `//*[local-name()='${tag}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tag}[${combinePattern.join(\" and \")}]`;\r\n }\r\n\r\n if (pattern)\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: pattern });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const xpaths = addAttributeSplitCombineXpaths(\r\n domNode.attributes,\r\n domNode,\r\n docmt,\r\n isTarget\r\n );\r\n if (xpaths?.length) {\r\n xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n return xpaths1;\r\n};\r\n\r\nexport const parseXml = (\r\n xmlStr: string,\r\n type: DOMParserSupportedType\r\n): Document | null => {\r\n if (window.DOMParser) {\r\n return new window.DOMParser().parseFromString(xmlStr, type);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const normalizeXPath = (xpath: string): string => {\r\n // Replace text() = \"value\" or text()='value'\r\n xpath = xpath.replace(\r\n /text\\(\\)\\s*=\\s*(['\"])(.*?)\\1/g,\r\n \"normalize-space(.)=$1$2$1\"\r\n );\r\n\r\n // Replace . = \"value\" or .='value'\r\n xpath = xpath.replace(/\\.\\s*=\\s*(['\"])(.*?)\\1/g, \"normalize-space(.)=$1$2$1\");\r\n\r\n return xpath;\r\n};\r\n\r\nexport const findMatchingParenthesis = (\r\n text: string,\r\n openPos: number\r\n): number => {\r\n let closePos = openPos;\r\n let counter = 1;\r\n while (counter > 0) {\r\n const c = text[++closePos];\r\n if (c == \"(\") {\r\n counter++;\r\n } else if (c == \")\") {\r\n counter--;\r\n }\r\n }\r\n return closePos;\r\n};\r\n\r\nexport function canonicalizeXPath(xpath: string): string {\r\n return (\r\n xpath\r\n .toLowerCase()\r\n // replace quoted values\r\n .replace(/'[^']*'/g, \"?\")\r\n .replace(/\"[^\"]*\"/g, \"?\")\r\n // replace numbers in predicates\r\n .replace(/\\[\\d+\\]/g, \"[?]\")\r\n // normalize node names\r\n .replace(/\\/\\/[a-z0-9_-]+/g, \"//node\")\r\n .replace(/\\/[a-z0-9_-]+/g, \"/node\")\r\n );\r\n}\r\n\r\nexport function extractXPathSignatureParts(xpath: string) {\r\n const xp = xpath.toLowerCase();\r\n\r\n const axisMatch = xp.match(\r\n /(ancestor-or-self|ancestor|descendant-or-self|descendant|following-sibling|preceding-sibling|following|preceding|parent|child|self)::/\r\n );\r\n const axis = axisMatch?.[1] ?? \"none\";\r\n\r\n const attrMatch = xp.match(/@([a-z0-9:-]+)/);\r\n const attribute = attrMatch?.[1] ?? \"none\";\r\n\r\n const usesNormalize = xp.includes(\"normalize-space\");\r\n\r\n return { axis, attribute, usesNormalize };\r\n}\r\n\r\nexport function getXPathPattern(xpath: string): string {\r\n const canonical = canonicalizeXPath(xpath);\r\n const parts = extractXPathSignatureParts(xpath);\r\n\r\n return [\r\n \"XPATH\",\r\n `axis:${parts.axis}`,\r\n `attr:${parts.attribute}`,\r\n `normalize:${parts.usesNormalize}`,\r\n `shape:${canonical}`\r\n ].join(\"|\");\r\n}\r\n\r\nexport function escapeAttrValue(value: string): string {\r\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\r\n}\r\n\r\nexport function isUniqueInDOM(\r\n docmt: Document,\r\n name: string,\r\n value: string\r\n): boolean {\r\n try {\r\n switch (name) {\r\n case \"id\":\r\n return (\r\n docmt.getElementById(value) !== null &&\r\n docmt.querySelectorAll(`#${value}`).length === 1\r\n );\r\n\r\n case \"name\":\r\n return (\r\n docmt.querySelectorAll(`[name=\"${escapeAttrValue(value)}\"]`)\r\n .length === 1\r\n );\r\n\r\n case \"className\":\r\n return docmt.getElementsByClassName(value).length === 1;\r\n\r\n case \"tagName\":\r\n return docmt.getElementsByTagName(value).length === 1;\r\n\r\n case \"linkText\":\r\n return (\r\n Array.from(docmt.querySelectorAll(\"a\")).filter(\r\n (a) => a.textContent?.trim() === value\r\n ).length === 1\r\n );\r\n case \"partialLinkText\":\r\n return (\r\n Array.from(docmt.querySelectorAll(\"a\")).filter((a) =>\r\n a.textContent?.includes(value)\r\n ).length === 1\r\n );\r\n default:\r\n return false;\r\n }\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport const xpathUtils = {\r\n parseXml,\r\n getReferenceElementsXpath,\r\n getAbsoluteXPath,\r\n getRelativeXPath,\r\n getCombinationXpath,\r\n getAttributeCombinationXpath,\r\n getElementFromXpath,\r\n isSvg,\r\n findXpathWithIndex,\r\n isNumberExist,\r\n getTextContent,\r\n getCountOfXPath,\r\n normalizeXPath,\r\n getShadowRoot,\r\n escapeCharacters,\r\n removeParenthesis,\r\n checkBlockedAttributes,\r\n getRelationship,\r\n findMatchingParenthesis,\r\n deleteGarbageFromInnerText,\r\n replaceTempAttributes,\r\n createObserver,\r\n startObserver,\r\n stopObserver,\r\n modifiedElementAttributes,\r\n cspEnabled,\r\n getXPathPattern,\r\n escapeAttrValue,\r\n isUniqueInDOM\r\n};\r\n","import {\r\n isNumberExist,\r\n getCountOfXPath,\r\n escapeCharacters,\r\n checkBlockedAttributes,\r\n replaceWhiteSpaces,\r\n getTextContent,\r\n getPropertyXPath,\r\n findXpathWithIndex,\r\n getFilteredText,\r\n intermediateXpathStep,\r\n getAttributeCombinationXpath,\r\n getFilteredTextXPath,\r\n isSvg,\r\n getXpathString,\r\n reWhiteSpace,\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathData: { key: string; value: string }[] = [];\r\nlet xpathDataWithIndex: { key: string; value: string; count: number }[] = [];\r\nlet referenceElementMode: boolean = false;\r\nlet xpathCache = new Map();\r\nlet cache = new Map();\r\n\r\nconst parentXpathCache = new Map(); // Cache for parent XPaths\r\n\r\nconst checkRelativeXpathRelation = (\r\n nodeXpath1: string,\r\n nodeXpath2: string,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n relationType: string\r\n) => {\r\n if (nodeXpath1 && !referenceElementMode) {\r\n let xpaths;\r\n\r\n if (relationType === \"parent\") {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/descendant-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/following::${nodeXpath2}`,\r\n ];\r\n } else {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/ancestor-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/preceding::${nodeXpath2}`,\r\n ];\r\n }\r\n\r\n // Iterate through XPath patterns\r\n for (const xpath of xpaths) {\r\n // Check if result is already cached to avoid recomputation\r\n if (!xpathCache?.get(xpath)) {\r\n // Compute and store result in cache\r\n xpathCache.set(xpath, getCountOfXPath(xpath, targetElemt, docmt));\r\n }\r\n\r\n const count = xpathCache?.get(xpath);\r\n\r\n // Short-circuit: Return the first valid XPath result found\r\n if (count === 1) {\r\n return xpath;\r\n }\r\n if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count,\r\n });\r\n }\r\n }\r\n\r\n if (count > 1 && isIndex && !xpathData.length) {\r\n // Try finding XPath with index if count is greater than 1\r\n const indexedXpath = findXpathWithIndex(\r\n xpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n\r\n // Cache the indexed XPath result\r\n if (\r\n indexedXpath &&\r\n getCountOfXPath(indexedXpath, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: indexedXpath,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nconst getUniqueParentXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean,\r\n nodeXpath: string,\r\n isIndex: boolean\r\n) => {\r\n try {\r\n if (parentXpathCache.has(domNode)) {\r\n return parentXpathCache.get(domNode);\r\n }\r\n\r\n // Direct XPath construction without loops\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n while (currentNode && currentNode.nodeType === 1) {\r\n const hasUniqueAttr = false;\r\n for (const attrName of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attrName.name;\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent && !currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${\r\n currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n } else {\r\n const combinePattern = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g)),\r\n ];\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (contentRes[i] && replaceWhiteSpaces(contentRes[i].trim())) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n const xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Construct the XPath based on the tag name\r\n if (!hasUniqueAttr) {\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Final constructed XPath\r\n const finalXPath = xpathParts.join(\"\") + nodeXpath;\r\n let count = getCountOfXPath(finalXPath, domNode, docmt);\r\n if (count === 1) {\r\n parentXpathCache.set(domNode, finalXPath); // Cache final result\r\n return finalXPath;\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getParentRelativeXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean\r\n) => {\r\n const cache = new Map(); // Cache to store computed results\r\n\r\n if (cache.has(domNode)) {\r\n return cache.get(domNode); // Return cached result if available\r\n }\r\n\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath\r\n let currentNode = domNode; // Start with the provided DOM node\r\n\r\n try {\r\n while (currentNode && currentNode.nodeType === 1) {\r\n // BASE CASE #1: If this isn't an element, we're above the root, return empty string\r\n if (!currentNode.tagName) {\r\n return \"\";\r\n }\r\n\r\n // BASE CASE #2: Check for unique attributes\r\n let uniqueAttrFound = false;\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, isTarget)) {\r\n let attrValue = attr.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(xpathe);\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(textXPath, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.unshift(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getChildRelativeXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n node: HTMLElement | Element\r\n) => {\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath.\r\n let currentNode: HTMLElement | Element | null;\r\n\r\n const st = [];\r\n if (\r\n domNode.firstElementChild != null &&\r\n domNode.firstElementChild.classList.contains(\"flntooltip\")\r\n ) {\r\n st.unshift(domNode.firstElementChild);\r\n } else if (domNode.nextElementSibling != null)\r\n st.unshift(domNode.nextElementSibling);\r\n\r\n for (\r\n let m = domNode.parentElement;\r\n m != null && m.nodeType === 1;\r\n m = m.parentElement\r\n ) {\r\n if (m.nextElementSibling) st.unshift(m.nextElementSibling);\r\n }\r\n\r\n try {\r\n do {\r\n let uniqueAttrFound = false;\r\n for (currentNode = st.pop()!; currentNode !== null; ) {\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, true)) {\r\n let attrValue = attr.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(xpathe);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(\r\n textXPath,\r\n currentNode,\r\n docmt\r\n );\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.push(xpathe);\r\n\r\n if (currentNode.firstElementChild != null) {\r\n st.push(currentNode.nextElementSibling);\r\n currentNode = currentNode.firstElementChild;\r\n } else {\r\n currentNode = currentNode.nextElementSibling;\r\n }\r\n } else {\r\n break;\r\n }\r\n }\r\n } while (st.length > 0);\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getSiblingRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n nodeXpath: string\r\n) => {\r\n try {\r\n const markedSpan = document.querySelector(\".flntooltip\");\r\n\r\n for (\r\n let m = domNode.nextElementSibling;\r\n m !== null && m !== markedSpan;\r\n m = m.nextElementSibling\r\n ) {\r\n processSibling(\r\n m,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"preceding-sibling\",\r\n isTarget\r\n );\r\n }\r\n\r\n for (\r\n let n = domNode.previousElementSibling;\r\n n !== null && n !== markedSpan;\r\n n = n.previousElementSibling\r\n ) {\r\n processSibling(\r\n n,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"following-sibling\",\r\n isTarget\r\n );\r\n }\r\n } catch (error) {\r\n console.error(\"sibling error\", error);\r\n return null;\r\n }\r\n};\r\n\r\nconst processSibling = (\r\n sibling: Element,\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n nodeXpath: string,\r\n axis: string,\r\n isTarget: boolean\r\n) => {\r\n try {\r\n if (sibling.hasAttributes()) {\r\n for (const attr of Array.from(sibling.attributes)) {\r\n let xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: attr.name,\r\n value: attr.value,\r\n },\r\n isTarget\r\n );\r\n if (xpathe) {\r\n xpathe += `/${axis}::${nodeXpath}`;\r\n\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe,\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!isTarget) {\r\n let xpathe;\r\n xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: \"text\",\r\n value: sibling.textContent,\r\n },\r\n isTarget\r\n );\r\n\r\n if (xpathe) {\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe,\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(`${axis} xpath-error`, error);\r\n }\r\n};\r\n\r\nfunction getXPathUsingAttributeAndText(\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n) {\r\n const { tagName } = targetElemt;\r\n const textContent = targetElemt.textContent.trim();\r\n for (const attrName of attributes) {\r\n if (checkBlockedAttributes(attrName, targetElemt, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attrName.name;\r\n const xpath = `//${tagName}[@${elementName}='${attrValue}' and text()='${textContent}']`;\r\n if (xpath) {\r\n const count = getCountOfXPath(xpath, targetElemt, docmt);\r\n if (count == 1) {\r\n return xpath;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nconst addRelativeXpaths = (\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n attribute: Attr[]\r\n) => {\r\n try {\r\n let nodeXpath: string[] = [];\r\n let relativeXpath, relativeChildXpath;\r\n xpathData = [];\r\n\r\n console.log(attribute);\r\n if (attribute) {\r\n for (const attrName of attribute) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: attrName.name,\r\n value: attrName.value,\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n }\r\n\r\n if (targetElemt.textContent) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: \"text\",\r\n value: targetElemt.textContent,\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n\r\n nodeXpath.push(targetElemt.tagName);\r\n\r\n if (nodeXpath?.length) {\r\n for (let i = 0; i < nodeXpath.length; i++) {\r\n if (!xpathData.length) {\r\n getSiblingRelativeXPath(targetElemt, docmt, isTarget, nodeXpath[i]);\r\n\r\n if (!xpathData.length) {\r\n if (!relativeXpath) {\r\n relativeXpath = getParentRelativeXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget\r\n );\r\n }\r\n\r\n console.log(relativeXpath);\r\n\r\n if (\r\n relativeXpath &&\r\n (relativeXpath.includes(\"@\") ||\r\n relativeXpath.includes(\"text()\") ||\r\n relativeXpath.includes(\".=\")) &&\r\n relativeXpath.match(/\\//g)?.length - 2 < 5\r\n ) {\r\n const fullRelativeXpath = relativeXpath + `/${nodeXpath[i]}`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative parent\",\r\n value: fullRelativeXpath,\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n if (!relativeChildXpath) {\r\n relativeChildXpath = getChildRelativeXpath(\r\n targetElemt,\r\n docmt,\r\n targetElemt\r\n );\r\n }\r\n\r\n if (\r\n relativeChildXpath &&\r\n (relativeChildXpath.includes(\"@\") ||\r\n relativeChildXpath.includes(\"text()\") ||\r\n relativeChildXpath.includes(\".=\"))\r\n ) {\r\n const fullRelativeXpath = `/${\r\n nodeXpath[i] + relativeChildXpath.substring(1)\r\n }`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative child\",\r\n value: fullRelativeXpath,\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (\r\n xpathData?.length === 1 &&\r\n xpathData?.[0]?.value?.match(/\\[([0-9]+)\\]/gm)?.length! > 3 &&\r\n !referenceElementMode\r\n ) {\r\n if (targetElemt.textContent) {\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, false);\r\n if (txtXpath) {\r\n xpathData.unshift({\r\n key: `xpath by text${isIndex ? \"index\" : \"\"}`,\r\n value: txtXpath,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n let tempRelativeXpath = getUniqueParentXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget,\r\n nodeXpath[i],\r\n isIndex\r\n );\r\n\r\n if (tempRelativeXpath) {\r\n xpathData.push({\r\n key: \"xpath by unique parent\",\r\n value: tempRelativeXpath,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return xpathData;\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const attributesBasedXPath = (\r\n attr: Attr,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let attrName;\r\n\r\n attrName = attr.name;\r\n let xpath = getPropertyXPath(\r\n targetElemt,\r\n docmt,\r\n `@${attrName}`,\r\n attr.value,\r\n isIndex,\r\n isTarget\r\n );\r\n\r\n return xpath;\r\n};\r\n\r\nexport const getUniqueClassName = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let value = element.className;\r\n if (typeof value !== \"string\") {\r\n value = \"\";\r\n }\r\n value = value?.replace(\"flndisabled\", \"disabled\");\r\n value = value?.replace(\"removePointers\", \"\");\r\n value = value?.trim();\r\n\r\n if (value) {\r\n return getPropertyXPath(element, docmt, `@class`, value, isIndex, isTarget);\r\n }\r\n};\r\n\r\nexport const getTextXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if (element.textContent != \"\") {\r\n const text = getTextContent(element);\r\n\r\n if (text) {\r\n return getPropertyXPath(element, docmt, \".\", text, isIndex, isTarget);\r\n }\r\n }\r\n};\r\n\r\nconst addAllXPathAttributes = (\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n const attributesArray = attributes;\r\n try {\r\n attributesArray.map((attr) => {\r\n if (!(attr.name === \"className\" || attr.name === \"class\")) {\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n const xpth = attributesBasedXPath(\r\n attr,\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget\r\n );\r\n if (xpth) {\r\n xpathData.push({\r\n key: `xpath by ${attr.name}${isIndex ? \" index\" : \"\"}`,\r\n value: xpth,\r\n });\r\n }\r\n }\r\n }\r\n });\r\n\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, isTarget);\r\n if (txtXpath) {\r\n xpathData.push({\r\n key: `xpath by text${isIndex ? \" index\" : \"\"}`,\r\n value: txtXpath,\r\n });\r\n }\r\n\r\n if (\r\n attributesArray.find((element) => element.name === \"className\") &&\r\n checkBlockedAttributes(\r\n attributesArray?.find((element) => element.name === \"className\")!,\r\n targetElemt,\r\n isTarget\r\n )\r\n ) {\r\n let xpath = getUniqueClassName(targetElemt, docmt, isIndex, isTarget);\r\n if (xpath) {\r\n xpathData.push({\r\n key: \"xpath by class\",\r\n value: xpath,\r\n });\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n const textAttribute = getXPathUsingAttributeAndText(\r\n attributes,\r\n targetElemt,\r\n docmt,\r\n isTarget\r\n );\r\n if (textAttribute)\r\n xpathData.push({\r\n key: \"xpath by textAttribute\",\r\n value: textAttribute,\r\n });\r\n }\r\n\r\n if (!xpathData.length && attributesArray.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n targetElemt,\r\n docmt,\r\n attributesArray,\r\n isTarget\r\n );\r\n if (combinationXpath)\r\n xpathData.push({\r\n key: \"xpath by combination\",\r\n value: combinationXpath,\r\n });\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const parseDOM = (\r\n element: HTMLElement | Element,\r\n doc: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n includedAttributes: Attr[] = []\r\n) => {\r\n xpathData = [];\r\n console.log(element);\r\n const targetElemt = element;\r\n const docmt = targetElemt?.ownerDocument || doc;\r\n const tag = targetElemt.tagName;\r\n const { attributes } = targetElemt;\r\n const attributesToUse =\r\n includedAttributes.length > 0 ? includedAttributes : Array.from(attributes);\r\n addAllXPathAttributes(\r\n attributesToUse,\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget\r\n );\r\n if (!referenceElementMode) {\r\n if (xpathData.length) {\r\n const len = xpathData.length;\r\n for (let i = 0; i < len; i++) {\r\n let xpth = xpathData[i].value;\r\n xpth = \"//*\" + xpth.substring(xpth.indexOf(\"//\") + 2 + tag.length);\r\n const count = getCountOfXPath(xpth, element, docmt);\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `${xpathData[i].key} regex`,\r\n value: xpth,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n addRelativeXpaths(\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget,\r\n Array.from(targetElemt.attributes)\r\n );\r\n }\r\n\r\n return xpathData;\r\n};\r\n\r\nconst xpath = {\r\n parseDOM,\r\n getTextXPath,\r\n getUniqueClassName,\r\n attributesBasedXPath,\r\n addAllXPathAttributes,\r\n addRelativeXpaths,\r\n getXPathUsingAttributeAndText,\r\n getSiblingRelativeXPath,\r\n getChildRelativeXpath,\r\n getParentRelativeXpath,\r\n getUniqueParentXpath,\r\n checkRelativeXpathRelation,\r\n};\r\n\r\nexport default xpath;\r\n","import { parseDOM } from \"./xpath.ts\";\r\nimport {\r\n findXpathWithIndex,\r\n getShadowRoot,\r\n getTextContent,\r\n escapeCharacters,\r\n getCountOfXPath,\r\n checkBlockedAttributes,\r\n getAbsoluteXPath,\r\n isSvg,\r\n getCombinationXpath,\r\n getTextXpathFunction,\r\n replaceTempAttributes,\r\n replaceActualAttributes,\r\n getReferenceElementsXpath,\r\n getRelativeXPath,\r\n findMatchingParenthesis,\r\n removeParenthesis\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathDataWithIndex: any[] = [];\r\nlet xpathData: { key: string; value: string }[] = [];\r\nconst reWhiteSpace = /^[\\S]+( [\\S]+)*$/gi;\r\n\r\nexport const findRelativeXpath = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n docmt: Document,\r\n xpaths1: any[],\r\n xpaths2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n // debugger;\r\n const par1 = element1.parentElement;\r\n const par2 = element2.parentElement;\r\n let rel_xpath: any[] = [];\r\n\r\n let tempElement;\r\n let finalXpaths: any[] = [];\r\n\r\n if (isIndex) {\r\n if (xpathDataWithIndex.length) {\r\n const xpathWithIndex = findXpathWithIndex(\r\n xpathDataWithIndex[0].value,\r\n element2,\r\n element2.ownerDocument,\r\n xpathDataWithIndex[0].count\r\n );\r\n if (xpathWithIndex) {\r\n finalXpaths = finalXpaths.concat({\r\n key: `${xpathDataWithIndex[0]?.key\r\n ? xpathDataWithIndex[0]?.key\r\n : \"xpath with \"\r\n } index`,\r\n value: xpathWithIndex,\r\n });\r\n xpathDataWithIndex.pop();\r\n }\r\n }\r\n }\r\n\r\n if (!finalXpaths.length) {\r\n // both are same\r\n if (element1.isSameNode(element2)) {\r\n // rel_xpath = xpath1 + \"/self::\" + element1.tagName;\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"self\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n // parent\r\n tempElement = element1.parentElement;\r\n\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"parent\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n // ancestor\r\n tempElement = element1.parentElement;\r\n\r\n while (tempElement !== null) {\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"ancestor\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n\r\n tempElement = tempElement.parentNode;\r\n }\r\n\r\n // ancestor-or-self\r\n tempElement = element1;\r\n do {\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"ancestor-or-self\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n\r\n tempElement = tempElement.parentNode;\r\n } while (tempElement !== null);\r\n\r\n // both has same parent\r\n if (par1?.isSameNode(par2)) {\r\n for (\r\n let m = element1.nextElementSibling;\r\n m != null;\r\n m = m.nextElementSibling\r\n ) {\r\n if (m != null && m.isSameNode(element2)) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"following-sibling\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n for (\r\n let n = element1.previousElementSibling;\r\n n != null;\r\n n = n.previousElementSibling\r\n ) {\r\n if (n != null && n.isSameNode(element2)) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"preceding-sibling\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // child\r\n if (element1?.children?.length) {\r\n for (let m = element1.children[0]; m !== null; m = m?.nextElementSibling!) {\r\n if (m === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"child\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // following\r\n const relation = element1.compareDocumentPosition(element2);\r\n if (relation === 2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"preceding\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n }\r\n\r\n if (relation === 4) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"following\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n }\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n const descendantXpath = getDescendantXpath(\r\n [element1, element2],\r\n docmt,\r\n xpaths1,\r\n xpaths2,\r\n \"descendant\",\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (descendantXpath) finalXpaths = finalXpaths.concat(descendantXpath);\r\n\r\n const descendantSelfXpath = getDescendantXpath(\r\n [element1, element2],\r\n docmt,\r\n xpaths1,\r\n xpaths2,\r\n \"descendant-or-self\",\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (descendantSelfXpath) {\r\n finalXpaths = finalXpaths.concat(descendantSelfXpath);\r\n }\r\n }\r\n\r\n if (finalXpaths.length) {\r\n if (finalXpaths.length > 1) {\r\n finalXpaths.sort(function (a, b) {\r\n return a.value.length - b.value.length;\r\n });\r\n }\r\n\r\n if (finalXpaths.filter((x) => !x.key?.includes(\"index\"))?.length) {\r\n return [finalXpaths.filter((x) => !x.key?.includes(\"index\"))[0]];\r\n }\r\n return [finalXpaths[0]];\r\n }\r\n};\r\n\r\nconst descendantExpression = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n xpath2: string,\r\n relation: string,\r\n docmt: Node,\r\n isIndex: any,\r\n expCommonParentXpathElements: string | any[],\r\n step4: string,\r\n refCommonParentXpathElementLength: number = 0,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n let finalExpectedElementXpath: string | undefined = \"\";\r\n\r\n if (\r\n xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g)?.length >=\r\n expCommonParentXpathElements.length\r\n ) {\r\n const xpaths2Els: string[] = [];\r\n const xpath2Elements = xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g);\r\n for (let x = 1; x <= expCommonParentXpathElements.length; x++) {\r\n xpaths2Els.unshift(\r\n x === expCommonParentXpathElements.length\r\n ? expCommonParentXpathElements[\r\n expCommonParentXpathElements.length - x\r\n ]\r\n : xpath2Elements[xpath2Elements.length - x]\r\n );\r\n }\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n xpaths2Els,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n } else {\r\n finalExpectedElementXpath = `//${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n refExpectElement[refExpectElement.length - 1]\r\n )}`;\r\n let rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation} ${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst getDescendantXpath = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Document,\r\n xpaths1: { key: string; value: string }[],\r\n xpaths2: { key: string; value: string }[],\r\n relation: \"descendant\" | \"descendant-or-self\",\r\n isIndex: boolean = false,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n const refElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 2];\r\n const expElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 1];\r\n const expElementDocmnt = getShadowRoot(expElement) ?? expElement.ownerDocument;\r\n\r\n const refAbsoluteXpath =\r\n xpaths1.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(refElement, refElement.ownerDocument);\r\n\r\n const refFullXpathElements: any[] = [];\r\n const refFullXpathElementsWithoutNumber: any[] = [];\r\n refAbsoluteXpath.split(\"/\").map((x) => refFullXpathElements.push(x));\r\n refFullXpathElements.map((x) =>\r\n refFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n const expAbsoluteXpath =\r\n xpaths2.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(expElement, expElement.ownerDocument);\r\n\r\n const expFullXpathElements: any[] = [];\r\n const expFullXpathElementsWithoutNumber: any[] = [];\r\n expAbsoluteXpath.split(\"/\").map((x) => expFullXpathElements.push(x));\r\n expFullXpathElements.map((x) =>\r\n expFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n for (\r\n var parentElementNumber = 0;\r\n parentElementNumber < refFullXpathElements.length;\r\n parentElementNumber++\r\n ) {\r\n if (\r\n refFullXpathElements[parentElementNumber] !=\r\n expFullXpathElements[parentElementNumber]\r\n ) {\r\n break;\r\n }\r\n }\r\n\r\n const refCommonParentXpathElements = [];\r\n for (let i = parentElementNumber - 1; i < refFullXpathElements.length; i++) {\r\n if (refFullXpathElements[i]) {\r\n refCommonParentXpathElements.push(refFullXpathElementsWithoutNumber[i]);\r\n }\r\n }\r\n\r\n const expCommonParentXpathElements: string[] = [];\r\n for (\r\n let j =\r\n relation === \"descendant\" ? parentElementNumber : parentElementNumber - 1;\r\n j < expFullXpathElements.length;\r\n j++\r\n ) {\r\n if (expFullXpathElements[j]) {\r\n if (expCommonParentXpathElements.length)\r\n expCommonParentXpathElements.push(expFullXpathElementsWithoutNumber[j]);\r\n else\r\n expCommonParentXpathElements.push(\r\n expFullXpathElementsWithoutNumber[j].replace(/\\[([0-9]+)\\]/gm, \"\")\r\n );\r\n }\r\n }\r\n\r\n xpathData = xpaths2;\r\n\r\n let nodeXpath2;\r\n if (refExpectElement[refExpectElement.length - 2].textContent) {\r\n if (\r\n !reWhiteSpace.test(\r\n refExpectElement[refExpectElement.length - 2].textContent\r\n )\r\n ) {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and ${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )})]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )}]`;\r\n } else {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and .=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[.=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`;\r\n }\r\n\r\n refCommonParentXpathElements[refCommonParentXpathElements.length - 1] =\r\n nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n if (xpath2) {\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (refExpectElement[refExpectElement.length - 2].attributes) {\r\n for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]\r\n .attributes)) {\r\n if (\r\n checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attrName.name;\r\n\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[@${elementName}=${escapeCharacters(attrValue)}]`;\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]\r\n .attributes)) {\r\n if (\r\n checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const combinationXpath = getCombinationXpath(\r\n attrName,\r\n refExpectElement[refExpectElement.length - 2]\r\n );\r\n if (combinationXpath) {\r\n if (combinationXpath.startsWith(\"//\")) {\r\n nodeXpath2 = combinationXpath.substring(\r\n combinationXpath.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n nodeXpath2 = combinationXpath; // No need to modify the value\r\n }\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n const step4 = refCommonParentXpath;\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n expCommonParentXpathElements,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n};\r\n\r\nconst getXpathRelationExpression = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n relation: string,\r\n xpath1: any[],\r\n xpath2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let xpaths1;\r\n let xpaths2;\r\n console.log('getXpathRelationExpression', relation)\r\n const finalXpaths: { key: string; value: any }[] = [];\r\n\r\n try {\r\n xpaths1 = xpath1.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n xpaths2 = xpath2.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n let rel_xpath: string | undefined = `//${xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(xpaths1[i].value.indexOf(\"//\") + 2),\r\n element1\r\n )\r\n }/${relation}::${xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths2[j].value, element2)\r\n : replaceActualAttributes(\r\n xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2),\r\n element2\r\n )\r\n }`;\r\n console.log('getXpathRelationExpression', rel_xpath)\r\n const rel_count = getCountOfXPath(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument\r\n );\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n rel_xpath = findXpathWithIndex(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument,\r\n rel_count\r\n );\r\n if (rel_xpath) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(rel_xpath),\r\n });\r\n return finalXpaths;\r\n }\r\n } else if (rel_count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (rel_count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count,\r\n });\r\n }\r\n }\r\n } else if (rel_count === 1) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(rel_xpath),\r\n });\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n if (!finalXpaths.length) {\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n const tempPath = `${xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? xpaths2[j].value\r\n : xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2)\r\n }`;\r\n const xpath2Elements: string[] = tempPath.split(\r\n /\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g\r\n );\r\n if (xpath2Elements.length > 1) {\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(\r\n xpaths1[i].value.indexOf(\"//\") + 2\r\n ),\r\n element1\r\n )\r\n }`,\r\n xpath2Elements,\r\n element2,\r\n [element1, element2],\r\n element2.ownerDocument,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n\r\n console.log('getXpathRelationExpression traverseXpath', traverseXpath)\r\n if (traverseXpath) {\r\n finalXpaths.concat(traverseXpath);\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return finalXpaths;\r\n};\r\n\r\nconst getReferenceElementXpath = (element: HTMLElement | Element) => {\r\n let xpaths1: {\r\n key: string;\r\n value: string;\r\n }[] = [];\r\n\r\n xpaths1 = parseDOM(element, element.ownerDocument, false, false);\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = parseDOM(element, element.ownerDocument, true, false);\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n } else {\r\n let xpaths = parseDOM(element, element.ownerDocument, true, false);\r\n if (xpaths?.length) {\r\n xpaths = xpaths?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(element, element.ownerDocument, false, false, Array.from(element.attributes)),\r\n },\r\n ];\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(element, element.ownerDocument, true, false, Array.from(element.attributes)),\r\n },\r\n ];\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = getReferenceElementsXpath(element, element.ownerDocument, false);\r\n } else {\r\n const xpaths = getReferenceElementsXpath(\r\n element,\r\n element.ownerDocument,\r\n false\r\n );\r\n if (xpaths?.length) {\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n const referenceXpathElement = getAbsoluteXPath(\r\n element,\r\n element.ownerDocument\r\n );\r\n xpaths1 = xpaths1.filter((x) => x.value !== referenceXpathElement);\r\n\r\n xpaths1.push({\r\n key: \"absolute xpath\",\r\n value: referenceXpathElement.slice(1),\r\n });\r\n\r\n return xpaths1;\r\n};\r\n\r\nconst getTraverseXpathExpression = (\r\n xpathe1: string,\r\n absoluteXpathElements: string[],\r\n element2: HTMLElement | Element,\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Node,\r\n relation: string,\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let finalExpectedElementXpath: string | undefined;\r\n if (!multiElementReferenceMode) {\r\n for (let x = 1; x <= absoluteXpathElements.length; x++) {\r\n const xpath2 = absoluteXpathElements\r\n .slice(absoluteXpathElements.length - x, absoluteXpathElements.length)\r\n .join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n const xpath2 = absoluteXpathElements.join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst referenceXpath = {\r\n findRelativeXpath,\r\n getDescendantXpath,\r\n getXpathRelationExpression,\r\n getTraverseXpathExpression,\r\n getReferenceElementXpath,\r\n};\r\n\r\nexport default referenceXpath;\r\n","import { ElementRecord, Locator } from \"../types/locator.ts\";\r\nimport { parseDOM } from \"./xpath.ts\";\r\nimport {\r\n isNumberExist,\r\n normalizeXPath,\r\n getXPathPattern,\r\n escapeAttrValue,\r\n isUniqueInDOM\r\n} from \"./xpathHelpers.ts\";\r\n\r\nconst isSameXPathStillValid = (\r\n xpath: string,\r\n docmt: Document,\r\n target: Element\r\n): boolean => {\r\n const found = getElementFromXPath(docmt, normalizeXPath(xpath));\r\n return found === target;\r\n};\r\n\r\nconst resolveIsSelfHealed = (\r\n locName: string,\r\n oldValue: string | null | undefined,\r\n newValue: string | null | undefined\r\n): \"Y\" | null => {\r\n if (!oldValue || !newValue) return \"Y\";\r\n return oldValue === newValue ? null : \"Y\";\r\n};\r\n\r\ntype ElementDetails = {\r\n id?: string | null;\r\n className?: string | null;\r\n xpathByText?: string | null;\r\n xpathById?: string | null;\r\n xpathByClass?: string | null;\r\n xpathAbsolute?: string | null;\r\n xpathByName?: string | null;\r\n xpathByPlaceholder?: string | null;\r\n xpathByType?: string | null;\r\n visibleText?: string | null;\r\n relativeXpath?: string | null;\r\n [key: string]: any;\r\n};\r\n\r\nconst getElementFromShadowRoot = (\r\n el: Element | ShadowRoot,\r\n selector: string\r\n): Element | null => {\r\n // const shadowRoot = (element as HTMLElement).shadowRoot;\r\n // if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n // return shadowRoot.querySelector(selector);\r\n // }\r\n\r\n const elements = Array.from(el.querySelectorAll(\"*\"));\r\n\r\n try {\r\n for (let i = 0; i < elements.length; i++) {\r\n if (elements[i].shadowRoot) {\r\n const { shadowRoot } = elements[i];\r\n if (shadowRoot) {\r\n getElementFromShadowRoot(shadowRoot, selector);\r\n if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n return shadowRoot.querySelector(selector);\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n return null;\r\n};\r\n\r\nconst getId = (element: Element | null): string | null => {\r\n return element?.id || null;\r\n};\r\n\r\nconst getClassName = (element: Element): string | null => {\r\n return (element as HTMLElement).className || null;\r\n};\r\n\r\nconst getVisibleText = (element: Element): string | null => {\r\n return element.textContent?.trim() || null;\r\n};\r\n\r\nconst getName = (element: Element): string | null => {\r\n const elementEl = element as HTMLElement;\r\n\r\n if (elementEl.hasAttribute(\"name\")) {\r\n const attrValue = elementEl.getAttribute(\"name\");\r\n const name = `${attrValue}`;\r\n return name || null;\r\n }\r\n return null;\r\n};\r\n\r\nconst relations: string[] = [\r\n \"/preceding-sibling\",\r\n \"/following-sibling\",\r\n \"/parent\",\r\n \"/descendant\",\r\n \"/ancestor\",\r\n \"/self\",\r\n \"/ancestor-or-self\",\r\n \"/child\",\r\n \"/preceding\",\r\n \"/following\"\r\n];\r\n\r\nfunction getElementFromXPath(docmt: Document, xpath: string): Element | null {\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n xpath,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n return xpathResult.singleNodeValue as Element | null;\r\n}\r\n\r\nfunction checkReferenceElementIsValid(\r\n locator: string,\r\n relation: string,\r\n docmt: Document\r\n): string | null {\r\n if (locator.includes(relation)) {\r\n const locatotSplitArray: string[] = locator.split(relation);\r\n const sourceLoc = locatotSplitArray[0].trim();\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n if (!locator.includes(\"dynamic\")) {\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n sourceLoc,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n\r\n const sourceElement = xpathResult.singleNodeValue;\r\n if (sourceElement) {\r\n const xpathResultComplete = xpathEvaluator.evaluate(\r\n locator,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n const completeElement = xpathResultComplete.singleNodeValue;\r\n let relativeXpath: string;\r\n if (completeElement) {\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n } else {\r\n console.error(\"Complete Locator is Invalid:\", locator);\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n }\r\n } else {\r\n console.error(\"Source Locator Not Found:\", sourceLoc);\r\n }\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nconst getElementsFromHTML = (\r\n record: ElementRecord,\r\n docmt: Document\r\n): ElementDetails | null => {\r\n const elementsToRemove = docmt.querySelectorAll(\r\n \"script, style, link[rel='stylesheet'], meta, noscript, embed, object, param, source, svg\"\r\n );\r\n\r\n if (elementsToRemove) {\r\n elementsToRemove.forEach((tag) => {\r\n (tag as Element).remove();\r\n });\r\n }\r\n\r\n const finalLocatorsSet: Set<string> = new Set();\r\n let finalLocators: any[] = [];\r\n\r\n function createLocator(base: any, overrides: Partial<any> = {}) {\r\n const oldValue = base?.value;\r\n const newValue = overrides.value ?? base?.value;\r\n const newLocator: any = {\r\n name: overrides.name ?? base?.name,\r\n type: overrides.type ?? base?.type,\r\n value: overrides.value ?? base?.value,\r\n reference: overrides.reference ?? base?.reference,\r\n status: overrides.status ?? base?.status,\r\n isRecorded: overrides.isRecorded ?? base?.isRecorded\r\n };\r\n\r\n const previousSelfHealed = base?.isSelfHealed === \"Y\";\r\n\r\n newLocator.isSelfHealed = previousSelfHealed\r\n ? \"Y\"\r\n : overrides.hasOwnProperty(\"isSelfHealed\")\r\n ? overrides.isSelfHealed\r\n : resolveIsSelfHealed(newLocator.name, oldValue, newValue);\r\n\r\n pushUniqueLocator(newLocator);\r\n }\r\n\r\n function pushUniqueLocator(obj: any) {\r\n const key = `${obj.name}:${obj.value}`;\r\n if (!finalLocatorsSet.has(key)) {\r\n finalLocatorsSet.add(key);\r\n finalLocators.push(obj);\r\n }\r\n }\r\n\r\n /** Locator Value Cleaner (Handles Special Scenarios) **/\r\n const cleanLocatorValue = (\r\n val: string | null | undefined,\r\n type?: string,\r\n isRecorded?: string\r\n ): string | null => {\r\n if (!val) return null;\r\n\r\n let cleaned = val.trim();\r\n\r\n // Return null for empty or literal \"null\"\r\n if (!cleaned || cleaned.toLowerCase() === \"null\") return null;\r\n\r\n // Unescape any escaped quotes\r\n cleaned = cleaned.replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\");\r\n\r\n // Remove surrounding single or double quotes\r\n cleaned = cleaned.replace(/^['\"](.+?)['\"]$/, \"$1\");\r\n\r\n // Replace double single quotes with a single quote inside XPath\r\n cleaned = cleaned.replace(/''/g, \"'\");\r\n\r\n // Normalize double quotes in XPath attribute selectors [@id=\"\" -> [@id='']\r\n cleaned = cleaned.replace(\r\n /\\[@(id|name)=['\"]{2}(.+?)['\"]{2}\\]/g,\r\n \"[@$1='$2']\"\r\n );\r\n\r\n // For DOM selectors (id or name), remove ALL quotes\r\n if (type === \"id\" || type === \"name\") {\r\n cleaned = cleaned.replace(/['\"]/g, \"\").trim();\r\n }\r\n\r\n if (type === \"xpath\" && isRecorded === \"Y\" && !val.startsWith(\"//\"))\r\n return null;\r\n\r\n // Final check for empty strings\r\n if (!cleaned || /^['\"]{2}$/.test(cleaned)) return null;\r\n\r\n return cleaned;\r\n };\r\n\r\n locators: for (const locator of record.locators) {\r\n try {\r\n const isRecorded = String(locator.isRecorded || \"\");\r\n const recordedNLocators = record.locators.filter(\r\n (l) => l.isRecorded === \"N\"\r\n );\r\n\r\n if (recordedNLocators.length > 0) {\r\n for (const locator of recordedNLocators) {\r\n createLocator(locator);\r\n }\r\n }\r\n\r\n const isDynamic = String(locator.value || locator.type || \"\");\r\n if (\r\n isDynamic.includes(\"dynamic\") ||\r\n isDynamic.match(\"dynamic\") ||\r\n isDynamic.includes(\"{\") ||\r\n isDynamic.includes(\"}\")\r\n ) {\r\n createLocator(locator);\r\n continue;\r\n }\r\n\r\n if (record.isShared.includes(\"Y\")) {\r\n break locators;\r\n }\r\n\r\n try {\r\n let targetElement: Element | null = null;\r\n if (locator.value.startsWith(\"iframe\")) {\r\n const iframe = docmt.querySelector(\r\n locator.value\r\n ) as HTMLIFrameElement;\r\n if (iframe) {\r\n const iframeDocument =\r\n iframe.contentDocument || iframe.contentWindow?.document;\r\n if (iframeDocument) {\r\n targetElement = iframeDocument.querySelector(\r\n locator.value.slice(6)\r\n );\r\n }\r\n }\r\n } else {\r\n const selectors = locator.value.split(\">>>\"); // Custom delimiter for shadow DOM\r\n\r\n for (const selector of selectors) {\r\n if (docmt) {\r\n const trimmedSelector = selector.trim();\r\n if (\r\n locator.name.includes(\"id\") ||\r\n trimmedSelector.startsWith(\"#\")\r\n ) {\r\n targetElement = docmt.querySelector(\"#\" + trimmedSelector);\r\n } else if (\r\n locator.name.includes(\"className\") ||\r\n trimmedSelector.startsWith(\".\")\r\n ) {\r\n targetElement = docmt.querySelector(\".\" + trimmedSelector);\r\n } else if (locator.name === \"name\") {\r\n const safeName = escapeAttrValue(trimmedSelector);\r\n targetElement = docmt.querySelector(`[name=\"${safeName}\"]`);\r\n } else if (locator.name === \"tagName\") {\r\n targetElement = docmt.querySelector(trimmedSelector);\r\n } else if (locator.name === \"linkText\") {\r\n targetElement =\r\n Array.from(docmt.querySelectorAll(\"a\")).find(\r\n (a) => a.textContent?.trim() === trimmedSelector\r\n ) || null;\r\n } else if (locator.name === \"partialLinkText\") {\r\n targetElement =\r\n Array.from(docmt.querySelectorAll(\"a\")).find((a) =>\r\n a.textContent?.includes(trimmedSelector)\r\n ) || null;\r\n } else if (\r\n (locator.name.includes(\"xpath\") ||\r\n trimmedSelector.startsWith(\"//\")) &&\r\n !locator.type.match(\"dynamic\")\r\n ) {\r\n const normalizedXPath = normalizeXPath(trimmedSelector);\r\n targetElement = getElementFromXPath(docmt, normalizedXPath);\r\n if (targetElement) {\r\n createLocator(locator, {\r\n value: trimmedSelector,\r\n isRecorded: String(locator.isRecorded).includes(\"N\")\r\n ? \"N\"\r\n : \"Y\"\r\n });\r\n }\r\n } else {\r\n targetElement = docmt.querySelector(trimmedSelector);\r\n if (!targetElement) {\r\n targetElement = getElementFromShadowRoot(\r\n docmt.body,\r\n trimmedSelector\r\n );\r\n }\r\n }\r\n } else {\r\n console.error(\"Element not found at:\", selector);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const locatorExists = (name: string, value: string): boolean => {\r\n const key = `${name}:${value}`;\r\n return finalLocatorsSet.has(key);\r\n };\r\n\r\n if (targetElement) {\r\n const payloadXPaths = record.locators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n\r\n for (const px of payloadXPaths) {\r\n if (isSameXPathStillValid(px.value, docmt, targetElement))\r\n createLocator(px, {\r\n isSelfHealed: null\r\n });\r\n }\r\n\r\n const existingXPaths = finalLocators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n\r\n // Track XPath patterns already used\r\n const usedXPathPatterns = new Set<string>(\r\n existingXPaths.map((x) => getXPathPattern(x.value))\r\n );\r\n\r\n const excludedAttributes: string[] = [];\r\n const idValue = getId(targetElement);\r\n if (\r\n idValue &&\r\n !locatorExists(\"id\", idValue) &&\r\n !isNumberExist(idValue)\r\n ) {\r\n const prevId = record.locators.find((l) => l.name === \"id\");\r\n if (isUniqueInDOM(docmt, \"id\", idValue)) {\r\n excludedAttributes.push(\"id\");\r\n createLocator(prevId, {\r\n name: \"id\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: idValue\r\n });\r\n }\r\n }\r\n\r\n const tagName = targetElement.tagName;\r\n if (tagName && !locatorExists(\"tagName\", tagName)) {\r\n const prevTag = record.locators.find((l) => l.name === \"tagName\");\r\n if (isUniqueInDOM(docmt, \"tagName\", tagName)) {\r\n excludedAttributes.push(\"tagName\");\r\n createLocator(prevTag, {\r\n name: \"tagName\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: tagName\r\n });\r\n }\r\n }\r\n\r\n const textValue = getVisibleText(targetElement);\r\n if (textValue && !isNumberExist(textValue)) {\r\n const prevLinkText = record.locators.find(\r\n (l) => l.name === \"linkText\"\r\n );\r\n if (isUniqueInDOM(docmt, \"linkText\", textValue)) {\r\n excludedAttributes.push(\"linkText\");\r\n createLocator(prevLinkText, {\r\n name: \"linkText\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: textValue\r\n });\r\n }\r\n }\r\n\r\n const nameLocator = getName(targetElement);\r\n if (\r\n nameLocator &&\r\n !locatorExists(\"name\", nameLocator) &&\r\n !isNumberExist(nameLocator)\r\n ) {\r\n const prevName = record.locators.find((l) => l.name === \"name\");\r\n if (isUniqueInDOM(docmt, \"name\", nameLocator)) {\r\n excludedAttributes.push(\"name\");\r\n createLocator(prevName, {\r\n name: \"name\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: nameLocator\r\n });\r\n }\r\n }\r\n\r\n const classValue = getClassName(targetElement);\r\n if (\r\n classValue &&\r\n classValue.trim() !== \"\" &&\r\n !locatorExists(\"className\", classValue) &&\r\n !isNumberExist(classValue)\r\n ) {\r\n const prevClassLocator = record.locators.find(\r\n (l) => l.name === \"className\"\r\n );\r\n if (isUniqueInDOM(docmt, \"className\", classValue)) {\r\n excludedAttributes.push(\"className\");\r\n createLocator(prevClassLocator, {\r\n name: \"className\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: classValue\r\n });\r\n }\r\n }\r\n\r\n const allAttributes = Array.from(targetElement.attributes);\r\n const includedAttributes = allAttributes.filter(\r\n (attr) => !excludedAttributes.includes(attr.name)\r\n );\r\n\r\n //If any direct locator is broken then we consider it as broken xpath\r\n\r\n const xpathResults = parseDOM(\r\n targetElement,\r\n docmt,\r\n false,\r\n true,\r\n includedAttributes\r\n );\r\n\r\n if (xpathResults?.length !== 0) {\r\n const brokenPayloadXPaths = payloadXPaths.filter(\r\n (px) => !isSameXPathStillValid(px.value, docmt, targetElement)\r\n );\r\n\r\n let xpathAdded = 0;\r\n\r\n for (const brokenPx of brokenPayloadXPaths) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n\r\n const originalPattern = getXPathPattern(brokenPx.value);\r\n if (usedXPathPatterns.has(originalPattern)) continue;\r\n\r\n const match = xpathResults.find(\r\n (r) => r.value && getXPathPattern(r.value) === originalPattern\r\n );\r\n\r\n if (match?.value) {\r\n createLocator(brokenPx, {\r\n name: \"xpath\",\r\n value: match.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(originalPattern);\r\n xpathAdded++;\r\n }\r\n }\r\n if (xpathAdded < brokenPayloadXPaths.length) {\r\n for (const result of xpathResults) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n if (!result.value) continue;\r\n\r\n const pattern = getXPathPattern(result.value);\r\n if (usedXPathPatterns.has(pattern)) continue;\r\n\r\n createLocator(result, {\r\n name: \"xpath\",\r\n value: result.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(pattern);\r\n xpathAdded++;\r\n }\r\n }\r\n }\r\n for (const locator of record.locators) {\r\n try {\r\n for (const loc of record.locators) {\r\n if (!loc.value) continue;\r\n\r\n for (const relation of relations) {\r\n if (loc.value.includes(relation)) {\r\n const relativeXpath = checkReferenceElementIsValid(\r\n loc.value,\r\n relation,\r\n docmt\r\n );\r\n if (relativeXpath) {\r\n createLocator(loc, {\r\n name: \"xpath\",\r\n value: relativeXpath,\r\n isRecorded:\r\n locator.isRecorded !== \"\" &&\r\n locator.isRecorded !== null\r\n ? locator.isRecorded\r\n : \"Y\"\r\n });\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n }\r\n }\r\n if (finalLocators.length < 5) {\r\n const fallbackCandidates = [\r\n { name: \"id\", value: getId(targetElement) },\r\n { name: \"name\", value: getName(targetElement) },\r\n { name: \"className\", value: getClassName(targetElement) },\r\n { name: \"tagName\", value: targetElement.tagName },\r\n { name: \"linkText\", value: getVisibleText(targetElement) }\r\n ];\r\n\r\n for (const candidate of fallbackCandidates) {\r\n if (finalLocators.length > 4) break;\r\n\r\n const { name, value } = candidate;\r\n if (!value) continue;\r\n if (isNumberExist(value)) continue;\r\n if (locatorExists(name, value)) continue;\r\n\r\n if (isUniqueInDOM(docmt, name, value)) {\r\n createLocator(undefined, {\r\n name,\r\n type: \"static\",\r\n value,\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n }\r\n }\r\n }\r\n\r\n const finalAutoHealedLocators = finalLocators.map((obj) => ({\r\n ...obj,\r\n value: cleanLocatorValue(obj.value, obj.name, obj.isRecorded)\r\n }));\r\n\r\n const jsonResult = [\r\n {\r\n name: `${record.name}`,\r\n desc: `${record.desc}`,\r\n type: `${record.type}`,\r\n locators: finalAutoHealedLocators.filter(\r\n (locator) => locator?.value != null && locator.value !== \"\"\r\n ),\r\n isShared: `${record.isShared}`,\r\n projectId: `${record.projectId}`,\r\n projectType: `${record.projectType}`,\r\n isRecorded: `${record.isRecorded}`,\r\n folder: `${record.folder}`,\r\n parentId: `${record.parentId}`,\r\n parentName: `${record.parentName}`,\r\n platform: `${record.platform}`,\r\n licenseId: `${record.licenseId}`,\r\n licenseType: `${record.licenseType}`,\r\n userId: `${record.userId}`\r\n }\r\n ];\r\n\r\n return jsonResult;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nexport { getElementsFromHTML };\r\n","import { isNumberExist } from \"./xpathHelpers.ts\";\r\n\r\nlet modifiedElementAttributes: [] = [];\r\n\r\nconst isCssSelectorUnique = (\r\n selector: string,\r\n el: Element,\r\n root: Document | ShadowRoot | ParentNode\r\n): boolean => {\r\n try {\r\n const matches = root.querySelectorAll(selector);\r\n return matches.length === 1 && matches[0] === el;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\n\r\nexport const parseCssSelectors = (el: Element) => {\r\n const selectors: { key: string; value: string }[] = [];\r\n const root = el.getRootNode() as Document | ShadowRoot;\r\n\r\n try {\r\n const idPath = getIdCssPath(el);\r\n if (idPath && isCssSelectorUnique(idPath, el, root)) {\r\n selectors.push({ key: 'cssSelector by id', value: idPath });\r\n return selectors;\r\n }\r\n const classPath = getClassCssPath(el);\r\n if (classPath && isCssSelectorUnique(classPath, el, root)) {\r\n selectors.push({ key: 'cssSelector by class', value: classPath });\r\n }\r\n const namePath = getAttributeCssPath(el);\r\n if (namePath) {\r\n selectors.push({ key: 'cssSelector by name', value: namePath });\r\n }\r\n const absPath = getAbsoluteCssPath(el);\r\n if (absPath && isCssSelectorUnique(absPath, el, root)) {\r\n selectors.push({ key: 'Absolute cssSelector', value: absPath });\r\n }\r\n } catch (e) {\r\n console.error(e);\r\n }\r\n return selectors;\r\n};\r\n\r\n\r\nexport const getIdCssPath = (el: HTMLElement | Element,) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n const tagName = el.tagName.toLowerCase();\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n if (el.id && !isNumberExist(el.id)) {\r\n selector += `#${CSS.escape(el.id)}`;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nconst EXCLUDED_ATTRS = new Set([\r\n 'id',\r\n 'class',\r\n 'style'\r\n]);\r\nfunction getAttributeSelectors(el: Element): string[] {\r\n return Array.from(el.attributes)\r\n .filter(attr =>\r\n !EXCLUDED_ATTRS.has(attr?.name?.toLowerCase()) &&\r\n attr.value &&\r\n !isNumberExist(attr.value)\r\n )\r\n .map(attr =>\r\n `[${attr.name}=\"${CSS.escape(attr.value)}\"]`\r\n );\r\n}\r\n\r\n\r\nexport const getAttributeCssPath = (\r\n el: Element\r\n): string | undefined => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n\r\n const root = el.getRootNode() as ParentNode;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === 'style' || tag === 'script') return;\r\n\r\n const attrSelectors = getAttributeSelectors(el);\r\n\r\n for (const attrSelector of attrSelectors) {\r\n const candidate = `${tag}${attrSelector}`;\r\n\r\n if (isCssSelectorUnique(candidate, el, root)) {\r\n return candidate;\r\n }\r\n }\r\n return;\r\n};\r\n\r\n\r\n\r\nexport const getClassCssPath = (el: HTMLElement | Element,) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n const tagName = el.tagName.toLowerCase();;\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n\r\n if (\r\n typeof el.className === 'string' &&\r\n el.className &&\r\n !isNumberExist(el.className) &&\r\n !modifiedElementAttributes?.find(\r\n (x: { element: HTMLElement | Element; attributeName: string; }) => x.element === el && x.attributeName === 'class'\r\n )\r\n ) {\r\n el.classList.remove('marked-element-temp');\r\n el.classList.remove('removePointers');\r\n if (el.className) {\r\n selector += `.${el.className.trim().replace(/\\s+/g, '.')}`;\r\n path.unshift(selector);\r\n break;\r\n }\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nexport const getAbsoluteCssPath = (el: Element) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n\r\n const path: string[] = [];\r\n\r\n while (el && el.nodeType === Node.ELEMENT_NODE) {\r\n const tagName = el.tagName.toLowerCase();\r\n\r\n if (tagName === 'style' || tagName === 'script') return;\r\n\r\n let selector = tagName;\r\n\r\n const parent = el.parentNode;\r\n\r\n if (parent) {\r\n const siblings = Array.from(parent.children)\r\n .filter(c => c.tagName === el.tagName);\r\n\r\n if (siblings.length > 1) {\r\n selector += `:nth-of-type(${siblings.indexOf(el) + 1})`;\r\n }\r\n }\r\n\r\n path.unshift(selector);\r\n\r\n el = el.parentElement!;\r\n }\r\n\r\n return path.join(' > ');\r\n};\r\n\r\nexport const cssSelectors = {\r\n parseCssSelectors,\r\n getIdCssPath,\r\n getAttributeCssPath,\r\n getClassCssPath,\r\n getAbsoluteCssPath\r\n}","import xpath from '../utils/xpath.ts';\r\nimport referenceXpaths from '../utils/referenceXpath.ts';\r\nimport { xpathUtils } from '../utils/xpathHelpers.ts';\r\nimport { getElementsFromHTML } from '../utils/getElementsFromHTML.ts';\r\nimport { cssSelectors } from '../utils/cssSelector.ts';\r\n\r\nexport const createXPathAPI = () => ({\r\n xpath,\r\n referenceXpaths,\r\n xpathUtils,\r\n getElementsFromHTML,\r\n cssSelectors\r\n});\r\n\r\nexport default createXPathAPI;"],"names":["reWhiteSpace","xpathCache","mutationObserver","relativeXPathCache","Map","modifiedElementAttributes","isNumberExist","str","test","getTextContent","targetElement","textContent","getFilteredText","element","childNodes","nodeValue","getCountOfXPath","xpath","docmt","multiElementReferenceMode","count","undefined","nodeType","ownerDocument","evaluate","XPathResult","NUMBER_TYPE","numberValue","Array","isArray","elementsFromXpath","getElementFromXpath","nodex","matchedCount","iterateNext","includes","error","console","escapeCharacters","text","indexOf","removeParenthesis","charArr","split","length","indexArray","push","reverse","finalStr","i","endBracketLength","firstpart","slice","startsWith","endsWith","findXpathWithIndex","val","node","owner","index","nodes","ANY_TYPE","isSameNode","log","deleteGarbageFromInnerText","a","deleteLineGap","reduce","b","c","trim","replaceWhiteSpaces","replace","getShadowRoot","el","getRootNode","root","host","checkBlockedAttributes","attribute","isTarget","value","some","x","name","isModified","find","doc","attributeName","isSvg","SVGElement","replaceTempAttributes","multi","contextNode","Node","DOCUMENT_FRAGMENT_NODE","DOCUMENT_NODE","FIRST_ORDERED_NODE_TYPE","singleNodeValue","getPropertyXPath","prop","isIndex","tagName","combinePattern","mergePattern","pattern","buildPattern","toLowerCase","splitText","contentRes","Set","match","endIndex","startIndexString","join","endIndexString","getAbsoluteXPath","domNode","xpathe","parentElement","prototype","call","children","filter","childNode","HTMLElement","offsetParent","getRelativeXPath","attributesArray","has","get","xpathParts","currentNode","hasUniqueAttr","attributes","attrName","from","attrValue","elementName","getXpathString","othersWithAttr","unshift","RegExp","tagBasedXPath","siblings","finalXPath","set","getCombinationXpath","getAttributeCombinationXpath","uniqueAttributes","xpathAttributes","nodeName","ign","JSON","stringify","intermediateXpathStep","targetElemt","attr","isSvgElement","expression","getFilteredTextXPath","filteredText","getTextXpathFunction","trimmedText","replaceActualAttributes","getReferenceElementsXpath","nodeXpath1","xpaths1","key","combinationXpath","tag","xpaths","map","xpth","addAttributeSplitCombineXpaths","concat","normalizeXPath","findMatchingParenthesis","openPos","closePos","counter","getXPathPattern","canonical","canonicalizeXPath","parts","xp","axisMatch","axis","attrMatch","usesNormalize","extractXPathSignatureParts","escapeAttrValue","isUniqueInDOM","getElementById","querySelectorAll","getElementsByClassName","getElementsByTagName","xpathUtils","parseXml","xmlStr","type","window","DOMParser","parseFromString","getRelationship","pos","compareDocumentPosition","createObserver","addedNodeCallBack","MutationObserver","mutations","forEach","mutation","addedNodes","target","oldValue","classList","url","baseURI","startObserver","options","observe","stopObserver","disconnect","cspEnabled","xpathData","xpathDataWithIndex","cache","parentXpathCache","checkRelativeXpathRelation","nodeXpath2","relationType","pop","indexedXpath","getUniqueParentXpath","nodeXpath","getParentRelativeXpath","uniqueAttrFound","textXPath","finalXpath","getChildRelativeXpath","st","firstElementChild","contains","nextElementSibling","m","getSiblingRelativeXPath","markedSpan","document","querySelector","processSibling","n","previousElementSibling","sibling","hasAttributes","getXPathUsingAttributeAndText","addRelativeXpaths","relativeXpath","relativeChildXpath","fullRelativeXpath","relativeXpathIndex","substring","txtXpath","getTextXPath","tempRelativeXpath","attributesBasedXPath","getUniqueClassName","className","addAllXPathAttributes","textAttribute","parseDOM","includedAttributes","attributesToUse","len","descendantExpression","refExpectElement","xpath2","relation","expCommonParentXpathElements","step4","refCommonParentXpathElementLength","finalExpectedElementXpath","xpaths2Els","xpath2Elements","traverseXpath","getTraverseXpathExpression","repeat","rel_count","getDescendantXpath","xpaths2","refElement","expElement","expElementDocmnt","refAbsoluteXpath","refFullXpathElements","refFullXpathElementsWithoutNumber","expAbsoluteXpath","expFullXpathElements","expFullXpathElementsWithoutNumber","parentElementNumber","refCommonParentXpathElements","j","refCommonParentXpath","getXpathRelationExpression","element1","element2","xpath1","finalXpaths","rel_xpath","xpathe1","absoluteXpathElements","referenceXpath","findRelativeXpath","par1","par2","tempElement","xpathWithIndex","parentNode","descendantXpath","descendantSelfXpath","sort","getReferenceElementXpath","charAt","lastIndexOf","referenceXpathElement","isSameXPathStillValid","getElementFromXPath","getElementFromShadowRoot","selector","elements","shadowRoot","getId","id","getClassName","getVisibleText","getName","elementEl","hasAttribute","getAttribute","relations","defaultView","XPathEvaluator","checkReferenceElementIsValid","locator","sourceLoc","xpathEvaluator","getElementsFromHTML","record","elementsToRemove","remove","finalLocatorsSet","finalLocators","createLocator","base","overrides","newValue","newLocator","reference","status","isRecorded","previousSelfHealed","isSelfHealed","hasOwnProperty","locName","resolveIsSelfHealed","obj","add","pushUniqueLocator","cleanLocatorValue","cleaned","locators","String","recordedNLocators","l","isDynamic","isShared","iframe","iframeDocument","contentDocument","contentWindow","selectors","trimmedSelector","safeName","body","normalizedXPath","locatorExists","payloadXPaths","px","existingXPaths","usedXPathPatterns","excludedAttributes","idValue","prevId","prevTag","textValue","prevLinkText","nameLocator","prevName","classValue","prevClassLocator","xpathResults","brokenPayloadXPaths","xpathAdded","brokenPx","originalPattern","r","result","loc","fallbackCandidates","candidate","finalAutoHealedLocators","jsonResult","desc","projectId","projectType","folder","parentId","parentName","platform","licenseId","licenseType","userId","isCssSelectorUnique","matches","getIdCssPath","view","Element","path","ELEMENT_NODE","CSS","escape","sib","nth","childElementCount","EXCLUDED_ATTRS","getAttributeCssPath","attrSelectors","getAttributeSelectors","attrSelector","getClassCssPath","getAbsoluteCssPath","parent","cssSelectors","parseCssSelectors","idPath","classPath","namePath","absPath","e","createXPathAPI","referenceXpaths"],"mappings":"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"}
|