From 46ffd908a2bbb65a1fbdf4d57c041e2cda982bab Mon Sep 17 00:00:00 2001 From: "wang.haoyu" <31119562+19Qingfeng@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:06:11 +0800 Subject: [PATCH] fix: useLockScroll whether the element scroll is in the end #6253 (#6254) * fix: useLockScroll whether the element scroll is in the end #6253 * test: useLockScroll test case #6253 * fix: useLockScroll whether the element scroll is in the end #6253 * test: useLockScroll whether the element scroll is in the end #6253 * test: useLockScroll with strict params #6253 * test: useLockScroll with strict params #6253 * fix: del px and remove {} #6253 --- src/utils/tests/use-lock-scroll.test.tsx | 154 ++++++++++++++++++++++- src/utils/use-lock-scroll.ts | 3 +- 2 files changed, 154 insertions(+), 3 deletions(-) diff --git a/src/utils/tests/use-lock-scroll.test.tsx b/src/utils/tests/use-lock-scroll.test.tsx index d294743421..f37e487a16 100644 --- a/src/utils/tests/use-lock-scroll.test.tsx +++ b/src/utils/tests/use-lock-scroll.test.tsx @@ -1,8 +1,48 @@ -import React, { useRef, createRef } from 'react' -import { render, fireEvent, screen, createEvent } from 'testing' +import React, { useRef } from 'react' +import { render, fireEvent, createEvent, screen } from 'testing' import { useLockScroll } from '../use-lock-scroll' describe('useLockScroll', () => { + let TestComponent: React.FC<{ + scrollParams: boolean | 'strict' + handleTouch?: () => void + }> + + beforeEach(() => { + TestComponent = (props: { + scrollParams: boolean | 'strict' + handleTouch?: () => void + }) => { + const divRef = useRef(null) + + useLockScroll(divRef, props.scrollParams) + + return ( +
props.handleTouch && props.handleTouch()} + > + {new Array(10).fill({}).map((_, i) => ( +

+ Test component {i} +

+ ))} +
+ ) + } + }) + + afterEach(() => { + TestComponent = null as any + }) + test('use preventDefault when event listener is treated as as passive', () => { const handleTouch = jest.fn() const TestComponent = () => { @@ -32,4 +72,114 @@ describe('useLockScroll', () => { expect(fn).toBeCalled() }) + + test('Scroll To Bottom', async () => { + const { getByTestId } = render() + + const testEl = getByTestId('lock') + + jest.spyOn(testEl, 'scrollHeight', 'get').mockImplementation(() => 200) + + const scrollTop = jest.spyOn(testEl, 'scrollTop', 'get') + scrollTop.mockImplementationOnce(() => 150) + + jest.spyOn(testEl, 'getBoundingClientRect').mockImplementation(() => ({ + height: 20, + top: 0, + left: 0, + x: 0, + y: 0, + bottom: 0, + right: 0, + width: 0, + toJSON: () => {}, + })) + + fireEvent.touchStart(testEl, { + touches: [{ clientX: 0, clientY: 100 }], + }) + + const triggerTruthy = fireEvent.touchMove(testEl, { + touches: [{ clientX: 0, clientY: 20 }], + }) + // 滚动事件正常触发 + expect(triggerTruthy).toBeTruthy() + + // 滚动高度到 180 + scrollTop.mockImplementationOnce(() => 180) + + const triggerFalsy = fireEvent.touchMove(testEl, { + touches: [{ clientX: 0, clientY: 10 }], + }) + + // 滚动事件被取消 + expect(triggerFalsy).toBeFalsy() + }) + + test('Scroll To Top', async () => { + const { getByTestId } = render() + + const testEl = getByTestId('lock') + + jest.spyOn(testEl, 'scrollHeight', 'get').mockImplementation(() => 200) + + const scrollTop = jest.spyOn(testEl, 'scrollTop', 'get') + scrollTop.mockImplementationOnce(() => 150) + + jest.spyOn(testEl, 'getBoundingClientRect').mockImplementation(() => ({ + height: 20, + top: 0, + left: 0, + x: 0, + y: 0, + bottom: 0, + right: 0, + width: 0, + toJSON: () => {}, + })) + + fireEvent.touchStart(testEl, { + touches: [{ clientX: 0, clientY: 100 }], + }) + + const triggerTruthy = fireEvent.touchMove(testEl, { + touches: [{ clientX: 0, clientY: 120 }], + }) + // 滚动事件正常触发 + expect(triggerTruthy).toBeTruthy() + + // 滚动高度到顶部 + scrollTop.mockImplementationOnce(() => 0) + + const triggerFalsy = fireEvent.touchMove(testEl, { + touches: [{ clientX: 0, clientY: 200 }], + }) + + // 滚动事件被取消 + expect(triggerFalsy).toBeFalsy() + }) + + test('Scroll With Strict Params', async () => { + const { getByTestId } = render() + + const testEl = getByTestId('lock') + + jest + .spyOn(document.body, 'clientHeight', 'get') + .mockImplementation(() => 20) + jest + .spyOn(document.body, 'scrollHeight', 'get') + .mockImplementation(() => 30) + + fireEvent.touchStart(testEl, { + touches: [{ clientX: 0, clientY: 100 }], + }) + + const cancelTrigger = fireEvent.touchMove(testEl, { + touches: [{ clientX: 0, clientY: 200 }], + }) + + // 事件被取消 + expect(cancelTrigger).toBeFalsy() + }) }) diff --git a/src/utils/use-lock-scroll.ts b/src/utils/use-lock-scroll.ts index 97301d308d..755a138821 100644 --- a/src/utils/use-lock-scroll.ts +++ b/src/utils/use-lock-scroll.ts @@ -51,11 +51,12 @@ export function useLockScroll( } const { scrollHeight, offsetHeight, scrollTop } = el + const { height } = el.getBoundingClientRect() let status = '11' if (scrollTop === 0) { status = offsetHeight >= scrollHeight ? '00' : '01' - } else if (scrollTop + offsetHeight >= scrollHeight) { + } else if (scrollHeight <= Math.round(height + scrollTop)) { status = '10' }