Files
short-drama-agent-front/src/features/workflows/selectors.test.ts
T

72 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { breakdownSnapshot, recoveryOptions, workflowCheckpoints } from './selectors'
import type { Checkpoint } from './types'
import type { BreakdownState } from '../breakdown/types'
/** 只构造测试所需的真实 checkpoint 字段,避免页面依赖虚构 DTO。 */
function checkpoint(index: number, state: BreakdownState, workflowName = 'breakdown'): Checkpoint {
return { checkpointId: String(index), workflowName, createdAt: new Date(index * 1000).toISOString(), state }
}
describe('Checkpoint 选择与恢复', () => {
it('按 graph 隔离并保持输入不可变', () => {
const records = [checkpoint(2, {}), checkpoint(1, {}, 'create-drama')]
expect(workflowCheckpoints(records, 'breakdown').map(item => item.checkpointId)).toEqual(['2'])
expect(records[0]?.checkpointId).toBe('2')
})
it('只有错误的最新 checkpoint 仍能展示上一份成果,同时保留最新失败状态', () => {
const result = breakdownSnapshot([
checkpoint(1, {
breakdownResult: { subjectCandidates: [] },
runConfig: { groupSize: 3, modules: ['character'], episodeGroups: [] }
}),
checkpoint(2, {
workflowExecution: {
executionId: 'e',
status: 'failed',
startedAt: '',
errorMessage: '模型未返回 JSON'
}
})
])
expect(result?.runConfig?.groupSize).toBe(3)
expect(result?.workflowExecution?.status).toBe('failed')
})
it('新阶段不能继承上一轮 completed 状态', () => {
const result = breakdownSnapshot([
checkpoint(1, {
workflowExecution: { executionId: 'e', status: 'completed', startedAt: '' },
breakdownResult: {}
}),
checkpoint(2, { runConfig: { groupSize: 2, modules: ['scene'], episodeGroups: [] } })
])
expect(result?.workflowExecution).toBeUndefined()
expect(result?.runConfig?.groupSize).toBe(2)
})
it('恢复窗口和后端一致,过旧的失败任务不启用重试', () => {
const records = Array.from({ length: 11 }, (_, index) =>
checkpoint(
index,
index === 0
? {
tasks: [
{
taskId: 't',
module: 'prop',
status: 'failed',
attempt: 1,
group: { groupId: 'g', groupNo: 1, startEpisodeNo: 1, endEpisodeNo: 1, episodes: [] }
}
]
}
: {}
)
)
expect(recoveryOptions(records).retry).toBe(false)
expect(recoveryOptions(records.slice(0, 10)).retry).toBe(true)
})
})