Files
crawler-plugin/admin-frontend-vue/tests/task-101.test.ts
T
huangzd1997 a877488f8f task-101(任务与重复分析中心): 定义统一任务状态和结果文件类型
新增 src/pages/tasks/task-model.ts:TaskStatus 归一(含同义词/终态判定)、
TaskId/ResultId 字符串兼容品牌类型与 ResultFileDescriptor 解析(snake/camel)。

TDD: task-101.test.ts 8 用例先 RED 后 GREEN。
2026-09-05 17:01:08 +08:00

87 lines
3.5 KiB
TypeScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readSource } from './helpers.ts'
import {
isTerminalTaskStatus,
normalizeResultFile,
normalizeTaskStatus,
toResultId,
toTaskId,
} from '../src/pages/tasks/task-model.ts'
test('test_task_101_task_types_normal_primary_path', () => {
// 正常主路径:任务/结果 id 归一与结果文件解析(蛇形 payload)为类型化描述。
assert.equal(normalizeTaskStatus('SUCCESS'), 'SUCCESS')
assert.equal(toResultId(123), '123')
const file = normalizeResultFile({
result_id: 123,
output_filename: 'shop_data_DE.xlsx',
file_url: 'https://oss.aishufu.top/shop_data_DE.xlsx',
file_size: 2048,
status: 'SUCCESS',
})
assert.ok(file)
assert.equal(file!.resultId, '123')
assert.equal(file!.filename, 'shop_data_DE.xlsx')
assert.equal(file!.url, 'https://oss.aishufu.top/shop_data_DE.xlsx')
assert.equal(file!.size, 2048)
assert.equal(file!.status, 'SUCCESS')
})
test('test_task_101_task_types_normal_variant_input', () => {
// 正常变体:camel payload 与状态同义词归一。
const file = normalizeResultFile({ resultId: 9, filename: 'a.zip', fileUrl: 'http://x/a.zip', status: 'completed' })
assert.ok(file)
assert.equal(file!.status, 'SUCCESS')
assert.equal(normalizeTaskStatus('done'), 'SUCCESS')
assert.equal(normalizeTaskStatus('running'), 'RUNNING')
assert.equal(toTaskId('task-7'), 'task-7')
})
test('test_task_101_task_types_repeated_is_idempotent', () => {
// 正常重复:归一稳定、不改输入。
const raw = { result_id: 2, filename: 'b', status: 'pending' }
assert.deepEqual(normalizeResultFile(raw), normalizeResultFile(raw))
assert.deepEqual(raw, { result_id: 2, filename: 'b', status: 'pending' })
assert.equal(normalizeTaskStatus('SUCCESS'), normalizeTaskStatus('success'))
})
test('test_task_101_task_types_boundary_empty_input', () => {
// 边界空值:缺 id/文件名视为无效描述。
assert.equal(normalizeResultFile(null), null)
assert.equal(normalizeResultFile({ filename: 'no-id' }), null)
})
test('test_task_101_task_types_boundary_single_item', () => {
// 边界单元素:单条描述字段完整;未知状态归 UNKNOWN。
const file = normalizeResultFile({ result_id: 1, filename: 'f', url: 'http://u', status: 'weird' })
assert.ok(file)
assert.equal(file!.status, 'UNKNOWN')
})
test('test_task_101_task_types_boundary_limit_or_missing_field', () => {
// 边界上限/缺字段:可选 size/error 缺省可空。
const file = normalizeResultFile({ result_id: 4, filename: 'g', fileUrl: 'http://u/g' })
assert.ok(file)
assert.equal(file!.size, undefined)
assert.equal(file!.error, undefined)
assert.equal(file!.url, 'http://u/g')
})
test('test_task_101_task_types_invalid_input_rejected', () => {
// 异常输入:空白/非法 id 与未知状态被拒绝或归 UNKNOWN。
assert.equal(normalizeResultFile({ result_id: '', filename: 'x' }), null)
assert.equal(toResultId(''), '')
assert.equal(isTerminalTaskStatus('SUCCESS'), true)
assert.equal(isTerminalTaskStatus('RUNNING'), false)
assert.equal(isTerminalTaskStatus('CANCELLED'), true)
})
test('test_task_101_task_types_dependency_failure_returns_actionable_message', () => {
// 依赖失败/可操作:类型模块纯逻辑、无框架/http。
const mod = readSource('src/pages/tasks/task-model.ts')
assert.equal(/axios|http\.|vue/.test(mod), false, '任务类型保持纯逻辑')
assert.match(mod, /ResultFileDescriptor/)
assert.match(mod, /ResultId/)
})