ff-dom 1.0.18-beta.6 → 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.
- package/dist/index.browser.cjs +198 -196
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +198 -196
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cdn.js +198 -196
- package/dist/types/browser/browser/xpath.d.ts +5 -2
- package/dist/types/browser/utils/xpath.d.ts +4 -1
- package/dist/types/browser/utils/xpathHelpers.d.ts +2 -2
- package/dist/types/node/node/xpath.d.ts +1 -1
- package/dist/xpath.mjs +7 -6
- package/dist/xpath.mjs.map +1 -1
- package/package.json +1 -1
- package/src/node/xpath.ts +7 -6
- package/src/utils/getElementsFromHTML.ts +240 -240
- package/src/utils/xpath.ts +3 -1
- package/src/utils/xpathHelpers.ts +2 -2
package/dist/index.browser.js
CHANGED
|
@@ -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,
|
|
870
|
+
return new window.DOMParser().parseFromString(xmlStr, type);
|
|
871
871
|
}
|
|
872
872
|
return null;
|
|
873
873
|
};
|
|
@@ -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 = (
|
|
2189
|
-
const shadowRoot = element.shadowRoot;
|
|
2190
|
-
if (shadowRoot && !selector.includes("dynamic")) {
|
|
2191
|
-
|
|
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(
|
|
2226
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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,135 +2360,126 @@ const getElementsFromHTML = (record, docmt) => {
|
|
|
2349
2360
|
if (record.isShared.includes("Y")) {
|
|
2350
2361
|
break locators;
|
|
2351
2362
|
}
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
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
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
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
|
-
|
|
2409
|
-
|
|
2402
|
+
targetElement = docmt.querySelector(trimmedSelector);
|
|
2403
|
+
if (!targetElement) {
|
|
2404
|
+
targetElement = getElementFromShadowRoot(docmt.body, trimmedSelector);
|
|
2405
|
+
}
|
|
2410
2406
|
}
|
|
2411
2407
|
}
|
|
2408
|
+
else {
|
|
2409
|
+
console.error("Element not found at:", selector);
|
|
2410
|
+
break;
|
|
2411
|
+
}
|
|
2412
2412
|
}
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
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",
|
|
2431
2431
|
});
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
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",
|
|
2443
2443
|
});
|
|
2444
|
-
}
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
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",
|
|
2459
2459
|
});
|
|
2460
|
-
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2460
|
+
});
|
|
2461
|
+
}
|
|
2462
|
+
const classValue = getClassName(targetElement);
|
|
2463
|
+
if (classValue &&
|
|
2464
|
+
classValue.trim() !== "" &&
|
|
2465
|
+
!locatorExists("className", classValue)) {
|
|
2466
|
+
record.locators.forEach((loc) => {
|
|
2467
|
+
createLocator(loc, {
|
|
2468
|
+
name: "className",
|
|
2469
|
+
value: classValue,
|
|
2470
|
+
isRecorded: loc.value === classValue && loc.name === "className"
|
|
2471
|
+
? loc.isRecorded
|
|
2472
|
+
: "Y",
|
|
2473
|
+
isSelfHealed: loc.value === classValue && loc.name === "className"
|
|
2474
|
+
? loc.isSelfHealed
|
|
2475
|
+
: "Y",
|
|
2476
2476
|
});
|
|
2477
|
-
}
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2477
|
+
});
|
|
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)) {
|
|
2481
2483
|
record.locators.forEach((loc) => {
|
|
2482
2484
|
createLocator(loc, {
|
|
2483
2485
|
name: 'xpath',
|
|
@@ -2486,71 +2488,71 @@ const getElementsFromHTML = (record, docmt) => {
|
|
|
2486
2488
|
isSelfHealed: loc.value === fnValue ? loc.isSelfHealed : 'Y',
|
|
2487
2489
|
});
|
|
2488
2490
|
});
|
|
2489
|
-
}
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
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;
|
|
2509
2511
|
}
|
|
2510
2512
|
}
|
|
2511
2513
|
}
|
|
2512
2514
|
}
|
|
2513
|
-
catch (error) {
|
|
2514
|
-
console.error("Error processing locator:", locator, error);
|
|
2515
|
-
}
|
|
2516
2515
|
}
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
}));
|
|
2521
|
-
const finalUniqueAutoHealedLocators = finalAutoHealedLocators.reduce((unique, locator) => {
|
|
2522
|
-
if (locator.value &&
|
|
2523
|
-
!unique.some((l) => l.value === locator.value)) {
|
|
2524
|
-
unique.push(locator);
|
|
2525
|
-
}
|
|
2526
|
-
return unique;
|
|
2527
|
-
}, []);
|
|
2528
|
-
const jsonResult = [
|
|
2529
|
-
{
|
|
2530
|
-
name: `${record.name}`,
|
|
2531
|
-
desc: `${record.desc}`,
|
|
2532
|
-
type: `${record.type}`,
|
|
2533
|
-
locators: finalUniqueAutoHealedLocators.filter((locator) => locator?.value != null && locator.value !== ""),
|
|
2534
|
-
isShared: `${record.isShared}`,
|
|
2535
|
-
projectId: `${record.projectId}`,
|
|
2536
|
-
projectType: `${record.projectType}`,
|
|
2537
|
-
isRecorded: `${record.isRecorded}`,
|
|
2538
|
-
folder: `${record.folder}`,
|
|
2539
|
-
parentId: `${record.parentId}`,
|
|
2540
|
-
parentName: `${record.parentName}`,
|
|
2541
|
-
platform: `${record.platform}`,
|
|
2542
|
-
licenseId: `${record.licenseId}`,
|
|
2543
|
-
licenseType: `${record.licenseType}`,
|
|
2544
|
-
userId: `${record.userId}`,
|
|
2545
|
-
},
|
|
2546
|
-
];
|
|
2547
|
-
return jsonResult;
|
|
2516
|
+
catch (error) {
|
|
2517
|
+
console.error("Error processing locator:", locator, error);
|
|
2518
|
+
}
|
|
2548
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;
|
|
2549
2551
|
}
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2552
|
+
}
|
|
2553
|
+
catch (error) {
|
|
2554
|
+
console.error("Error processing locator:", locator, error);
|
|
2555
|
+
continue;
|
|
2554
2556
|
}
|
|
2555
2557
|
}
|
|
2556
2558
|
catch (error) {
|