88 lines
3.3 KiB
TypeScript
88 lines
3.3 KiB
TypeScript
import { effectScope, nextTick, ref } from 'vue'
|
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import { usePolling } from '@/composables/usePolling'
|
|
|
|
afterEach(() => vi.useRealTimers())
|
|
|
|
describe('异步轮询生命周期', () => {
|
|
it('关闭定时刷新后仍支持首次读取、手动刷新及查询目标切换', async () => {
|
|
vi.useFakeTimers()
|
|
const key = ref('first')
|
|
const loader = vi.fn<(id: string) => Promise<string>>(async id => id)
|
|
const scope = effectScope()
|
|
const query = scope.run(() => usePolling(key, loader, false))!
|
|
await Promise.resolve()
|
|
expect(query.data.value).toBe('first')
|
|
await vi.advanceTimersByTimeAsync(30_000)
|
|
expect(loader).toHaveBeenCalledTimes(1)
|
|
await query.refresh()
|
|
expect(loader).toHaveBeenCalledTimes(2)
|
|
key.value = 'second'
|
|
await nextTick()
|
|
await Promise.resolve()
|
|
expect(query.data.value).toBe('second')
|
|
await vi.advanceTimersByTimeAsync(30_000)
|
|
expect(loader).toHaveBeenCalledTimes(3)
|
|
scope.stop()
|
|
})
|
|
|
|
it('响应式暂停清除旧定时器,恢复只创建一个轮询链', async () => {
|
|
vi.useFakeTimers()
|
|
const interval = ref<number | false>(1000)
|
|
const loader = vi.fn<() => Promise<string>>(async () => '数据')
|
|
const scope = effectScope()
|
|
scope.run(() => usePolling(ref('p'), loader, interval))
|
|
await Promise.resolve()
|
|
interval.value = false
|
|
await nextTick()
|
|
await vi.advanceTimersByTimeAsync(5000)
|
|
expect(loader).toHaveBeenCalledTimes(1)
|
|
interval.value = 1000
|
|
await nextTick()
|
|
await vi.advanceTimersByTimeAsync(2000)
|
|
expect(loader).toHaveBeenCalledTimes(3)
|
|
scope.stop()
|
|
await vi.advanceTimersByTimeAsync(5000)
|
|
expect(loader).toHaveBeenCalledTimes(3)
|
|
})
|
|
|
|
it('切换项目忽略旧响应,卸载时不再排队请求', async () => {
|
|
vi.useFakeTimers()
|
|
const key = ref('first')
|
|
const finish = new Map<string, (value: string) => void>()
|
|
const loader = vi.fn<(id: string) => Promise<string>>(
|
|
(id: string) =>
|
|
new Promise<string>(resolve => {
|
|
finish.set(id, resolve)
|
|
})
|
|
)
|
|
const scope = effectScope()
|
|
const query = scope.run(() => usePolling(key, loader, 1000))!
|
|
key.value = 'second'
|
|
await nextTick()
|
|
finish.get('second')!('新项目')
|
|
await Promise.resolve()
|
|
finish.get('first')!('旧项目')
|
|
await Promise.resolve()
|
|
expect(query.data.value).toBe('新项目')
|
|
scope.stop()
|
|
await vi.advanceTimersByTimeAsync(10_000)
|
|
expect(loader).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('失败时保留已有数据,并向页面显示错误', async () => {
|
|
const scope = effectScope()
|
|
const loader = vi
|
|
.fn<() => Promise<string>>()
|
|
.mockResolvedValueOnce('上次成功数据')
|
|
.mockRejectedValueOnce(new Error('连接已断开'))
|
|
const query = scope.run(() => usePolling(ref('p'), loader))!
|
|
await Promise.resolve()
|
|
await query.refresh()
|
|
expect(query.data.value).toBe('上次成功数据')
|
|
expect(query.error.value).toBe('连接已断开')
|
|
scope.stop()
|
|
})
|
|
})
|
|
|