diff --git a/src/components/connection/connection-relative-time.test.ts b/src/components/connection/connection-relative-time.test.ts index b525c06e6..2b24ce123 100644 --- a/src/components/connection/connection-relative-time.test.ts +++ b/src/components/connection/connection-relative-time.test.ts @@ -1,72 +1,40 @@ -import dayjs from 'dayjs' -import relativeTime from 'dayjs/plugin/relativeTime' import { useSyncExternalStore } from 'react' -import { afterEach, beforeEach, expect, it, vi } from 'vitest' - -dayjs.extend(relativeTime) +import { afterEach, expect, it, vi } from 'vitest' +vi.mock('dayjs', () => ({ default: () => ({ from: () => '' }) })) vi.mock('react', () => ({ memo: (component: unknown) => component, useSyncExternalStore: vi.fn((_subscribe, getSnapshot) => getSnapshot()), })) -let visibility: EventTarget & { hidden: boolean } - -beforeEach(() => { - vi.resetModules() - vi.clearAllMocks() - vi.useFakeTimers() - vi.stubGlobal('window', globalThis) - visibility = Object.assign(new EventTarget(), { hidden: false }) - vi.stubGlobal('document', visibility) -}) - afterEach(() => { vi.useRealTimers() vi.unstubAllGlobals() }) -it('shares one clock, stops while hidden, refreshes on visibility, and cleans up the last subscriber', async () => { +it('keeps at most one interval while visible and none while hidden or unsubscribed', async () => { + vi.useFakeTimers() + vi.stubGlobal('window', globalThis) + const visibility = Object.assign(new EventTarget(), { hidden: true }) + vi.stubGlobal('document', visibility) const { RelativeTime } = await import('./connection-relative-time') - RelativeTime({ start: '2026-01-01T00:00:00Z' }) - const [subscribe, getSnapshot] = vi.mocked(useSyncExternalStore).mock.calls[0] - const first = vi.fn() - const second = vi.fn() - const unsubscribeFirst = subscribe(first) - const unsubscribeSecond = subscribe(second) + RelativeTime({ start: '' }) + const [subscribe] = vi.mocked(useSyncExternalStore).mock.calls[0] + const unsubscribeFirst = subscribe(() => {}) + const unsubscribeSecond = subscribe(() => {}) + expect(vi.getTimerCount()).toBe(0) + visibility.hidden = false + visibility.dispatchEvent(new Event('visibilitychange')) expect(vi.getTimerCount()).toBe(1) - vi.advanceTimersByTime(5_000) - expect(first).toHaveBeenCalledOnce() - expect(second).toHaveBeenCalledOnce() - visibility.hidden = true visibility.dispatchEvent(new Event('visibilitychange')) expect(vi.getTimerCount()).toBe(0) - vi.advanceTimersByTime(60_000) - expect(first).toHaveBeenCalledOnce() visibility.hidden = false visibility.dispatchEvent(new Event('visibilitychange')) - expect(getSnapshot()).toBe(Date.now()) - expect(first).toHaveBeenCalledTimes(2) expect(vi.getTimerCount()).toBe(1) unsubscribeFirst() - expect(vi.getTimerCount()).toBe(1) unsubscribeSecond() expect(vi.getTimerCount()).toBe(0) visibility.dispatchEvent(new Event('visibilitychange')) expect(vi.getTimerCount()).toBe(0) - expect(second).toHaveBeenCalledTimes(2) -}) - -it('does not start a clock when mounted hidden', async () => { - visibility.hidden = true - const { RelativeTime } = await import('./connection-relative-time') - RelativeTime({ start: '2026-01-01T00:00:00Z' }) - const [subscribe] = vi.mocked(useSyncExternalStore).mock.calls[0] - const unsubscribe = subscribe(vi.fn()) - expect(vi.getTimerCount()).toBe(0) - unsubscribe() - visibility.hidden = false - visibility.dispatchEvent(new Event('visibilitychange')) - expect(vi.getTimerCount()).toBe(0) })