@skrillex1224/playwright-toolkit 2.1.245 → 2.1.247

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.js CHANGED
@@ -3408,56 +3408,6 @@ var initializedPages = /* @__PURE__ */ new WeakSet();
3408
3408
  var DEFAULT_TAP_TIMEOUT_MS = 2500;
3409
3409
  var DEFAULT_MOUSE_TAP_FALLBACK_TIMEOUT_MS = 1200;
3410
3410
  var DEFAULT_ACTIVATE_FALLBACK_TIMEOUT_MS = 900;
3411
- var INTERACTIVE_SELECTOR = [
3412
- "button",
3413
- '[role="button"]',
3414
- '[role="link"]',
3415
- '[role="menuitem"]',
3416
- '[role="tab"]',
3417
- '[role="switch"]',
3418
- '[role="checkbox"]',
3419
- "a[href]",
3420
- "label",
3421
- "input",
3422
- "textarea",
3423
- "select",
3424
- "summary",
3425
- '[contenteditable="true"]',
3426
- '[tabindex]:not([tabindex="-1"])'
3427
- ].join(",");
3428
- var EDITABLE_SELECTOR = [
3429
- "input",
3430
- "textarea",
3431
- '[contenteditable="true"]'
3432
- ].join(",");
3433
- var INTERACTIVE_HINT_PATTERN = [
3434
- "btn",
3435
- "button",
3436
- "send",
3437
- "submit",
3438
- "confirm",
3439
- "cancel",
3440
- "retry",
3441
- "reload",
3442
- "search",
3443
- "copy",
3444
- "share",
3445
- "close",
3446
- "more",
3447
- "\u53D1\u9001",
3448
- "\u63D0\u4EA4",
3449
- "\u786E\u5B9A",
3450
- "\u786E\u8BA4",
3451
- "\u53D6\u6D88",
3452
- "\u91CD\u8BD5",
3453
- "\u641C\u7D22",
3454
- "\u590D\u5236",
3455
- "\u5206\u4EAB",
3456
- "\u5173\u95ED",
3457
- "\u66F4\u591A",
3458
- "\u5C55\u5F00",
3459
- "\u6536\u8D77"
3460
- ].join("|");
3461
3411
  var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
3462
3412
  var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
3463
3413
  var describeTarget = (target) => {
@@ -3497,47 +3447,7 @@ var withTimeout = async (operation, timeoutMs, label) => {
3497
3447
  }
3498
3448
  };
