ff-dom 2.0.0 → 2.0.2

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.
@@ -1,953 +0,0 @@
1
- import { parseDOM } from "./xpath.ts";
2
- import {
3
- findXpathWithIndex,
4
- getShadowRoot,
5
- getTextContent,
6
- escapeCharacters,
7
- getCountOfXPath,
8
- checkBlockedAttributes,
9
- getAbsoluteXPath,
10
- isSvg,
11
- getCombinationXpath,
12
- getTextXpathFunction,
13
- replaceTempAttributes,
14
- replaceActualAttributes,
15
- getReferenceElementsXpath,
16
- getRelativeXPath,
17
- findMatchingParenthesis,
18
- removeParenthesis
19
- } from "./xpathHelpers.ts";
20
-
21
- let xpathDataWithIndex: any[] = [];
22
- let xpathData: { key: string; value: string }[] = [];
23
- const reWhiteSpace = /^[\S]+( [\S]+)*$/gi;
24
-
25
- export const findRelativeXpath = (
26
- element1: HTMLElement | Element,
27
- element2: HTMLElement | Element,
28
- docmt: Document,
29
- xpaths1: any[],
30
- xpaths2: any[],
31
- isIndex: boolean,
32
- multiElementReferenceMode: boolean = false
33
- ) => {
34
- // debugger;
35
- const par1 = element1.parentElement;
36
- const par2 = element2.parentElement;
37
- let rel_xpath: any[] = [];
38
-
39
- let tempElement;
40
- let finalXpaths: any[] = [];
41
-
42
- if (isIndex) {
43
- if (xpathDataWithIndex.length) {
44
- const xpathWithIndex = findXpathWithIndex(
45
- xpathDataWithIndex[0].value,
46
- element2,
47
- element2.ownerDocument,
48
- xpathDataWithIndex[0].count
49
- );
50
- if (xpathWithIndex) {
51
- finalXpaths = finalXpaths.concat({
52
- key: `${xpathDataWithIndex[0]?.key
53
- ? xpathDataWithIndex[0]?.key
54
- : "xpath with "
55
- } index`,
56
- value: xpathWithIndex,
57
- });
58
- xpathDataWithIndex.pop();
59
- }
60
- }
61
- }
62
-
63
- if (!finalXpaths.length) {
64
- // both are same
65
- if (element1.isSameNode(element2)) {
66
- // rel_xpath = xpath1 + "/self::" + element1.tagName;
67
- rel_xpath = getXpathRelationExpression(
68
- element1,
69
- element2,
70
- "self",
71
- xpaths1,
72
- xpaths2,
73
- isIndex,
74
- multiElementReferenceMode
75
- );
76
- if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);
77
- }
78
-
79
- // parent
80
- tempElement = element1.parentElement;
81
-
82
- if (tempElement === element2) {
83
- rel_xpath = getXpathRelationExpression(
84
- element1,
85
- element2,
86
- "parent",
87
- xpaths1,
88
- xpaths2,
89
- isIndex,
90
- multiElementReferenceMode
91
- );
92
- if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);
93
- }
94
-
95
- // ancestor
96
- tempElement = element1.parentElement;
97
-
98
- while (tempElement !== null) {
99
- if (tempElement === element2) {
100
- rel_xpath = getXpathRelationExpression(
101
- element1,
102
- element2,
103
- "ancestor",
104
- xpaths1,
105
- xpaths2,
106
- isIndex,
107
- multiElementReferenceMode
108
- );
109
- if (rel_xpath) {
110
- finalXpaths = finalXpaths.concat(rel_xpath);
111
- break;
112
- }
113
- }
114
-
115
- tempElement = tempElement.parentNode;
116
- }
117
-
118
- // ancestor-or-self
119
- tempElement = element1;
120
- do {
121
- if (tempElement === element2) {
122
- rel_xpath = getXpathRelationExpression(
123
- element1,
124
- element2,
125
- "ancestor-or-self",
126
- xpaths1,
127
- xpaths2,
128
- isIndex,
129
- multiElementReferenceMode
130
- );
131
- if (rel_xpath) {
132
- finalXpaths = finalXpaths.concat(rel_xpath);
133
- break;
134
- }
135
- }
136
-
137
- tempElement = tempElement.parentNode;
138
- } while (tempElement !== null);
139
-
140
- // both has same parent
141
- if (par1?.isSameNode(par2)) {
142
- for (
143
- let m = element1.nextElementSibling;
144
- m != null;
145
- m = m.nextElementSibling
146
- ) {
147
- if (m != null && m.isSameNode(element2)) {
148
- rel_xpath = getXpathRelationExpression(
149
- element1,
150
- element2,
151
- "following-sibling",
152
- xpaths1,
153
- xpaths2,
154
- isIndex,
155
- multiElementReferenceMode
156
- );
157
- if (rel_xpath) {
158
- finalXpaths = finalXpaths.concat(rel_xpath);
159
- break;
160
- }
161
- }
162
- }
163
-
164
- for (
165
- let n = element1.previousElementSibling;
166
- n != null;
167
- n = n.previousElementSibling
168
- ) {
169
- if (n != null && n.isSameNode(element2)) {
170
- rel_xpath = getXpathRelationExpression(
171
- element1,
172
- element2,
173
- "preceding-sibling",
174
- xpaths1,
175
- xpaths2,
176
- isIndex,
177
- multiElementReferenceMode
178
- );
179
- if (rel_xpath) {
180
- finalXpaths = finalXpaths.concat(rel_xpath);
181
- break;
182
- }
183
- }
184
- }
185
- }
186
-
187
- // child
188
- if (element1?.children?.length) {
189
- for (let m = element1.children[0]; m !== null; m = m?.nextElementSibling!) {
190
- if (m === element2) {
191
- rel_xpath = getXpathRelationExpression(
192
- element1,
193
- element2,
194
- "child",
195
- xpaths1,
196
- xpaths2,
197
- isIndex,
198
- multiElementReferenceMode
199
- );
200
- if (rel_xpath) {
201
- finalXpaths = finalXpaths.concat(rel_xpath);
202
- break;
203
- }
204
- }
205
- }
206
- }
207
-
208
- // following
209
- const relation = element1.compareDocumentPosition(element2);
210
- if (relation === 2) {
211
- rel_xpath = getXpathRelationExpression(
212
- element1,
213
- element2,
214
- "preceding",
215
- xpaths1,
216
- xpaths2,
217
- isIndex,
218
- multiElementReferenceMode
219
- );
220
- }
221
-
222
- if (relation === 4) {
223
- rel_xpath = getXpathRelationExpression(
224
- element1,
225
- element2,
226
- "following",
227
- xpaths1,
228
- xpaths2,
229
- isIndex,
230
- multiElementReferenceMode
231
- );
232
- }
233
- if (rel_xpath) {
234
- finalXpaths = finalXpaths.concat(rel_xpath);
235
- }
236
-
237
- const descendantXpath = getDescendantXpath(
238
- [element1, element2],
239
- docmt,
240
- xpaths1,
241
- xpaths2,
242
- "descendant",
243
- isIndex,
244
- multiElementReferenceMode
245
- );
246
- if (descendantXpath) finalXpaths = finalXpaths.concat(descendantXpath);
247
-
248
- const descendantSelfXpath = getDescendantXpath(
249
- [element1, element2],
250
- docmt,
251
- xpaths1,
252
- xpaths2,
253
- "descedant-or-self",
254
- isIndex,
255
- multiElementReferenceMode
256
- );
257
- if (descendantSelfXpath) {
258
- finalXpaths = finalXpaths.concat(descendantSelfXpath);
259
- }
260
- }
261
-
262
- if (finalXpaths.length) {
263
- if (finalXpaths.length > 1) {
264
- finalXpaths.sort(function (a, b) {
265
- return a.value.length - b.value.length;
266
- });
267
- }
268
-
269
- if (finalXpaths.filter((x) => !x.key?.includes("index"))?.length) {
270
- return [finalXpaths.filter((x) => !x.key?.includes("index"))[0]];
271
- }
272
- return [finalXpaths[0]];
273
- }
274
- };
275
-
276
- const descendantExpression = (
277
- refExpectElement: Array<HTMLElement | Element>,
278
- xpath2: string,
279
- relation: string,
280
- docmt: Node,
281
- isIndex: any,
282
- expCommonParentXpathElements: string | any[],
283
- step4: string,
284
- refCommonParentXpathElementLength: number = 0,
285
- multiElementReferenceMode: boolean = false
286
- ) => {
287
- let finalExpectedElementXpath: string | undefined = "";
288
-
289
- if (
290
- xpath2.split(/\/(?=(?:[^']*\'[^\']*\')*[^\']*$)/g)?.length >=
291
- expCommonParentXpathElements.length
292
- ) {
293
- const xpaths2Els: string[] = [];
294
- const xpath2Elements = xpath2.split(/\/(?=(?:[^']*\'[^\']*\')*[^\']*$)/g);
295
- for (let x = 1; x <= expCommonParentXpathElements.length; x++) {
296
- xpaths2Els.unshift(
297
- x === expCommonParentXpathElements.length
298
- ? expCommonParentXpathElements[
299
- expCommonParentXpathElements.length - x
300
- ]
301
- : xpath2Elements[xpath2Elements.length - x]
302
- );
303
- }
304
- const traverseXpath = getTraverseXpathExpression(
305
- `${step4 +
306
- (refCommonParentXpathElementLength
307
- ? "]".repeat(refCommonParentXpathElementLength)
308
- : "")
309
- }`,
310
- xpaths2Els,
311
- refExpectElement[refExpectElement.length - 1],
312
- refExpectElement,
313
- docmt,
314
- relation,
315
- isIndex,
316
- multiElementReferenceMode
317
- );
318
- if (traverseXpath) {
319
- return traverseXpath;
320
- }
321
- } else {
322
- finalExpectedElementXpath = `//${step4 +
323
- (refCommonParentXpathElementLength
324
- ? "]".repeat(refCommonParentXpathElementLength)
325
- : "")
326
- }/${relation}::${replaceActualAttributes(
327
- xpath2,
328
- refExpectElement[refExpectElement.length - 1]
329
- )}`;
330
- let rel_count = getCountOfXPath(
331
- finalExpectedElementXpath,
332
- refExpectElement[refExpectElement.length - 1],
333
- docmt
334
- );
335
- if (rel_count === 1) {
336
- return [
337
- {
338
- key: `dynamic ${relation}`,
339
- value: replaceTempAttributes(finalExpectedElementXpath),
340
- },
341
- ];
342
- }
343
- if (rel_count > 1) {
344
- if (isIndex) {
345
- finalExpectedElementXpath = findXpathWithIndex(
346
- finalExpectedElementXpath,
347
- refExpectElement[refExpectElement.length - 1],
348
- docmt,
349
- rel_count
350
- );
351
- if (finalExpectedElementXpath) {
352
- rel_count = getCountOfXPath(
353
- finalExpectedElementXpath,
354
- refExpectElement[refExpectElement.length - 1],
355
- docmt
356
- );
357
- if (rel_count === 1) {
358
- return [
359
- {
360
- key: `dynamic ${relation} ${isIndex ? " index" : ""}`,
361
- value: replaceTempAttributes(finalExpectedElementXpath),
362
- },
363
- ];
364
- }
365
- }
366
- }
367
- }
368
- }
369
- };
370
-
371
- const getDescendantXpath = (
372
- refExpectElement: Array<HTMLElement | Element>,
373
- docmt: Document,
374
- xpaths1: { key: string; value: string }[],
375
- xpaths2: { key: string; value: string }[],
376
- relation: "descendant" | "descedant-or-self",
377
- isIndex: boolean = false,
378
- multiElementReferenceMode: boolean = false
379
- ) => {
380
- const refElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 2];
381
- const expElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 1];
382
- const expElementDocmnt = getShadowRoot(expElement) ?? expElement.ownerDocument;
383
-
384
- const refAbsoluteXpath =
385
- xpaths1.find((x) => x?.key?.includes("absolute"))?.value ||
386
- getAbsoluteXPath(refElement, refElement.ownerDocument);
387
-
388
- const refFullXpathElements: any[] = [];
389
- const refFullXpathElementsWithoutNumber: any[] = [];
390
- refAbsoluteXpath.split("/").map((x) => refFullXpathElements.push(x));
391
- refFullXpathElements.map((x) =>
392
- refFullXpathElementsWithoutNumber.push(x.replace(/\[([0-9]+)\]/gm, ""))
393
- );
394
-
395
- const expAbsoluteXpath =
396
- xpaths2.find((x) => x?.key?.includes("absolute"))?.value ||
397
- getAbsoluteXPath(expElement, expElement.ownerDocument);
398
-
399
- const expFullXpathElements: any[] = [];
400
- const expFullXpathElementsWithoutNumber: any[] = [];
401
- expAbsoluteXpath.split("/").map((x) => expFullXpathElements.push(x));
402
- expFullXpathElements.map((x) =>
403
- expFullXpathElementsWithoutNumber.push(x.replace(/\[([0-9]+)\]/gm, ""))
404
- );
405
-
406
- for (
407
- var parentElementNumber = 0;
408
- parentElementNumber < refFullXpathElements.length;
409
- parentElementNumber++
410
- ) {
411
- if (
412
- refFullXpathElements[parentElementNumber] !=
413
- expFullXpathElements[parentElementNumber]
414
- ) {
415
- break;
416
- }
417
- }
418
-
419
- const refCommonParentXpathElements = [];
420
- for (let i = parentElementNumber - 1; i < refFullXpathElements.length; i++) {
421
- if (refFullXpathElements[i]) {
422
- refCommonParentXpathElements.push(refFullXpathElementsWithoutNumber[i]);
423
- }
424
- }
425
-
426
- const expCommonParentXpathElements: string[] = [];
427
- for (
428
- let j =
429
- relation === "descendant" ? parentElementNumber : parentElementNumber - 1;
430
- j < expFullXpathElements.length;
431
- j++
432
- ) {
433
- if (expFullXpathElements[j]) {
434
- if (expCommonParentXpathElements.length)
435
- expCommonParentXpathElements.push(expFullXpathElementsWithoutNumber[j]);
436
- else
437
- expCommonParentXpathElements.push(
438
- expFullXpathElementsWithoutNumber[j].replace(/\[([0-9]+)\]/gm, "")
439
- );
440
- }
441
- }
442
-
443
- xpathData = xpaths2;
444
-
445
- let nodeXpath2;
446
- if (refExpectElement[refExpectElement.length - 2].textContent) {
447
- if (
448
- !reWhiteSpace.test(
449
- refExpectElement[refExpectElement.length - 2].textContent
450
- )
451
- ) {
452
- nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])
453
- ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName
454
- }' and ${getTextXpathFunction(
455
- refExpectElement[refExpectElement.length - 2]
456
- )})]`
457
- : `${refExpectElement[refExpectElement.length - 2].tagName
458
- }[${getTextXpathFunction(
459
- refExpectElement[refExpectElement.length - 2]
460
- )}]`;
461
- } else {
462
- nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])
463
- ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName
464
- }' and .=${escapeCharacters(
465
- getTextContent(refExpectElement[refExpectElement.length - 2])
466
- )}]`
467
- : `${refExpectElement[refExpectElement.length - 2].tagName
468
- }[.=${escapeCharacters(
469
- getTextContent(refExpectElement[refExpectElement.length - 2])
470
- )}]`;
471
- }
472
-
473
- refCommonParentXpathElements[refCommonParentXpathElements.length - 1] =
474
- nodeXpath2;
475
-
476
- const refCommonParentXpath = refCommonParentXpathElements.join("[");
477
- const refCommonParentXpathElementLength =
478
- refCommonParentXpathElements.length - 1;
479
-
480
- const step4 = refCommonParentXpath;
481
-
482
- for (let i = 0; i < xpathData.length; i++) {
483
- let xpath2;
484
-
485
- if (xpathData[i].value.startsWith("//")) {
486
- xpath2 = xpathData[i].value.substring(
487
- xpathData[i].value.indexOf("//") + 2
488
- );
489
- } else {
490
- xpath2 = xpathData[i].value; // No need to modify the value
491
- }
492
- if (xpath2) {
493
- return descendantExpression(
494
- refExpectElement,
495
- xpath2,
496
- relation,
497
- expElementDocmnt || docmt,
498
- isIndex,
499
- expCommonParentXpathElements,
500
- step4,
501
- refCommonParentXpathElementLength,
502
- multiElementReferenceMode
503
- );
504
- }
505
- }
506
- }
507
-
508
- if (refExpectElement[refExpectElement.length - 2].attributes) {
509
- for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]
510
- .attributes)) {
511
- if (
512
- checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)
513
- ) {
514
- let attrValue = attrName.nodeValue;
515
- if (attrValue) {
516
- attrValue = attrValue.replace("removePointers", "");
517
- const elementName = attrName.name;
518
-
519
- nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])
520
- ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName
521
- }' and @${elementName}=${escapeCharacters(attrValue)}]`
522
- : `${refExpectElement[refExpectElement.length - 2].tagName
523
- }[@${elementName}=${escapeCharacters(attrValue)}]`;
524
-
525
- refCommonParentXpathElements[
526
- refCommonParentXpathElements.length - 1
527
- ] = nodeXpath2;
528
-
529
- const refCommonParentXpath = refCommonParentXpathElements.join("[");
530
- const refCommonParentXpathElementLength =
531
- refCommonParentXpathElements.length - 1;
532
-
533
- const step4 = refCommonParentXpath;
534
-
535
- for (let i = 0; i < xpathData.length; i++) {
536
- let xpath2;
537
- if (xpathData[i].value.startsWith("//")) {
538
- xpath2 = xpathData[i].value.substring(
539
- xpathData[i].value.indexOf("//") + 2
540
- );
541
- } else {
542
- xpath2 = xpathData[i].value; // No need to modify the value
543
- }
544
-
545
- return descendantExpression(
546
- refExpectElement,
547
- xpath2,
548
- relation,
549
- expElementDocmnt || docmt,
550
- isIndex,
551
- expCommonParentXpathElements,
552
- step4,
553
- refCommonParentXpathElementLength,
554
- multiElementReferenceMode
555
- );
556
- }
557
- }
558
- }
559
- }
560
-
561
- for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]
562
- .attributes)) {
563
- if (
564
- checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)
565
- ) {
566
- let attrValue = attrName.nodeValue;
567
- if (attrValue) {
568
- attrValue = attrValue.replace("removePointers", "");
569
- const combinationXpath = getCombinationXpath(
570
- attrName,
571
- refExpectElement[refExpectElement.length - 2]
572
- );
573
- if (combinationXpath) {
574
- if (combinationXpath.startsWith("//")) {
575
- nodeXpath2 = combinationXpath.substring(
576
- combinationXpath.indexOf("//") + 2
577
- );
578
- } else {
579
- nodeXpath2 = combinationXpath; // No need to modify the value
580
- }
581
-
582
- refCommonParentXpathElements[
583
- refCommonParentXpathElements.length - 1
584
- ] = nodeXpath2;
585
-
586
- const refCommonParentXpath = refCommonParentXpathElements.join("[");
587
- const refCommonParentXpathElementLength =
588
- refCommonParentXpathElements.length - 1;
589
-
590
- const step4 = refCommonParentXpath;
591
-
592
- for (let i = 0; i < xpathData.length; i++) {
593
- let xpath2;
594
- if (xpathData[i].value.startsWith("//")) {
595
- xpath2 = xpathData[i].value.substring(
596
- xpathData[i].value.indexOf("//") + 2
597
- );
598
- } else {
599
- xpath2 = xpathData[i].value; // No need to modify the value
600
- }
601
-
602
- return descendantExpression(
603
- refExpectElement,
604
- xpath2,
605
- relation,
606
- expElementDocmnt || docmt,
607
- isIndex,
608
- expCommonParentXpathElements,
609
- step4,
610
- refCommonParentXpathElementLength,
611
- multiElementReferenceMode
612
- );
613
- }
614
- }
615
- }
616
- }
617
- }
618
- }
619
-
620
- const refCommonParentXpath = refCommonParentXpathElements.join("[");
621
- const refCommonParentXpathElementLength =
622
- refCommonParentXpathElements.length - 1;
623
- const step4 = refCommonParentXpath;
624
- const traverseXpath = getTraverseXpathExpression(
625
- `${step4 +
626
- (refCommonParentXpathElementLength
627
- ? "]".repeat(refCommonParentXpathElementLength)
628
- : "")
629
- }`,
630
- expCommonParentXpathElements,
631
- refExpectElement[refExpectElement.length - 1],
632
- refExpectElement,
633
- docmt,
634
- relation,
635
- isIndex,
636
- multiElementReferenceMode
637
- );
638
- if (traverseXpath) {
639
- return traverseXpath;
640
- }
641
- };
642
-
643
- const getXpathRelationExpression = (
644
- element1: HTMLElement | Element,
645
- element2: HTMLElement | Element,
646
- relation: string,
647
- xpath1: any[],
648
- xpath2: any[],
649
- isIndex: boolean,
650
- multiElementReferenceMode: boolean
651
- ) => {
652
- let xpaths1;
653
- let xpaths2;
654
- console.log('getXpathRelationExpression', relation)
655
- const finalXpaths: { key: string; value: any }[] = [];
656
-
657
- try {
658
- xpaths1 = xpath1.filter((x) => !x?.key?.includes("absolute"));
659
-
660
- xpaths2 = xpath2.filter((x) => !x?.key?.includes("absolute"));
661
-
662
- for (let i = 0; i < xpaths1.length; i++) {
663
- for (let j = 0; j < xpaths2.length; j++) {
664
- let rel_xpath: string | undefined = `//${xpaths1[i].value.indexOf("//") !== 0
665
- ? replaceActualAttributes(xpaths1[i].value, element1)
666
- : replaceActualAttributes(
667
- xpaths1[i].value.substring(xpaths1[i].value.indexOf("//") + 2),
668
- element1
669
- )
670
- }/${relation}::${xpaths2[j].value.indexOf("//") !== 0
671
- ? replaceActualAttributes(xpaths2[j].value, element2)
672
- : replaceActualAttributes(
673
- xpaths2[j].value.substring(xpaths2[j].value.indexOf("//") + 2),
674
- element2
675
- )
676
- }`;
677
- console.log('getXpathRelationExpression', rel_xpath)
678
- const rel_count = getCountOfXPath(
679
- rel_xpath,
680
- element2,
681
- element2.ownerDocument
682
- );
683
- if (rel_count > 1) {
684
- if (isIndex) {
685
- rel_xpath = findXpathWithIndex(
686
- rel_xpath,
687
- element2,
688
- element2.ownerDocument,
689
- rel_count
690
- );
691
- if (rel_xpath) {
692
- finalXpaths.push({
693
- key: `dynamic ${relation}${isIndex ? " index" : ""}`,
694
- value: replaceTempAttributes(rel_xpath),
695
- });
696
- return finalXpaths;
697
- }
698
- } else if (rel_count > 1) {
699
- if (xpathDataWithIndex.length) {
700
- if (rel_count < xpathDataWithIndex[0].count) {
701
- xpathDataWithIndex.pop();
702
- xpathDataWithIndex.push({
703
- key: `relative xpath by relative child ${isIndex ? "index" : ""
704
- }`,
705
- value: rel_xpath,
706
- count: rel_count,
707
- });
708
- }
709
- } else {
710
- xpathDataWithIndex.push({
711
- key: `relative xpath by relative child ${isIndex ? "index" : ""
712
- }`,
713
- value: rel_xpath,
714
- count: rel_count,
715
- });
716
- }
717
- }
718
- } else if (rel_count === 1) {
719
- finalXpaths.push({
720
- key: `dynamic ${relation}`,
721
- value: replaceTempAttributes(rel_xpath),
722
- });
723
- return finalXpaths;
724
- }
725
- }
726
- }
727
- if (!finalXpaths.length) {
728
- for (let i = 0; i < xpaths1.length; i++) {
729
- for (let j = 0; j < xpaths2.length; j++) {
730
- const tempPath = `${xpaths2[j].value.indexOf("//") !== 0
731
- ? xpaths2[j].value
732
- : xpaths2[j].value.substring(xpaths2[j].value.indexOf("//") + 2)
733
- }`;
734
- const xpath2Elements: string[] = tempPath.split(
735
- /\/(?=(?:[^']*\'[^\']*\')*[^\']*$)/g
736
- );
737
- if (xpath2Elements.length > 1) {
738
- const traverseXpath = getTraverseXpathExpression(
739
- `${xpaths1[i].value.indexOf("//") !== 0
740
- ? replaceActualAttributes(xpaths1[i].value, element1)
741
- : replaceActualAttributes(
742
- xpaths1[i].value.substring(
743
- xpaths1[i].value.indexOf("//") + 2
744
- ),
745
- element1
746
- )
747
- }`,
748
- xpath2Elements,
749
- element2,
750
- [element1, element2],
751
- element2.ownerDocument,
752
- relation,
753
- isIndex,
754
- multiElementReferenceMode
755
- );
756
-
757
- console.log('getXpathRelationExpression traverseXpath', traverseXpath)
758
- if (traverseXpath) {
759
- finalXpaths.concat(traverseXpath);
760
- return finalXpaths;
761
- }
762
- }
763
- }
764
- }
765
- }
766
- } catch (error) {
767
- console.log(error);
768
- }
769
-
770
- return finalXpaths;
771
- };
772
-
773
- const getReferenceElementXpath = (element: HTMLElement | Element) => {
774
- let xpaths1: {
775
- key: string;
776
- value: string;
777
- }[] = [];
778
-
779
- xpaths1 = parseDOM(element, element.ownerDocument, false, false);
780
-
781
- if (!xpaths1?.length) {
782
- xpaths1 = parseDOM(element, element.ownerDocument, true, false);
783
- xpaths1 = xpaths1?.map((x) =>
784
- x.value.charAt(0) == "(" &&
785
- findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf("[")
786
- ? { key: "", value: removeParenthesis(x.value) }
787
- : { key: "", value: x.value }
788
- );
789
- } else {
790
- let xpaths = parseDOM(element, element.ownerDocument, true, false);
791
- if (xpaths?.length) {
792
- xpaths = xpaths?.map((x) =>
793
- x.value.charAt(0) == "(" &&
794
- findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf("[")
795
- ? { key: "", value: removeParenthesis(x.value) }
796
- : { key: "", value: x.value }
797
- );
798
- xpaths1 = xpaths1.concat(xpaths);
799
- }
800
- }
801
-
802
- if (!xpaths1?.length) {
803
- xpaths1 = [
804
- {
805
- key: "",
806
- value: getRelativeXPath(element, element.ownerDocument, false, false, Array.from(element.attributes)),
807
- },
808
- ];
809
- }
810
-
811
- if (!xpaths1?.length) {
812
- xpaths1 = [
813
- {
814
- key: "",
815
- value: getRelativeXPath(element, element.ownerDocument, true, false, Array.from(element.attributes)),
816
- },
817
- ];
818
- xpaths1 = xpaths1?.map((x) =>
819
- x.value.charAt(0) == "(" &&
820
- findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf("[")
821
- ? { key: "", value: removeParenthesis(x.value) }
822
- : { key: "", value: x.value }
823
- );
824
- }
825
-
826
- if (!xpaths1?.length) {
827
- xpaths1 = getReferenceElementsXpath(element, element.ownerDocument, false);
828
- } else {
829
- const xpaths = getReferenceElementsXpath(
830
- element,
831
- element.ownerDocument,
832
- false
833
- );
834
- if (xpaths?.length) {
835
- xpaths1 = xpaths1.concat(xpaths);
836
- }
837
- }
838
-
839
- const referenceXpathElement = getAbsoluteXPath(
840
- element,
841
- element.ownerDocument
842
- );
843
- xpaths1 = xpaths1.filter((x) => x.value !== referenceXpathElement);
844
-
845
- xpaths1.push({
846
- key: "absolute xpath",
847
- value: referenceXpathElement.slice(1),
848
- });
849
-
850
- return xpaths1;
851
- };
852
-
853
- const getTraverseXpathExpression = (
854
- xpathe1: string,
855
- absoluteXpathElements: string[],
856
- element2: HTMLElement | Element,
857
- refExpectElement: Array<HTMLElement | Element>,
858
- docmt: Node,
859
- relation: string,
860
- isIndex: boolean,
861
- multiElementReferenceMode: boolean
862
- ) => {
863
- let finalExpectedElementXpath: string | undefined;
864
- if (!multiElementReferenceMode) {
865
- for (let x = 1; x <= absoluteXpathElements.length; x++) {
866
- const xpath2 = absoluteXpathElements
867
- .slice(absoluteXpathElements.length - x, absoluteXpathElements.length)
868
- .join("/");
869
- finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(
870
- xpath2,
871
- element2
872
- )}`;
873
- const rel_count = getCountOfXPath(
874
- finalExpectedElementXpath,
875
- element2,
876
- docmt
877
- );
878
- if (rel_count === 1) {
879
- return [
880
- {
881
- key: `dynamic ${relation}`,
882
- value: replaceTempAttributes(finalExpectedElementXpath),
883
- },
884
- ];
885
- }
886
- if (rel_count > 1) {
887
- if (isIndex) {
888
- finalExpectedElementXpath = findXpathWithIndex(
889
- finalExpectedElementXpath,
890
- refExpectElement[refExpectElement.length - 1],
891
- docmt,
892
- rel_count
893
- );
894
- if (finalExpectedElementXpath) {
895
- return [
896
- {
897
- key: `dynamic ${relation}${isIndex ? " index" : ""}`,
898
- value: replaceTempAttributes(finalExpectedElementXpath),
899
- },
900
- ];
901
- }
902
- }
903
- }
904
- }
905
- } else {
906
- const xpath2 = absoluteXpathElements.join("/");
907
- finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(
908
- xpath2,
909
- element2
910
- )}`;
911
- const rel_count = getCountOfXPath(
912
- finalExpectedElementXpath,
913
- element2,
914
- docmt
915
- );
916
- if (rel_count === 1) {
917
- return [
918
- {
919
- key: `dynamic ${relation}`,
920
- value: replaceTempAttributes(finalExpectedElementXpath),
921
- },
922
- ];
923
- }
924
- if (rel_count > 1) {
925
- if (isIndex) {
926
- finalExpectedElementXpath = findXpathWithIndex(
927
- finalExpectedElementXpath,
928
- refExpectElement[refExpectElement.length - 1],
929
- docmt,
930
- rel_count
931
- );
932
- if (finalExpectedElementXpath) {
933
- return [
934
- {
935
- key: `dynamic ${relation}${isIndex ? " index" : ""}`,
936
- value: replaceTempAttributes(finalExpectedElementXpath),
937
- },
938
- ];
939
- }
940
- }
941
- }
942
- }
943
- };
944
-
945
- const referenceXpath = {
946
- findRelativeXpath,
947
- getDescendantXpath,
948
- getXpathRelationExpression,
949
- getTraverseXpathExpression,
950
- getReferenceElementXpath,
951
- };
952
-
953
- export default referenceXpath;