import { afterEach, expect, it, vi } from 'vitest' import { ApiResponseError } from '@/shared/api/http' import { useWorkSyncRead } from './useWorkSyncRead' const pending = () => new ApiResponseError('预约批次或运输关联已变化,服务端正在协调完整工作清单', 'A0409', 409, undefined, 'request-sync', 'trace-sync') afterEach(() => vi.useRealTimers()) it('waits only for the full-work synchronization guard and returns the fresh result', async () => { vi.useFakeTimers() const reader = useWorkSyncRead(), load = vi.fn().mockRejectedValueOnce(pending()).mockResolvedValue('fresh') const result = reader.read(load, new AbortController().signal) await vi.advanceTimersByTimeAsync(0) expect(reader.syncing.value).toBe(true) expect(load).toHaveBeenCalledTimes(1) await vi.advanceTimersByTimeAsync(2000) expect(await result).toBe('fresh') expect(reader.syncing.value).toBe(false) }) it.each([new ApiResponseError('事项版本已变化', 'A0409', 409), new ApiResponseError('无权查看', 'A0403', 403), new Error('network')])('does not retry other failures: %s', async error => { const reader = useWorkSyncRead(), load = vi.fn().mockRejectedValue(error) await expect(reader.read(load, new AbortController().signal)).rejects.toBe(error) expect(load).toHaveBeenCalledTimes(1) expect(reader.syncing.value).toBe(false) }) it('stops waiting at the limit and preserves diagnostic IDs on the original error', async () => { vi.useFakeTimers() const error = pending(), reader = useWorkSyncRead(), load = vi.fn().mockRejectedValue(error) const result = expect(reader.read(load, new AbortController().signal)).rejects.toBe(error) await vi.advanceTimersByTimeAsync(30000) await result expect(load).toHaveBeenCalledTimes(16) expect(reader.syncing.value).toBe(false) expect(error.traceId).toBe('trace-sync') expect(vi.getTimerCount()).toBe(0) }) it('cancels a waiting read without sending another request', async () => { vi.useFakeTimers() const controller = new AbortController(), reader = useWorkSyncRead(), load = vi.fn().mockRejectedValue(pending()) const result = expect(reader.read(load, controller.signal)).rejects.toHaveProperty('name', 'AbortError') await vi.advanceTimersByTimeAsync(0) controller.abort() await result await vi.advanceTimersByTimeAsync(30000) expect(load).toHaveBeenCalledTimes(1) expect(reader.syncing.value).toBe(false) expect(vi.getTimerCount()).toBe(0) })