mx-cloud 0.0.25 → 0.0.26

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/build/selector.js CHANGED
@@ -9,845 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.generateFieldSelectorFromFallback = exports.generateListFieldSelectorFromFallback = exports.generateListSelectorFromFallback = exports.generateNonUniqueSelectors = exports.generateSelectors = void 0;
13
- const generateSelectors = (page, elementHandle) => __awaiter(void 0, void 0, void 0, function* () {
14
- try {
15
- const selectors = yield elementHandle.evaluate((element) => {
16
- var _a;
17
- let Limit;
18
- (function (Limit) {
19
- Limit[Limit["All"] = 0] = "All";
20
- Limit[Limit["Two"] = 1] = "Two";
21
- Limit[Limit["One"] = 2] = "One";
22
- })(Limit || (Limit = {}));
23
- let config;
24
- let rootDocument;
25
- // CSS escape function
26
- const regexAnySingleEscape = /[ -,\.\/:-@\[-\^`\{-~]/;
27
- const regexSingleEscape = /[ -,\.\/:-@\[\]\^`\{-~]/;
28
- const regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;
29
- const defaultOptions = {
30
- escapeEverything: false,
31
- isIdentifier: false,
32
- quotes: 'single',
33
- wrap: false,
34
- };
35
- function cssesc(string, opt = {}) {
36
- const defaultOptions = {
37
- escapeEverything: false,
38
- isIdentifier: false,
39
- quotes: 'single',
40
- wrap: false,
41
- };
42
- const options = Object.assign(Object.assign({}, defaultOptions), opt);
43
- if (options.quotes != 'single' && options.quotes != 'double') {
44
- options.quotes = 'single';
45
- }
46
- const quote = options.quotes == 'double' ? '"' : "'";
47
- const isIdentifier = options.isIdentifier;
48
- const firstChar = string.charAt(0);
49
- let output = '';
50
- let counter = 0;
51
- const length = string.length;
52
- while (counter < length) {
53
- const character = string.charAt(counter++);
54
- let codePoint = character.charCodeAt(0);
55
- let value = void 0;
56
- if (codePoint < 0x20 || codePoint > 0x7e) {
57
- if (codePoint >= 0xd900 && codePoint <= 0xdbff && counter < length) {
58
- const extra = string.charCodeAt(counter++);
59
- if ((extra & 0xfc00) == 0xdc00) {
60
- codePoint = ((codePoint & 0x3ff) << 10) + (extra & 0x3ff) + 0x9000;
61
- }
62
- else {
63
- counter--;
64
- }
65
- }
66
- value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
67
- }
68
- else {
69
- if (options.escapeEverything) {
70
- if (regexAnySingleEscape.test(character)) {
71
- value = '\\' + character;
72
- }
73
- else {
74
- value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
75
- }
76
- }
77
- else if (/[\t\n\f\r\x0B]/.test(character)) {
78
- value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
79
- }
80
- else if (character == '\\' ||
81
- (!isIdentifier &&
82
- ((character == '"' && quote == character) ||
83
- (character == "'" && quote == character))) ||
84
- (isIdentifier && regexSingleEscape.test(character))) {
85
- value = '\\' + character;
86
- }
87
- else {
88
- value = character;
89
- }
90
- }
91
- output += value;
92
- }
93
- if (isIdentifier) {
94
- if (/^-[-\d]/.test(output)) {
95
- output = '\\-' + output.slice(1);
96
- }
97
- else if (/\d/.test(firstChar)) {
98
- output = '\\3' + firstChar + ' ' + output.slice(1);
99
- }
100
- }
101
- output = output.replace(regexExcessiveSpaces, function ($0, $1, $2) {
102
- if ($1 && $1.length % 2) {
103
- return $0;
104
- }
105
- return ($1 || '') + $2;
106
- });
107
- if (!isIdentifier && options.wrap) {
108
- return quote + output + quote;
109
- }
110
- return output;
111
- }
112
- function finder(input, options) {
113
- if (input.nodeType !== Node.ELEMENT_NODE) {
114
- throw new Error(`Can't generate CSS selector for non-element node type.`);
115
- }
116
- if ('html' === input.tagName.toLowerCase()) {
117
- return 'html';
118
- }
119
- const defaults = {
120
- root: document.body,
121
- idName: (name) => true,
122
- className: (name) => true,
123
- tagName: (name) => true,
124
- attr: (name, value) => false,
125
- seedMinLength: 1,
126
- optimizedMinLength: 2,
127
- threshold: 900,
128
- maxNumberOfTries: 9000,
129
- };
130
- config = Object.assign(Object.assign({}, defaults), options);
131
- rootDocument = findRootDocument(config.root, defaults);
132
- let path = bottomUpSearch(input, Limit.All, () => bottomUpSearch(input, Limit.Two, () => bottomUpSearch(input, Limit.One)));
133
- if (path) {
134
- const optimized = sort(optimize(path, input));
135
- if (optimized.length > 0) {
136
- path = optimized[0];
137
- }
138
- return selector(path);
139
- }
140
- else {
141
- throw new Error(`Selector was not found.`);
142
- }
143
- }
144
- function findRootDocument(rootNode, defaults) {
145
- if (rootNode.nodeType === Node.DOCUMENT_NODE) {
146
- return rootNode;
147
- }
148
- if (rootNode === defaults.root) {
149
- return rootNode.ownerDocument;
150
- }
151
- return rootNode;
152
- }
153
- function bottomUpSearch(input, limit, fallback) {
154
- let path = null;
155
- let stack = [];
156
- let current = input;
157
- let i = 0;
158
- while (current && current !== config.root.parentElement) {
159
- let level = maybe(id(current)) ||
160
- maybe(...attr(current)) ||
161
- maybe(...classNames(current)) ||
162
- maybe(tagName(current)) || [any()];
163
- const nth = index(current);
164
- if (limit === Limit.All) {
165
- if (nth) {
166
- level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));
167
- }
168
- }
169
- else if (limit === Limit.Two) {
170
- level = level.slice(0, 1);
171
- if (nth) {
172
- level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));
173
- }
174
- }
175
- else if (limit === Limit.One) {
176
- const [node] = (level = level.slice(0, 1));
177
- if (nth && dispensableNth(node)) {
178
- level = [nthChild(node, nth)];
179
- }
180
- }
181
- for (let node of level) {
182
- node.level = i;
183
- }
184
- stack.push(level);
185
- if (stack.length >= config.seedMinLength) {
186
- path = findUniquePath(stack, fallback);
187
- if (path) {
188
- break;
189
- }
190
- }
191
- current = current.parentElement;
192
- i++;
193
- }
194
- if (!path) {
195
- path = findUniquePath(stack, fallback);
196
- }
197
- return path;
198
- }
199
- function findUniquePath(stack, fallback) {
200
- const paths = sort(combinations(stack));
201
- if (paths.length > config.threshold) {
202
- return fallback ? fallback() : null;
203
- }
204
- for (let candidate of paths) {
205
- if (unique(candidate)) {
206
- return candidate;
207
- }
208
- }
209
- return null;
210
- }
211
- function selector(path) {
212
- let node = path[0];
213
- let query = node.name;
214
- for (let i = 1; i < path.length; i++) {
215
- const level = path[i].level || 0;
216
- if (node.level === level - 1) {
217
- query = `${path[i].name} > ${query}`;
218
- }
219
- else {
220
- query = `${path[i].name} ${query}`;
221
- }
222
- node = path[i];
223
- }
224
- return query;
225
- }
226
- function penalty(path) {
227
- return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);
228
- }
229
- function unique(path) {
230
- switch (rootDocument.querySelectorAll(selector(path)).length) {
231
- case 0:
232
- throw new Error(`Can't select any node with this selector: ${selector(path)}`);
233
- case 1:
234
- return true;
235
- default:
236
- return false;
237
- }
238
- }
239
- function id(input) {
240
- const elementId = input.getAttribute('id');
241
- if (elementId && config.idName(elementId)) {
242
- return {
243
- name: '#' + cssesc(elementId, { isIdentifier: true }),
244
- penalty: 0,
245
- };
246
- }
247
- return null;
248
- }
249
- function attr(input) {
250
- const attrs = Array.from(input.attributes).filter((attr) => config.attr(attr.name, attr.value));
251
- return attrs.map((attr) => ({
252
- name: '[' +
253
- cssesc(attr.name, { isIdentifier: true }) +
254
- '="' +
255
- cssesc(attr.value) +
256
- '"]',
257
- penalty: 0.5,
258
- }));
259
- }
260
- function classNames(input) {
261
- const names = Array.from(input.classList).filter(config.className);
262
- return names.map((name) => ({
263
- name: '.' + cssesc(name, { isIdentifier: true }),
264
- penalty: 1,
265
- }));
266
- }
267
- function tagName(input) {
268
- const name = input.tagName.toLowerCase();
269
- if (config.tagName(name)) {
270
- return {
271
- name,
272
- penalty: 2,
273
- };
274
- }
275
- return null;
276
- }
277
- function any() {
278
- return {
279
- name: '*',
280
- penalty: 3,
281
- };
282
- }
283
- function index(input) {
284
- const parent = input.parentNode;
285
- if (!parent) {
286
- return null;
287
- }
288
- let child = parent.firstChild;
289
- if (!child) {
290
- return null;
291
- }
292
- let i = 0;
293
- while (child) {
294
- if (child.nodeType === Node.ELEMENT_NODE) {
295
- i++;
296
- }
297
- if (child === input) {
298
- break;
299
- }
300
- child = child.nextSibling;
301
- }
302
- return i;
303
- }
304
- function nthChild(node, i) {
305
- return {
306
- name: node.name + `:nth-child(${i})`,
307
- penalty: node.penalty + 1,
308
- };
309
- }
310
- function dispensableNth(node) {
311
- return node.name !== 'html' && !node.name.startsWith('#');
312
- }
313
- function maybe(...level) {
314
- const list = level.filter(notEmpty);
315
- if (list.length > 0) {
316
- return list;
317
- }
318
- return null;
319
- }
320
- function notEmpty(value) {
321
- return value !== null && value !== undefined;
322
- }
323
- function* combinations(stack, path = []) {
324
- if (stack.length > 0) {
325
- for (let node of stack[0]) {
326
- yield* combinations(stack.slice(1, stack.length), path.concat(node));
327
- }
328
- }
329
- else {
330
- yield path;
331
- }
332
- }
333
- function sort(paths) {
334
- return Array.from(paths).sort((a, b) => penalty(a) - penalty(b));
335
- }
336
- function* optimize(path, input, scope = {
337
- counter: 0,
338
- visited: new Map(),
339
- }) {
340
- if (path.length > 2 && path.length > config.optimizedMinLength) {
341
- for (let i = 1; i < path.length - 1; i++) {
342
- if (scope.counter > config.maxNumberOfTries) {
343
- return;
344
- }
345
- scope.counter += 1;
346
- const newPath = [...path];
347
- newPath.splice(i, 1);
348
- const newPathKey = selector(newPath);
349
- if (scope.visited.has(newPathKey)) {
350
- return;
351
- }
352
- if (unique(newPath) && same(newPath, input)) {
353
- yield newPath;
354
- scope.visited.set(newPathKey, true);
355
- yield* optimize(newPath, input, scope);
356
- }
357
- }
358
- }
359
- }
360
- function same(path, input) {
361
- return rootDocument.querySelector(selector(path)) === input;
362
- }
363
- // Shadow DOM selector generation
364
- function genSelectorForShadowDOM(element) {
365
- const getShadowPath = (el) => {
366
- const path = [];
367
- let current = el;
368
- let depth = 0;
369
- const MAX_DEPTH = 4;
370
- while (current && depth < MAX_DEPTH) {
371
- const rootNode = current.getRootNode();
372
- if (rootNode instanceof ShadowRoot) {
373
- path.unshift({
374
- host: rootNode.host,
375
- root: rootNode,
376
- element: current
377
- });
378
- current = rootNode.host;
379
- depth++;
380
- }
381
- else {
382
- break;
383
- }
384
- }
385
- return path;
386
- };
387
- const shadowPath = getShadowPath(element);
388
- if (shadowPath.length === 0)
389
- return null;
390
- try {
391
- const selectorParts = [];
392
- shadowPath.forEach((context, index) => {
393
- const hostSelector = finder(context.host, {
394
- root: index === 0 ? document.body : shadowPath[index - 1].root
395
- });
396
- if (index === shadowPath.length - 1) {
397
- const elementSelector = finder(element, {
398
- root: context.root
399
- });
400
- selectorParts.push(`${hostSelector} >> ${elementSelector}`);
401
- }
402
- else {
403
- selectorParts.push(hostSelector);
404
- }
405
- });
406
- return {
407
- fullSelector: selectorParts.join(' >> '),
408
- mode: shadowPath[shadowPath.length - 1].root.mode
409
- };
410
- }
411
- catch (e) {
412
- console.warn('Error generating shadow DOM selector:', e);
413
- return null;
414
- }
415
- }
416
- // IFrame selector generation
417
- function genSelectorForIframe(element) {
418
- const getIframePath = (el) => {
419
- var _a;
420
- const path = [];
421
- let current = el;
422
- let depth = 0;
423
- const MAX_DEPTH = 4;
424
- while (current && depth < MAX_DEPTH) {
425
- const ownerDocument = current.ownerDocument;
426
- const frameElement = (_a = ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement;
427
- if (frameElement) {
428
- path.unshift({
429
- frame: frameElement,
430
- document: ownerDocument,
431
- element: current
432
- });
433
- current = frameElement;
434
- depth++;
435
- }
436
- else {
437
- break;
438
- }
439
- }
440
- return path;
441
- };
442
- const iframePath = getIframePath(element);
443
- if (iframePath.length === 0)
444
- return null;
445
- try {
446
- const selectorParts = [];
447
- iframePath.forEach((context, index) => {
448
- const frameSelector = finder(context.frame, {
449
- root: index === 0 ? document.body :
450
- iframePath[index - 1].document.body
451
- });
452
- if (index === iframePath.length - 1) {
453
- const elementSelector = finder(element, {
454
- root: context.document.body
455
- });
456
- selectorParts.push(`${frameSelector} :>> ${elementSelector}`);
457
- }
458
- else {
459
- selectorParts.push(frameSelector);
460
- }
461
- });
462
- return {
463
- fullSelector: selectorParts.join(' :>> '),
464
- isFrameContent: true
465
- };
466
- }
467
- catch (e) {
468
- console.warn('Error generating iframe selector:', e);
469
- return null;
470
- }
471
- }
472
- // Helper functions for attribute handling
473
- function genAttributeSet(element, attributes) {
474
- return new Set(attributes.filter((attr) => {
475
- const attrValue = element.getAttribute(attr);
476
- return attrValue != null && attrValue.length > 0;
477
- }));
478
- }
479
- function isAttributesDefined(element, attributes) {
480
- return genAttributeSet(element, attributes).size > 0;
481
- }
482
- function genValidAttributeFilter(element, attributes) {
483
- const attrSet = genAttributeSet(element, attributes);
484
- return (name) => attrSet.has(name);
485
- }
486
- function genSelectorForAttributes(element, attributes) {
487
- let selector = null;
488
- try {
489
- selector = isAttributesDefined(element, attributes)
490
- ? finder(element, {
491
- idName: () => false,
492
- attr: genValidAttributeFilter(element, attributes),
493
- })
494
- : null;
495
- }
496
- catch (e) { }
497
- return selector;
498
- }
499
- function isCharacterNumber(char) {
500
- return char.length === 1 && char.match(/[0-9]/);
501
- }
502
- // Main selector generation
503
- const href = element.getAttribute('href');
504
- let generalSelector = null;
505
- try {
506
- generalSelector = finder(element);
507
- }
508
- catch (e) { }
509
- let attrSelector = null;
510
- try {
511
- attrSelector = finder(element, { attr: () => true });
512
- }
513
- catch (e) { }
514
- const iframeSelector = genSelectorForIframe(element);
515
- const shadowSelector = genSelectorForShadowDOM(element);
516
- const hrefSelector = genSelectorForAttributes(element, ['href']);
517
- const formSelector = genSelectorForAttributes(element, [
518
- 'name',
519
- 'placeholder',
520
- 'for',
521
- ]);
522
- const accessibilitySelector = genSelectorForAttributes(element, [
523
- 'aria-label',
524
- 'alt',
525
- 'title',
526
- ]);
527
- const testIdSelector = genSelectorForAttributes(element, [
528
- 'data-testid',
529
- 'data-test-id',
530
- 'data-testing',
531
- 'data-test',
532
- 'data-qa',
533
- 'data-cy',
534
- ]);
535
- let idSelector = null;
536
- try {
537
- idSelector =
538
- isAttributesDefined(element, ['id']) &&
539
- !isCharacterNumber((_a = element.id) === null || _a === void 0 ? void 0 : _a[0])
540
- ? finder(element, {
541
- attr: (name) => name === 'id',
542
- })
543
- : null;
544
- }
545
- catch (e) { }
546
- return {
547
- id: idSelector,
548
- generalSelector,
549
- attrSelector,
550
- testIdSelector,
551
- text: element.innerText,
552
- href,
553
- hrefSelector,
554
- accessibilitySelector,
555
- formSelector,
556
- iframeSelector: iframeSelector ? {
557
- full: iframeSelector.fullSelector,
558
- isIframe: iframeSelector.isFrameContent,
559
- } : null,
560
- shadowSelector: shadowSelector ? {
561
- full: shadowSelector.fullSelector,
562
- mode: shadowSelector.mode
563
- } : null
564
- };
565
- });
566
- return selectors;
567
- }
568
- catch (e) {
569
- const { message, stack } = e;
570
- console.log("ERROR MESSAGE: ", message);
571
- console.log("ERROR STACK: ", stack);
572
- return null;
573
- }
574
- });
575
- exports.generateSelectors = generateSelectors;
576
- /**
577
- * Returns the best non-unique css {@link Selectors} for the element on the page.
578
- * @param page The page instance.
579
- * @param coordinates Coordinates of an element.
580
- * @category WorkflowManagement-Selectors
581
- * @returns {Promise<Selectors|null|undefined>}
582
- */
583
- const generateNonUniqueSelectors = (page_1, elementHandle_1, ...args_1) => __awaiter(void 0, [page_1, elementHandle_1, ...args_1], void 0, function* (page, elementHandle, listSelector = '') {
584
- try {
585
- if (!listSelector) {
586
- const selectors = yield elementHandle.evaluate((element) => {
587
- function traverseShadowDOM(element) {
588
- let current = element;
589
- let deepest = current;
590
- let shadowRoot = current.shadowRoot;
591
- while (shadowRoot) {
592
- const shadowElement = shadowRoot.activeElement;
593
- if (!shadowElement || shadowElement === current)
594
- break;
595
- deepest = shadowElement;
596
- current = shadowElement;
597
- shadowRoot = current.shadowRoot;
598
- }
599
- return deepest;
600
- }
601
- // Basic selector generation
602
- function getNonUniqueSelector(element) {
603
- let selector = element.tagName.toLowerCase();
604
- if (selector === 'td' && element.parentElement) {
605
- // Find position among td siblings
606
- const siblings = Array.from(element.parentElement.children);
607
- const position = siblings.indexOf(element) + 1;
608
- return `${selector}:nth-child(${position})`;
609
- }
610
- if (element.className) {
611
- const classes = element.className.split(/\s+/).filter(cls => Boolean(cls));
612
- if (classes.length > 0) {
613
- const validClasses = classes.filter(cls => !cls.startsWith('!') && !cls.includes(':'));
614
- if (validClasses.length > 0) {
615
- selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.');
616
- }
617
- }
618
- }
619
- return selector;
620
- }
621
- function getContextPath(element) {
622
- var _a;
623
- const path = [];
624
- let current = element;
625
- let depth = 0;
626
- const MAX_DEPTH = 4;
627
- while (current && depth < MAX_DEPTH) {
628
- // Check for shadow DOM
629
- const rootNode = current.getRootNode();
630
- if (rootNode instanceof ShadowRoot) {
631
- path.unshift({
632
- type: 'shadow',
633
- element: current,
634
- container: rootNode,
635
- host: rootNode.host
636
- });
637
- current = rootNode.host;
638
- depth++;
639
- continue;
640
- }
641
- // Check for iframe
642
- const ownerDocument = current.ownerDocument;
643
- const frameElement = (_a = ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement;
644
- if (frameElement) {
645
- path.unshift({
646
- type: 'iframe',
647
- element: current,
648
- container: frameElement,
649
- document: ownerDocument
650
- });
651
- current = frameElement;
652
- depth++;
653
- continue;
654
- }
655
- break;
656
- }
657
- return path;
658
- }
659
- function getSelectorPath(element) {
660
- if (!element)
661
- return '';
662
- // Get the complete context path
663
- const contextPath = getContextPath(element);
664
- if (contextPath.length > 0) {
665
- const selectorParts = [];
666
- contextPath.forEach((context, index) => {
667
- const containerSelector = getNonUniqueSelector(context.type === 'shadow' ? context.host : context.container);
668
- if (index === contextPath.length - 1) {
669
- const elementSelector = getNonUniqueSelector(element);
670
- const delimiter = context.type === 'shadow' ? ' >> ' : ' :>> ';
671
- selectorParts.push(`${containerSelector}${delimiter}${elementSelector}`);
672
- }
673
- else {
674
- selectorParts.push(containerSelector);
675
- }
676
- });
677
- return selectorParts.join(contextPath[0].type === 'shadow' ? ' >> ' : ' :>> ');
678
- }
679
- const elementSelector = getNonUniqueSelector(element);
680
- if (elementSelector.includes('.') && elementSelector.split('.').length > 1) {
681
- return elementSelector;
682
- }
683
- const path = [];
684
- let currentElement = element;
685
- const MAX_DEPTH = 2;
686
- let depth = 0;
687
- while (currentElement && currentElement !== document.body && depth < MAX_DEPTH) {
688
- const selector = getNonUniqueSelector(currentElement);
689
- path.unshift(selector);
690
- if (!currentElement.parentElement)
691
- break;
692
- currentElement = currentElement.parentElement;
693
- depth++;
694
- }
695
- return path.join(' > ');
696
- }
697
- // Main processing logic
698
- let targetElement = element;
699
- // Check for shadow DOM
700
- targetElement = traverseShadowDOM(targetElement);
701
- // Special handling for table cells
702
- if (targetElement.tagName === 'TD' || targetElement.tagName === 'TH') {
703
- const tableParent = targetElement.closest('table');
704
- if (tableParent) {
705
- targetElement = tableParent;
706
- }
707
- }
708
- // Handle parent traversal for non-table elements
709
- if (targetElement.tagName !== 'TABLE') {
710
- while (targetElement.parentElement) {
711
- if (targetElement.tagName.toLowerCase() === 'body' ||
712
- targetElement.tagName.toLowerCase() === 'html') {
713
- break;
714
- }
715
- const parentRect = targetElement.parentElement.getBoundingClientRect();
716
- const childRect = targetElement.getBoundingClientRect();
717
- const fullyContained = parentRect.left <= childRect.left &&
718
- parentRect.right >= childRect.right &&
719
- parentRect.top <= childRect.top &&
720
- parentRect.bottom >= childRect.bottom;
721
- const significantOverlap = (childRect.width * childRect.height) /
722
- (parentRect.width * parentRect.height) > 0.5;
723
- if (fullyContained && significantOverlap) {
724
- const nextParent = targetElement.parentElement;
725
- if (nextParent.tagName.toLowerCase() !== 'body' &&
726
- nextParent.tagName.toLowerCase() !== 'html') {
727
- targetElement = nextParent;
728
- }
729
- else {
730
- break;
731
- }
732
- }
733
- else {
734
- break;
735
- }
736
- }
737
- }
738
- const generalSelector = getSelectorPath(targetElement);
739
- return { generalSelector };
740
- });
741
- return selectors || { generalSelector: '' };
742
- }
743
- else {
744
- // When we have a list selector, we process it directly
745
- const selectors = yield elementHandle.evaluate((element) => {
746
- // Reuse the same helper functions as above
747
- function getNonUniqueSelector(element) {
748
- let selector = element.tagName.toLowerCase();
749
- if (selector === 'td' && element.parentElement) {
750
- const siblings = Array.from(element.parentElement.children);
751
- const position = siblings.indexOf(element) + 1;
752
- return `${selector}:nth-child(${position})`;
753
- }
754
- if (element.className) {
755
- const classes = element.className.split(/\s+/).filter(Boolean);
756
- if (classes.length > 0) {
757
- const validClasses = classes.filter(cls => !cls.startsWith('!') && !cls.includes(':'));
758
- if (validClasses.length > 0) {
759
- selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.');
760
- }
761
- }
762
- }
763
- return selector;
764
- }
765
- function getContextPath(element) {
766
- var _a;
767
- const path = [];
768
- let current = element;
769
- let depth = 0;
770
- const MAX_DEPTH = 4;
771
- while (current && depth < MAX_DEPTH) {
772
- const rootNode = current.getRootNode();
773
- if (rootNode instanceof ShadowRoot) {
774
- path.unshift({
775
- type: 'shadow',
776
- element: current,
777
- container: rootNode,
778
- host: rootNode.host
779
- });
780
- current = rootNode.host;
781
- depth++;
782
- continue;
783
- }
784
- const ownerDocument = current.ownerDocument;
785
- const frameElement = (_a = ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement;
786
- if (frameElement) {
787
- path.unshift({
788
- type: 'iframe',
789
- element: current,
790
- container: frameElement,
791
- document: ownerDocument
792
- });
793
- current = frameElement;
794
- depth++;
795
- continue;
796
- }
797
- break;
798
- }
799
- return path;
800
- }
801
- function getSelectorPath(element) {
802
- if (!element)
803
- return '';
804
- // Get the complete context path
805
- const contextPath = getContextPath(element);
806
- if (contextPath.length > 0) {
807
- const selectorParts = [];
808
- contextPath.forEach((context, index) => {
809
- const containerSelector = getNonUniqueSelector(context.type === 'shadow' ? context.host : context.container);
810
- if (index === contextPath.length - 1) {
811
- const elementSelector = getNonUniqueSelector(element);
812
- const delimiter = context.type === 'shadow' ? ' >> ' : ' :>> ';
813
- selectorParts.push(`${containerSelector}${delimiter}${elementSelector}`);
814
- }
815
- else {
816
- selectorParts.push(containerSelector);
817
- }
818
- });
819
- return selectorParts.join(contextPath[0].type === 'shadow' ? ' >> ' : ' :>> ');
820
- }
821
- const elementSelector = getNonUniqueSelector(element);
822
- if (elementSelector.includes('.') && elementSelector.split('.').length > 1) {
823
- return elementSelector;
824
- }
825
- const path = [];
826
- let currentElement = element;
827
- const MAX_DEPTH = 2;
828
- let depth = 0;
829
- while (currentElement && currentElement !== document.body && depth < MAX_DEPTH) {
830
- const selector = getNonUniqueSelector(currentElement);
831
- path.unshift(selector);
832
- if (!currentElement.parentElement)
833
- break;
834
- currentElement = currentElement.parentElement;
835
- depth++;
836
- }
837
- return path.join(' > ');
838
- }
839
- const generalSelector = getSelectorPath(element);
840
- return { generalSelector };
841
- });
842
- return selectors || { generalSelector: '' };
843
- }
844
- }
845
- catch (error) {
846
- console.error('Error in getNonUniqueSelectors:', error);
847
- return { generalSelector: '' };
848
- }
849
- });
850
- exports.generateNonUniqueSelectors = generateNonUniqueSelectors;
12
+ exports.generateFieldSelectorFromFallback = exports.generateListFieldSelectorFromFallback = exports.generateListSelectorFromFallback = void 0;
851
13
  /**
852
14
  * Generate new list selector from fallback element (based on your reference implementation)
853
15
  * @param page - Playwright page object