Files
clash-verge-rev/src/components/connection/connection-relative-time.test.ts
T
Tunglies f84be8df72 perf(connections): reduce snapshot and table allocation churn
Reuse unchanged connection lists, sort traffic columns without display snapshots, and suspend the relative-time clock while hidden. Keep rule rows indexed and release resize listeners on unmount.
2026-11-10 07:52:02 +08:00

73 lines
2.4 KiB
TypeScript

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)
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 () => {
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)
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)
})