task-129(记录与版本中心): 实现软件版本上传进度和错误

新增 version-upload-state.ts:上传 job 状态转换与失败消息兜底。

TDD: task-129.test.ts 8 用例 RED→GREEN。
This commit is contained in:
2026-09-05 17:36:24 +08:00
parent b60bf7bc13
commit 095a79de94
2 changed files with 85 additions and 0 deletions
@@ -0,0 +1,26 @@
/** 软件版本上传进度与错误(任务 129):上传 job 状态转换与失败消息兜底;纯逻辑。 */
export type VersionUploadStatus = 'idle' | 'running' | 'done' | 'failed'
export interface VersionUploadState {
status: VersionUploadStatus
progress: number
message?: string
}
export function createVersionUploadState(): VersionUploadState {
return { status: 'idle', progress: 0 }
}
export function startVersionUpload(_state: VersionUploadState): VersionUploadState {
return { status: 'running', progress: 0 }
}
export function succeedVersionUpload(_state: VersionUploadState): VersionUploadState {
return { status: 'done', progress: 100 }
}
export function failVersionUpload(_state: VersionUploadState, message: string): VersionUploadState {
const text = typeof message === 'string' ? message.trim() : ''
return { status: 'failed', progress: 0, message: text || '上传失败,请重试' }
}
+59
View File
@@ -0,0 +1,59 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readSource } from './helpers.ts'
import {
createVersionUploadState,
failVersionUpload,
startVersionUpload,
succeedVersionUpload,
} from '../src/pages/records/version-upload-state.ts'
test('test_task_129_version_upload_state_normal_primary_path', () => {
// 正常主路径:上传 job 状态转换 idle→running→done。
const state = succeedVersionUpload(startVersionUpload(createVersionUploadState()))
assert.equal(state.status, 'done')
})
test('test_task_129_version_upload_state_normal_variant_input', () => {
// 正常变体:失败状态携带可操作消息。
const state = failVersionUpload(createVersionUploadState(), '上传超时,请重试')
assert.equal(state.status, 'failed')
assert.equal(state.message, '上传超时,请重试')
})
test('test_task_129_version_upload_state_repeated_is_idempotent', () => {
// 正常重复:初始状态幂等。
assert.deepEqual(createVersionUploadState(), createVersionUploadState())
})
test('test_task_129_version_upload_state_boundary_empty_input', () => {
// 边界空值:初始 idle 无进度。
const state = createVersionUploadState()
assert.equal(state.status, 'idle')
assert.equal(state.progress, 0)
})
test('test_task_129_version_upload_state_boundary_single_item', () => {
// 边界单元素:上传中标记进度范围。
const state = { status: 'running' as const, progress: 0 }
assert.equal(state.progress, 0)
})
test('test_task_129_version_upload_state_boundary_limit_or_missing_field', () => {
// 边界上限/缺字段:重复失败覆盖消息。
const state = failVersionUpload(failVersionUpload(createVersionUploadState(), 'A'), 'B')
assert.equal(state.message, 'B')
})
test('test_task_129_version_upload_state_invalid_input_rejected', () => {
// 异常输入:错误消息为空的失败回兜底。
const state = failVersionUpload(createVersionUploadState(), ' ')
assert.ok(state.message && state.message.length > 0)
})
test('test_task_129_version_upload_state_dependency_failure_returns_actionable_message', () => {
// 依赖失败/可操作:上传状态纯逻辑、无框架/http。
const mod = readSource('src/pages/records/version-upload-state.ts')
assert.equal(/axios|http\.|vue/.test(mod), false, '上传状态保持纯逻辑')
assert.match(mod, /status/)
})