@skrillex1224/playwright-toolkit 2.1.243 → 2.1.245
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 +262 -26
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +262 -26
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3439,6 +3439,11 @@ var DEFAULT_ACTIVATE_FALLBACK_TIMEOUT_MS = 900;
|
|
|
3439
3439
|
var INTERACTIVE_SELECTOR = [
|
|
3440
3440
|
"button",
|
|
3441
3441
|
'[role="button"]',
|
|
3442
|
+
'[role="link"]',
|
|
3443
|
+
'[role="menuitem"]',
|
|
3444
|
+
'[role="tab"]',
|
|
3445
|
+
'[role="switch"]',
|
|
3446
|
+
'[role="checkbox"]',
|
|
3442
3447
|
"a[href]",
|
|
3443
3448
|
"label",
|
|
3444
3449
|
"input",
|
|
@@ -3453,6 +3458,34 @@ var EDITABLE_SELECTOR = [
|
|
|
3453
3458
|
"textarea",
|
|
3454
3459
|
'[contenteditable="true"]'
|
|
3455
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("|");
|
|
3456
3489
|
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
3457
3490
|
var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
|
|
3458
3491
|
var describeTarget = (target) => {
|
|
@@ -3492,7 +3525,47 @@ var withTimeout = async (operation, timeoutMs, label) => {
|
|
|
3492
3525
|
}
|
|
3493
3526
|
};
|
|
3494
3527
|
var checkElementVisibility = async (element) => {
|
|
3495
|
-
return element.evaluate((el, interactiveSelector) => {
|
|
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
|
+
};
|
|
3496
3569
|
const targetStyle = window.getComputedStyle(el);
|
|
3497
3570
|
if (!targetStyle || targetStyle.display === "none" || targetStyle.visibility === "hidden" || targetStyle.visibility === "collapse") {
|
|
3498
3571
|
return { code: "NOT_INTERACTABLE", reason: "\u5143\u7D20\u4E0D\u53EF\u89C1", direction: "down" };
|
|
@@ -3554,16 +3627,13 @@ var checkElementVisibility = async (element) => {
|
|
|
3554
3627
|
positioning
|
|
3555
3628
|
};
|
|
3556
3629
|
}
|
|
3557
|
-
const targetInteractive =
|
|
3630
|
+
const targetInteractive = closestInteractive(el);
|
|
3558
3631
|
const sameInteractiveTarget = (pointElement) => {
|
|
3559
3632
|
if (!pointElement) return false;
|
|
3560
3633
|
if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
|
|
3561
3634
|
return true;
|
|
3562
3635
|
}
|
|
3563
|
-
|
|
3564
|
-
return false;
|
|
3565
|
-
}
|
|
3566
|
-
return pointElement.closest(interactiveSelector) === targetInteractive;
|
|
3636
|
+
return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
|
|
3567
3637
|
};
|
|
3568
3638
|
const describeElement = (node) => {
|
|
3569
3639
|
if (!node) return null;
|
|
@@ -3610,10 +3680,53 @@ var checkElementVisibility = async (element) => {
|
|
|
3610
3680
|
};
|
|
3611
3681
|
}
|
|
3612
3682
|
return { code: "VISIBLE", isFixed, positioning };
|
|
3613
|
-
},
|
|
3683
|
+
}, {
|
|
3684
|
+
interactiveSelector: INTERACTIVE_SELECTOR,
|
|
3685
|
+
interactiveHintPattern: INTERACTIVE_HINT_PATTERN
|
|
3686
|
+
});
|
|
3614
3687
|
};
|
|
3615
3688
|
var resolveSafeTapPoint = async (element) => {
|
|
3616
|
-
return element.evaluate((el, interactiveSelector) => {
|
|
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
|
+
};
|
|
3617
3730
|
const rect = el.getBoundingClientRect();
|
|
3618
3731
|
if (!rect || rect.width <= 0 || rect.height <= 0) {
|
|
3619
3732
|
return null;
|
|
@@ -3650,16 +3763,13 @@ var resolveSafeTapPoint = async (element) => {
|
|
|
3650
3763
|
if (visibleWidth <= 1 || visibleHeight <= 1) {
|
|
3651
3764
|
return null;
|
|
3652
3765
|
}
|
|
3653
|
-
const targetInteractive =
|
|
3766
|
+
const targetInteractive = closestInteractive(el);
|
|
3654
3767
|
const sameInteractiveTarget = (pointElement) => {
|
|
3655
3768
|
if (!pointElement) return false;
|
|
3656
3769
|
if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
|
|
3657
3770
|
return true;
|
|
3658
3771
|
}
|
|
3659
|
-
|
|
3660
|
-
return false;
|
|
3661
|
-
}
|
|
3662
|
-
return pointElement.closest(interactiveSelector) === targetInteractive;
|
|
3772
|
+
return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
|
|
3663
3773
|
};
|
|
3664
3774
|
const cx = visibleLeft + visibleWidth / 2;
|
|
3665
3775
|
const cy = visibleTop + visibleHeight / 2;
|
|
@@ -3687,14 +3797,53 @@ var resolveSafeTapPoint = async (element) => {
|
|
|
3687
3797
|
x: chosen.x,
|
|
3688
3798
|
y: chosen.y
|
|
3689
3799
|
};
|
|
3690
|
-
},
|
|
3800
|
+
}, {
|
|
3801
|
+
interactiveSelector: INTERACTIVE_SELECTOR,
|
|
3802
|
+
interactiveHintPattern: INTERACTIVE_HINT_PATTERN
|
|
3803
|
+
});
|
|
3691
3804
|
};
|
|
3692
3805
|
var activateElementFallback = async (element, point = null, options = {}) => {
|
|
3693
|
-
return element.evaluate((el, { innerPoint, innerOptions, interactiveSelector, editableSelector }) => {
|
|
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;
|
|
3834
|
+
};
|
|
3694
3835
|
const pointElement = innerPoint ? document.elementFromPoint(innerPoint.x, innerPoint.y) : null;
|
|
3695
3836
|
const nearestInteractive = (node) => {
|
|
3696
|
-
|
|
3697
|
-
|
|
3837
|
+
let best = null;
|
|
3838
|
+
let bestScore = 0;
|
|
3839
|
+
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
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
return best;
|
|
3698
3847
|
};
|
|
3699
3848
|
const targetInteractive = nearestInteractive(el);
|
|
3700
3849
|
const pointInteractive = nearestInteractive(pointElement);
|
|
@@ -3726,7 +3875,8 @@ var activateElementFallback = async (element, point = null, options = {}) => {
|
|
|
3726
3875
|
innerPoint: point,
|
|
3727
3876
|
innerOptions: options || {},
|
|
3728
3877
|
interactiveSelector: INTERACTIVE_SELECTOR,
|
|
3729
|
-
editableSelector: EDITABLE_SELECTOR
|
|
3878
|
+
editableSelector: EDITABLE_SELECTOR,
|
|
3879
|
+
interactiveHintPattern: INTERACTIVE_HINT_PATTERN
|
|
3730
3880
|
});
|
|
3731
3881
|
};
|
|
3732
3882
|
var getScrollableRect = async (element) => {
|
|
@@ -3830,6 +3980,47 @@ var scrollAwayFromObstruction = async (element, status) => {
|
|
|
3830
3980
|
};
|
|
3831
3981
|
}, status);
|
|
3832
3982
|
};
|
|
3983
|
+
var getElementViewportSnapshot = async (element) => {
|
|
3984
|
+
return element.evaluate((el) => {
|
|
3985
|
+
const rect = el.getBoundingClientRect();
|
|
3986
|
+
return {
|
|
3987
|
+
top: rect.top,
|
|
3988
|
+
bottom: rect.bottom,
|
|
3989
|
+
left: rect.left,
|
|
3990
|
+
right: rect.right,
|
|
3991
|
+
width: rect.width,
|
|
3992
|
+
height: rect.height,
|
|
3993
|
+
scrollX: window.scrollX,
|
|
3994
|
+
scrollY: window.scrollY
|
|
3995
|
+
};
|
|
3996
|
+
});
|
|
3997
|
+
};
|
|
3998
|
+
var isTargetImmobileAfterScroll = (before, after) => {
|
|
3999
|
+
if (!before || !after) return false;
|
|
4000
|
+
const rectDeltaY = Number(after.top || 0) - Number(before.top || 0);
|
|
4001
|
+
const rectDeltaX = Number(after.left || 0) - Number(before.left || 0);
|
|
4002
|
+
const scrollDeltaY = Number(after.scrollY || 0) - Number(before.scrollY || 0);
|
|
4003
|
+
const scrollDeltaX = Number(after.scrollX || 0) - Number(before.scrollX || 0);
|
|
4004
|
+
const rectMoved = Math.abs(rectDeltaY) > 3 || Math.abs(rectDeltaX) > 3;
|
|
4005
|
+
const pageMoved = Math.abs(scrollDeltaY) > 3 || Math.abs(scrollDeltaX) > 3;
|
|
4006
|
+
if (!rectMoved && !pageMoved) return true;
|
|
4007
|
+
if (pageMoved && !rectMoved) return true;
|
|
4008
|
+
if (Math.abs(scrollDeltaY) > 12 && Math.abs(rectDeltaY) < Math.min(12, Math.abs(scrollDeltaY) * 0.2)) {
|
|
4009
|
+
return true;
|
|
4010
|
+
}
|
|
4011
|
+
return false;
|
|
4012
|
+
};
|
|
4013
|
+
var restoreWindowFromSnapshot = async (page, before, after) => {
|
|
4014
|
+
if (!before || !after) return;
|
|
4015
|
+
if (Math.abs(Number(after.scrollX || 0) - Number(before.scrollX || 0)) <= 2 && Math.abs(Number(after.scrollY || 0) - Number(before.scrollY || 0)) <= 2) {
|
|
4016
|
+
return;
|
|
4017
|
+
}
|
|
4018
|
+
await page.evaluate(
|
|
4019
|
+
(state) => window.scrollTo(state.x, state.y),
|
|
4020
|
+
{ x: Number(before.scrollX || 0), y: Number(before.scrollY || 0) }
|
|
4021
|
+
).catch(() => {
|
|
4022
|
+
});
|
|
4023
|
+
};
|
|
3833
4024
|
var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
|
|
3834
4025
|
const viewport = resolveViewport(page);
|
|
3835
4026
|
const rawRect = options.rect || null;
|
|
@@ -4010,11 +4201,11 @@ var MobileHumanize = {
|
|
|
4010
4201
|
const scrollRect = await getScrollableRect(element);
|
|
4011
4202
|
if (!scrollRect && status.isFixed && status.code === "OUT_OF_VIEWPORT") {
|
|
4012
4203
|
logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u4E0D\u5728\u89C6\u53E3\u5185\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (direction=${status.direction || "unknown"})`);
|
|
4013
|
-
return { element, didScroll, restore: null };
|
|
4204
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
4014
4205
|
}
|
|
4015
4206
|
if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
|
|
4016
4207
|
logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
|
|
4017
|
-
return { element, didScroll, restore: null };
|
|
4208
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
4018
4209
|
}
|
|
4019
4210
|
if (scrollRect && status.code === "OBSTRUCTED" && status.obstruction?.isFixed) {
|
|
4020
4211
|
const moved = await scrollAwayFromObstruction(element, status);
|
|
@@ -4045,6 +4236,7 @@ var MobileHumanize = {
|
|
|
4045
4236
|
}
|
|
4046
4237
|
}
|
|
4047
4238
|
const beforeWindowState = scrollRect ? await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })) : null;
|
|
4239
|
+
const beforeElementSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4048
4240
|
const beforeState = scrollRect ? await element.evaluate((el) => {
|
|
4049
4241
|
const isScrollable = (node) => {
|
|
4050
4242
|
const style = window.getComputedStyle(node);
|
|
@@ -4074,6 +4266,21 @@ var MobileHumanize = {
|
|
|
4074
4266
|
logger7.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
|
|
4075
4267
|
}
|
|
4076
4268
|
}
|
|
4269
|
+
let afterElementSnapshot = null;
|
|
4270
|
+
const readAfterElementSnapshot = async () => {
|
|
4271
|
+
if (!afterElementSnapshot) {
|
|
4272
|
+
afterElementSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4273
|
+
}
|
|
4274
|
+
return afterElementSnapshot;
|
|
4275
|
+
};
|
|
4276
|
+
if (!scrollRect && beforeElementSnapshot) {
|
|
4277
|
+
const afterSnapshot = await readAfterElementSnapshot();
|
|
4278
|
+
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4279
|
+
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4280
|
+
logger7.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u9875\u9762\u6EDA\u52A8\u79FB\u52A8\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
|
|
4281
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4077
4284
|
if (scrollRect && beforeState) {
|
|
4078
4285
|
const afterState = await element.evaluate((el) => {
|
|
4079
4286
|
const isScrollable = (node) => {
|
|
@@ -4111,6 +4318,14 @@ var MobileHumanize = {
|
|
|
4111
4318
|
}
|
|
4112
4319
|
}
|
|
4113
4320
|
}
|
|
4321
|
+
if (scrollRect && beforeElementSnapshot) {
|
|
4322
|
+
const afterSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4323
|
+
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4324
|
+
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4325
|
+
logger7.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u6EDA\u52A8\u5BB9\u5668\u79FB\u52A8\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
|
|
4326
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
4327
|
+
}
|
|
4328
|
+
}
|
|
4114
4329
|
didScroll = true;
|
|
4115
4330
|
}
|
|
4116
4331
|
try {
|
|
@@ -4160,21 +4375,28 @@ var MobileHumanize = {
|
|
|
4160
4375
|
logger7.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
|
|
4161
4376
|
return false;
|
|
4162
4377
|
}
|
|
4163
|
-
|
|
4164
|
-
await MobileHumanize.humanScroll(page, element, { throwOnMissing });
|
|
4165
|
-
}
|
|
4378
|
+
const scrollResult = scrollIfNeeded ? await MobileHumanize.humanScroll(page, element, { throwOnMissing }) : null;
|
|
4166
4379
|
const status = await checkElementVisibility(element).catch(() => null);
|
|
4167
4380
|
if (status && status.code !== "VISIBLE") {
|
|
4168
|
-
if (fallbackDomClick && status.
|
|
4169
|
-
|
|
4381
|
+
if (fallbackDomClick && (status.code === "OUT_OF_VIEWPORT" || status.code === "OBSTRUCTED") && (status.isFixed || scrollResult?.unscrollable)) {
|
|
4382
|
+
let fallback = await withTimeout(
|
|
4170
4383
|
() => activateElementFallback(element, null, {
|
|
4171
4384
|
editableOnly: true
|
|
4172
4385
|
}),
|
|
4173
4386
|
activateFallbackTimeoutMs,
|
|
4174
4387
|
"focus fallback"
|
|
4175
4388
|
).catch(() => null);
|
|
4389
|
+
if (!fallback?.activated) {
|
|
4390
|
+
fallback = await withTimeout(
|
|
4391
|
+
() => activateElementFallback(element, null, {
|
|
4392
|
+
editableOnly: false
|
|
4393
|
+
}),
|
|
4394
|
+
activateFallbackTimeoutMs,
|
|
4395
|
+
"activation fallback"
|
|
4396
|
+
).catch(() => null);
|
|
4397
|
+
}
|
|
4176
4398
|
if (fallback?.activated) {
|
|
4177
|
-
logger7.warn(`humanClick:
|
|
4399
|
+
logger7.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
|
|
4178
4400
|
return true;
|
|
4179
4401
|
}
|
|
4180
4402
|
}
|
|
@@ -4291,6 +4513,20 @@ var MobileHumanize = {
|
|
|
4291
4513
|
const locator = page.locator(selector);
|
|
4292
4514
|
await MobileHumanize.humanClick(page, locator, { scrollIfNeeded: true });
|
|
4293
4515
|
await waitJitter(160, 0.4);
|
|
4516
|
+
const readValue = async () => {
|
|
4517
|
+
try {
|
|
4518
|
+
return await locator.inputValue({ timeout: 600 });
|
|
4519
|
+
} catch {
|
|
4520
|
+
return await locator.evaluate((el) => "value" in el ? String(el.value || "") : String(el.textContent || "")).catch(() => "");
|
|
4521
|
+
}
|
|
4522
|
+
};
|
|
4523
|
+
const currentValue = await readValue();
|
|
4524
|
+
if (!currentValue) return;
|
|
4525
|
+
await page.keyboard.press("ControlOrMeta+A");
|
|
4526
|
+
await waitJitter(90, 0.35);
|
|
4527
|
+
await page.keyboard.press("Backspace");
|
|
4528
|
+
await waitJitter(120, 0.35);
|
|
4529
|
+
if (!await readValue()) return;
|
|
4294
4530
|
await locator.evaluate((el) => {
|
|
4295
4531
|
if ("value" in el) {
|
|
4296
4532
|
el.value = "";
|