3499
3449
  var checkElementVisibility = async (element) => {
3500
- return element.evaluate((el, { interactiveSelector, interactiveHintPattern }) => {
3501
- const interactiveHintRe = new RegExp(interactiveHintPattern, "i");
3502
- const nodeClassName = (node) => {
3503
- if (!node) return "";
3504
- if (typeof node.className === "string") return node.className;
3505
- if (node.className && typeof node.className.baseVal === "string") return node.className.baseVal;
3506
- return "";
3507
- };
3508
- const interactiveScore = (node) => {
3509
- if (!node || node.nodeType !== Node.ELEMENT_NODE) return 0;
3510
- let score = 0;
3511
- if (typeof node.matches === "function" && node.matches(interactiveSelector)) score += 8;
3512
- const hints = [
3513
- node.id || "",
3514
- nodeClassName(node),
3515
- node.getAttribute?.("aria-label") || "",
3516
- node.getAttribute?.("title") || "",
3517
- node.getAttribute?.("data-testid") || "",
3518
- node.getAttribute?.("data-test") || "",
3519
- node.getAttribute?.("data-click") || "",
3520
- node.getAttribute?.("data-action") || "",
3521
- node.getAttribute?.("onclick") || "",
3522
- String(node.textContent || "").trim().slice(0, 24)
3523
- ].join(" ");
3524
- if (interactiveHintRe.test(hints)) score += 4;
3525
- const style = window.getComputedStyle(node);
3526
- if (style?.cursor === "pointer") score += 2;
3527
- return score;
3528
- };
3529
- const closestInteractive = (node) => {
3530
- let best = null;
3531
- let bestScore = 0;
3532
- for (let current = node; current && current !== document.body; current = current.parentElement) {
3533
- const score = interactiveScore(current);
3534
- if (score > bestScore || score > 0 && score === bestScore) {
3535
- best = current;
3536
- bestScore = score;
3537
- }
3538
- }
3539
- return best;
3540
- };
3450
+ return element.evaluate((el) => {
3541
3451
  const targetStyle = window.getComputedStyle(el);
3542
3452
  if (!targetStyle || targetStyle.display === "none" || targetStyle.visibility === "hidden" || targetStyle.visibility === "collapse") {
3543
3453
  return { code: "NOT_INTERACTABLE", reason: "\u5143\u7D20\u4E0D\u53EF\u89C1", direction: "down" };
@@ -3599,13 +3509,30 @@ var checkElementVisibility = async (element) => {
3599
3509
  positioning
3600
3510
  };
3601
3511
  }
3602
- const targetInteractive = closestInteractive(el);
3603
- const sameInteractiveTarget = (pointElement) => {
3512
+ const isRootNode = (node) => !node || node === document || node === document.body || node === document.documentElement;
3513
+ const commonAncestor = (a, b) => {
3514
+ for (let current = a; current && !isRootNode(current); current = current.parentElement) {
3515
+ if (current.contains(b)) return current;
3516
+ }
3517
+ return null;
3518
+ };
3519
+ const sameTapTarget = (pointElement) => {
3604
3520
  if (!pointElement) return false;
3605
3521
  if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
3606
3522
  return true;
3607
3523
  }
3608
- return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
3524
+ const common = commonAncestor(el, pointElement);
3525
+ if (!common) return false;
3526
+ const commonRect = common.getBoundingClientRect?.();
3527
+ if (!commonRect || commonRect.width <= 0 || commonRect.height <= 0) return false;
3528
+ const commonArea = commonRect.width * commonRect.height;
3529
+ const targetArea = Math.max(1, rect.width * rect.height);
3530
+ const maxSharedRegionArea = Math.max(targetArea * 12, 4096);
3531
+ if (commonArea > maxSharedRegionArea) return false;
3532
+ if (commonRect.width > Math.max(rect.width * 8, 120) || commonRect.height > Math.max(rect.height * 8, 120)) {
3533
+ return false;
3534
+ }
3535
+ return common.contains(el) && common.contains(pointElement);
3609
3536
  };
3610
3537
  const describeElement = (node) => {
3611
3538
  if (!node) return null;
@@ -3634,7 +3561,7 @@ var checkElementVisibility = async (element) => {
3634
3561
  let obstruction = null;
3635
3562
  for (const point of samplePoints) {
3636
3563
  const pointElement = document.elementFromPoint(point.x, point.y);
3637
- if (sameInteractiveTarget(pointElement)) {
3564
+ if (sameTapTarget(pointElement)) {
3638
3565
  return { code: "VISIBLE", isFixed, positioning };
3639
3566
  }
3640
3567
  obstruction = obstruction || describeElement(pointElement);
@@ -3652,53 +3579,10 @@ var checkElementVisibility = async (element) => {
3652
3579
  };
3653
3580
  }
3654
3581
  return { code: "VISIBLE", isFixed, positioning };
3655
- }, {
3656
- interactiveSelector: INTERACTIVE_SELECTOR,
3657
- interactiveHintPattern: INTERACTIVE_HINT_PATTERN
3658
3582
  });
3659
3583
  };
3660
3584
  var resolveSafeTapPoint = async (element) => {
3661
- return element.evaluate((el, { interactiveSelector, interactiveHintPattern }) => {
3662
- const interactiveHintRe = new RegExp(interactiveHintPattern, "i");
3663
- const nodeClassName = (node) => {
3664
- if (!node) return "";
3665
- if (typeof node.className === "string") return node.className;
3666
- if (node.className && typeof node.className.baseVal === "string") return node.className.baseVal;
3667
- return "";
3668
- };
3669
- const interactiveScore = (node) => {
3670
- if (!node || node.nodeType !== Node.ELEMENT_NODE) return 0;
3671
- let score = 0;
3672
- if (typeof node.matches === "function" && node.matches(interactiveSelector)) score += 8;
3673
- const hints = [
3674
- node.id || "",
3675
- nodeClassName(node),
3676
- node.getAttribute?.("aria-label") || "",
3677
- node.getAttribute?.("title") || "",
3678
- node.getAttribute?.("data-testid") || "",
3679
- node.getAttribute?.("data-test") || "",
3680
- node.getAttribute?.("data-click") || "",
3681
- node.getAttribute?.("data-action") || "",
3682
- node.getAttribute?.("onclick") || "",
3683
- String(node.textContent || "").trim().slice(0, 24)
3684
- ].join(" ");
3685
- if (interactiveHintRe.test(hints)) score += 4;
3686
- const style = window.getComputedStyle(node);
3687
- if (style?.cursor === "pointer") score += 2;
3688
- return score;
3689
- };
3690
- const closestInteractive = (node) => {
3691
- let best = null;
3692
- let bestScore = 0;
3693
- for (let current = node; current && current !== document.body; current = current.parentElement) {
3694
- const score = interactiveScore(current);
3695
- if (score > bestScore || score > 0 && score === bestScore) {
3696
- best = current;
3697
- bestScore = score;
3698
- }
3699
- }
3700
- return best;
3701
- };
3585
+ return element.evaluate((el) => {
3702
3586
  const rect = el.getBoundingClientRect();
3703
3587
  if (!rect || rect.width <= 0 || rect.height <= 0) {
3704
3588
  return null;
@@ -3735,13 +3619,30 @@ var resolveSafeTapPoint = async (element) => {
3735
3619
  if (visibleWidth <= 1 || visibleHeight <= 1) {
3736
3620
  return null;
3737
3621
  }
3738
- const targetInteractive = closestInteractive(el);
3739
- const sameInteractiveTarget = (pointElement) => {
3622
+ const isRootNode = (node) => !node || node === document || node === document.body || node === document.documentElement;
3623
+ const commonAncestor = (a, b) => {
3624
+ for (let current = a; current && !isRootNode(current); current = current.parentElement) {
3625
+ if (current.contains(b)) return current;
3626
+ }
3627
+ return null;
3628
+ };
3629
+ const sameTapTarget = (pointElement) => {
3740
3630
  if (!pointElement) return false;
3741
3631
  if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
3742
3632
  return true;
3743
3633
  }
3744
- return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
3634
+ const common = commonAncestor(el, pointElement);
3635
+ if (!common) return false;
3636
+ const commonRect = common.getBoundingClientRect?.();
3637
+ if (!commonRect || commonRect.width <= 0 || commonRect.height <= 0) return false;
3638
+ const commonArea = commonRect.width * commonRect.height;
3639
+ const targetArea = Math.max(1, rect.width * rect.height);
3640
+ const maxSharedRegionArea = Math.max(targetArea * 12, 4096);
3641
+ if (commonArea > maxSharedRegionArea) return false;
3642
+ if (commonRect.width > Math.max(rect.width * 8, 120) || commonRect.height > Math.max(rect.height * 8, 120)) {
3643
+ return false;
3644
+ }
3645
+ return common.contains(el) && common.contains(pointElement);
3745
3646
  };
3746
3647
  const cx = visibleLeft + visibleWidth / 2;
3747
3648
  const cy = visibleTop + visibleHeight / 2;
@@ -3760,7 +3661,7 @@ var resolveSafeTapPoint = async (element) => {
3760
3661
  ];
3761
3662
  const safePoints = points.filter((point) => {
3762
3663
  const pointElement = document.elementFromPoint(point.x, point.y);
3763
- return sameInteractiveTarget(pointElement);
3664
+ return sameTapTarget(pointElement);
3764
3665
  });
3765
3666
  const candidates = safePoints.length ? safePoints : points;
3766
3667
  const chosen = candidates[Math.floor(Math.random() * candidates.length)];
@@ -3769,86 +3670,57 @@ var resolveSafeTapPoint = async (element) => {
3769
3670
  x: chosen.x,
3770
3671
  y: chosen.y
3771
3672
  };
3772
- }, {
3773
- interactiveSelector: INTERACTIVE_SELECTOR,
3774
- interactiveHintPattern: INTERACTIVE_HINT_PATTERN
3775
3673
  });
3776
3674
  };
3777
3675
  var activateElementFallback = async (element, point = null, options = {}) => {
3778
- return element.evaluate((el, { innerPoint, innerOptions, interactiveSelector, editableSelector, interactiveHintPattern }) => {
3779
- const interactiveHintRe = new RegExp(interactiveHintPattern, "i");
3780
- const nodeClassName = (node) => {
3781
- if (!node) return "";
3782
- if (typeof node.className === "string") return node.className;
3783
- if (node.className && typeof node.className.baseVal === "string") return node.className.baseVal;
3784
- return "";
3785
- };
3786
- const interactiveScore = (node) => {
3787
- if (!node || node.nodeType !== Node.ELEMENT_NODE) return 0;
3788
- let score = 0;
3789
- if (typeof node.matches === "function" && node.matches(interactiveSelector)) score += 8;
3790
- const hints = [
3791
- node.id || "",
3792
- nodeClassName(node),
3793
- node.getAttribute?.("aria-label") || "",
3794
- node.getAttribute?.("title") || "",
3795
- node.getAttribute?.("data-testid") || "",
3796
- node.getAttribute?.("data-test") || "",
3797
- node.getAttribute?.("data-click") || "",
3798
- node.getAttribute?.("data-action") || "",
3799
- node.getAttribute?.("onclick") || "",
3800
- String(node.textContent || "").trim().slice(0, 24)
3801
- ].join(" ");
3802
- if (interactiveHintRe.test(hints)) score += 4;
3803
- const style = window.getComputedStyle(node);
3804
- if (style?.cursor === "pointer") score += 2;
3805
- return score;
3676
+ return element.evaluate((el, { innerOptions }) => {
3677
+ const isEditable = (node) => {
3678
+ if (!node || node.nodeType !== Node.ELEMENT_NODE) return false;
3679
+ if (node.isContentEditable) return true;
3680
+ if (node instanceof HTMLTextAreaElement) return !node.disabled && !node.readOnly;
3681
+ if (node instanceof HTMLInputElement) {
3682
+ return !node.disabled && !node.readOnly && typeof node.select === "function";
3683
+ }
3684
+ return false;
3806
3685
  };
3807
- const pointElement = innerPoint ? document.elementFromPoint(innerPoint.x, innerPoint.y) : null;
3808
- const nearestInteractive = (node) => {
3809
- let best = null;
3810
- let bestScore = 0;
3686
+ const findEditable = (node) => {
3811
3687
  for (let current = node; current && current !== document.body; current = current.parentElement) {
3812
- const score = interactiveScore(current);
3813
- if (score > bestScore || score > 0 && score === bestScore) {
3814
- best = current;
3815
- bestScore = score;
3816
- }
3688
+ if (isEditable(current)) return current;
3817
3689
  }
3818
- return best;
3690
+ return null;
3819
3691
  };
3820
- const targetInteractive = nearestInteractive(el);
3821
- const pointInteractive = nearestInteractive(pointElement);
3822
- let target = null;
3823
- if (pointInteractive && (pointInteractive === targetInteractive || pointInteractive === el || pointInteractive.contains(el) || el.contains(pointInteractive))) {
3824
- target = pointInteractive;
3825
- }
3826
- target = target || targetInteractive || el;
3827
- const editable = typeof target.closest === "function" ? target.closest(editableSelector) : null;
3692
+ const editable = findEditable(el);
3828
3693
  if (editable && typeof editable.focus === "function") {
3829
3694
  editable.focus({ preventScroll: true });
3830
3695
  if (innerOptions.editableOnly) {
3831
3696
  return { activated: true, method: "focus", tag: editable.tagName || "" };
3832
3697
  }
3833
3698
  }
3834
- if (typeof target.focus === "function") {
3835
- target.focus({ preventScroll: true });
3699
+ if (innerOptions.editableOnly) {
3700
+ return { activated: false, method: "none", tag: el?.tagName || "" };
3836
3701
  }
3837
- if (!innerOptions.editableOnly && typeof target.click === "function") {
3838
- target.click();
3839
- return { activated: true, method: "dom-click", tag: target.tagName || "" };
3702
+ if (typeof el.focus === "function") {
3703
+ el.focus({ preventScroll: true });
3704
+ }
3705
+ if (typeof el.click === "function") {
3706
+ el.click();
3707
+ return { activated: true, method: "dom-click", tag: el.tagName || "" };
3708
+ }
3709
+ if (typeof el.dispatchEvent === "function") {
3710
+ el.dispatchEvent(new MouseEvent("click", {
3711
+ bubbles: true,
3712
+ cancelable: true,
3713
+ view: window
3714
+ }));
3715
+ return { activated: true, method: "dispatch-click", tag: el.tagName || "" };
3840
3716
  }
3841
3717
  return {
3842
3718
  activated: Boolean(editable),
3843
3719
  method: editable ? "focus" : "none",
3844
- tag: target?.tagName || ""
3720
+ tag: el?.tagName || ""
3845
3721
  };
3846
3722
  }, {
3847
- innerPoint: point,
3848
- innerOptions: options || {},
3849
- interactiveSelector: INTERACTIVE_SELECTOR,
3850
- editableSelector: EDITABLE_SELECTOR,
3851
- interactiveHintPattern: INTERACTIVE_HINT_PATTERN
3723
+ innerOptions: options || {}
3852
3724
  });
3853
3725
  };
3854
3726
  var getScrollableRect = async (element) => {