@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.cjs CHANGED
@@ -3436,56 +3436,6 @@ var initializedPages = /* @__PURE__ */ new WeakSet();
3436
3436
  var DEFAULT_TAP_TIMEOUT_MS = 2500;
3437
3437
  var DEFAULT_MOUSE_TAP_FALLBACK_TIMEOUT_MS = 1200;
3438
3438
  var DEFAULT_ACTIVATE_FALLBACK_TIMEOUT_MS = 900;
3439
- var INTERACTIVE_SELECTOR = [
3440
- "button",
3441
- '[role="button"]',
3442
- '[role="link"]',
3443
- '[role="menuitem"]',
3444
- '[role="tab"]',
3445
- '[role="switch"]',
3446
- '[role="checkbox"]',
3447
- "a[href]",
3448
- "label",
3449
- "input",
3450
- "textarea",
3451
- "select",
3452
- "summary",
3453
- '[contenteditable="true"]',
3454
- '[tabindex]:not([tabindex="-1"])'
3455
- ].join(",");
3456
- var EDITABLE_SELECTOR = [
3457
- "input",
3458
- "textarea",
3459
- '[contenteditable="true"]'
3460
- ].join(",");
3461
- var INTERACTIVE_HINT_PATTERN = [
3462
- "btn",
3463
- "button",
3464
- "send",
3465
- "submit",
3466
- "confirm",
3467
- "cancel",
3468
- "retry",
3469
- "reload",
3470
- "search",
3471
- "copy",
3472
- "share",
3473
- "close",
3474
- "more",
3475
- "\u53D1\u9001",
3476
- "\u63D0\u4EA4",
3477
- "\u786E\u5B9A",
3478
- "\u786E\u8BA4",
3479
- "\u53D6\u6D88",
3480
- "\u91CD\u8BD5",
3481
- "\u641C\u7D22",
3482
- "\u590D\u5236",
3483
- "\u5206\u4EAB",
3484
- "\u5173\u95ED",
3485
- "\u66F4\u591A",
3486
- "\u5C55\u5F00",
3487
- "\u6536\u8D77"
3488
- ].join("|");
3489
3439
  var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
3490
3440
  var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
3491
3441
  var describeTarget = (target) => {
@@ -3525,47 +3475,7 @@ var withTimeout = async (operation, timeoutMs, label) => {
3525
3475
  }
3526
3476
  };
