ff-dom 1.0.18-beta.1 → 1.0.18-beta.3
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 +87 -51
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +87 -51
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cdn.js +87 -51
- package/dist/types/browser/browser/xpath.d.ts +8 -7
- package/dist/types/browser/utils/referenceXpath.d.ts +5 -5
- package/dist/types/browser/utils/xpathHelpers.d.ts +8 -7
- package/dist/xpath.mjs +0 -2
- package/dist/xpath.mjs.map +1 -1
- package/package.json +1 -1
- package/src/utils/referenceXpath.ts +95 -78
- package/src/utils/xpath.ts +9 -7
- package/src/utils/xpathHelpers.ts +26 -33
- package/tsconfig.json +1 -1
package/dist/index.browser.cjs
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
const reWhiteSpace$1 = /^[\S]+( [\S]+)*$/gi;
|
|
6
|
+
let cspEnabled = false;
|
|
6
7
|
const xpathCache$1 = {};
|
|
7
|
-
let multiElementReferenceMode = false;
|
|
8
8
|
let relativeXPathCache = new Map();
|
|
9
9
|
let modifiedElementAttributes$1 = [];
|
|
10
10
|
let mutationObserver;
|
|
@@ -63,7 +63,7 @@ const getTextContent = (targetElement) => {
|
|
|
63
63
|
const getFilteredText = (element) => {
|
|
64
64
|
return element?.childNodes[0]?.nodeValue || "";
|
|
65
65
|
};
|
|
66
|
-
const getCountOfXPath = (xpath, element, docmt) => {
|
|
66
|
+
const getCountOfXPath = (xpath, element, docmt, multiElementReferenceMode = false) => {
|
|
67
67
|
try {
|
|
68
68
|
let count;
|
|
69
69
|
// Check if result is cached
|
|
@@ -77,7 +77,23 @@ const getCountOfXPath = (xpath, element, docmt) => {
|
|
|
77
77
|
count = owner.evaluate(`count(${xpath})`, docmt, null, XPathResult.NUMBER_TYPE, null).numberValue;
|
|
78
78
|
xpathCache$1[xpath] = count;
|
|
79
79
|
}
|
|
80
|
-
if (multiElementReferenceMode && Array.isArray(element))
|
|
80
|
+
if (multiElementReferenceMode && Array.isArray(element)) {
|
|
81
|
+
if (count > 1) {
|
|
82
|
+
const elementsFromXpath = getElementFromXpath(xpath, docmt, true);
|
|
83
|
+
let nodex, matchedCount = 0;
|
|
84
|
+
if (elementsFromXpath instanceof XPathResult) {
|
|
85
|
+
while ((nodex = elementsFromXpath?.iterateNext())) {
|
|
86
|
+
if (element.includes(nodex)) {
|
|
87
|
+
matchedCount += 1;
|
|
88
|
+
if (matchedCount === 2)
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (matchedCount !== 2)
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
81
97
|
else {
|
|
82
98
|
// Short-circuit if we only need to match one element
|
|
83
99
|
if (count === 1) {
|
|
@@ -216,12 +232,6 @@ const getRelationship = (a, b) => {
|
|
|
216
232
|
? "self"
|
|
217
233
|
: "";
|
|
218
234
|
};
|
|
219
|
-
const findRoot = (node) => {
|
|
220
|
-
while (node && node.parentNode) {
|
|
221
|
-
node = node.parentNode;
|
|
222
|
-
}
|
|
223
|
-
return node;
|
|
224
|
-
};
|
|
225
235
|
const isSvg = (element) => {
|
|
226
236
|
return element instanceof SVGElement;
|
|
227
237
|
};
|
|
@@ -463,9 +473,9 @@ const getRelativeXPath = (domNode, docmt, isIndex, isTarget = false, attributesA
|
|
|
463
473
|
while (currentNode) {
|
|
464
474
|
let xpathe = "";
|
|
465
475
|
let hasUniqueAttr = false;
|
|
466
|
-
let attributes = domNode === currentNode ? attributesArray : currentNode.attributes;
|
|
476
|
+
let attributes = domNode === currentNode ? attributesArray ?? currentNode.attributes : currentNode.attributes;
|
|
467
477
|
// Loop through attributes to check for unique identifiers
|
|
468
|
-
for (const attrName of attributes) {
|
|
478
|
+
for (const attrName of Array.from(attributes)) {
|
|
469
479
|
if (checkBlockedAttributes(attrName, currentNode, isTarget)) {
|
|
470
480
|
let attrValue = attrName.nodeValue;
|
|
471
481
|
// Clean up attribute value
|
|
@@ -782,7 +792,7 @@ const getReferenceElementsXpath = (domNode, docmt, isTarget) => {
|
|
|
782
792
|
}
|
|
783
793
|
}
|
|
784
794
|
if (domNode.attributes) {
|
|
785
|
-
for (const attrName of domNode.attributes) {
|
|
795
|
+
for (const attrName of Array.from(domNode.attributes)) {
|
|
786
796
|
if (checkBlockedAttributes(attrName, domNode, isTarget)) {
|
|
787
797
|
let attrValue = attrName.nodeValue;
|
|
788
798
|
if (attrValue) {
|
|
@@ -859,12 +869,12 @@ const getReferenceElementsXpath = (domNode, docmt, isTarget) => {
|
|
|
859
869
|
}
|
|
860
870
|
return xpaths1;
|
|
861
871
|
};
|
|
862
|
-
|
|
872
|
+
const parseXml = (xmlStr) => {
|
|
863
873
|
if (window.DOMParser) {
|
|
864
874
|
return new window.DOMParser().parseFromString(xmlStr, "text/xml");
|
|
865
875
|
}
|
|
866
876
|
return null;
|
|
867
|
-
}
|
|
877
|
+
};
|
|
868
878
|
const normalizeXPath = (xpath) => {
|
|
869
879
|
// Replace text() = "value" or text()='value'
|
|
870
880
|
xpath = xpath.replace(/text\(\)\s*=\s*(['"])(.*?)\1/g, "normalize-space(.)=$1$2$1");
|
|
@@ -912,6 +922,7 @@ const xpathUtils = {
|
|
|
912
922
|
startObserver,
|
|
913
923
|
stopObserver,
|
|
914
924
|
modifiedElementAttributes: modifiedElementAttributes$1,
|
|
925
|
+
cspEnabled
|
|
915
926
|
};
|
|
916
927
|
|
|
917
928
|
let xpathData$1 = [];
|
|
@@ -994,7 +1005,7 @@ const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex
|
|
|
994
1005
|
let currentNode = domNode;
|
|
995
1006
|
while (currentNode && currentNode.nodeType === 1) {
|
|
996
1007
|
const hasUniqueAttr = false;
|
|
997
|
-
for (const attrName of currentNode.attributes) {
|
|
1008
|
+
for (const attrName of Array.from(currentNode.attributes)) {
|
|
998
1009
|
if (checkBlockedAttributes(attrName, currentNode, isTarget)) {
|
|
999
1010
|
let attrValue = attrName.nodeValue;
|
|
1000
1011
|
attrValue = attrValue?.replace("removePointers", "") ?? "";
|
|
@@ -1100,7 +1111,7 @@ const getParentRelativeXpath = (domNode, docmt, node, isTarget) => {
|
|
|
1100
1111
|
}
|
|
1101
1112
|
// BASE CASE #2: Check for unique attributes
|
|
1102
1113
|
let uniqueAttrFound = false;
|
|
1103
|
-
for (const attr of currentNode.attributes) {
|
|
1114
|
+
for (const attr of Array.from(currentNode.attributes)) {
|
|
1104
1115
|
if (checkBlockedAttributes(attr, currentNode, isTarget)) {
|
|
1105
1116
|
let attrValue = attr.nodeValue;
|
|
1106
1117
|
attrValue = attrValue?.replace("removePointers", "") ?? "";
|
|
@@ -1176,7 +1187,7 @@ const getChildRelativeXpath = (domNode, docmt, node) => {
|
|
|
1176
1187
|
do {
|
|
1177
1188
|
let uniqueAttrFound = false;
|
|
1178
1189
|
for (currentNode = st.pop(); currentNode !== null;) {
|
|
1179
|
-
for (const attr of currentNode.attributes) {
|
|
1190
|
+
for (const attr of Array.from(currentNode.attributes)) {
|
|
1180
1191
|
if (checkBlockedAttributes(attr, currentNode, true)) {
|
|
1181
1192
|
let attrValue = attr.nodeValue;
|
|
1182
1193
|
attrValue = attrValue?.replace("removePointers", "") ?? "";
|
|
@@ -1258,7 +1269,7 @@ const getSiblingRelativeXPath = (domNode, docmt, isTarget, nodeXpath) => {
|
|
|
1258
1269
|
const processSibling = (sibling, domNode, docmt, nodeXpath, axis, isTarget) => {
|
|
1259
1270
|
try {
|
|
1260
1271
|
if (sibling.hasAttributes()) {
|
|
1261
|
-
for (const attr of sibling.attributes) {
|
|
1272
|
+
for (const attr of Array.from(sibling.attributes)) {
|
|
1262
1273
|
let xpathe = intermediateXpathStep(sibling, {
|
|
1263
1274
|
name: attr.name,
|
|
1264
1275
|
value: attr.value,
|
|
@@ -1615,13 +1626,13 @@ const parseDOM = (element, doc, isIndex, isTarget) => {
|
|
|
1615
1626
|
const docmt = targetElemt?.ownerDocument || doc;
|
|
1616
1627
|
const tag = targetElemt.tagName;
|
|
1617
1628
|
const { attributes } = targetElemt;
|
|
1618
|
-
addAllXPathAttributes(
|
|
1629
|
+
addAllXPathAttributes(Array.from(attributes), targetElemt, docmt, isIndex, isTarget);
|
|
1619
1630
|
{
|
|
1620
1631
|
if (xpathData$1.length) {
|
|
1621
1632
|
const len = xpathData$1.length;
|
|
1622
1633
|
for (let i = 0; i < len; i++) {
|
|
1623
1634
|
let xpth = xpathData$1[i].value;
|
|
1624
|
-
xpth = xpth.
|
|
1635
|
+
xpth = "//*" + xpth.substring(xpth.indexOf("//") + 2 + tag.length);
|
|
1625
1636
|
const count = getCountOfXPath(xpth, element, docmt);
|
|
1626
1637
|
if (count === 1) {
|
|
1627
1638
|
xpathData$1.push({
|
|
@@ -1634,7 +1645,7 @@ const parseDOM = (element, doc, isIndex, isTarget) => {
|
|
|
1634
1645
|
}
|
|
1635
1646
|
console.log(xpathData$1);
|
|
1636
1647
|
if (!xpathData$1.length) {
|
|
1637
|
-
addRelativeXpaths(targetElemt, docmt, isIndex, isTarget,
|
|
1648
|
+
addRelativeXpaths(targetElemt, docmt, isIndex, isTarget, Array.from(targetElemt.attributes));
|
|
1638
1649
|
}
|
|
1639
1650
|
return xpathData$1;
|
|
1640
1651
|
};
|
|
@@ -1656,13 +1667,12 @@ const xpath = {
|
|
|
1656
1667
|
let xpathDataWithIndex = [];
|
|
1657
1668
|
let xpathData = [];
|
|
1658
1669
|
const reWhiteSpace = /^[\S]+( [\S]+)*$/gi;
|
|
1659
|
-
const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex) => {
|
|
1670
|
+
const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex, multiElementReferenceMode = false) => {
|
|
1660
1671
|
// debugger;
|
|
1661
1672
|
const par1 = element1.parentElement;
|
|
1662
1673
|
const par2 = element2.parentElement;
|
|
1663
1674
|
let rel_xpath = [];
|
|
1664
1675
|
let tempElement;
|
|
1665
|
-
findRoot(element1);
|
|
1666
1676
|
let finalXpaths = [];
|
|
1667
1677
|
if (isIndex) {
|
|
1668
1678
|
if (xpathDataWithIndex.length) {
|
|
@@ -1682,14 +1692,14 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1682
1692
|
// both are same
|
|
1683
1693
|
if (element1.isSameNode(element2)) {
|
|
1684
1694
|
// rel_xpath = xpath1 + "/self::" + element1.tagName;
|
|
1685
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "self", xpaths1, xpaths2, isIndex);
|
|
1695
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "self", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1686
1696
|
if (rel_xpath)
|
|
1687
1697
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1688
1698
|
}
|
|
1689
1699
|
// parent
|
|
1690
1700
|
tempElement = element1.parentElement;
|
|
1691
1701
|
if (tempElement === element2) {
|
|
1692
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "parent", xpaths1, xpaths2, isIndex);
|
|
1702
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "parent", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1693
1703
|
if (rel_xpath)
|
|
1694
1704
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1695
1705
|
}
|
|
@@ -1697,7 +1707,7 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1697
1707
|
tempElement = element1.parentElement;
|
|
1698
1708
|
while (tempElement !== null) {
|
|
1699
1709
|
if (tempElement === element2) {
|
|
1700
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "ancestor", xpaths1, xpaths2, isIndex);
|
|
1710
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "ancestor", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1701
1711
|
if (rel_xpath) {
|
|
1702
1712
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1703
1713
|
break;
|
|
@@ -1709,7 +1719,7 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1709
1719
|
tempElement = element1;
|
|
1710
1720
|
do {
|
|
1711
1721
|
if (tempElement === element2) {
|
|
1712
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "ancestor-or-self", xpaths1, xpaths2, isIndex);
|
|
1722
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "ancestor-or-self", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1713
1723
|
if (rel_xpath) {
|
|
1714
1724
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1715
1725
|
break;
|
|
@@ -1721,7 +1731,7 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1721
1731
|
if (par1?.isSameNode(par2)) {
|
|
1722
1732
|
for (let m = element1.nextElementSibling; m != null; m = m.nextElementSibling) {
|
|
1723
1733
|
if (m != null && m.isSameNode(element2)) {
|
|
1724
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "following-sibling", xpaths1, xpaths2, isIndex);
|
|
1734
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "following-sibling", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1725
1735
|
if (rel_xpath) {
|
|
1726
1736
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1727
1737
|
break;
|
|
@@ -1730,7 +1740,7 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1730
1740
|
}
|
|
1731
1741
|
for (let n = element1.previousElementSibling; n != null; n = n.previousElementSibling) {
|
|
1732
1742
|
if (n != null && n.isSameNode(element2)) {
|
|
1733
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "preceding-sibling", xpaths1, xpaths2, isIndex);
|
|
1743
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "preceding-sibling", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1734
1744
|
if (rel_xpath) {
|
|
1735
1745
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1736
1746
|
break;
|
|
@@ -1742,7 +1752,7 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1742
1752
|
if (element1?.children?.length) {
|
|
1743
1753
|
for (let m = element1.children[0]; m !== null; m = m?.nextElementSibling) {
|
|
1744
1754
|
if (m === element2) {
|
|
1745
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "child", xpaths1, xpaths2, isIndex);
|
|
1755
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "child", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1746
1756
|
if (rel_xpath) {
|
|
1747
1757
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1748
1758
|
break;
|
|
@@ -1753,18 +1763,18 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1753
1763
|
// following
|
|
1754
1764
|
const relation = element1.compareDocumentPosition(element2);
|
|
1755
1765
|
if (relation === 2) {
|
|
1756
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "preceding", xpaths1, xpaths2, isIndex);
|
|
1766
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "preceding", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1757
1767
|
}
|
|
1758
1768
|
if (relation === 4) {
|
|
1759
|
-
rel_xpath = getXpathRelationExpression(element1, element2, "following", xpaths1, xpaths2, isIndex);
|
|
1769
|
+
rel_xpath = getXpathRelationExpression(element1, element2, "following", xpaths1, xpaths2, isIndex, multiElementReferenceMode);
|
|
1760
1770
|
}
|
|
1761
1771
|
if (rel_xpath) {
|
|
1762
1772
|
finalXpaths = finalXpaths.concat(rel_xpath);
|
|
1763
1773
|
}
|
|
1764
|
-
const descendantXpath = getDescendantXpath([element1, element2], docmt, xpaths1, xpaths2, "descendant", isIndex);
|
|
1774
|
+
const descendantXpath = getDescendantXpath([element1, element2], docmt, xpaths1, xpaths2, "descendant", isIndex, multiElementReferenceMode);
|
|
1765
1775
|
if (descendantXpath)
|
|
1766
1776
|
finalXpaths = finalXpaths.concat(descendantXpath);
|
|
1767
|
-
const descendantSelfXpath = getDescendantXpath([element1, element2], docmt, xpaths1, xpaths2, "descedant-or-self", isIndex);
|
|
1777
|
+
const descendantSelfXpath = getDescendantXpath([element1, element2], docmt, xpaths1, xpaths2, "descedant-or-self", isIndex, multiElementReferenceMode);
|
|
1768
1778
|
if (descendantSelfXpath) {
|
|
1769
1779
|
finalXpaths = finalXpaths.concat(descendantSelfXpath);
|
|
1770
1780
|
}
|
|
@@ -1781,7 +1791,7 @@ const findRelativeXpath = (element1, element2, docmt, xpaths1, xpaths2, isIndex)
|
|
|
1781
1791
|
return [finalXpaths[0]];
|
|
1782
1792
|
}
|
|
1783
1793
|
};
|
|
1784
|
-
const descendantExpression = (refExpectElement, xpath2, relation, docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength) => {
|
|
1794
|
+
const descendantExpression = (refExpectElement, xpath2, relation, docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength = 0, multiElementReferenceMode = false) => {
|
|
1785
1795
|
let finalExpectedElementXpath = "";
|
|
1786
1796
|
if (xpath2.split(/\/(?=(?:[^']*\'[^\']*\')*[^\']*$)/g)?.length >=
|
|
1787
1797
|
expCommonParentXpathElements.length) {
|
|
@@ -1795,7 +1805,7 @@ const descendantExpression = (refExpectElement, xpath2, relation, docmt, isIndex
|
|
|
1795
1805
|
const traverseXpath = getTraverseXpathExpression(`${step4 +
|
|
1796
1806
|
(refCommonParentXpathElementLength
|
|
1797
1807
|
? "]".repeat(refCommonParentXpathElementLength)
|
|
1798
|
-
: "")}`, xpaths2Els, refExpectElement[refExpectElement.length - 1], refExpectElement, docmt, relation, isIndex);
|
|
1808
|
+
: "")}`, xpaths2Els, refExpectElement[refExpectElement.length - 1], refExpectElement, docmt, relation, isIndex, multiElementReferenceMode);
|
|
1799
1809
|
if (traverseXpath) {
|
|
1800
1810
|
return traverseXpath;
|
|
1801
1811
|
}
|
|
@@ -1832,7 +1842,7 @@ const descendantExpression = (refExpectElement, xpath2, relation, docmt, isIndex
|
|
|
1832
1842
|
}
|
|
1833
1843
|
}
|
|
1834
1844
|
};
|
|
1835
|
-
const getDescendantXpath = (refExpectElement, docmt, xpaths1, xpaths2, relation, isIndex) => {
|
|
1845
|
+
const getDescendantXpath = (refExpectElement, docmt, xpaths1, xpaths2, relation, isIndex = false, multiElementReferenceMode = false) => {
|
|
1836
1846
|
const refElement = refExpectElement[refExpectElement.length - 2];
|
|
1837
1847
|
const expElement = refExpectElement[refExpectElement.length - 1];
|
|
1838
1848
|
const expElementDocmnt = getShadowRoot(expElement) ?? expElement.ownerDocument;
|
|
@@ -1896,13 +1906,13 @@ const getDescendantXpath = (refExpectElement, docmt, xpaths1, xpaths2, relation,
|
|
|
1896
1906
|
xpath2 = xpathData[i].value; // No need to modify the value
|
|
1897
1907
|
}
|
|
1898
1908
|
if (xpath2) {
|
|
1899
|
-
return descendantExpression(refExpectElement, xpath2, relation, expElementDocmnt || docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength);
|
|
1909
|
+
return descendantExpression(refExpectElement, xpath2, relation, expElementDocmnt || docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength, multiElementReferenceMode);
|
|
1900
1910
|
}
|
|
1901
1911
|
}
|
|
1902
1912
|
}
|
|
1903
1913
|
if (refExpectElement[refExpectElement.length - 2].attributes) {
|
|
1904
|
-
for (const attrName of refExpectElement[refExpectElement.length - 2]
|
|
1905
|
-
.attributes) {
|
|
1914
|
+
for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]
|
|
1915
|
+
.attributes)) {
|
|
1906
1916
|
if (checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)) {
|
|
1907
1917
|
let attrValue = attrName.nodeValue;
|
|
1908
1918
|
if (attrValue) {
|
|
@@ -1923,13 +1933,13 @@ const getDescendantXpath = (refExpectElement, docmt, xpaths1, xpaths2, relation,
|
|
|
1923
1933
|
else {
|
|
1924
1934
|
xpath2 = xpathData[i].value; // No need to modify the value
|
|
1925
1935
|
}
|
|
1926
|
-
return descendantExpression(refExpectElement, xpath2, relation, expElementDocmnt || docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength);
|
|
1936
|
+
return descendantExpression(refExpectElement, xpath2, relation, expElementDocmnt || docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength, multiElementReferenceMode);
|
|
1927
1937
|
}
|
|
1928
1938
|
}
|
|
1929
1939
|
}
|
|
1930
1940
|
}
|
|
1931
|
-
for (const attrName of refExpectElement[refExpectElement.length - 2]
|
|
1932
|
-
.attributes) {
|
|
1941
|
+
for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]
|
|
1942
|
+
.attributes)) {
|
|
1933
1943
|
if (checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)) {
|
|
1934
1944
|
let attrValue = attrName.nodeValue;
|
|
1935
1945
|
if (attrValue) {
|
|
@@ -1954,7 +1964,7 @@ const getDescendantXpath = (refExpectElement, docmt, xpaths1, xpaths2, relation,
|
|
|
1954
1964
|
else {
|
|
1955
1965
|
xpath2 = xpathData[i].value; // No need to modify the value
|
|
1956
1966
|
}
|
|
1957
|
-
return descendantExpression(refExpectElement, xpath2, relation, expElementDocmnt || docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength);
|
|
1967
|
+
return descendantExpression(refExpectElement, xpath2, relation, expElementDocmnt || docmt, isIndex, expCommonParentXpathElements, step4, refCommonParentXpathElementLength, multiElementReferenceMode);
|
|
1958
1968
|
}
|
|
1959
1969
|
}
|
|
1960
1970
|
}
|
|
@@ -1967,12 +1977,12 @@ const getDescendantXpath = (refExpectElement, docmt, xpaths1, xpaths2, relation,
|
|
|
1967
1977
|
const traverseXpath = getTraverseXpathExpression(`${step4 +
|
|
1968
1978
|
(refCommonParentXpathElementLength
|
|
1969
1979
|
? "]".repeat(refCommonParentXpathElementLength)
|
|
1970
|
-
: "")}`, expCommonParentXpathElements
|
|
1980
|
+
: "")}`, expCommonParentXpathElements, refExpectElement[refExpectElement.length - 1], refExpectElement, docmt, relation, isIndex, multiElementReferenceMode);
|
|
1971
1981
|
if (traverseXpath) {
|
|
1972
1982
|
return traverseXpath;
|
|
1973
1983
|
}
|
|
1974
1984
|
};
|
|
1975
|
-
const getXpathRelationExpression = (element1, element2, relation, xpath1, xpath2, isIndex) => {
|
|
1985
|
+
const getXpathRelationExpression = (element1, element2, relation, xpath1, xpath2, isIndex, multiElementReferenceMode) => {
|
|
1976
1986
|
let xpaths1;
|
|
1977
1987
|
let xpaths2;
|
|
1978
1988
|
console.log('getXpathRelationExpression', relation);
|
|
@@ -2039,7 +2049,7 @@ const getXpathRelationExpression = (element1, element2, relation, xpath1, xpath2
|
|
|
2039
2049
|
if (xpath2Elements.length > 1) {
|
|
2040
2050
|
const traverseXpath = getTraverseXpathExpression(`${xpaths1[i].value.indexOf("//") !== 0
|
|
2041
2051
|
? replaceActualAttributes(xpaths1[i].value, element1)
|
|
2042
|
-
: replaceActualAttributes(xpaths1[i].value.substring(xpaths1[i].value.indexOf("//") + 2), element1)}`, xpath2Elements, element2, [element1, element2], element2.ownerDocument, relation, isIndex);
|
|
2052
|
+
: replaceActualAttributes(xpaths1[i].value.substring(xpaths1[i].value.indexOf("//") + 2), element1)}`, xpath2Elements, element2, [element1, element2], element2.ownerDocument, relation, isIndex, multiElementReferenceMode);
|
|
2043
2053
|
console.log('getXpathRelationExpression traverseXpath', traverseXpath);
|
|
2044
2054
|
if (traverseXpath) {
|
|
2045
2055
|
finalXpaths.concat(traverseXpath);
|
|
@@ -2079,7 +2089,7 @@ const getReferenceElementXpath = (element) => {
|
|
|
2079
2089
|
xpaths1 = [
|
|
2080
2090
|
{
|
|
2081
2091
|
key: "",
|
|
2082
|
-
value: getRelativeXPath(element, element.ownerDocument, false, false,
|
|
2092
|
+
value: getRelativeXPath(element, element.ownerDocument, false, false, Array.from(element.attributes)),
|
|
2083
2093
|
},
|
|
2084
2094
|
];
|
|
2085
2095
|
}
|
|
@@ -2087,7 +2097,7 @@ const getReferenceElementXpath = (element) => {
|
|
|
2087
2097
|
xpaths1 = [
|
|
2088
2098
|
{
|
|
2089
2099
|
key: "",
|
|
2090
|
-
value: getRelativeXPath(element, element.ownerDocument, true, false,
|
|
2100
|
+
value: getRelativeXPath(element, element.ownerDocument, true, false, Array.from(element.attributes)),
|
|
2091
2101
|
},
|
|
2092
2102
|
];
|
|
2093
2103
|
xpaths1 = xpaths1?.map((x) => x.value.charAt(0) == "(" &&
|
|
@@ -2112,9 +2122,9 @@ const getReferenceElementXpath = (element) => {
|
|
|
2112
2122
|
});
|
|
2113
2123
|
return xpaths1;
|
|
2114
2124
|
};
|
|
2115
|
-
const getTraverseXpathExpression = (xpathe1, absoluteXpathElements, element2, refExpectElement, docmt, relation, isIndex) => {
|
|
2125
|
+
const getTraverseXpathExpression = (xpathe1, absoluteXpathElements, element2, refExpectElement, docmt, relation, isIndex, multiElementReferenceMode) => {
|
|
2116
2126
|
let finalExpectedElementXpath;
|
|
2117
|
-
{
|
|
2127
|
+
if (!multiElementReferenceMode) {
|
|
2118
2128
|
for (let x = 1; x <= absoluteXpathElements.length; x++) {
|
|
2119
2129
|
const xpath2 = absoluteXpathElements
|
|
2120
2130
|
.slice(absoluteXpathElements.length - x, absoluteXpathElements.length)
|
|
@@ -2144,6 +2154,32 @@ const getTraverseXpathExpression = (xpathe1, absoluteXpathElements, element2, re
|
|
|
2144
2154
|
}
|
|
2145
2155
|
}
|
|
2146
2156
|
}
|
|
2157
|
+
else {
|
|
2158
|
+
const xpath2 = absoluteXpathElements.join("/");
|
|
2159
|
+
finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(xpath2)}`;
|
|
2160
|
+
const rel_count = getCountOfXPath(finalExpectedElementXpath, element2, docmt);
|
|
2161
|
+
if (rel_count === 1) {
|
|
2162
|
+
return [
|
|
2163
|
+
{
|
|
2164
|
+
key: `dynamic ${relation}`,
|
|
2165
|
+
value: replaceTempAttributes(finalExpectedElementXpath),
|
|
2166
|
+
},
|
|
2167
|
+
];
|
|
2168
|
+
}
|
|
2169
|
+
if (rel_count > 1) {
|
|
2170
|
+
if (isIndex) {
|
|
2171
|
+
finalExpectedElementXpath = findXpathWithIndex(finalExpectedElementXpath, refExpectElement[refExpectElement.length - 1], docmt, rel_count);
|
|
2172
|
+
if (finalExpectedElementXpath) {
|
|
2173
|
+
return [
|
|
2174
|
+
{
|
|
2175
|
+
key: `dynamic ${relation}${isIndex ? " index" : ""}`,
|
|
2176
|
+
value: replaceTempAttributes(finalExpectedElementXpath),
|
|
2177
|
+
},
|
|
2178
|
+
];
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2147
2183
|
};
|
|
2148
2184
|
const referenceXpath = {
|
|
2149
2185
|
findRelativeXpath,
|