d2ef1ce4d8
新增 image-video-download.ts(选择键解析/打包请求体/响应头计数/下载 job 状态), image-video-api.ts 增加 requestVideoZipDownload(POST /download-zip, blob)。 TDD: task-106.test.ts 8 用例先 RED 后 GREEN。
75 lines
3.2 KiB
TypeScript
75 lines
3.2 KiB
TypeScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { readSource } from './helpers.ts'
|
|
import {
|
|
createBatchDownloadJob,
|
|
downloadZipHeaderCounts,
|
|
failBatchDownload,
|
|
parseVideoSelectionKey,
|
|
startBatchDownload,
|
|
succeedBatchDownload,
|
|
toVideoZipRequest,
|
|
} from '../src/pages/tasks/image-video-download.ts'
|
|
|
|
test('test_task_106_video_batch_download_normal_primary_path', () => {
|
|
// 正常主路径:选择键解析为 {task_id, video_index} 打包请求体。
|
|
const key = parseVideoSelectionKey('11:2')
|
|
assert.deepEqual(key, { taskId: 11, videoIndex: 2 })
|
|
assert.deepEqual(toVideoZipRequest(['11:2', '7:0']), {
|
|
items: [
|
|
{ task_id: 11, video_index: 2 },
|
|
{ task_id: 7, video_index: 0 },
|
|
],
|
|
})
|
|
})
|
|
|
|
test('test_task_106_video_batch_download_normal_variant_input', () => {
|
|
// 正常变体:job 从 running 到 done 携带成功/失败计数。
|
|
const job = succeedBatchDownload(startBatchDownload(createBatchDownloadJob()), 18, 2)
|
|
assert.equal(job.status, 'done')
|
|
assert.equal(job.fileCount, 18)
|
|
assert.equal(job.errorCount, 2)
|
|
})
|
|
|
|
test('test_task_106_video_batch_download_repeated_is_idempotent', () => {
|
|
// 正常重复:请求体构建稳定、去重键不重复。
|
|
assert.deepEqual(toVideoZipRequest(['1:0', '1:0', '2:1']), { items: [{ task_id: 1, video_index: 0 }, { task_id: 2, video_index: 1 }] })
|
|
})
|
|
|
|
test('test_task_106_video_batch_download_boundary_empty_input', () => {
|
|
// 边界空值:无选择/空任务 id 键被忽略。
|
|
assert.deepEqual(toVideoZipRequest([]), { items: [] })
|
|
assert.equal(parseVideoSelectionKey('9:empty'), null)
|
|
})
|
|
|
|
test('test_task_106_video_batch_download_boundary_single_item', () => {
|
|
// 边界单元素:单键请求体。
|
|
assert.deepEqual(toVideoZipRequest(['5:0']), { items: [{ task_id: 5, video_index: 0 }] })
|
|
assert.deepEqual(createBatchDownloadJob(), { status: 'idle' })
|
|
})
|
|
|
|
test('test_task_106_video_batch_download_boundary_limit_or_missing_field', () => {
|
|
// 边界上限/缺字段:响应头大小写不敏感解析计数。
|
|
assert.deepEqual(downloadZipHeaderCounts({ 'X-Archive-File-Count': '3', 'x-archive-error-count': '1' }), { fileCount: 3, errorCount: 1 })
|
|
assert.deepEqual(downloadZipHeaderCounts({}), {})
|
|
})
|
|
|
|
test('test_task_106_video_batch_download_invalid_input_rejected', () => {
|
|
// 异常输入:失败 job 带可操作消息;非数字头忽略。
|
|
const job = failBatchDownload(createBatchDownloadJob(), '单次最多打包 100 个视频')
|
|
assert.equal(job.status, 'failed')
|
|
assert.equal(job.message, '单次最多打包 100 个视频')
|
|
assert.deepEqual(downloadZipHeaderCounts({ 'x-archive-file-count': 'abc' }), {})
|
|
assert.equal(parseVideoSelectionKey('bad'), null)
|
|
})
|
|
|
|
test('test_task_106_video_batch_download_dependency_failure_returns_actionable_message', () => {
|
|
// 依赖失败/下载走 adapter:打包模型纯逻辑;adapter POST /download-zip + blob。
|
|
const model = readSource('src/pages/tasks/image-video-download.ts')
|
|
assert.equal(/axios|http\.|vue/.test(model), false, '批量下载模型保持纯逻辑')
|
|
const api = readSource('src/pages/tasks/image-video-api.ts')
|
|
assert.match(api, /download-zip/)
|
|
assert.match(api, /requestVideoZipDownload/)
|
|
assert.match(api, /responseType:\s*['\"]blob['\"]/)
|
|
})
|