@skrillex1224/playwright-toolkit 2.1.232 → 2.1.234
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/README.md +10 -3
- package/dist/browser.js +1 -0
- package/dist/browser.js.map +2 -2
- package/dist/index.cjs +454 -205
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +454 -205
- package/dist/index.js.map +4 -4
- package/index.d.ts +35 -13
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -312,6 +312,7 @@ var ActorInfo = {
|
|
|
312
312
|
name: "\u901A\u4E49\u5343\u95EE",
|
|
313
313
|
domain: "www.qianwen.com",
|
|
314
314
|
path: "/chat",
|
|
315
|
+
device: Device.Mobile,
|
|
315
316
|
share: {
|
|
316
317
|
mode: "response",
|
|
317
318
|
prefix: "https://www.qianwen.com/share/chat/",
|
|
@@ -469,6 +470,9 @@ function createInternalLogger(moduleName, explicitLogger) {
|
|
|
469
470
|
// src/internals/screenshot.js
|
|
470
471
|
var import_delay = __toESM(require("delay"), 1);
|
|
471
472
|
|
|
473
|
+
// src/internals/constants.js
|
|
474
|
+
var PageRuntimeStateKey = "__playwright_toolkit_runtime_state__";
|
|
475
|
+
|
|
472
476
|
// src/internals/viewport.js
|
|
473
477
|
var toPositiveInt = (value) => {
|
|
474
478
|
const number = Math.round(Number(value) || 0);
|
|
@@ -505,9 +509,7 @@ var SUPPORTED_TYPES = /* @__PURE__ */ new Set(["png", "jpeg", "webp"]);
|
|
|
505
509
|
var EXPANDED_SCROLLABLE_CLASS = "__pk_expanded__";
|
|
506
510
|
var DEFAULT_MAX_HEIGHT = 8e3;
|
|
507
511
|
var DEFAULT_SETTLE_MS = 1e3;
|
|
508
|
-
var
|
|
509
|
-
var DEFAULT_BUFFER_MIN = 120;
|
|
510
|
-
var DEFAULT_BUFFER_MAX = 320;
|
|
512
|
+
var DEFAULT_MOBILE_SETTLE_MS = 50;
|
|
511
513
|
var toPositiveNumber = (value, fallback = 0) => {
|
|
512
514
|
const n = Number(value);
|
|
513
515
|
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
@@ -517,10 +519,6 @@ var toPositiveInteger = (value, fallback = 0) => {
|
|
|
517
519
|
const number = Math.round(Number(value) || 0);
|
|
518
520
|
return number > 0 ? number : fallback;
|
|
519
521
|
};
|
|
520
|
-
var resolveDefaultBuffer = (viewport = {}) => {
|
|
521
|
-
const height = Math.max(1, Number(viewport.height) || 0);
|
|
522
|
-
return Math.round(Math.min(DEFAULT_BUFFER_MAX, Math.max(DEFAULT_BUFFER_MIN, height * DEFAULT_BUFFER_RATIO)));
|
|
523
|
-
};
|
|
524
522
|
var normalizeType = (value) => {
|
|
525
523
|
const raw = String(value || "png").trim().toLowerCase();
|
|
526
524
|
if (!SUPPORTED_TYPES.has(raw)) return "png";
|
|
@@ -534,6 +532,7 @@ var normalizeQuality = (value, type) => {
|
|
|
534
532
|
if (rounded < 0 || rounded > 100) return void 0;
|
|
535
533
|
return rounded;
|
|
536
534
|
};
|
|
535
|
+
var resolvePageDevice = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
537
536
|
var buildFullPageClip = (metrics, viewport, maxClipHeight) => {
|
|
538
537
|
const contentSize = metrics && typeof metrics === "object" ? metrics.contentSize || null : null;
|
|
539
538
|
const width = Math.max(1, Math.ceil(viewport.width || contentSize?.width || 1));
|
|
@@ -550,7 +549,7 @@ var buildFullPageClip = (metrics, viewport, maxClipHeight) => {
|
|
|
550
549
|
};
|
|
551
550
|
};
|
|
552
551
|
var expandScrollableContent = async (page, options = {}) => {
|
|
553
|
-
return await page.evaluate(({ className, forceScrollableHeight, visibleOnly }) => {
|
|
552
|
+
return await page.evaluate(({ className, forceScrollableHeight, visibleOnly, expandDocumentElements }) => {
|
|
554
553
|
const body = document.body;
|
|
555
554
|
const root = document.documentElement;
|
|
556
555
|
const scrollingElement = document.scrollingElement;
|
|
@@ -575,8 +574,8 @@ var expandScrollableContent = async (page, options = {}) => {
|
|
|
575
574
|
if (Number(style.opacity) === 0) return false;
|
|
576
575
|
return rect.width > 0 && rect.height > 0;
|
|
577
576
|
};
|
|
578
|
-
const rememberOriginalBoxStyles = (el) => {
|
|
579
|
-
if (!el || isDocumentElement(el) || el.classList.contains(className)) {
|
|
577
|
+
const rememberOriginalBoxStyles = (el, { includeDocumentElement = false } = {}) => {
|
|
578
|
+
if (!el || !includeDocumentElement && isDocumentElement(el) || el.classList.contains(className)) {
|
|
580
579
|
return;
|
|
581
580
|
}
|
|
582
581
|
el.dataset.pkOrigOverflow = el.style.overflow;
|
|
@@ -589,6 +588,19 @@ var expandScrollableContent = async (page, options = {}) => {
|
|
|
589
588
|
el.dataset.pkOrigMaxHeightPriority = el.style.getPropertyPriority("max-height") || "";
|
|
590
589
|
el.classList.add(className);
|
|
591
590
|
};
|
|
591
|
+
const expandDocumentElementsToHeight = (height) => {
|
|
592
|
+
if (!expandDocumentElements) return;
|
|
593
|
+
const targetHeight = Math.ceil(Number(height) || 0);
|
|
594
|
+
if (targetHeight <= 0) return;
|
|
595
|
+
[root, body, scrollingElement].forEach((el) => {
|
|
596
|
+
if (!el) return;
|
|
597
|
+
rememberOriginalBoxStyles(el, { includeDocumentElement: true });
|
|
598
|
+
el.style.setProperty("overflow", "visible", "important");
|
|
599
|
+
el.style.setProperty("height", `${targetHeight}px`, "important");
|
|
600
|
+
el.style.setProperty("min-height", `${targetHeight}px`, "important");
|
|
601
|
+
el.style.setProperty("max-height", "none", "important");
|
|
602
|
+
});
|
|
603
|
+
};
|
|
592
604
|
const isScrollableY = (el, style, rect) => {
|
|
593
605
|
if (!el || el.scrollHeight <= el.clientHeight + 1) {
|
|
594
606
|
return false;
|
|
@@ -625,6 +637,7 @@ var expandScrollableContent = async (page, options = {}) => {
|
|
|
625
637
|
return documentTop + scrollHeight;
|
|
626
638
|
};
|
|
627
639
|
const scrollableElements = [];
|
|
640
|
+
const expandedAncestors = [];
|
|
628
641
|
const expandElementToScrollHeight = (el) => {
|
|
629
642
|
if (!el || isDocumentElement(el)) return;
|
|
630
643
|
const scrollHeight = Math.ceil(el.scrollHeight || 0);
|
|
@@ -647,13 +660,44 @@ var expandScrollableContent = async (page, options = {}) => {
|
|
|
647
660
|
rememberOriginalBoxStyles(node);
|
|
648
661
|
node.style.setProperty("overflow", "visible", "important");
|
|
649
662
|
node.style.setProperty("max-height", "none", "important");
|
|
650
|
-
|
|
663
|
+
expandedAncestors.push(node);
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
const expandAncestorsToCurrentScrollHeight = () => {
|
|
667
|
+
const ancestors = [...new Set(expandedAncestors)];
|
|
668
|
+
for (let pass = 0; pass < 2; pass += 1) {
|
|
669
|
+
ancestors.forEach((node) => {
|
|
670
|
+
if (!node || isDocumentElement(node)) return;
|
|
651
671
|
const scrollHeight = Math.ceil(node.scrollHeight || 0);
|
|
672
|
+
if (scrollHeight <= node.clientHeight + 1) return;
|
|
673
|
+
rememberOriginalBoxStyles(node);
|
|
652
674
|
node.style.setProperty("height", `${scrollHeight}px`, "important");
|
|
653
675
|
node.style.setProperty("min-height", `${scrollHeight}px`, "important");
|
|
654
|
-
|
|
676
|
+
node.style.setProperty("max-height", "none", "important");
|
|
677
|
+
});
|
|
655
678
|
}
|
|
656
679
|
};
|
|
680
|
+
const measureExpandedRenderedBottom = () => {
|
|
681
|
+
let renderedBottom = maxHeight;
|
|
682
|
+
const scrollY = window.scrollY || window.pageYOffset || 0;
|
|
683
|
+
candidates.forEach((el) => {
|
|
684
|
+
if (!el || isDocumentElement(el)) return;
|
|
685
|
+
if (!el.classList.contains(className) && !el.closest(`.${className}`)) return;
|
|
686
|
+
const style = window.getComputedStyle(el);
|
|
687
|
+
const rect = el.getBoundingClientRect();
|
|
688
|
+
if (!isVisible(el, style, rect)) return;
|
|
689
|
+
renderedBottom = Math.max(renderedBottom, Math.ceil(rect.bottom + scrollY));
|
|
690
|
+
});
|
|
691
|
+
return renderedBottom;
|
|
692
|
+
};
|
|
693
|
+
const measureDocumentScrollHeight = () => {
|
|
694
|
+
return Math.max(
|
|
695
|
+
maxHeight,
|
|
696
|
+
Math.ceil(root?.scrollHeight || 0),
|
|
697
|
+
Math.ceil(body?.scrollHeight || 0),
|
|
698
|
+
Math.ceil(scrollingElement?.scrollHeight || 0)
|
|
699
|
+
);
|
|
700
|
+
};
|
|
657
701
|
candidates.forEach((el) => {
|
|
658
702
|
const style = window.getComputedStyle(el);
|
|
659
703
|
const rect = el.getBoundingClientRect();
|
|
@@ -684,46 +728,69 @@ var expandScrollableContent = async (page, options = {}) => {
|
|
|
684
728
|
el.style.height = "auto";
|
|
685
729
|
el.style.maxHeight = "none";
|
|
686
730
|
});
|
|
731
|
+
expandAncestorsToCurrentScrollHeight();
|
|
687
732
|
scrollableElements.forEach((el) => {
|
|
688
733
|
const neededHeight = measureNeededHeight(el);
|
|
689
734
|
if (neededHeight > maxHeight) {
|
|
690
735
|
maxHeight = neededHeight;
|
|
691
736
|
}
|
|
692
737
|
});
|
|
693
|
-
|
|
738
|
+
maxHeight = Math.max(maxHeight, measureDocumentScrollHeight(), measureExpandedRenderedBottom());
|
|
739
|
+
if (expandDocumentElements) {
|
|
740
|
+
for (let pass = 0; pass < 2; pass += 1) {
|
|
741
|
+
expandDocumentElementsToHeight(maxHeight);
|
|
742
|
+
maxHeight = Math.max(maxHeight, measureDocumentScrollHeight(), measureExpandedRenderedBottom());
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
return Math.ceil(maxHeight);
|
|
694
746
|
}, {
|
|
695
747
|
className: EXPANDED_SCROLLABLE_CLASS,
|
|
696
748
|
forceScrollableHeight: options.forceScrollableHeight !== false,
|
|
697
|
-
visibleOnly: options.visibleOnly !== false
|
|
749
|
+
visibleOnly: options.visibleOnly !== false,
|
|
750
|
+
expandDocumentElements: options.expandDocumentElements === true
|
|
698
751
|
});
|
|
699
752
|
};
|
|
700
753
|
var prepareExpandedFullPageScreenshot = async (page, options = {}) => {
|
|
701
754
|
const originalViewport = await resolveCurrentViewportSize(page);
|
|
702
|
-
const defaultBuffer = resolveDefaultBuffer(originalViewport);
|
|
703
|
-
const buffer = options.buffer ?? defaultBuffer;
|
|
704
755
|
const maxHeight = toPositiveInteger(options.maxHeight, DEFAULT_MAX_HEIGHT);
|
|
705
|
-
const
|
|
756
|
+
const preserveViewport = options.preserveViewport ?? resolvePageDevice(page) === Device.Mobile;
|
|
757
|
+
const defaultSettleMs = preserveViewport ? DEFAULT_MOBILE_SETTLE_MS : DEFAULT_SETTLE_MS;
|
|
758
|
+
const requestedSettleMs = Math.max(0, Number(options.settleMs ?? defaultSettleMs) || 0);
|
|
759
|
+
const settleMs = preserveViewport ? Math.min(requestedSettleMs, DEFAULT_MOBILE_SETTLE_MS) : requestedSettleMs;
|
|
706
760
|
const maxScrollHeight = await expandScrollableContent(page, {
|
|
707
761
|
forceScrollableHeight: options.forceScrollableHeight,
|
|
708
|
-
visibleOnly: options.visibleOnly !== false
|
|
709
|
-
|
|
710
|
-
const targetHeight = Math.min(maxScrollHeight + buffer, maxHeight);
|
|
711
|
-
await page.setViewportSize({
|
|
712
|
-
width: originalViewport.width,
|
|
713
|
-
height: targetHeight
|
|
762
|
+
visibleOnly: options.visibleOnly !== false,
|
|
763
|
+
expandDocumentElements: preserveViewport
|
|
714
764
|
});
|
|
765
|
+
const targetHeight = Math.min(maxScrollHeight, maxHeight);
|
|
766
|
+
let viewportResized = false;
|
|
767
|
+
if (!preserveViewport) {
|
|
768
|
+
await page.setViewportSize({
|
|
769
|
+
width: originalViewport.width,
|
|
770
|
+
height: targetHeight
|
|
771
|
+
});
|
|
772
|
+
viewportResized = true;
|
|
773
|
+
}
|
|
715
774
|
if (settleMs > 0) {
|
|
716
775
|
await (0, import_delay.default)(settleMs);
|
|
717
776
|
}
|
|
718
777
|
return {
|
|
719
778
|
originalViewport,
|
|
720
779
|
maxScrollHeight,
|
|
721
|
-
targetHeight
|
|
780
|
+
targetHeight,
|
|
781
|
+
preserveViewport,
|
|
782
|
+
viewportResized
|
|
722
783
|
};
|
|
723
784
|
};
|
|
724
785
|
var restoreExpandedFullPageScreenshot = async (page, state = {}) => {
|
|
725
786
|
await page.evaluate((className) => {
|
|
726
|
-
|
|
787
|
+
const targets = new Set([
|
|
788
|
+
...document.querySelectorAll(`.${className}`),
|
|
789
|
+
document.documentElement,
|
|
790
|
+
document.body,
|
|
791
|
+
document.scrollingElement
|
|
792
|
+
].filter((el) => el?.classList?.contains(className)));
|
|
793
|
+
targets.forEach((el) => {
|
|
727
794
|
el.style.setProperty("overflow", el.dataset.pkOrigOverflow || "", el.dataset.pkOrigOverflowPriority || "");
|
|
728
795
|
el.style.setProperty("height", el.dataset.pkOrigHeight || "", el.dataset.pkOrigHeightPriority || "");
|
|
729
796
|
el.style.setProperty("min-height", el.dataset.pkOrigMinHeight || "", el.dataset.pkOrigMinHeightPriority || "");
|
|
@@ -739,7 +806,7 @@ var restoreExpandedFullPageScreenshot = async (page, state = {}) => {
|
|
|
739
806
|
el.classList.remove(className);
|
|
740
807
|
});
|
|
741
808
|
}, EXPANDED_SCROLLABLE_CLASS);
|
|
742
|
-
if (state?.originalViewport) {
|
|
809
|
+
if (state?.originalViewport && state?.viewportResized) {
|
|
743
810
|
await page.setViewportSize(state.originalViewport);
|
|
744
811
|
}
|
|
745
812
|
};
|
|
@@ -1237,9 +1304,6 @@ var ProxyMeterRuntime = {
|
|
|
1237
1304
|
getProxyMeterSnapshot
|
|
1238
1305
|
};
|
|
1239
1306
|
|
|
1240
|
-
// src/internals/constants.js
|
|
1241
|
-
var PageRuntimeStateKey = "__playwright_toolkit_runtime_state__";
|
|
1242
|
-
|
|
1243
1307
|
// src/runtime-env.js
|
|
1244
1308
|
var BROWSER_PROFILE_SCHEMA_VERSION = 1;
|
|
1245
1309
|
var rememberedRuntimeState = null;
|
|
@@ -2350,6 +2414,358 @@ var AntiCheat = {
|
|
|
2350
2414
|
}
|
|
2351
2415
|
};
|
|
2352
2416
|
|
|
2417
|
+
// src/device-input.js
|
|
2418
|
+
var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
2419
|
+
var assertPage = (page, method) => {
|
|
2420
|
+
if (!page || typeof page !== "object") {
|
|
2421
|
+
throw new Error(`DeviceInput.${method} requires a Playwright page`);
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2424
|
+
var isPoint = (value) => value && typeof value === "object" && Number.isFinite(Number(value.x)) && Number.isFinite(Number(value.y));
|
|
2425
|
+
var pointFromArgs = (pointOrX, maybeY) => {
|
|
2426
|
+
if (isPoint(pointOrX)) {
|
|
2427
|
+
return { x: Number(pointOrX.x), y: Number(pointOrX.y) };
|
|
2428
|
+
}
|
|
2429
|
+
return { x: Number(pointOrX), y: Number(maybeY) };
|
|
2430
|
+
};
|
|
2431
|
+
var resolveNativeTarget = (page, target) => {
|
|
2432
|
+
if (!target) return null;
|
|
2433
|
+
if (typeof target === "string") return page.locator(target);
|
|
2434
|
+
return target;
|
|
2435
|
+
};
|
|
2436
|
+
var normalizeSelectorOptions = (options = {}) => ({
|
|
2437
|
+
targetParent: Boolean(options.targetParent ?? options.parent ?? false),
|
|
2438
|
+
pick: options.pick === "last" || options.last ? "last" : "first",
|
|
2439
|
+
visibleOnly: options.visibleOnly !== false,
|
|
2440
|
+
fallbackDomClick: Boolean(options.fallbackDomClick),
|
|
2441
|
+
forceMouse: Boolean(options.forceMouse),
|
|
2442
|
+
forceClick: Boolean(options.forceClick),
|
|
2443
|
+
mouseOptions: options.mouseOptions || {},
|
|
2444
|
+
clickOptions: options.clickOptions || {},
|
|
2445
|
+
tapOptions: options.tapOptions || {}
|
|
2446
|
+
});
|
|
2447
|
+
var waitFor = (page, timeout) => {
|
|
2448
|
+
if (!timeout) return Promise.resolve();
|
|
2449
|
+
if (page && typeof page.waitForTimeout === "function") {
|
|
2450
|
+
return page.waitForTimeout(timeout);
|
|
2451
|
+
}
|
|
2452
|
+
return new Promise((resolve) => setTimeout(resolve, timeout));
|
|
2453
|
+
};
|
|
2454
|
+
var getTargetBoundingBox = async (target) => {
|
|
2455
|
+
if (!target) return null;
|
|
2456
|
+
if (typeof target.boundingBox === "function") return target.boundingBox();
|
|
2457
|
+
if (typeof target.elementHandle === "function") {
|
|
2458
|
+
const handle = await target.elementHandle();
|
|
2459
|
+
try {
|
|
2460
|
+
return await handle?.boundingBox?.();
|
|
2461
|
+
} finally {
|
|
2462
|
+
if (handle && typeof handle.dispose === "function") {
|
|
2463
|
+
await handle.dispose().catch(() => {
|
|
2464
|
+
});
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
return null;
|
|
2469
|
+
};
|
|
2470
|
+
var assertPoint = (point) => {
|
|
2471
|
+
if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {
|
|
2472
|
+
throw new Error(`Invalid input point: ${JSON.stringify(point)}`);
|
|
2473
|
+
}
|
|
2474
|
+
};
|
|
2475
|
+
var dispatchMouseMove = (page, point, options = {}) => page.mouse.move(point.x, point.y, options);
|
|
2476
|
+
var dispatchMouseStart = (page, options = {}) => page.mouse.down(options);
|
|
2477
|
+
var dispatchMouseEnd = (page, options = {}) => page.mouse.up(options);
|
|
2478
|
+
var dragWithMouse = async (page, points, options = {}) => {
|
|
2479
|
+
await dispatchMouseMove(page, points.start, { steps: 8 });
|
|
2480
|
+
await waitFor(page, options.initialDelayMs ?? 250);
|
|
2481
|
+
await dispatchMouseStart(page);
|
|
2482
|
+
await waitFor(page, options.holdDelayMs ?? 350);
|
|
2483
|
+
await dispatchMouseMove(page, points.lift, { steps: 6 });
|
|
2484
|
+
await waitFor(page, options.liftDelayMs ?? 250);
|
|
2485
|
+
for (let step = 1; step <= points.steps; step += 1) {
|
|
2486
|
+
const progress = step / points.steps;
|
|
2487
|
+
const easedProgress = 1 - (1 - progress) * (1 - progress);
|
|
2488
|
+
await dispatchMouseMove(page, {
|
|
2489
|
+
x: points.lift.x + (points.end.x - points.lift.x) * easedProgress,
|
|
2490
|
+
y: points.lift.y + (points.end.y - points.lift.y) * easedProgress
|
|
2491
|
+
}, { steps: 2 });
|
|
2492
|
+
await waitFor(page, options.stepDelayMs ?? 90);
|
|
2493
|
+
}
|
|
2494
|
+
await waitFor(page, options.beforeReleaseDelayMs ?? 100);
|
|
2495
|
+
await dispatchMouseEnd(page);
|
|
2496
|
+
await waitFor(page, options.afterReleaseDelayMs ?? 100);
|
|
2497
|
+
return true;
|
|
2498
|
+
};
|
|
2499
|
+
var dragWithTouch = async (page, points, options = {}) => {
|
|
2500
|
+
let client = null;
|
|
2501
|
+
try {
|
|
2502
|
+
client = await page.context().newCDPSession(page);
|
|
2503
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2504
|
+
type: "touchStart",
|
|
2505
|
+
touchPoints: [{ x: points.start.x, y: points.start.y, id: 1 }]
|
|
2506
|
+
});
|
|
2507
|
+
await waitFor(page, options.holdDelayMs ?? 350);
|
|
2508
|
+
const totalSteps = points.steps + 1;
|
|
2509
|
+
for (let step = 1; step <= totalSteps; step += 1) {
|
|
2510
|
+
const progress = step / totalSteps;
|
|
2511
|
+
const easedProgress = 1 - (1 - progress) * (1 - progress);
|
|
2512
|
+
const from = step === 1 ? points.start : points.lift;
|
|
2513
|
+
const to = points.end;
|
|
2514
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2515
|
+
type: "touchMove",
|
|
2516
|
+
touchPoints: [{
|
|
2517
|
+
x: from.x + (to.x - from.x) * easedProgress,
|
|
2518
|
+
y: from.y + (to.y - from.y) * easedProgress,
|
|
2519
|
+
id: 1
|
|
2520
|
+
}]
|
|
2521
|
+
});
|
|
2522
|
+
await waitFor(page, options.stepDelayMs ?? 90);
|
|
2523
|
+
}
|
|
2524
|
+
await waitFor(page, options.beforeReleaseDelayMs ?? 100);
|
|
2525
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2526
|
+
type: "touchEnd",
|
|
2527
|
+
touchPoints: []
|
|
2528
|
+
});
|
|
2529
|
+
await waitFor(page, options.afterReleaseDelayMs ?? 100);
|
|
2530
|
+
return true;
|
|
2531
|
+
} finally {
|
|
2532
|
+
if (client && typeof client.detach === "function") {
|
|
2533
|
+
await client.detach().catch(() => {
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
};
|
|
2538
|
+
var clickTargetWithDevice = async (page, target, options = {}) => {
|
|
2539
|
+
const normalizedOptions = normalizeSelectorOptions(options);
|
|
2540
|
+
const resolvedDevice = resolveDeviceFromPage(page);
|
|
2541
|
+
if (target && resolvedDevice === Device.Mobile && !normalizedOptions.forceClick) {
|
|
2542
|
+
if (typeof target.tap === "function") {
|
|
2543
|
+
await target.tap(normalizedOptions.tapOptions);
|
|
2544
|
+
return true;
|
|
2545
|
+
}
|
|
2546
|
+
const box = await getTargetBoundingBox(target);
|
|
2547
|
+
if (box) {
|
|
2548
|
+
await DeviceInput.clickPoint(page, {
|
|
2549
|
+
x: box.x + box.width / 2,
|
|
2550
|
+
y: box.y + box.height / 2
|
|
2551
|
+
}, normalizedOptions);
|
|
2552
|
+
return true;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
if (!target || typeof target.click !== "function") {
|
|
2556
|
+
throw new Error("DeviceInput click target does not expose click()");
|
|
2557
|
+
}
|
|
2558
|
+
await target.click(normalizedOptions.clickOptions || options);
|
|
2559
|
+
return true;
|
|
2560
|
+
};
|
|
2561
|
+
var DeviceInput = {
|
|
2562
|
+
device(page) {
|
|
2563
|
+
return resolveDeviceFromPage(page);
|
|
2564
|
+
},
|
|
2565
|
+
isMobile(page) {
|
|
2566
|
+
return resolveDeviceFromPage(page) === Device.Mobile;
|
|
2567
|
+
},
|
|
2568
|
+
async clickPoint(page, pointOrX, maybeY, options = {}) {
|
|
2569
|
+
assertPage(page, "clickPoint");
|
|
2570
|
+
const clickOptions = isPoint(pointOrX) && maybeY && typeof maybeY === "object" ? maybeY : options;
|
|
2571
|
+
const point = pointFromArgs(pointOrX, maybeY);
|
|
2572
|
+
assertPoint(point);
|
|
2573
|
+
if (resolveDeviceFromPage(page) === Device.Mobile && !clickOptions.forceMouse && page.touchscreen && typeof page.touchscreen.tap === "function") {
|
|
2574
|
+
await page.touchscreen.tap(point.x, point.y);
|
|
2575
|
+
return true;
|
|
2576
|
+
}
|
|
2577
|
+
await page.mouse.click(point.x, point.y, clickOptions.mouseOptions || {});
|
|
2578
|
+
return true;
|
|
2579
|
+
},
|
|
2580
|
+
async tapPoint(page, pointOrX, maybeY, options = {}) {
|
|
2581
|
+
return DeviceInput.clickPoint(page, pointOrX, maybeY, options);
|
|
2582
|
+
},
|
|
2583
|
+
async click(page, target, options = {}) {
|
|
2584
|
+
assertPage(page, "click");
|
|
2585
|
+
if (isPoint(target)) {
|
|
2586
|
+
return DeviceInput.clickPoint(page, target, void 0, options);
|
|
2587
|
+
}
|
|
2588
|
+
const nativeTarget = resolveNativeTarget(page, target);
|
|
2589
|
+
return clickTargetWithDevice(page, nativeTarget, options);
|
|
2590
|
+
},
|
|
2591
|
+
async tap(page, target, options = {}) {
|
|
2592
|
+
return DeviceInput.click(page, target, options);
|
|
2593
|
+
},
|
|
2594
|
+
async move(page, pointOrX, maybeY, options = {}) {
|
|
2595
|
+
assertPage(page, "move");
|
|
2596
|
+
const moveOptions = isPoint(pointOrX) && maybeY && typeof maybeY === "object" ? maybeY : options;
|
|
2597
|
+
const point = pointFromArgs(pointOrX, maybeY);
|
|
2598
|
+
assertPoint(point);
|
|
2599
|
+
if (resolveDeviceFromPage(page) === Device.Mobile && !moveOptions.forceMouse) {
|
|
2600
|
+
return true;
|
|
2601
|
+
}
|
|
2602
|
+
await page.mouse.move(point.x, point.y, moveOptions.mouseOptions || moveOptions);
|
|
2603
|
+
return true;
|
|
2604
|
+
},
|
|
2605
|
+
async focus(page, target, options = {}) {
|
|
2606
|
+
assertPage(page, "focus");
|
|
2607
|
+
const nativeTarget = resolveNativeTarget(page, target);
|
|
2608
|
+
if (!nativeTarget || typeof nativeTarget.focus !== "function") {
|
|
2609
|
+
throw new Error("DeviceInput focus target does not expose focus()");
|
|
2610
|
+
}
|
|
2611
|
+
await nativeTarget.focus(options);
|
|
2612
|
+
return true;
|
|
2613
|
+
},
|
|
2614
|
+
async fill(page, target, value, options = {}) {
|
|
2615
|
+
assertPage(page, "fill");
|
|
2616
|
+
const nativeTarget = resolveNativeTarget(page, target);
|
|
2617
|
+
if (!nativeTarget || typeof nativeTarget.fill !== "function") {
|
|
2618
|
+
throw new Error("DeviceInput fill target does not expose fill()");
|
|
2619
|
+
}
|
|
2620
|
+
await nativeTarget.fill(value, options);
|
|
2621
|
+
return true;
|
|
2622
|
+
},
|
|
2623
|
+
async keyboardType(page, text, options = {}) {
|
|
2624
|
+
assertPage(page, "keyboardType");
|
|
2625
|
+
await page.keyboard.type(text, options);
|
|
2626
|
+
return true;
|
|
2627
|
+
},
|
|
2628
|
+
async type(page, targetOrText, maybeText, options = {}) {
|
|
2629
|
+
assertPage(page, "type");
|
|
2630
|
+
if (maybeText == null || typeof maybeText === "object" && !Array.isArray(maybeText)) {
|
|
2631
|
+
return DeviceInput.keyboardType(page, targetOrText, maybeText || options);
|
|
2632
|
+
}
|
|
2633
|
+
const nativeTarget = resolveNativeTarget(page, targetOrText);
|
|
2634
|
+
if (!nativeTarget || typeof nativeTarget.type !== "function") {
|
|
2635
|
+
throw new Error("DeviceInput type target does not expose type()");
|
|
2636
|
+
}
|
|
2637
|
+
await nativeTarget.type(maybeText, options);
|
|
2638
|
+
return true;
|
|
2639
|
+
},
|
|
2640
|
+
async press(page, targetOrKey, maybeKey, options = {}) {
|
|
2641
|
+
assertPage(page, "press");
|
|
2642
|
+
const hasTarget = typeof maybeKey === "string";
|
|
2643
|
+
const key = hasTarget ? maybeKey : targetOrKey;
|
|
2644
|
+
const pressOptions = hasTarget ? options : maybeKey || options;
|
|
2645
|
+
if (hasTarget) {
|
|
2646
|
+
await DeviceInput.click(page, targetOrKey, pressOptions.clickOptions || {});
|
|
2647
|
+
}
|
|
2648
|
+
await page.keyboard.press(key, pressOptions.keyboardOptions || pressOptions);
|
|
2649
|
+
return true;
|
|
2650
|
+
},
|
|
2651
|
+
async selectorCenterPoint(page, selector, options = {}) {
|
|
2652
|
+
assertPage(page, "selectorCenterPoint");
|
|
2653
|
+
const normalizedOptions = normalizeSelectorOptions(options);
|
|
2654
|
+
return page.evaluate(({ innerSelector, innerOptions }) => {
|
|
2655
|
+
const nodes = Array.from(document.querySelectorAll(innerSelector));
|
|
2656
|
+
const ordered = innerOptions.pick === "last" ? nodes.reverse() : nodes;
|
|
2657
|
+
let rect = null;
|
|
2658
|
+
for (const node of ordered) {
|
|
2659
|
+
if (!node) continue;
|
|
2660
|
+
const target = innerOptions.targetParent ? node.parentElement || node : node;
|
|
2661
|
+
rect = target.getBoundingClientRect?.() || null;
|
|
2662
|
+
const isVisible = Boolean(rect && rect.width > 0 && rect.height > 0);
|
|
2663
|
+
if (innerOptions.visibleOnly && !isVisible) continue;
|
|
2664
|
+
break;
|
|
2665
|
+
}
|
|
2666
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) return null;
|
|
2667
|
+
return {
|
|
2668
|
+
x: rect.left + rect.width / 2,
|
|
2669
|
+
y: rect.top + rect.height / 2
|
|
2670
|
+
};
|
|
2671
|
+
}, { innerSelector: selector, innerOptions: normalizedOptions });
|
|
2672
|
+
},
|
|
2673
|
+
async domClick(page, selector, options = {}) {
|
|
2674
|
+
assertPage(page, "domClick");
|
|
2675
|
+
const normalizedOptions = normalizeSelectorOptions(options);
|
|
2676
|
+
return page.evaluate(({ innerSelector, innerOptions }) => {
|
|
2677
|
+
const nodes = Array.from(document.querySelectorAll(innerSelector));
|
|
2678
|
+
const ordered = innerOptions.pick === "last" ? nodes.reverse() : nodes;
|
|
2679
|
+
let target = null;
|
|
2680
|
+
for (const node of ordered) {
|
|
2681
|
+
if (!node) continue;
|
|
2682
|
+
const candidate = innerOptions.targetParent ? node.parentElement || node : node;
|
|
2683
|
+
const rect = candidate.getBoundingClientRect?.() || null;
|
|
2684
|
+
const isVisible = Boolean(rect && rect.width > 0 && rect.height > 0);
|
|
2685
|
+
if (innerOptions.visibleOnly && !isVisible) continue;
|
|
2686
|
+
target = candidate;
|
|
2687
|
+
break;
|
|
2688
|
+
}
|
|
2689
|
+
if (!target || typeof target.click !== "function") return false;
|
|
2690
|
+
target.click();
|
|
2691
|
+
return true;
|
|
2692
|
+
}, { innerSelector: selector, innerOptions: normalizedOptions });
|
|
2693
|
+
},
|
|
2694
|
+
async clickSelectorCenter(page, selector, options = {}) {
|
|
2695
|
+
assertPage(page, "clickSelectorCenter");
|
|
2696
|
+
const normalizedOptions = normalizeSelectorOptions(options);
|
|
2697
|
+
try {
|
|
2698
|
+
const point = await DeviceInput.selectorCenterPoint(page, selector, normalizedOptions);
|
|
2699
|
+
if (point) {
|
|
2700
|
+
await DeviceInput.clickPoint(page, point, void 0, normalizedOptions);
|
|
2701
|
+
return true;
|
|
2702
|
+
}
|
|
2703
|
+
} catch (error) {
|
|
2704
|
+
if (!normalizedOptions.fallbackDomClick) throw error;
|
|
2705
|
+
}
|
|
2706
|
+
if (normalizedOptions.fallbackDomClick) {
|
|
2707
|
+
return DeviceInput.domClick(page, selector, normalizedOptions);
|
|
2708
|
+
}
|
|
2709
|
+
return false;
|
|
2710
|
+
},
|
|
2711
|
+
async clickText(frameOrPage, texts, options = {}) {
|
|
2712
|
+
for (const text of texts || []) {
|
|
2713
|
+
if (!text) continue;
|
|
2714
|
+
const candidates = [
|
|
2715
|
+
frameOrPage.getByText(text, { exact: false }).first(),
|
|
2716
|
+
frameOrPage.locator(`text=${text}`).first()
|
|
2717
|
+
];
|
|
2718
|
+
for (const candidate of candidates) {
|
|
2719
|
+
const isVisible = await candidate.isVisible({
|
|
2720
|
+
timeout: options.visibleTimeoutMs ?? options.actionVisibleTimeoutMs ?? 1500
|
|
2721
|
+
}).catch(() => false);
|
|
2722
|
+
if (!isVisible) continue;
|
|
2723
|
+
const page = options.page || (frameOrPage && typeof frameOrPage.context === "function" ? frameOrPage : null) || candidate.page?.();
|
|
2724
|
+
if (!page) {
|
|
2725
|
+
throw new Error("DeviceInput.clickText requires options.page when used with a frame locator");
|
|
2726
|
+
}
|
|
2727
|
+
await DeviceInput.click(page, candidate, options);
|
|
2728
|
+
return true;
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
return false;
|
|
2732
|
+
},
|
|
2733
|
+
async drag(page, sourceLocator, targetLocator, options = {}) {
|
|
2734
|
+
assertPage(page, "drag");
|
|
2735
|
+
const sourceBox = await sourceLocator.boundingBox();
|
|
2736
|
+
const targetBox = await targetLocator.boundingBox();
|
|
2737
|
+
if (!sourceBox || !targetBox) {
|
|
2738
|
+
throw new Error("Unable to resolve drag coordinates.");
|
|
2739
|
+
}
|
|
2740
|
+
const steps = options.steps || 10;
|
|
2741
|
+
const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
|
|
2742
|
+
const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
|
|
2743
|
+
const points = {
|
|
2744
|
+
start: {
|
|
2745
|
+
x: sourceBox.x + sourceBox.width / 2,
|
|
2746
|
+
y: sourceBox.y + sourceBox.height / 2
|
|
2747
|
+
},
|
|
2748
|
+
lift: {
|
|
2749
|
+
x: sourceBox.x + sourceBox.width / 2 + liftOffsetX,
|
|
2750
|
+
y: sourceBox.y + sourceBox.height / 2 + liftOffsetY
|
|
2751
|
+
},
|
|
2752
|
+
end: {
|
|
2753
|
+
x: targetBox.x + targetBox.width / 2,
|
|
2754
|
+
y: targetBox.y + targetBox.height / 2
|
|
2755
|
+
},
|
|
2756
|
+
steps
|
|
2757
|
+
};
|
|
2758
|
+
if (resolveDeviceFromPage(page) === Device.Mobile && !options.forceMouse) {
|
|
2759
|
+
try {
|
|
2760
|
+
return await dragWithTouch(page, points, options);
|
|
2761
|
+
} catch (error) {
|
|
2762
|
+
if (options.allowMouseFallback === false) throw error;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
return dragWithMouse(page, points, options);
|
|
2766
|
+
}
|
|
2767
|
+
};
|
|
2768
|
+
|
|
2353
2769
|
// src/internals/humanize/desktop.js
|
|
2354
2770
|
var import_delay2 = __toESM(require("delay"), 1);
|
|
2355
2771
|
var import_ghost_cursor_playwright = require("ghost-cursor-playwright");
|
|
@@ -2865,141 +3281,6 @@ var Humanize = {
|
|
|
2865
3281
|
}
|
|
2866
3282
|
};
|
|
2867
3283
|
|
|
2868
|
-
// src/internals/humanize/machine.js
|
|
2869
|
-
var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
2870
|
-
var isPoint = (value) => value && typeof value === "object" && Number.isFinite(Number(value.x)) && Number.isFinite(Number(value.y));
|
|
2871
|
-
var resolveNativeTarget = (page, target) => {
|
|
2872
|
-
if (!target) return null;
|
|
2873
|
-
if (typeof target === "string") {
|
|
2874
|
-
return page.locator(target);
|
|
2875
|
-
}
|
|
2876
|
-
return target;
|
|
2877
|
-
};
|
|
2878
|
-
var normalizeSelectorOptions = (options = {}) => ({
|
|
2879
|
-
targetParent: Boolean(options.targetParent ?? options.parent ?? false),
|
|
2880
|
-
pick: options.pick === "last" || options.last ? "last" : "first",
|
|
2881
|
-
visibleOnly: options.visibleOnly !== false,
|
|
2882
|
-
fallbackDomClick: Boolean(options.fallbackDomClick),
|
|
2883
|
-
forceMouse: Boolean(options.forceMouse)
|
|
2884
|
-
});
|
|
2885
|
-
var MachineHumanize = {
|
|
2886
|
-
async clickPoint(page, pointOrX, maybeY, options = {}) {
|
|
2887
|
-
const clickOptions = isPoint(pointOrX) && maybeY && typeof maybeY === "object" ? maybeY : options;
|
|
2888
|
-
const point = isPoint(pointOrX) ? pointOrX : { x: pointOrX, y: maybeY };
|
|
2889
|
-
const x = Number(point.x);
|
|
2890
|
-
const y = Number(point.y);
|
|
2891
|
-
if (!Number.isFinite(x) || !Number.isFinite(y)) {
|
|
2892
|
-
throw new Error(`Invalid click point: ${JSON.stringify(point)}`);
|
|
2893
|
-
}
|
|
2894
|
-
const resolvedDevice = resolveDeviceFromPage(page);
|
|
2895
|
-
if (resolvedDevice === Device.Mobile && !clickOptions.forceMouse && page.touchscreen && typeof page.touchscreen.tap === "function") {
|
|
2896
|
-
await page.touchscreen.tap(x, y);
|
|
2897
|
-
return true;
|
|
2898
|
-
}
|
|
2899
|
-
await page.mouse.click(x, y, clickOptions.mouseOptions || {});
|
|
2900
|
-
return true;
|
|
2901
|
-
},
|
|
2902
|
-
async click(page, target, options = {}) {
|
|
2903
|
-
if (isPoint(target)) {
|
|
2904
|
-
return MachineHumanize.clickPoint(page, target, void 0, options);
|
|
2905
|
-
}
|
|
2906
|
-
const nativeTarget = resolveNativeTarget(page, target);
|
|
2907
|
-
if (!nativeTarget || typeof nativeTarget.click !== "function") {
|
|
2908
|
-
throw new Error("Machine click target does not expose click()");
|
|
2909
|
-
}
|
|
2910
|
-
await nativeTarget.click(options.clickOptions || options);
|
|
2911
|
-
return true;
|
|
2912
|
-
},
|
|
2913
|
-
async focus(page, target, options = {}) {
|
|
2914
|
-
const nativeTarget = resolveNativeTarget(page, target);
|
|
2915
|
-
if (!nativeTarget || typeof nativeTarget.focus !== "function") {
|
|
2916
|
-
throw new Error("Machine focus target does not expose focus()");
|
|
2917
|
-
}
|
|
2918
|
-
await nativeTarget.focus(options);
|
|
2919
|
-
return true;
|
|
2920
|
-
},
|
|
2921
|
-
async fill(page, target, value, options = {}) {
|
|
2922
|
-
const nativeTarget = resolveNativeTarget(page, target);
|
|
2923
|
-
if (!nativeTarget || typeof nativeTarget.fill !== "function") {
|
|
2924
|
-
throw new Error("Machine fill target does not expose fill()");
|
|
2925
|
-
}
|
|
2926
|
-
await nativeTarget.fill(value, options);
|
|
2927
|
-
return true;
|
|
2928
|
-
},
|
|
2929
|
-
async keyboardType(page, text, options = {}) {
|
|
2930
|
-
await page.keyboard.type(text, options);
|
|
2931
|
-
return true;
|
|
2932
|
-
},
|
|
2933
|
-
async type(page, targetOrText, maybeText, options = {}) {
|
|
2934
|
-
if (maybeText == null || typeof maybeText === "object" && !Array.isArray(maybeText)) {
|
|
2935
|
-
return MachineHumanize.keyboardType(page, targetOrText, maybeText || options);
|
|
2936
|
-
}
|
|
2937
|
-
const nativeTarget = resolveNativeTarget(page, targetOrText);
|
|
2938
|
-
if (!nativeTarget || typeof nativeTarget.type !== "function") {
|
|
2939
|
-
throw new Error("Machine type target does not expose type()");
|
|
2940
|
-
}
|
|
2941
|
-
await nativeTarget.type(maybeText, options);
|
|
2942
|
-
return true;
|
|
2943
|
-
},
|
|
2944
|
-
async selectorCenterPoint(page, selector, options = {}) {
|
|
2945
|
-
const normalizedOptions = normalizeSelectorOptions(options);
|
|
2946
|
-
return page.evaluate(({ innerSelector, innerOptions }) => {
|
|
2947
|
-
const nodes = Array.from(document.querySelectorAll(innerSelector));
|
|
2948
|
-
const ordered = innerOptions.pick === "last" ? nodes.reverse() : nodes;
|
|
2949
|
-
let rect = null;
|
|
2950
|
-
for (const node of ordered) {
|
|
2951
|
-
if (!node) continue;
|
|
2952
|
-
const target = innerOptions.targetParent ? node.parentElement || node : node;
|
|
2953
|
-
rect = target.getBoundingClientRect?.() || null;
|
|
2954
|
-
const isVisible = Boolean(rect && rect.width > 0 && rect.height > 0);
|
|
2955
|
-
if (innerOptions.visibleOnly && !isVisible) continue;
|
|
2956
|
-
break;
|
|
2957
|
-
}
|
|
2958
|
-
if (!rect || rect.width <= 0 || rect.height <= 0) return null;
|
|
2959
|
-
return {
|
|
2960
|
-
x: rect.left + rect.width / 2,
|
|
2961
|
-
y: rect.top + rect.height / 2
|
|
2962
|
-
};
|
|
2963
|
-
}, { innerSelector: selector, innerOptions: normalizedOptions });
|
|
2964
|
-
},
|
|
2965
|
-
async domClick(page, selector, options = {}) {
|
|
2966
|
-
const normalizedOptions = normalizeSelectorOptions(options);
|
|
2967
|
-
return page.evaluate(({ innerSelector, innerOptions }) => {
|
|
2968
|
-
const nodes = Array.from(document.querySelectorAll(innerSelector));
|
|
2969
|
-
const ordered = innerOptions.pick === "last" ? nodes.reverse() : nodes;
|
|
2970
|
-
let target = null;
|
|
2971
|
-
for (const node of ordered) {
|
|
2972
|
-
if (!node) continue;
|
|
2973
|
-
const candidate = innerOptions.targetParent ? node.parentElement || node : node;
|
|
2974
|
-
const rect = candidate.getBoundingClientRect?.() || null;
|
|
2975
|
-
const isVisible = Boolean(rect && rect.width > 0 && rect.height > 0);
|
|
2976
|
-
if (innerOptions.visibleOnly && !isVisible) continue;
|
|
2977
|
-
target = candidate;
|
|
2978
|
-
break;
|
|
2979
|
-
}
|
|
2980
|
-
if (!target || typeof target.click !== "function") return false;
|
|
2981
|
-
target.click();
|
|
2982
|
-
return true;
|
|
2983
|
-
}, { innerSelector: selector, innerOptions: normalizedOptions });
|
|
2984
|
-
},
|
|
2985
|
-
async clickSelectorCenter(page, selector, options = {}) {
|
|
2986
|
-
const normalizedOptions = normalizeSelectorOptions(options);
|
|
2987
|
-
try {
|
|
2988
|
-
const point = await MachineHumanize.selectorCenterPoint(page, selector, normalizedOptions);
|
|
2989
|
-
if (point) {
|
|
2990
|
-
await MachineHumanize.clickPoint(page, point, void 0, normalizedOptions);
|
|
2991
|
-
return true;
|
|
2992
|
-
}
|
|
2993
|
-
} catch (error) {
|
|
2994
|
-
if (!normalizedOptions.fallbackDomClick) throw error;
|
|
2995
|
-
}
|
|
2996
|
-
if (normalizedOptions.fallbackDomClick) {
|
|
2997
|
-
return MachineHumanize.domClick(page, selector, normalizedOptions);
|
|
2998
|
-
}
|
|
2999
|
-
return false;
|
|
3000
|
-
}
|
|
3001
|
-
};
|
|
3002
|
-
|
|
3003
3284
|
// src/internals/humanize/shared.js
|
|
3004
3285
|
var import_delay3 = __toESM(require("delay"), 1);
|
|
3005
3286
|
var jitterMs = (base, jitterPercent = 0.3) => {
|
|
@@ -3828,9 +4109,6 @@ var callDelegate = (method, page, args) => {
|
|
|
3828
4109
|
return delegate[method](page, ...args);
|
|
3829
4110
|
};
|
|
3830
4111
|
var Humanize2 = {
|
|
3831
|
-
// M = Machine: native/mechanical operations for兼容路径。
|
|
3832
|
-
// 这组 API 不做人类化处理,只保留原生 click / focus / fill / type 等语义。
|
|
3833
|
-
M: MachineHumanize,
|
|
3834
4112
|
jitterMs(base, jitterPercent = 0.3) {
|
|
3835
4113
|
return Humanize.jitterMs(base, jitterPercent);
|
|
3836
4114
|
},
|
|
@@ -4406,42 +4684,14 @@ var clickCaptchaAction = async (frame, texts, options) => {
|
|
|
4406
4684
|
if (!isVisible) {
|
|
4407
4685
|
continue;
|
|
4408
4686
|
}
|
|
4409
|
-
await
|
|
4687
|
+
await DeviceInput.click(options.page, candidate);
|
|
4410
4688
|
return true;
|
|
4411
4689
|
}
|
|
4412
4690
|
}
|
|
4413
4691
|
return false;
|
|
4414
4692
|
};
|
|
4415
|
-
var
|
|
4416
|
-
|
|
4417
|
-
const targetBox = await targetLocator.boundingBox();
|
|
4418
|
-
if (!sourceBox || !targetBox) {
|
|
4419
|
-
throw new Error("Unable to resolve captcha drag coordinates.");
|
|
4420
|
-
}
|
|
4421
|
-
const startX = sourceBox.x + sourceBox.width / 2;
|
|
4422
|
-
const startY = sourceBox.y + sourceBox.height / 2;
|
|
4423
|
-
const endX = targetBox.x + targetBox.width / 2;
|
|
4424
|
-
const endY = targetBox.y + targetBox.height / 2;
|
|
4425
|
-
const steps = 10;
|
|
4426
|
-
const liftOffsetX = Math.min(18, Math.max(8, sourceBox.width * 0.12));
|
|
4427
|
-
const liftOffsetY = Math.min(12, Math.max(4, sourceBox.height * 0.08));
|
|
4428
|
-
await page.mouse.move(startX, startY, { steps: 8 });
|
|
4429
|
-
await page.waitForTimeout(250);
|
|
4430
|
-
await page.mouse.down();
|
|
4431
|
-
await page.waitForTimeout(350);
|
|
4432
|
-
await page.mouse.move(startX + liftOffsetX, startY + liftOffsetY, { steps: 6 });
|
|
4433
|
-
await page.waitForTimeout(250);
|
|
4434
|
-
for (let step = 1; step <= steps; step++) {
|
|
4435
|
-
const progress = step / steps;
|
|
4436
|
-
const easedProgress = 1 - (1 - progress) * (1 - progress);
|
|
4437
|
-
const currentX = startX + liftOffsetX + (endX - startX - liftOffsetX) * easedProgress;
|
|
4438
|
-
const currentY = startY + liftOffsetY + (endY - startY - liftOffsetY) * easedProgress;
|
|
4439
|
-
await page.mouse.move(currentX, currentY, { steps: 2 });
|
|
4440
|
-
await page.waitForTimeout(90);
|
|
4441
|
-
}
|
|
4442
|
-
await page.waitForTimeout(100);
|
|
4443
|
-
await page.mouse.up();
|
|
4444
|
-
await page.waitForTimeout(100);
|
|
4693
|
+
var dragCaptchaAction = async (page, sourceLocator, targetLocator) => {
|
|
4694
|
+
await DeviceInput.drag(page, sourceLocator, targetLocator);
|
|
4445
4695
|
};
|
|
4446
4696
|
|
|
4447
4697
|
// src/internals/captcha/bytedance.js
|
|
@@ -4537,7 +4787,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
4537
4787
|
return { iframeLocator, frame };
|
|
4538
4788
|
};
|
|
4539
4789
|
var refreshCaptcha = async (page, frame, options) => {
|
|
4540
|
-
const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
|
|
4790
|
+
const clicked = await clickCaptchaAction(frame, options.refreshTexts, { ...options, page }).catch(() => false);
|
|
4541
4791
|
if (!clicked) {
|
|
4542
4792
|
logger10.warn("Refresh button not found.");
|
|
4543
4793
|
return false;
|
|
@@ -4663,9 +4913,9 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
4663
4913
|
state: "visible",
|
|
4664
4914
|
timeout: config.sourceImageVisibleTimeoutMs
|
|
4665
4915
|
});
|
|
4666
|
-
await
|
|
4916
|
+
await dragCaptchaAction(page, sourceImage, dropTarget);
|
|
4667
4917
|
}
|
|
4668
|
-
const submitted = await clickCaptchaAction(frame, config.submitTexts, config).catch(() => false);
|
|
4918
|
+
const submitted = await clickCaptchaAction(frame, config.submitTexts, { ...config, page }).catch(() => false);
|
|
4669
4919
|
if (!submitted) {
|
|
4670
4920
|
logger10.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
|
|
4671
4921
|
}
|
|
@@ -7168,11 +7418,11 @@ var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
|
7168
7418
|
watermark: options.watermark,
|
|
7169
7419
|
strip: options.strip,
|
|
7170
7420
|
stripLogoSrc,
|
|
7171
|
-
device:
|
|
7421
|
+
device: resolvePageDevice2(page)
|
|
7172
7422
|
};
|
|
7173
7423
|
};
|
|
7174
7424
|
var buildFontFamily = () => 'MiSans, "SF Pro Display", "PingFang SC", "Helvetica Neue", Arial, sans-serif';
|
|
7175
|
-
var
|
|
7425
|
+
var resolvePageDevice2 = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
7176
7426
|
var findStripSegment = (segments, kind) => {
|
|
7177
7427
|
const found = Array.isArray(segments) ? segments.find((segment) => segment?.kind === kind) : null;
|
|
7178
7428
|
return found && typeof found === "object" ? found : {};
|
|
@@ -8371,7 +8621,6 @@ var Share = {
|
|
|
8371
8621
|
*
|
|
8372
8622
|
* @param {import('playwright').Page} page
|
|
8373
8623
|
* @param {Object} [options]
|
|
8374
|
-
* @param {number} [options.buffer] 额外缓冲高度;默认按视口高度自动计算,传 0 可关闭
|
|
8375
8624
|
* @param {boolean} [options.restore]
|
|
8376
8625
|
* @param {number} [options.maxHeight]
|
|
8377
8626
|
* @param {number} [options.maxBytes] 默认 5MiB,返回 base64 超过后会压缩
|
|
@@ -8384,7 +8633,6 @@ var Share = {
|
|
|
8384
8633
|
const screenshotWatermarkify = resolveCaptureScreenWatermarkify(page, options.watermarkify);
|
|
8385
8634
|
const compression = resolveImageCompression(options);
|
|
8386
8635
|
const captureOptions = {
|
|
8387
|
-
...Object.prototype.hasOwnProperty.call(options, "buffer") ? { buffer: options.buffer } : {},
|
|
8388
8636
|
restore,
|
|
8389
8637
|
maxHeight: options.maxHeight,
|
|
8390
8638
|
type: "png",
|
|
@@ -8410,6 +8658,7 @@ var usePlaywrightToolKit = () => {
|
|
|
8410
8658
|
return {
|
|
8411
8659
|
ApifyKit,
|
|
8412
8660
|
AntiCheat,
|
|
8661
|
+
DeviceInput,
|
|
8413
8662
|
Humanize: Humanize2,
|
|
8414
8663
|
Launch,
|
|
8415
8664
|
LiveView,
|