3527
3477
  var checkElementVisibility = async (element) => {
3528
- return element.evaluate((el, { interactiveSelector, interactiveHintPattern }) => {
3529
- const interactiveHintRe = new RegExp(interactiveHintPattern, "i");
3530
- const nodeClassName = (node) => {
3531
- if (!node) return "";
3532
- if (typeof node.className === "string") return node.className;
3533
- if (node.className && typeof node.className.baseVal === "string") return node.className.baseVal;
3534
- return "";
3535
- };
3536
- const interactiveScore = (node) => {
3537
- if (!node || node.nodeType !== Node.ELEMENT_NODE) return 0;
3538
- let score = 0;
3539
- if (typeof node.matches === "function" && node.matches(interactiveSelector)) score += 8;
3540
- const hints = [
3541
- node.id || "",
3542
- nodeClassName(node),
3543
- node.getAttribute?.("aria-label") || "",
3544
- node.getAttribute?.("title") || "",
3545
- node.getAttribute?.("data-testid") || "",
3546
- node.getAttribute?.("data-test") || "",
3547
- node.getAttribute?.("data-click") || "",
3548
- node.getAttribute?.("data-action") || "",
3549
- node.getAttribute?.("onclick") || "",
3550
- String(node.textContent || "").trim().slice(0, 24)
3551
- ].join(" ");
3552
- if (interactiveHintRe.test(hints)) score += 4;
3553
- const style = window.getComputedStyle(node);
3554
- if (style?.cursor === "pointer") score += 2;
3555
- return score;
3556
- };
3557
- const closestInteractive = (node) => {
3558
- let best = null;
3559
- let bestScore = 0;
3560
- for (let current = node; current && current !== document.body; current = current.parentElement) {
3561
- const score = interactiveScore(current);
3562
- if (score > bestScore || score > 0 && score === bestScore) {
3563
- best = current;
3564
- bestScore = score;
3565
- }
3566
- }
3567
- return best;
3568
- };
3478
+ return element.evaluate((el) => {
3569
3479
  const targetStyle = window.getComputedStyle(el);
3570
3480
  if (!targetStyle || targetStyle.display === "none" || targetStyle.visibility === "hidden" || targetStyle.visibility === "collapse") {
3571
3481
  return { code: "NOT_INTERACTABLE", reason: "\u5143\u7D20\u4E0D\u53EF\u89C1", direction: "down" };
@@ -3627,13 +3537,30 @@ var checkElementVisibility = async (element) => {
3627
3537
  positioning
3628
3538
  };
3629
3539
  }
3630
- const targetInteractive = closestInteractive(el);
3631
- const sameInteractiveTarget = (pointElement) => {
3540
+ const isRootNode = (node) => !node || node === document || node === document.body || node === document.documentElement;
3541
+ const commonAncestor = (a, b) => {
3542
+ for (let current = a; current && !isRootNode(current); current = current.parentElement) {
3543
+ if (current.contains(b)) return current;
3544
+ }
3545
+ return null;
3546
+ };
3547
+ const sameTapTarget = (pointElement) => {
3632
3548
  if (!pointElement) return false;
3633
3549
  if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
3634
3550
  return true;
3635
3551
  }
3636
- return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
3552
+ const common = commonAncestor(el, pointElement);
3553
+ if (!common) return false;
3554
+ const commonRect = common.getBoundingClientRect?.();
3555
+ if (!commonRect || commonRect.width <= 0 || commonRect.height <= 0) return false;
3556
+ const commonArea = commonRect.width * commonRect.height;
3557
+ const targetArea = Math.max(1, rect.width * rect.height);
3558
+ const maxSharedRegionArea = Math.max(targetArea * 12, 4096);
3559
+ if (commonArea > maxSharedRegionArea) return false;
3560
+ if (commonRect.width > Math.max(rect.width * 8, 120) || commonRect.height > Math.max(rect.height * 8, 120)) {
3561
+ return false;
3562
+ }
3563
+ return common.contains(el) && common.contains(pointElement);
3637
3564
  };
3638
3565
  const describeElement = (node) => {
3639
3566
  if (!node) return null;
@@ -3662,7 +3589,7 @@ var checkElementVisibility = async (element) => {
3662
3589
  let obstruction = null;
3663
3590
  for (const point of samplePoints) {
3664
3591
  const pointElement = document.elementFromPoint(point.x, point.y);
3665
- if (sameInteractiveTarget(pointElement)) {
3592
+ if (sameTapTarget(pointElement)) {
3666
3593
  return { code: "VISIBLE", isFixed, positioning };
3667
3594
  }
3668
3595
  obstruction = obstruction || describeElement(pointElement);
@@ -3680,53 +3607,10 @@ var checkElementVisibility = async (element) => {
3680
3607
  };
3681
3608
  }
3682
3609
  return { code: "VISIBLE", isFixed, positioning };
3683
- }, {
3684
- interactiveSelector: INTERACTIVE_SELECTOR,
3685
- interactiveHintPattern: INTERACTIVE_HINT_PATTERN
3686
3610
  });
3687
3611
  };
3688
3612
  var resolveSafeTapPoint = async (element) => {
3689
- return element.evaluate((el, { interactiveSelector, interactiveHintPattern }) => {
3690
- const interactiveHintRe = new RegExp(interactiveHintPattern, "i");
3691
- const nodeClassName = (node) => {
3692
- if (!node) return "";
3693
- if (typeof node.className === "string") return node.className;
3694
- if (node.className && typeof node.className.baseVal === "string") return node.className.baseVal;
3695
- return "";
3696
- };
3697
- const interactiveScore = (node) => {
3698
- if (!node || node.nodeType !== Node.ELEMENT_NODE) return 0;
3699
- let score = 0;
3700
- if (typeof node.matches === "function" && node.matches(interactiveSelector)) score += 8;
3701
- const hints = [
3702
- node.id || "",
3703
- nodeClassName(node),
3704
- node.getAttribute?.("aria-label") || "",
3705
- node.getAttribute?.("title") || "",
3706
- node.getAttribute?.("data-testid") || "",
3707
- node.getAttribute?.("data-test") || "",
3708
- node.getAttribute?.("data-click") || "",
3709
- node.getAttribute?.("data-action") || "",
3710
- node.getAttribute?.("onclick") || "",
3711
- String(node.textContent || "").trim().slice(0, 24)
3712
- ].join(" ");
3713
- if (interactiveHintRe.test(hints)) score += 4;
3714
- const style = window.getComputedStyle(node);
3715
- if (style?.cursor === "pointer") score += 2;
3716
- return score;
3717
- };
3718
- const closestInteractive = (node) => {
3719
- let best = null;
3720
- let bestScore = 0;
3721
- for (let current = node; current && current !== document.body; current = current.parentElement) {
3722
- const score = interactiveScore(current);
3723
- if (score > bestScore || score > 0 && score === bestScore) {
3724
- best = current;
3725
- bestScore = score;
3726
- }
3727
- }
3728
- return best;
3729
- };
3613
+ return element.evaluate((el) => {
3730
3614
  const rect = el.getBoundingClientRect();
3731
3615
  if (!rect || rect.width <= 0 || rect.height <= 0) {
3732
3616
  return null;
@@ -3763,13 +3647,30 @@ var resolveSafeTapPoint = async (element) => {
3763
3647
  if (visibleWidth <= 1 || visibleHeight <= 1) {
3764
3648
  return null;
3765
3649
  }
3766
- const targetInteractive = closestInteractive(el);
3767
- const sameInteractiveTarget = (pointElement) => {
3650
+ const isRootNode = (node) => !node || node === document || node === document.body || node === document.documentElement;
3651
+ const commonAncestor = (a, b) => {
3652
+ for (let current = a; current && !isRootNode(current); current = current.parentElement) {
3653
+ if (current.contains(b)) return current;
3654
+ }
3655
+ return null;
3656
+ };
3657
+ const sameTapTarget = (pointElement) => {
3768
3658
  if (!pointElement) return false;
3769
3659
  if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
3770
3660
  return true;
3771
3661
  }
3772
- return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
3662
+ const common = commonAncestor(el, pointElement);
3663
+ if (!common) return false;
3664
+ const commonRect = common.getBoundingClientRect?.();
3665
+ if (!commonRect || commonRect.width <= 0 || commonRect.height <= 0) return false;
3666
+ const commonArea = commonRect.width * commonRect.height;
3667
+ const targetArea = Math.max(1, rect.width * rect.height);
3668
+ const maxSharedRegionArea = Math.max(targetArea * 12, 4096);
3669
+ if (commonArea > maxSharedRegionArea) return false;
3670
+ if (commonRect.width > Math.max(rect.width * 8, 120) || commonRect.height > Math.max(rect.height * 8, 120)) {
3671
+ return false;
3672
+ }
3673
+ return common.contains(el) && common.contains(pointElement);
3773
3674
  };
3774
3675
  const cx = visibleLeft + visibleWidth / 2;
3775
3676
  const cy = visibleTop + visibleHeight / 2;
@@ -3788,7 +3689,7 @@ var resolveSafeTapPoint = async (element) => {
3788
3689
  ];
3789
3690
  const safePoints = points.filter((point) => {
3790
3691
  const pointElement = document.elementFromPoint(point.x, point.y);
3791
- return sameInteractiveTarget(pointElement);
3692
+ return sameTapTarget(pointElement);
3792
3693
  });
3793
3694
  const candidates = safePoints.length ? safePoints : points;
3794
3695
  const chosen = candidates[Math.floor(Math.random() * candidates.length)];
@@ -3797,86 +3698,57 @@ var resolveSafeTapPoint = async (element) => {
3797
3698
  x: chosen.x,
3798
3699
  y: chosen.y
3799
3700
  };
3800
- }, {
3801
- interactiveSelector: INTERACTIVE_SELECTOR,
3802
- interactiveHintPattern: INTERACTIVE_HINT_PATTERN
3803
3701
  });
3804
3702
  };
3805
3703
  var activateElementFallback = async (element, point = null, options = {}) => {
3806
- return element.evaluate((el, { innerPoint, innerOptions, interactiveSelector, editableSelector, interactiveHintPattern }) => {
3807
- const interactiveHintRe = new RegExp(interactiveHintPattern, "i");
3808
- const nodeClassName = (node) => {
3809
- if (!node) return "";
3810
- if (typeof node.className === "string") return node.className;
3811
- if (node.className && typeof node.className.baseVal === "string") return node.className.baseVal;
3812
- return "";
3813
- };
3814
- const interactiveScore = (node) => {
3815
- if (!node || node.nodeType !== Node.ELEMENT_NODE) return 0;
3816
- let score = 0;
3817
- if (typeof node.matches === "function" && node.matches(interactiveSelector)) score += 8;
3818
- const hints = [
3819
- node.id || "",
3820
- nodeClassName(node),
3821
- node.getAttribute?.("aria-label") || "",
3822
- node.getAttribute?.("title") || "",
3823
- node.getAttribute?.("data-testid") || "",
3824
- node.getAttribute?.("data-test") || "",
3825
- node.getAttribute?.("data-click") || "",
3826
- node.getAttribute?.("data-action") || "",
3827
- node.getAttribute?.("onclick") || "",
3828
- String(node.textContent || "").trim().slice(0, 24)
3829
- ].join(" ");
3830
- if (interactiveHintRe.test(hints)) score += 4;
3831
- const style = window.getComputedStyle(node);
3832
- if (style?.cursor === "pointer") score += 2;
3833
- return score;
3704
+ return element.evaluate((el, { innerOptions }) => {
3705
+ const isEditable = (node) => {
3706
+ if (!node || node.nodeType !== Node.ELEMENT_NODE) return false;
3707
+ if (node.isContentEditable) return true;
3708
+ if (node instanceof HTMLTextAreaElement) return !node.disabled && !node.readOnly;
3709
+ if (node instanceof HTMLInputElement) {
3710
+ return !node.disabled && !node.readOnly && typeof node.select === "function";
3711
+ }
3712
+ return false;
3834
3713
  };
3835
- const pointElement = innerPoint ? document.elementFromPoint(innerPoint.x, innerPoint.y) : null;
3836
- const nearestInteractive = (node) => {
3837
- let best = null;
3838
- let bestScore = 0;
3714
+ const findEditable = (node) => {
3839
3715
  for (let current = node; current && current !== document.body; current = current.parentElement) {
3840
- const score = interactiveScore(current);
3841
- if (score > bestScore || score > 0 && score === bestScore) {
3842
- best = current;
3843
- bestScore = score;
3844
- }
3716
+ if (isEditable(current)) return current;
3845
3717
  }
3846
- return best;
3718
+ return null;
3847
3719
  };
3848
- const targetInteractive = nearestInteractive(el);
3849
- const pointInteractive = nearestInteractive(pointElement);
3850
- let target = null;
3851
- if (pointInteractive && (pointInteractive === targetInteractive || pointInteractive === el || pointInteractive.contains(el) || el.contains(pointInteractive))) {
3852
- target = pointInteractive;
3853
- }
3854
- target = target || targetInteractive || el;
3855
- const editable = typeof target.closest === "function" ? target.closest(editableSelector) : null;
3720
+ const editable = findEditable(el);
3856
3721
  if (editable && typeof editable.focus === "function") {
3857
3722
  editable.focus({ preventScroll: true });
3858
3723
  if (innerOptions.editableOnly) {
3859
3724
  return { activated: true, method: "focus", tag: editable.tagName || "" };
3860
3725
  }
3861
3726
  }
3862
- if (typeof target.focus === "function") {
3863
- target.focus({ preventScroll: true });
3727
+ if (innerOptions.editableOnly) {
3728
+ return { activated: false, method: "none", tag: el?.tagName || "" };
3864
3729
  }
3865
- if (!innerOptions.editableOnly && typeof target.click === "function") {
3866
- target.click();
3867
- return { activated: true, method: "dom-click", tag: target.tagName || "" };
3730
+ if (typeof el.focus === "function") {
3731
+ el.focus({ preventScroll: true });
3732
+ }
3733
+ if (typeof el.click === "function") {
3734
+ el.click();
3735
+ return { activated: true, method: "dom-click", tag: el.tagName || "" };
3736
+ }
3737
+ if (typeof el.dispatchEvent === "function") {
3738
+ el.dispatchEvent(new MouseEvent("click", {
3739
+ bubbles: true,
3740
+ cancelable: true,
3741
+ view: window
3742
+ }));
3743
+ return { activated: true, method: "dispatch-click", tag: el.tagName || "" };
3868
3744
  }
3869
3745
  return {
3870
3746
  activated: Boolean(editable),
3871
3747
  method: editable ? "focus" : "none",
3872
- tag: target?.tagName || ""
3748
+ tag: el?.tagName || ""
3873
3749
  };
3874
3750
  }, {
3875
- innerPoint: point,
3876
- innerOptions: options || {},
3877
- interactiveSelector: INTERACTIVE_SELECTOR,
3878
- editableSelector: EDITABLE_SELECTOR,
3879
- interactiveHintPattern: INTERACTIVE_HINT_PATTERN
3751
+ innerOptions: options || {}
3880
3752
  });
3881
3753
  };
3882
3754
  var getScrollableRect = async (element) => {