@skrillex1224/playwright-toolkit 2.1.28 → 2.1.30

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
@@ -686,46 +686,19 @@ var Humanize = {
686
686
  async humanScroll(page, target, options = {}) {
687
687
  const { maxSteps = 25, minStep = 80, maxStep = 220 } = options;
688
688
  const targetDesc = typeof target === "string" ? target : "ElementHandle";
689
- logger4.debug("humanScroll", `target=${targetDesc}`);
689
+ logger4.debug(`humanScroll| target=${targetDesc}`);
690
690
  let element;
691
691
  if (typeof target === "string") {
692
692
  element = await page.$(target);
693
693
  if (!element) {
694
- logger4.warn("humanScroll", `Element not found: ${target}`);
694
+ logger4.warn(`humanScroll| Element not found: ${target}`);
695
695
  return { element: null, didScroll: false, restore: async () => {
696
696
  } };
697
697
  }
698
698
  } else {
699
699
  element = target;
700
700
  }
701
- const needsScroll = await element.evaluate((el) => {
702
- const isScrollable = (node) => {
703
- if (!node || node === document.body) return false;
704
- const style = window.getComputedStyle(node);
705
- const overflowY = style.overflowY || style.overflow;
706
- return (overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay") && node.scrollHeight > node.clientHeight + 1;
707
- };
708
- const rect = el.getBoundingClientRect();
709
- if (!rect || rect.width === 0 || rect.height === 0) return true;
710
- const inViewport = rect.top >= 0 && rect.bottom <= window.innerHeight;
711
- if (!inViewport) return true;
712
- let current = el.parentElement;
713
- while (current) {
714
- if (isScrollable(current)) {
715
- const crect = current.getBoundingClientRect();
716
- if (rect.top < crect.top || rect.bottom > crect.bottom) {
717
- return true;
718
- }
719
- }
720
- current = current.parentElement;
721
- }
722
- return false;
723
- });
724
- if (!needsScroll) {
725
- logger4.debug("humanScroll", "Element already in view");
726
- return { element, didScroll: false, restore: async () => {
727
- } };
728
- }
701
+ let didScroll = false;
729
702
  const scrollStateHandle = await element.evaluateHandle((el) => {
730
703
  const isScrollable = (node) => {
731
704
  if (!node || node === document.body) return false;
@@ -771,9 +744,21 @@ var Humanize = {
771
744
  }
772
745
  const scrollingElement = document.scrollingElement || document.documentElement;
773
746
  if (scrollingElement) scrollables.push(scrollingElement);
747
+ const cx = rect.left + rect.width / 2;
748
+ const cy = rect.top + rect.height / 2;
749
+ const viewH = window.innerHeight;
750
+ let isObstructed = false;
751
+ if (cy < 0 || cy > viewH) {
752
+ isObstructed = true;
753
+ } else {
754
+ const pointElement = document.elementFromPoint(cx, cy);
755
+ if (pointElement && !el.contains(pointElement) && !pointElement.contains(el)) {
756
+ isObstructed = true;
757
+ }
758
+ }
774
759
  let target2 = null;
775
760
  for (const container of scrollables) {
776
- const crect = container === scrollingElement ? { top: 0, bottom: window.innerHeight } : container.getBoundingClientRect();
761
+ const crect = container === scrollingElement ? { top: 0, bottom: viewH } : container.getBoundingClientRect();
777
762
  if (rect.top < crect.top + 2) {
778
763
  target2 = { container, direction: -1 };
779
764
  break;
@@ -782,26 +767,40 @@ var Humanize = {
782
767
  target2 = { container, direction: 1 };
783
768
  break;
784
769
  }
770
+ if (isObstructed) {
771
+ const containerCenter = (crect.top + crect.bottom) / 2;
772
+ const elementCenter = (rect.top + rect.bottom) / 2;
773
+ const forceDirection = elementCenter > containerCenter ? 1 : -1;
774
+ const canScroll = forceDirection === 1 ? container.scrollTop < container.scrollHeight - container.clientHeight : container.scrollTop > 0;
775
+ if (canScroll) {
776
+ target2 = { container, direction: forceDirection };
777
+ break;
778
+ }
779
+ }
785
780
  }
786
781
  if (!target2) {
787
- return { moved: false, inView: true };
782
+ return { moved: false, inView: !isObstructed };
788
783
  }
789
784
  const maxScroll = target2.container.scrollHeight - target2.container.clientHeight;
790
785
  if (maxScroll <= 0) {
791
- return { moved: false, inView: false };
786
+ return { moved: false, inView: !isObstructed };
792
787
  }
793
788
  const before = target2.container.scrollTop;
794
789
  let next = before + target2.direction * stepPx;
795
790
  if (next < 0) next = 0;
796
791
  if (next > maxScroll) next = maxScroll;
797
- if (next === before) {
798
- return { moved: false, inView: false };
792
+ if (Math.abs(next - before) < 1) {
793
+ return { moved: false, inView: !isObstructed };
799
794
  }
800
795
  target2.container.scrollTop = next;
801
796
  return { moved: true, inView: false };
802
797
  }, step);
798
+ if (result.moved) didScroll = true;
803
799
  if (result.inView) break;
804
- if (!result.moved) break;
800
+ if (!result.moved && !result.inView) {
801
+ logger4.warn("humanScroll| Stuck: cannot scroll further but element still obstructed/hidden");
802
+ break;
803
+ }
805
804
  await (0, import_delay2.default)(this.jitterMs(120, 0.4));
806
805
  }
807
806
  const restore = async () => {
@@ -833,7 +832,7 @@ var Humanize = {
833
832
  }
834
833
  };
835
834
  logger4.success("humanScroll", "Scroll completed");
836
- return { element, didScroll: true, restore };
835
+ return { element, didScroll, restore };
837
836
  },
838
837
  /**
839
838
  * 人类化点击 - 使用 ghost-cursor 模拟人类鼠标移动轨迹并点击