From 6d51a53f48b0237640727ce65dfae96dd32c38e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 30 Sep 2026 17:40:10 +0800 Subject: [PATCH] fix: preserve remaining duration when paused repeatedly --- src/hooks/useNoticeTimer.ts | 1 + tests/useNoticeTimer.test.tsx | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/useNoticeTimer.test.tsx diff --git a/src/hooks/useNoticeTimer.ts b/src/hooks/useNoticeTimer.ts index dafc03ea..d055f6f0 100644 --- a/src/hooks/useNoticeTimer.ts +++ b/src/hooks/useNoticeTimer.ts @@ -32,6 +32,7 @@ export default function useNoticeTimer( const onPause = React.useCallback(() => { syncPassTime(); + lastRafTimeRef.current = null; setWalking(false); }, []); diff --git a/tests/useNoticeTimer.test.tsx b/tests/useNoticeTimer.test.tsx new file mode 100644 index 00000000..ff499a2f --- /dev/null +++ b/tests/useNoticeTimer.test.tsx @@ -0,0 +1,43 @@ +import { act, renderHook } from '@testing-library/react'; +import useNoticeTimer from '../src/hooks/useNoticeTimer'; + +describe('useNoticeTimer', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('preserves the remaining duration when paused repeatedly', () => { + const onClose = vi.fn(); + const onUpdate = vi.fn(); + const { result, unmount } = renderHook(() => useNoticeTimer(1, onClose, onUpdate)); + + act(() => vi.advanceTimersByTime(200)); + act(() => result.current[1]()); + const updateCount = onUpdate.mock.calls.length; + + for (let i = 0; i < 3; i += 1) { + act(() => vi.advanceTimersByTime(2000)); + act(() => result.current[1]()); + } + + expect(onUpdate).toHaveBeenCalledTimes(updateCount); + expect(onClose).not.toHaveBeenCalled(); + + act(() => result.current[0]()); + expect(onUpdate).toHaveBeenLastCalledWith(0.2); + expect(onClose).not.toHaveBeenCalled(); + + act(() => vi.advanceTimersByTime(700)); + expect(onClose).not.toHaveBeenCalled(); + + act(() => vi.advanceTimersByTime(200)); + expect(onUpdate).toHaveBeenLastCalledWith(1); + expect(onClose).toHaveBeenCalledTimes(1); + + unmount(); + }); +});