import { test } from 'node:test' import assert from 'node:assert/strict' import { createPollingStateMachine } from '../src/shared/polling-state-machine.ts' test('test_task_095_task_normal_default_path', () => { const fsm = createPollingStateMachine({ maxAttempts: 3 }) assert.equal(fsm.status, 'idle') fsm.start() assert.equal(fsm.status, 'polling') fsm.succeed('SUCCESS') assert.equal(fsm.status, 'done') assert.equal(fsm.terminalStatus, 'SUCCESS') assert.equal(fsm.attempts, 1) assert.equal(fsm.errorCount, 0) assert.deepEqual(fsm.retries(), []) // 终态刷新:刷新计数 fsm.markRefreshed() assert.equal(fsm.refreshed, true) assert.equal(fsm.refreshCount, 1) }) test('test_task_095_task_normal_multiple_items', () => { // 多任务独立状态机:互不串扰 const fsmA = createPollingStateMachine({ maxAttempts: 3 }) const fsmB = createPollingStateMachine({ maxAttempts: 3 }) fsmA.start() fsmB.start() fsmA.fail('Network Error') fsmB.succeed('SUCCESS') assert.equal(fsmA.status, 'retrying') assert.equal(fsmB.status, 'done') assert.equal(fsmA.errorCount, 1) assert.equal(fsmB.errorCount, 0) assert.equal(fsmB.terminalStatus, 'SUCCESS') assert.deepEqual(fsmA.retries(), [1]) }) test('test_task_095_task_normal_repeated_operation_is_idempotent', () => { const fsm = createPollingStateMachine({ maxAttempts: 5 }) fsm.start() fsm.fail('e1') fsm.fail('e2') fsm.succeed('SUCCESS') // 重复进入终态幂等:不重复计数、不覆盖状态 fsm.succeed('SUCCESS') fsm.succeed('SUCCESS') assert.equal(fsm.status, 'done') assert.equal(fsm.attempts, 3) assert.equal(fsm.errorCount, 2) // 重复刷新幂等:refreshCount 只计一次 fsm.markRefreshed() fsm.markRefreshed() fsm.markRefreshed() assert.equal(fsm.refreshed, true) assert.equal(fsm.refreshCount, 1) // 终态后 start 无效 fsm.start() assert.equal(fsm.status, 'done') }) test('test_task_095_task_boundary_empty_input', () => { const fsm = createPollingStateMachine({ maxAttempts: 3 }) assert.equal(fsm.status, 'idle') assert.equal(fsm.attempts, 0) assert.equal(fsm.errorCount, 0) assert.equal(fsm.retries().length, 0) assert.equal(fsm.refreshed, false) // idle 状态不触发任何刷新 fsm.markRefreshed() assert.equal(fsm.refreshCount, 0) }) test('test_task_095_task_boundary_single_item', () => { const fsm = createPollingStateMachine({ maxAttempts: 1 }) fsm.start() fsm.succeed('FAILED') assert.equal(fsm.status, 'done') assert.equal(fsm.terminalStatus, 'FAILED', '终态单次成功') assert.equal(fsm.attempts, 1) }) test('test_task_095_task_boundary_limit_and_overflow', () => { // 重试有界:超过 maxAttempts 后失败进入 failed,不再重试 const fsm = createPollingStateMachine({ maxAttempts: 2 }) fsm.start() fsm.fail('e1') assert.equal(fsm.status, 'retrying') assert.equal(fsm.retrying, true) fsm.fail('e2') assert.equal(fsm.status, 'failed', '达到上限后失败不再重试') assert.equal(fsm.retrying, false) assert.deepEqual(fsm.retries(), [1], '仅成功重试过 1 次,第二次失败直接进入 failed') // 失败状态下再次 fail:不越界 fsm.fail('e3') assert.equal(fsm.attempts, 2) assert.equal(fsm.errorCount, 2) }) test('test_task_095_task_invalid_input_rejected', () => { assert.throws(() => createPollingStateMachine({} as never), /maxAttempts 必须为正数/) assert.throws(() => createPollingStateMachine({ maxAttempts: 0 }), /maxAttempts 必须为正数/) assert.throws(() => createPollingStateMachine({ maxAttempts: -1 }), /maxAttempts 必须为正数/) assert.throws(() => createPollingStateMachine({ maxAttempts: 1.5 }), /maxAttempts 必须为整数/) assert.throws( () => createPollingStateMachine({ maxAttempts: 2, isTerminal: 'x' as never }), /isTerminal 必须是函数/, ) // 未 start 时 fail/succeed 拒绝 const fsm = createPollingStateMachine({ maxAttempts: 3 }) assert.throws(() => fsm.fail('e'), /未开始轮询/) assert.throws(() => fsm.succeed('SUCCESS'), /未开始轮询/) }) test('test_task_095_task_dependency_failure_releases_resources', () => { // isTerminal 依赖抛错:fail 调用失败但状态不污染,恢复后可用 let broken = true const fsm = createPollingStateMachine({ maxAttempts: 3, isTerminal: (status: string) => { if (broken) throw new Error('isTerminal down') return status === 'SUCCESS' }, }) fsm.start() assert.throws(() => fsm.succeed('SUCCESS'), /isTerminal down/) assert.equal(fsm.status, 'polling', '失败不产生状态变更') broken = false fsm.succeed('SUCCESS') assert.equal(fsm.status, 'done') assert.equal(fsm.terminalStatus, 'SUCCESS') assert.equal(fsm.attempts, 1) })