import { effectScope, nextTick, ref } from 'vue' import { afterEach, describe, expect, it, vi } from 'vitest' import { usePolling } from './usePolling' afterEach(() => vi.useRealTimers()) describe('异步轮询生命周期', () => { it('切换项目忽略旧响应,卸载时不再排队请求', async () => { vi.useFakeTimers() const key = ref('first') const finish = new Map void>() const loader = vi.fn<(id: string) => Promise>( (id: string) => new Promise(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>() .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() }) })