@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.js
CHANGED
|
@@ -3411,6 +3411,11 @@ var DEFAULT_ACTIVATE_FALLBACK_TIMEOUT_MS = 900;
|
|
|
3411
3411
|
var INTERACTIVE_SELECTOR = [
|
|
3412
3412
|
"button",
|
|
3413
3413
|
'[role="button"]',
|
|
3414
|
+
'[role="link"]',
|
|
3415
|
+
'[role="menuitem"]',
|
|
3416
|
+
'[role="tab"]',
|
|
3417
|
+
'[role="switch"]',
|
|
3418
|
+
'[role="checkbox"]',
|
|
3414
3419
|
"a[href]",
|
|
3415
3420
|
"label",
|
|
3416
3421
|
"input",
|
|
@@ -3425,6 +3430,34 @@ var EDITABLE_SELECTOR = [
|
|
|
3425
3430
|
"textarea",
|
|
3426
3431
|
'[contenteditable="true"]'
|
|
3427
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("|");
|
|
3428
3461
|
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
3429
3462
|
var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
|
|
3430
3463
|
var describeTarget = (target) => {
|
|
@@ -3464,7 +3497,47 @@ var withTimeout = async (operation, timeoutMs, label) => {
|
|
|
3464
3497
|
}
|
|
3465
3498
|
};
|
|
3466
3499
|
var checkElementVisibility = async (element) => {
|
|
3467
|
-
return element.evaluate((el, interactiveSelector) => {
|
|
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
|
+
};
|
|
3468
3541
|
const targetStyle = window.getComputedStyle(el);
|
|
3469
3542
|
if (!targetStyle || targetStyle.display === "none" || targetStyle.visibility === "hidden" || targetStyle.visibility === "collapse") {
|
|
3470
3543
|
return { code: "NOT_INTERACTABLE", reason: "\u5143\u7D20\u4E0D\u53EF\u89C1", direction: "down" };
|
|
@@ -3526,16 +3599,13 @@ var checkElementVisibility = async (element) => {
|
|
|
3526
3599
|
positioning
|
|
3527
3600
|
};
|
|
3528
3601
|
}
|
|
3529
|
-
const targetInteractive =
|
|
3602
|
+
const targetInteractive = closestInteractive(el);
|
|
3530
3603
|
const sameInteractiveTarget = (pointElement) => {
|
|
3531
3604
|
if (!pointElement) return false;
|
|
3532
3605
|
if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
|
|
3533
3606
|
return true;
|
|
3534
3607
|
}
|
|
3535
|
-
|
|
3536
|
-
return false;
|
|
3537
|
-
}
|
|
3538
|
-
return pointElement.closest(interactiveSelector) === targetInteractive;
|
|
3608
|
+
return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
|
|
3539
3609
|
};
|
|
3540
3610
|
const describeElement = (node) => {
|
|
3541
3611
|
if (!node) return null;
|
|
@@ -3582,10 +3652,53 @@ var checkElementVisibility = async (element) => {
|
|
|
3582
3652
|
};
|
|
3583
3653
|
}
|
|
3584
3654
|
return { code: "VISIBLE", isFixed, positioning };
|
|
3585
|
-
},
|
|
3655
|
+
}, {
|
|
3656
|
+
interactiveSelector: INTERACTIVE_SELECTOR,
|
|
3657
|
+
interactiveHintPattern: INTERACTIVE_HINT_PATTERN
|
|
3658
|
+
});
|
|
3586
3659
|
};
|
|
3587
3660
|
var resolveSafeTapPoint = async (element) => {
|
|
3588
|
-
return element.evaluate((el, interactiveSelector) => {
|
|
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
|
+
};
|
|
3589
3702
|
const rect = el.getBoundingClientRect();
|
|
3590
3703
|
if (!rect || rect.width <= 0 || rect.height <= 0) {
|
|
3591
3704
|
return null;
|
|
@@ -3622,16 +3735,13 @@ var resolveSafeTapPoint = async (element) => {
|
|
|
3622
3735
|
if (visibleWidth <= 1 || visibleHeight <= 1) {
|
|
3623
3736
|
return null;
|
|
3624
3737
|
}
|
|
3625
|
-
const targetInteractive =
|
|
3738
|
+
const targetInteractive = closestInteractive(el);
|
|
3626
3739
|
const sameInteractiveTarget = (pointElement) => {
|
|
3627
3740
|
if (!pointElement) return false;
|
|
3628
3741
|
if (pointElement === el || el.contains(pointElement) || pointElement.contains(el)) {
|
|
3629
3742
|
return true;
|
|
3630
3743
|
}
|
|
3631
|
-
|
|
3632
|
-
return false;
|
|
3633
|
-
}
|
|
3634
|
-
return pointElement.closest(interactiveSelector) === targetInteractive;
|
|
3744
|
+
return Boolean(targetInteractive && closestInteractive(pointElement) === targetInteractive);
|
|
3635
3745
|
};
|
|
3636
3746
|
const cx = visibleLeft + visibleWidth / 2;
|
|
3637
3747
|
const cy = visibleTop + visibleHeight / 2;
|
|
@@ -3659,14 +3769,53 @@ var resolveSafeTapPoint = async (element) => {
|
|
|
3659
3769
|
x: chosen.x,
|
|
3660
3770
|
y: chosen.y
|
|
3661
3771
|
};
|
|
3662
|
-
},
|
|
3772
|
+
}, {
|
|
3773
|
+
interactiveSelector: INTERACTIVE_SELECTOR,
|
|
3774
|
+
interactiveHintPattern: INTERACTIVE_HINT_PATTERN
|
|
3775
|
+
});
|
|
3663
3776
|
};
|
|
3664
3777
|
var activateElementFallback = async (element, point = null, options = {}) => {
|
|
3665
|
-
return element.evaluate((el, { innerPoint, innerOptions, interactiveSelector, editableSelector }) => {
|
|
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;
|
|
3806
|
+
};
|
|
3666
3807
|
const pointElement = innerPoint ? document.elementFromPoint(innerPoint.x, innerPoint.y) : null;
|
|
3667
3808
|
const nearestInteractive = (node) => {
|
|
3668
|
-
|
|
3669
|
-
|
|
3809
|
+
let best = null;
|
|
3810
|
+
let bestScore = 0;
|
|
3811
|
+
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
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
return best;
|
|
3670
3819
|
};
|
|
3671
3820
|
const targetInteractive = nearestInteractive(el);
|
|
3672
3821
|
const pointInteractive = nearestInteractive(pointElement);
|
|
@@ -3698,7 +3847,8 @@ var activateElementFallback = async (element, point = null, options = {}) => {
|
|
|
3698
3847
|
innerPoint: point,
|
|
3699
3848
|
innerOptions: options || {},
|
|
3700
3849
|
interactiveSelector: INTERACTIVE_SELECTOR,
|
|
3701
|
-
editableSelector: EDITABLE_SELECTOR
|
|
3850
|
+
editableSelector: EDITABLE_SELECTOR,
|
|
3851
|
+
interactiveHintPattern: INTERACTIVE_HINT_PATTERN
|
|
3702
3852
|
});
|
|
3703
3853
|
};
|
|
3704
3854
|
var getScrollableRect = async (element) => {
|
|
@@ -3802,6 +3952,47 @@ var scrollAwayFromObstruction = async (element, status) => {
|
|
|
3802
3952
|
};
|
|
3803
3953
|
}, status);
|
|
3804
3954
|
};
|
|
3955
|
+
var getElementViewportSnapshot = async (element) => {
|
|
3956
|
+
return element.evaluate((el) => {
|
|
3957
|
+
const rect = el.getBoundingClientRect();
|
|
3958
|
+
return {
|
|
3959
|
+
top: rect.top,
|
|
3960
|
+
bottom: rect.bottom,
|
|
3961
|
+
left: rect.left,
|
|
3962
|
+
right: rect.right,
|
|
3963
|
+
width: rect.width,
|
|
3964
|
+
height: rect.height,
|
|
3965
|
+
scrollX: window.scrollX,
|
|
3966
|
+
scrollY: window.scrollY
|
|
3967
|
+
};
|
|
3968
|
+
});
|
|
3969
|
+
};
|
|
3970
|
+
var isTargetImmobileAfterScroll = (before, after) => {
|
|
3971
|
+
if (!before || !after) return false;
|
|
3972
|
+
const rectDeltaY = Number(after.top || 0) - Number(before.top || 0);
|
|
3973
|
+
const rectDeltaX = Number(after.left || 0) - Number(before.left || 0);
|
|
3974
|
+
const scrollDeltaY = Number(after.scrollY || 0) - Number(before.scrollY || 0);
|
|
3975
|
+
const scrollDeltaX = Number(after.scrollX || 0) - Number(before.scrollX || 0);
|
|
3976
|
+
const rectMoved = Math.abs(rectDeltaY) > 3 || Math.abs(rectDeltaX) > 3;
|
|
3977
|
+
const pageMoved = Math.abs(scrollDeltaY) > 3 || Math.abs(scrollDeltaX) > 3;
|
|
3978
|
+
if (!rectMoved && !pageMoved) return true;
|
|
3979
|
+
if (pageMoved && !rectMoved) return true;
|
|
3980
|
+
if (Math.abs(scrollDeltaY) > 12 && Math.abs(rectDeltaY) < Math.min(12, Math.abs(scrollDeltaY) * 0.2)) {
|
|
3981
|
+
return true;
|
|
3982
|
+
}
|
|
3983
|
+
return false;
|
|
3984
|
+
};
|
|
3985
|
+
var restoreWindowFromSnapshot = async (page, before, after) => {
|
|
3986
|
+
if (!before || !after) return;
|
|
3987
|
+
if (Math.abs(Number(after.scrollX || 0) - Number(before.scrollX || 0)) <= 2 && Math.abs(Number(after.scrollY || 0) - Number(before.scrollY || 0)) <= 2) {
|
|
3988
|
+
return;
|
|
3989
|
+
}
|
|
3990
|
+
await page.evaluate(
|
|
3991
|
+
(state) => window.scrollTo(state.x, state.y),
|
|
3992
|
+
{ x: Number(before.scrollX || 0), y: Number(before.scrollY || 0) }
|
|
3993
|
+
).catch(() => {
|
|
3994
|
+
});
|
|
3995
|
+
};
|
|
3805
3996
|
var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
|
|
3806
3997
|
const viewport = resolveViewport(page);
|
|
3807
3998
|
const rawRect = options.rect || null;
|
|
@@ -3982,11 +4173,11 @@ var MobileHumanize = {
|
|
|
3982
4173
|
const scrollRect = await getScrollableRect(element);
|
|
3983
4174
|
if (!scrollRect && status.isFixed && status.code === "OUT_OF_VIEWPORT") {
|
|
3984
4175
|
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"})`);
|
|
3985
|
-
return { element, didScroll, restore: null };
|
|
4176
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
3986
4177
|
}
|
|
3987
4178
|
if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
|
|
3988
4179
|
logger7.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
|
|
3989
|
-
return { element, didScroll, restore: null };
|
|
4180
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
3990
4181
|
}
|
|
3991
4182
|
if (scrollRect && status.code === "OBSTRUCTED" && status.obstruction?.isFixed) {
|
|
3992
4183
|
const moved = await scrollAwayFromObstruction(element, status);
|
|
@@ -4017,6 +4208,7 @@ var MobileHumanize = {
|
|
|
4017
4208
|
}
|
|
4018
4209
|
}
|
|
4019
4210
|
const beforeWindowState = scrollRect ? await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })) : null;
|
|
4211
|
+
const beforeElementSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4020
4212
|
const beforeState = scrollRect ? await element.evaluate((el) => {
|
|
4021
4213
|
const isScrollable = (node) => {
|
|
4022
4214
|
const style = window.getComputedStyle(node);
|
|
@@ -4046,6 +4238,21 @@ var MobileHumanize = {
|
|
|
4046
4238
|
logger7.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
|
|
4047
4239
|
}
|
|
4048
4240
|
}
|
|
4241
|
+
let afterElementSnapshot = null;
|
|
4242
|
+
const readAfterElementSnapshot = async () => {
|
|
4243
|
+
if (!afterElementSnapshot) {
|
|
4244
|
+
afterElementSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4245
|
+
}
|
|
4246
|
+
return afterElementSnapshot;
|
|
4247
|
+
};
|
|
4248
|
+
if (!scrollRect && beforeElementSnapshot) {
|
|
4249
|
+
const afterSnapshot = await readAfterElementSnapshot();
|
|
4250
|
+
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4251
|
+
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4252
|
+
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"})`);
|
|
4253
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4049
4256
|
if (scrollRect && beforeState) {
|
|
4050
4257
|
const afterState = await element.evaluate((el) => {
|
|
4051
4258
|
const isScrollable = (node) => {
|
|
@@ -4083,6 +4290,14 @@ var MobileHumanize = {
|
|
|
4083
4290
|
}
|
|
4084
4291
|
}
|
|
4085
4292
|
}
|
|
4293
|
+
if (scrollRect && beforeElementSnapshot) {
|
|
4294
|
+
const afterSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4295
|
+
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4296
|
+
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4297
|
+
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"})`);
|
|
4298
|
+
return { element, didScroll, restore: null, unscrollable: true };
|
|
4299
|
+
}
|
|
4300
|
+
}
|
|
4086
4301
|
didScroll = true;
|
|
4087
4302
|
}
|
|
4088
4303
|
try {
|
|
@@ -4132,21 +4347,28 @@ var MobileHumanize = {
|
|
|
4132
4347
|
logger7.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
|
|
4133
4348
|
return false;
|
|
4134
4349
|
}
|
|
4135
|
-
|
|
4136
|
-
await MobileHumanize.humanScroll(page, element, { throwOnMissing });
|
|
4137
|
-
}
|
|
4350
|
+
const scrollResult = scrollIfNeeded ? await MobileHumanize.humanScroll(page, element, { throwOnMissing }) : null;
|
|
4138
4351
|
const status = await checkElementVisibility(element).catch(() => null);
|
|
4139
4352
|
if (status && status.code !== "VISIBLE") {
|
|
4140
|
-
if (fallbackDomClick && status.
|
|
4141
|
-
|
|
4353
|
+
if (fallbackDomClick && (status.code === "OUT_OF_VIEWPORT" || status.code === "OBSTRUCTED") && (status.isFixed || scrollResult?.unscrollable)) {
|
|
4354
|
+
let fallback = await withTimeout(
|
|
4142
4355
|
() => activateElementFallback(element, null, {
|
|
4143
4356
|
editableOnly: true
|
|
4144
4357
|
}),
|
|
4145
4358
|
activateFallbackTimeoutMs,
|
|
4146
4359
|
"focus fallback"
|
|
4147
4360
|
).catch(() => null);
|
|
4361
|
+
if (!fallback?.activated) {
|
|
4362
|
+
fallback = await withTimeout(
|
|
4363
|
+
() => activateElementFallback(element, null, {
|
|
4364
|
+
editableOnly: false
|
|
4365
|
+
}),
|
|
4366
|
+
activateFallbackTimeoutMs,
|
|
4367
|
+
"activation fallback"
|
|
4368
|
+
).catch(() => null);
|
|
4369
|
+
}
|
|
4148
4370
|
if (fallback?.activated) {
|
|
4149
|
-
logger7.warn(`humanClick:
|
|
4371
|
+
logger7.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
|
|
4150
4372
|
return true;
|
|
4151
4373
|
}
|
|
4152
4374
|
}
|
|
@@ -4263,6 +4485,20 @@ var MobileHumanize = {
|
|
|
4263
4485
|
const locator = page.locator(selector);
|
|
4264
4486
|
await MobileHumanize.humanClick(page, locator, { scrollIfNeeded: true });
|
|
4265
4487
|
await waitJitter(160, 0.4);
|
|
4488
|
+
const readValue = async () => {
|
|
4489
|
+
try {
|
|
4490
|
+
return await locator.inputValue({ timeout: 600 });
|
|
4491
|
+
} catch {
|
|
4492
|
+
return await locator.evaluate((el) => "value" in el ? String(el.value || "") : String(el.textContent || "")).catch(() => "");
|
|
4493
|
+
}
|
|
4494
|
+
};
|
|
4495
|
+
const currentValue = await readValue();
|
|
4496
|
+
if (!currentValue) return;
|
|
4497
|
+
await page.keyboard.press("ControlOrMeta+A");
|
|
4498
|
+
await waitJitter(90, 0.35);
|
|
4499
|
+
await page.keyboard.press("Backspace");
|
|
4500
|
+
await waitJitter(120, 0.35);
|
|
4501
|
+
if (!await readValue()) return;
|
|
4266
4502
|
await locator.evaluate((el) => {
|
|
4267
4503
|
if ("value" in el) {
|
|
4268
4504
|
el.value = "";
|