From 8a9d5e26b715b5fa2e9023620b8b3b5ebc7518e5 Mon Sep 17 00:00:00 2001 From: Oliver Lazoroski Date: Mon, 26 Oct 2026 14:45:58 +0100 Subject: [PATCH] fix(MediaRecorder): stop the recording timer when the preview unmounts useTimeElapsed cleared its interval only on stopCounter() or when it was started with startOnMount. AudioRecordingPreview starts it from the MediaRecorder start/resume events, so a preview unmounted while recording kept updating state every second. Stop the counter on unmount however it was started. --- .../hooks/__tests__/useTimeElapsed.test.ts | 44 +++++++++++++++++++ .../AudioRecorder/hooks/useTimeElapsed.ts | 3 ++ 2 files changed, 47 insertions(+) create mode 100644 src/components/MediaRecorder/AudioRecorder/hooks/__tests__/useTimeElapsed.test.ts diff --git a/src/components/MediaRecorder/AudioRecorder/hooks/__tests__/useTimeElapsed.test.ts b/src/components/MediaRecorder/AudioRecorder/hooks/__tests__/useTimeElapsed.test.ts new file mode 100644 index 0000000000..b508102ae7 --- /dev/null +++ b/src/components/MediaRecorder/AudioRecorder/hooks/__tests__/useTimeElapsed.test.ts @@ -0,0 +1,44 @@ +import { act, renderHook } from '@testing-library/react'; + +import { useTimeElapsed } from '../useTimeElapsed'; + +describe('useTimeElapsed', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('counts one second per second after startCounter() until stopCounter()', () => { + const { result } = renderHook(() => useTimeElapsed()); + + act(() => result.current.startCounter()); + act(() => vi.advanceTimersByTime(3000)); + expect(result.current.secondsElapsed).toBe(3); + + act(() => result.current.stopCounter()); + act(() => vi.advanceTimersByTime(3000)); + expect(result.current.secondsElapsed).toBe(3); + }); + + it('stops counting on unmount when started with startOnMount', () => { + const { unmount } = renderHook(() => useTimeElapsed({ startOnMount: true })); + expect(vi.getTimerCount()).toBe(1); + + unmount(); + + expect(vi.getTimerCount()).toBe(0); + }); + + it('stops counting on unmount when started with startCounter()', () => { + const { result, unmount } = renderHook(() => useTimeElapsed()); + act(() => result.current.startCounter()); + expect(vi.getTimerCount()).toBe(1); + + unmount(); + + expect(vi.getTimerCount()).toBe(0); + }); +}); diff --git a/src/components/MediaRecorder/AudioRecorder/hooks/useTimeElapsed.ts b/src/components/MediaRecorder/AudioRecorder/hooks/useTimeElapsed.ts index 051f4b487e..c613bfeec1 100644 --- a/src/components/MediaRecorder/AudioRecorder/hooks/useTimeElapsed.ts +++ b/src/components/MediaRecorder/AudioRecorder/hooks/useTimeElapsed.ts @@ -38,6 +38,9 @@ export const useTimeElapsed = ({ }; }, [startCounter, startOnMount, stopCounter]); + // The counter can also be started through startCounter(), so stop it on unmount too + useEffect(() => stopCounter, [stopCounter]); + return { secondsElapsed, startCounter,