import { test } from 'node:test' import assert from 'node:assert/strict' import { createPollingStateMachine } from '../src/shared/polling-state-machine.ts' import { useTaskProgressLoop } from '../src/shared/composables/useTaskProgressLoop.ts' test('test_pending_not_terminal', () => { const fsm = createPollingStateMachine({ maxAttempts: 3 }) fsm.start() fsm.succeed('PENDING') assert.equal(fsm.status, 'retrying', 'PENDING 不判终态,沿用重试语义') assert.equal(fsm.terminalStatus, '') }) test('test_syncing_not_terminal', () => { const fsm = createPollingStateMachine({ maxAttempts: 3 }) fsm.start() fsm.succeed('SYNCING') assert.equal(fsm.status, 'retrying', 'SYNCING 不判终态') assert.equal(fsm.terminalStatus, '') }) test('test_empty_status_not_terminal', () => { const fsm = createPollingStateMachine({ maxAttempts: 3 }) fsm.start() fsm.succeed('') assert.equal(fsm.status, 'retrying', '空串不判终态') assert.equal(fsm.terminalStatus, '') }) test('test_undefined_status_not_terminal', () => { const fsm = createPollingStateMachine({ maxAttempts: 3 }) fsm.start() fsm.succeed(undefined as never) assert.equal(fsm.status, 'retrying', 'undefined 不判终态') assert.equal(fsm.terminalStatus, '') }) test('test_unknown_status_continues_polling', async () => { const storage = new Map() ;(globalThis as Record).window = { localStorage: { getItem: (k: string) => storage.get(k) ?? null, setItem: (k: string, v: string) => { storage.set(k, v) }, removeItem: (k: string) => { storage.delete(k) }, }, setTimeout: (fn: () => void, ms: number) => globalThis.setTimeout(fn, ms), clearTimeout: (id: unknown) => globalThis.clearTimeout(id as number), setInterval: (fn: () => void, ms: number) => globalThis.setInterval(fn, ms), clearInterval: (id: unknown) => globalThis.clearInterval(id as number), } const terminalCalls: number[] = [] const loop = useTaskProgressLoop<{ taskId?: number; status?: string }>({ scope: 'unknown-status', fetchProgress: async () => ({ items: [{ taskId: 1, status: 'MYSTERY' }] }), extractTaskId: (d) => d?.taskId, extractStatus: (d) => d?.status, getIntervalMs: () => 60000, onTerminal: (taskId) => { terminalCalls.push(taskId) }, }) loop.reset([1]) await new Promise((r) => globalThis.setTimeout(r, 0)) await loop.refreshOnce() assert.deepEqual(loop.taskIds.value, [1], '未知状态任务仍在轮询集合') assert.equal(terminalCalls.length, 0, '未知状态不触发终态回调') loop.dispose() }) test('test_mixed_terminal_unknown', async () => { const storage = new Map() ;(globalThis as Record).window = { localStorage: { getItem: (k: string) => storage.get(k) ?? null, setItem: (k: string, v: string) => { storage.set(k, v) }, removeItem: (k: string) => { storage.delete(k) }, }, setTimeout: (fn: () => void, ms: number) => globalThis.setTimeout(fn, ms), clearTimeout: (id: unknown) => globalThis.clearTimeout(id as number), setInterval: (fn: () => void, ms: number) => globalThis.setInterval(fn, ms), clearInterval: (id: unknown) => globalThis.clearInterval(id as number), } const terminalCalls: number[] = [] const all = [ { taskId: 1, status: 'SUCCESS' }, { taskId: 2, status: 'QUEUED' }, { taskId: 3, status: 'FAILED' }, ] const loop = useTaskProgressLoop<{ taskId?: number; status?: string }>({ scope: 'mixed-status', fetchProgress: async (ids) => ({ items: all.filter((item) => ids.includes(item.taskId ?? -1)), }), extractTaskId: (d) => d?.taskId, extractStatus: (d) => d?.status, getIntervalMs: () => 60000, onTerminal: (taskId) => { terminalCalls.push(taskId) }, }) loop.reset([1, 2, 3]) await new Promise((r) => globalThis.setTimeout(r, 0)) await loop.refreshOnce() assert.deepEqual(terminalCalls, [1, 3], '同批终态+未知分开处理') assert.deepEqual(loop.taskIds.value, [2], '未知状态任务保留') loop.dispose() }) test('test_custom_is_terminal', () => { const fsm = createPollingStateMachine({ maxAttempts: 3, isTerminal: (status) => status === 'COMPLETED', }) fsm.start() fsm.succeed('SUCCESS') assert.equal(fsm.status, 'retrying', '自定义判定下 SUCCESS 非终态') fsm.succeed('COMPLETED') assert.equal(fsm.status, 'done', '自定义判定生效') assert.equal(fsm.terminalStatus, 'COMPLETED') }) test('test_lowercase_unknown', () => { const fsm = createPollingStateMachine({ maxAttempts: 3 }) fsm.start() fsm.succeed('success') assert.equal(fsm.status, 'retrying', '小写 success 不误判终态') assert.equal(fsm.terminalStatus, '') })