ff-dom 1.0.18-beta.5 → 1.0.18

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.
@@ -865,9 +865,9 @@ const getReferenceElementsXpath = (domNode, docmt, isTarget) => {
865
865
  }
866
866
  return xpaths1;
867
867
  };
868
- const parseXml = (xmlStr) => {
868
+ const parseXml = (xmlStr, type) => {
869
869
  if (window.DOMParser) {
870
- return new window.DOMParser().parseFromString(xmlStr, "text/xml");
870
+ return new window.DOMParser().parseFromString(xmlStr, type);
871
871
  }
872
872
  return null;
873
873
  };
@@ -1080,7 +1080,7 @@ const getUniqueParentXpath = (domNode, docmt, node, isTarget, nodeXpath, isIndex
1080
1080
  currentNode = currentNode.parentElement;
1081
1081
  }
1082
1082
  // Final constructed XPath
1083
- const finalXPath = xpathParts.join("");
1083
+ const finalXPath = xpathParts.join("") + nodeXpath;
1084
1084
  let count = getCountOfXPath(finalXPath, domNode, docmt);
1085
1085
  if (count === 1) {
1086
1086
  parentXpathCache.set(domNode, finalXPath); // Cache final result
@@ -1614,6 +1614,7 @@ const addAllXPathAttributes = (attributes, targetElemt, docmt, isIndex, isTarget
1614
1614
  catch (error) {
1615
1615
  console.log(error);
1616
1616
  }
1617
+ return xpathData$1;
1617
1618
  };
1618
1619
  const parseDOM = (element, doc, isIndex, isTarget) => {
1619
1620
  xpathData$1 = [];
@@ -2185,10 +2186,27 @@ const referenceXpath = {
2185
2186
  getReferenceElementXpath,
2186
2187
  };
2187
2188
 
2188
- const getElementFromShadowRoot = (element, selector) => {
2189
- const shadowRoot = element.shadowRoot;
2190
- if (shadowRoot && !selector.includes("dynamic")) {
2191
- return shadowRoot.querySelector(selector);
2189
+ const getElementFromShadowRoot = (el, selector) => {
2190
+ // const shadowRoot = (element as HTMLElement).shadowRoot;
2191
+ // if (shadowRoot && !selector.includes("dynamic")) {
2192
+ // return shadowRoot.querySelector(selector);
2193
+ // }
2194
+ const elements = Array.from(el.querySelectorAll('*'));
2195
+ try {
2196
+ for (let i = 0; i < elements.length; i++) {
2197
+ if (elements[i].shadowRoot) {
2198
+ const { shadowRoot } = elements[i];
2199
+ if (shadowRoot) {
2200
+ getElementFromShadowRoot(shadowRoot, selector);
2201
+ if (shadowRoot && !selector.includes("dynamic")) {
2202
+ return shadowRoot.querySelector(selector);
2203
+ }
2204
+ }
2205
+ }
2206
+ }
2207
+ }
2208
+ catch (error) {
2209
+ console.log(error);
2192
2210
  }
2193
2211
  return null;
2194
2212
  };
@@ -2222,30 +2240,27 @@ const relations = [
2222
2240
  "/preceding",
2223
2241
  "/following",
2224
2242
  ];
2225
- function getElementFromXPath(tempDiv, xpath) {
2226
- let currentElement = tempDiv;
2227
- const window = currentElement.ownerDocument.defaultView;
2243
+ function getElementFromXPath(docmt, xpath) {
2244
+ const window = docmt.defaultView;
2228
2245
  if (!window)
2229
2246
  return null;
2230
2247
  const xpathEvaluator = new window.XPathEvaluator();
2231
- const xpathResult = xpathEvaluator.evaluate(xpath, currentElement.ownerDocument, //here even tempDiv can be passed
2232
- null, window.XPathResult.FIRST_ORDERED_NODE_TYPE, null);
2248
+ const xpathResult = xpathEvaluator.evaluate(xpath, docmt, null, window.XPathResult.FIRST_ORDERED_NODE_TYPE, null);
2233
2249
  return xpathResult.singleNodeValue;
2234
2250
  }
2235
- function checkReferenceElementIsValid(locator, relation, tempDiv) {
2251
+ function checkReferenceElementIsValid(locator, relation, docmt) {
2236
2252
  if (locator.includes(relation)) {
2237
2253
  const locatotSplitArray = locator.split(relation);
2238
2254
  const sourceLoc = locatotSplitArray[0].trim();
2239
- let currentElement = tempDiv;
2240
- const window = currentElement.ownerDocument.defaultView;
2255
+ const window = docmt.defaultView;
2241
2256
  if (!window)
2242
2257
  return null;
2243
2258
  if (!locator.includes("dynamic")) {
2244
2259
  const xpathEvaluator = new window.XPathEvaluator();
2245
- const xpathResult = xpathEvaluator.evaluate(sourceLoc, currentElement.ownerDocument, null, window.XPathResult.FIRST_ORDERED_NODE_TYPE, null);
2260
+ const xpathResult = xpathEvaluator.evaluate(sourceLoc, docmt, null, window.XPathResult.FIRST_ORDERED_NODE_TYPE, null);
2246
2261
  const sourceElement = xpathResult.singleNodeValue;
2247
2262
  if (sourceElement) {
2248
- const xpathResultComplete = xpathEvaluator.evaluate(locator, currentElement.ownerDocument, null, window.XPathResult.FIRST_ORDERED_NODE_TYPE, null);
2263
+ const xpathResultComplete = xpathEvaluator.evaluate(locator, docmt, null, window.XPathResult.FIRST_ORDERED_NODE_TYPE, null);
2249
2264
  const completeElement = xpathResultComplete.singleNodeValue;
2250
2265
  let relativeXpath;
2251
2266
  if (completeElement) {
@@ -2266,16 +2281,12 @@ function checkReferenceElementIsValid(locator, relation, tempDiv) {
2266
2281
  return null;
2267
2282
  }
2268
2283
  const getElementsFromHTML = (record, docmt) => {
2269
- const document = docmt;
2270
- // global.SVGElement = document.defaultView?.SVGElement!;
2271
- const tempDiv = document.createElement("div");
2272
- const elementsToRemove = document.querySelectorAll("script, style, link[rel='stylesheet'], meta, noscript, embed, object, param, source, svg");
2284
+ const elementsToRemove = docmt.querySelectorAll("script, style, link[rel='stylesheet'], meta, noscript, embed, object, param, source, svg");
2273
2285
  if (elementsToRemove) {
2274
2286
  elementsToRemove.forEach((tag) => {
2275
2287
  tag.remove();
2276
2288
  });
2277
2289
  }
2278
- tempDiv.innerHTML = document.body.innerHTML;
2279
2290
  const finalLocatorsSet = new Set();
2280
2291
  let finalLocators = [];
2281
2292
  function createLocator(base, overrides = {}) {
@@ -2349,209 +2360,199 @@ const getElementsFromHTML = (record, docmt) => {
2349
2360
  if (record.isShared.includes("Y")) {
2350
2361
  break locators;
2351
2362
  }
2352
- for (const relation of relations) {
2353
- try {
2354
- let targetElement = null;
2355
- if (locator.value.startsWith("iframe")) {
2356
- const iframe = tempDiv.querySelector(locator.value);
2357
- if (iframe) {
2358
- const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
2359
- if (iframeDocument) {
2360
- targetElement = iframeDocument.querySelector(locator.value.slice(6));
2361
- }
2363
+ try {
2364
+ let targetElement = null;
2365
+ if (locator.value.startsWith("iframe")) {
2366
+ const iframe = docmt.querySelector(locator.value);
2367
+ if (iframe) {
2368
+ const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
2369
+ if (iframeDocument) {
2370
+ targetElement = iframeDocument.querySelector(locator.value.slice(6));
2362
2371
  }
2363
2372
  }
2364
- else {
2365
- const selectors = locator.value.split(">>>"); // Custom delimiter for shadow DOM
2366
- let currentElement = tempDiv;
2367
- for (const selector of selectors) {
2368
- if (currentElement) {
2369
- const trimmedSelector = selector.trim();
2370
- if (locator.name.includes("id") ||
2371
- trimmedSelector.startsWith("#")) {
2372
- targetElement = currentElement.querySelector("#" + trimmedSelector);
2373
- }
2374
- else if (locator.name.includes("className") ||
2375
- trimmedSelector.startsWith(".")) {
2376
- targetElement = currentElement.querySelector("." + trimmedSelector);
2377
- }
2378
- else if ((locator.name.includes("xpath") ||
2379
- trimmedSelector.startsWith("//")) &&
2380
- !locator.type.match("dynamic")) {
2381
- if (tempDiv.innerHTML) {
2382
- const normalizedXPath = normalizeXPath(trimmedSelector);
2383
- targetElement = getElementFromXPath(tempDiv, normalizedXPath);
2384
- if (targetElement) {
2385
- createLocator(locator, {
2386
- value: trimmedSelector,
2387
- isRecorded: String(locator.isRecorded).includes("N")
2388
- ? "N"
2389
- : "Y",
2390
- });
2391
- }
2392
- }
2393
- }
2394
- else {
2395
- targetElement = currentElement.querySelector(trimmedSelector);
2396
- if (!targetElement) {
2397
- targetElement = getElementFromShadowRoot(currentElement, trimmedSelector);
2398
- }
2399
- }
2400
- if (!targetElement &&
2401
- isSvg(currentElement) &&
2402
- !locator.type.match("dynamic")) {
2403
- targetElement = currentElement.querySelector(trimmedSelector);
2373
+ }
2374
+ else {
2375
+ const selectors = locator.value.split(">>>"); // Custom delimiter for shadow DOM
2376
+ for (const selector of selectors) {
2377
+ if (docmt) {
2378
+ const trimmedSelector = selector.trim();
2379
+ if (locator.name.includes("id") ||
2380
+ trimmedSelector.startsWith("#")) {
2381
+ targetElement = docmt.querySelector("#" + trimmedSelector);
2382
+ }
2383
+ else if (locator.name.includes("className") ||
2384
+ trimmedSelector.startsWith(".")) {
2385
+ targetElement = docmt.querySelector("." + trimmedSelector);
2386
+ }
2387
+ else if ((locator.name.includes("xpath") ||
2388
+ trimmedSelector.startsWith("//")) &&
2389
+ !locator.type.match("dynamic")) {
2390
+ const normalizedXPath = normalizeXPath(trimmedSelector);
2391
+ targetElement = getElementFromXPath(docmt, normalizedXPath);
2392
+ if (targetElement) {
2393
+ createLocator(locator, {
2394
+ value: trimmedSelector,
2395
+ isRecorded: String(locator.isRecorded).includes("N")
2396
+ ? "N"
2397
+ : "Y",
2398
+ });
2404
2399
  }
2405
- currentElement = targetElement;
2406
2400
  }
2407
2401
  else {
2408
- console.error("Element not found at:", selector);
2409
- break;
2402
+ targetElement = docmt.querySelector(trimmedSelector);
2403
+ if (!targetElement) {
2404
+ targetElement = getElementFromShadowRoot(docmt.body, trimmedSelector);
2405
+ }
2410
2406
  }
2411
2407
  }
2412
- }
2413
- const locatorExists = (name, value) => {
2414
- const key = `${name}:${value}`;
2415
- return finalLocatorsSet.has(key);
2416
- };
2417
- if (targetElement) {
2418
- const idValue = getId(targetElement);
2419
- if (idValue && !locatorExists("id", idValue)) {
2420
- record.locators.forEach((loc) => {
2421
- createLocator(loc, {
2422
- name: "id",
2423
- value: idValue,
2424
- isRecorded: loc.value === idValue && loc.name === "id"
2425
- ? loc.isRecorded
2426
- : "Y",
2427
- isSelfHealed: loc.value === idValue && loc.name === "id"
2428
- ? loc.isSelfHealed
2429
- : "Y",
2430
- });
2431
- });
2408
+ else {
2409
+ console.error("Element not found at:", selector);
2410
+ break;
2432
2411
  }
2433
- const textValue = getVisibleText(targetElement);
2434
- if (textValue) {
2435
- record.locators.forEach((loc) => {
2436
- createLocator(loc, {
2437
- name: "linkText",
2438
- type: "static",
2439
- value: textValue,
2440
- isRecorded: loc.value === textValue ? loc.isRecorded : "Y",
2441
- isSelfHealed: loc.value === textValue ? loc.isSelfHealed : "Y",
2442
- });
2412
+ }
2413
+ }
2414
+ const locatorExists = (name, value) => {
2415
+ const key = `${name}:${value}`;
2416
+ return finalLocatorsSet.has(key);
2417
+ };
2418
+ if (targetElement) {
2419
+ const idValue = getId(targetElement);
2420
+ if (idValue && !locatorExists("id", idValue)) {
2421
+ record.locators.forEach((loc) => {
2422
+ createLocator(loc, {
2423
+ name: "id",
2424
+ value: idValue,
2425
+ isRecorded: loc.value === idValue && loc.name === "id"
2426
+ ? loc.isRecorded
2427
+ : "Y",
2428
+ isSelfHealed: loc.value === idValue && loc.name === "id"
2429
+ ? loc.isSelfHealed
2430
+ : "Y",
2443
2431
  });
2444
- }
2445
- const nameLocator = getName(targetElement);
2446
- if (nameLocator && !locatorExists("name", nameLocator)) {
2447
- record.locators.forEach((loc) => {
2448
- createLocator(loc, {
2449
- name: "name",
2450
- type: "static",
2451
- value: nameLocator,
2452
- isRecorded: loc.value === nameLocator && loc.name === "name"
2453
- ? loc.isRecorded
2454
- : "Y",
2455
- isSelfHealed: loc.value === nameLocator && loc.name === "name"
2456
- ? loc.isSelfHealed
2457
- : "Y",
2458
- });
2432
+ });
2433
+ }
2434
+ const textValue = getVisibleText(targetElement);
2435
+ if (textValue) {
2436
+ record.locators.forEach((loc) => {
2437
+ createLocator(loc, {
2438
+ name: "linkText",
2439
+ type: "static",
2440
+ value: textValue,
2441
+ isRecorded: loc.value === textValue ? loc.isRecorded : "Y",
2442
+ isSelfHealed: loc.value === textValue ? loc.isSelfHealed : "Y",
2459
2443
  });
2460
- }
2461
- const classValue = getClassName(targetElement);
2462
- if (classValue &&
2463
- classValue.trim() !== "" &&
2464
- !locatorExists("className", classValue)) {
2465
- record.locators.forEach((loc) => {
2466
- createLocator(loc, {
2467
- name: "className",
2468
- value: classValue,
2469
- isRecorded: loc.value === classValue && loc.name === "className"
2470
- ? loc.isRecorded
2471
- : "Y",
2472
- isSelfHealed: loc.value === classValue && loc.name === "className"
2473
- ? loc.isSelfHealed
2474
- : "Y",
2475
- });
2444
+ });
2445
+ }
2446
+ const nameLocator = getName(targetElement);
2447
+ if (nameLocator && !locatorExists("name", nameLocator)) {
2448
+ record.locators.forEach((loc) => {
2449
+ createLocator(loc, {
2450
+ name: "name",
2451
+ type: "static",
2452
+ value: nameLocator,
2453
+ isRecorded: loc.value === nameLocator && loc.name === "name"
2454
+ ? loc.isRecorded
2455
+ : "Y",
2456
+ isSelfHealed: loc.value === nameLocator && loc.name === "name"
2457
+ ? loc.isSelfHealed
2458
+ : "Y",
2476
2459
  });
2477
- }
2478
- const fnValue = parseDOM(targetElement, document, false, true);
2460
+ });
2461
+ }
2462
+ const classValue = getClassName(targetElement);
2463
+ if (classValue &&
2464
+ classValue.trim() !== "" &&
2465
+ !locatorExists("className", classValue)) {
2479
2466
  record.locators.forEach((loc) => {
2480
2467
  createLocator(loc, {
2481
- name: 'xpath',
2482
- value: fnValue,
2483
- isRecorded: fnValue?.find((x) => x.value === loc.value)
2468
+ name: "className",
2469
+ value: classValue,
2470
+ isRecorded: loc.value === classValue && loc.name === "className"
2484
2471
  ? loc.isRecorded
2485
2472
  : "Y",
2486
- isSelfHealed: fnValue?.find((x) => x.value === loc.value)
2473
+ isSelfHealed: loc.value === classValue && loc.name === "className"
2487
2474
  ? loc.isSelfHealed
2488
2475
  : "Y",
2489
2476
  });
2490
2477
  });
2491
- for (const locator of record.locators) {
2492
- try {
2493
- for (const loc of record.locators) {
2494
- if (!loc.value)
2495
- continue;
2496
- for (const relation of relations) {
2497
- if (loc.value.includes(relation)) {
2498
- const relativeXpath = checkReferenceElementIsValid(loc.value, relation, tempDiv);
2499
- if (relativeXpath) {
2500
- createLocator(loc, {
2501
- name: "xpath",
2502
- value: relativeXpath,
2503
- isRecorded: locator.isRecorded !== "" &&
2504
- locator.isRecorded !== null
2505
- ? locator.isRecorded
2506
- : "Y",
2507
- });
2508
- break;
2509
- }
2478
+ }
2479
+ const xpathResults = parseDOM(targetElement, docmt, false, true);
2480
+ xpathResults.forEach((result) => {
2481
+ const fnValue = result.value;
2482
+ if (fnValue && !locatorExists(result.key.replace('xpath by', '').trim(), fnValue)) {
2483
+ record.locators.forEach((loc) => {
2484
+ createLocator(loc, {
2485
+ name: 'xpath',
2486
+ value: fnValue,
2487
+ isRecorded: loc.value === fnValue ? loc.isRecorded : 'Y',
2488
+ isSelfHealed: loc.value === fnValue ? loc.isSelfHealed : 'Y',
2489
+ });
2490
+ });
2491
+ }
2492
+ });
2493
+ for (const locator of record.locators) {
2494
+ try {
2495
+ for (const loc of record.locators) {
2496
+ if (!loc.value)
2497
+ continue;
2498
+ for (const relation of relations) {
2499
+ if (loc.value.includes(relation)) {
2500
+ const relativeXpath = checkReferenceElementIsValid(loc.value, relation, docmt);
2501
+ if (relativeXpath) {
2502
+ createLocator(loc, {
2503
+ name: "xpath",
2504
+ value: relativeXpath,
2505
+ isRecorded: locator.isRecorded !== "" &&
2506
+ locator.isRecorded !== null
2507
+ ? locator.isRecorded
2508
+ : "Y",
2509
+ });
2510
+ break;
2510
2511
  }
2511
2512
  }
2512
2513
  }
2513
2514
  }
2514
- catch (error) {
2515
- console.error("Error processing locator:", locator, error);
2516
- }
2517
2515
  }
2518
- const finalAutoHealedLocators = finalLocators.map((obj) => ({
2519
- ...obj,
2520
- value: cleanLocatorValue(obj.value, obj.name, obj.isRecorded),
2521
- }));
2522
- const finalUniqueAutoHealedLocators = finalAutoHealedLocators.reduce((unique, locator) => {
2523
- if (locator.value &&
2524
- !unique.some((l) => l.value === locator.value)) {
2525
- unique.push(locator);
2526
- }
2527
- return unique;
2528
- }, []);
2529
- const jsonResult = [
2530
- {
2531
- name: `${record.name}`,
2532
- desc: `${record.desc}`,
2533
- type: `${record.type}`,
2534
- locators: finalUniqueAutoHealedLocators.filter((locator) => locator?.value != null && locator.value !== ""),
2535
- isShared: `${record.isShared}`,
2536
- projectId: `${record.projectId}`,
2537
- projectType: `${record.projectType}`,
2538
- isRecorded: `${record.isRecorded}`,
2539
- folder: `${record.folder}`,
2540
- parentId: `${record.parentId}`,
2541
- parentName: `${record.parentName}`,
2542
- platform: `${record.platform}`,
2543
- licenseId: `${record.licenseId}`,
2544
- licenseType: `${record.licenseType}`,
2545
- userId: `${record.userId}`,
2546
- },
2547
- ];
2548
- return jsonResult;
2516
+ catch (error) {
2517
+ console.error("Error processing locator:", locator, error);
2518
+ }
2549
2519
  }
2520
+ const finalAutoHealedLocators = finalLocators.map((obj) => ({
2521
+ ...obj,
2522
+ value: cleanLocatorValue(obj.value, obj.name, obj.isRecorded),
2523
+ }));
2524
+ const finalUniqueAutoHealedLocators = finalAutoHealedLocators.reduce((unique, locator) => {
2525
+ if (locator.value &&
2526
+ !unique.some((l) => l.value === locator.value)) {
2527
+ unique.push(locator);
2528
+ }
2529
+ return unique;
2530
+ }, []);
2531
+ const jsonResult = [
2532
+ {
2533
+ name: `${record.name}`,
2534
+ desc: `${record.desc}`,
2535
+ type: `${record.type}`,
2536
+ locators: finalUniqueAutoHealedLocators.filter((locator) => locator?.value != null && locator.value !== ""),
2537
+ isShared: `${record.isShared}`,
2538
+ projectId: `${record.projectId}`,
2539
+ projectType: `${record.projectType}`,
2540
+ isRecorded: `${record.isRecorded}`,
2541
+ folder: `${record.folder}`,
2542
+ parentId: `${record.parentId}`,
2543
+ parentName: `${record.parentName}`,
2544
+ platform: `${record.platform}`,
2545
+ licenseId: `${record.licenseId}`,
2546
+ licenseType: `${record.licenseType}`,
2547
+ userId: `${record.userId}`,
2548
+ },
2549
+ ];
2550
+ return jsonResult;
2550
2551
  }
2551
- catch (error) {
2552
- console.error("Error processing locator:", locator, error);
2553
- continue;
2554
- }
2552
+ }
2553
+ catch (error) {
2554
+ console.error("Error processing locator:", locator, error);
2555
+ continue;
2555
2556
  }
2556
2557
  }
2557
2558
  catch (error) {