135 lines
5.2 KiB
TypeScript
135 lines
5.2 KiB
TypeScript
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
|
|
import {
|
|
canDownloadItem,
|
|
FILE_PROGRESS_KEYS,
|
|
hasMeaningfulProgress,
|
|
mergeHistoryItemPreservingLiveProgress,
|
|
} from '../src/shared/merge-live-progress.ts'
|
|
|
|
interface HistoryItem {
|
|
taskId: number
|
|
resultId?: number
|
|
fileReady?: boolean
|
|
fileStatus?: string
|
|
fileProgressPercent?: number
|
|
fileProgressCurrent?: number
|
|
fileProgressTotal?: number
|
|
fileProgressMessage?: string
|
|
downloadUrl?: string
|
|
sourceFilename?: string
|
|
}
|
|
|
|
const historyMissingProgress: HistoryItem = {
|
|
taskId: 1,
|
|
resultId: 100,
|
|
fileStatus: 'RUNNING',
|
|
sourceFilename: 'source.xlsx',
|
|
}
|
|
|
|
const liveWithProgress: HistoryItem = {
|
|
taskId: 1,
|
|
resultId: 100,
|
|
fileStatus: 'RUNNING',
|
|
fileProgressPercent: 45,
|
|
fileProgressCurrent: 9,
|
|
fileProgressTotal: 20,
|
|
fileProgressMessage: 'LLM 处理中',
|
|
}
|
|
|
|
test('merge keeps live progress when history missing file progress', () => {
|
|
const merged = mergeHistoryItemPreservingLiveProgress(historyMissingProgress, liveWithProgress)
|
|
assert.equal(merged.fileProgressPercent, 45, 'history 缺失进度时保留 live 的百分比')
|
|
assert.equal(merged.fileProgressCurrent, 9)
|
|
assert.equal(merged.fileProgressTotal, 20)
|
|
assert.equal(merged.fileProgressMessage, 'LLM 处理中')
|
|
assert.equal(merged.sourceFilename, 'source.xlsx', '非进度字段保留 history')
|
|
})
|
|
|
|
test('merge incoming wins when live has progress', () => {
|
|
const history = { ...historyMissingProgress, fileProgressPercent: 10, fileProgressMessage: '旧消息' }
|
|
const merged = mergeHistoryItemPreservingLiveProgress(history, liveWithProgress)
|
|
assert.equal(merged.fileProgressPercent, 45, 'live 有有效进度时以 live 为准')
|
|
assert.equal(merged.fileProgressMessage, 'LLM 处理中')
|
|
})
|
|
|
|
test('merge does not keep live when history is downloadable', () => {
|
|
const history: HistoryItem = {
|
|
taskId: 1,
|
|
resultId: 100,
|
|
fileReady: true,
|
|
fileStatus: 'SUCCESS',
|
|
fileProgressPercent: 100,
|
|
downloadUrl: 'https://dl.example/a.xlsx',
|
|
}
|
|
const merged = mergeHistoryItemPreservingLiveProgress(history, liveWithProgress)
|
|
assert.equal(merged.fileProgressPercent, 100, '可下载时保留 history 的终态进度')
|
|
assert.equal(merged.downloadUrl, 'https://dl.example/a.xlsx')
|
|
assert.equal(merged.fileReady, true)
|
|
})
|
|
|
|
test('merge without live returns history as-is', () => {
|
|
const merged = mergeHistoryItemPreservingLiveProgress(historyMissingProgress, undefined)
|
|
assert.equal(merged, historyMissingProgress, '无 live 时原样返回 history')
|
|
assert.equal(merged.fileProgressPercent, undefined)
|
|
})
|
|
|
|
test('merge partial fields keeps only present live values', () => {
|
|
const live: HistoryItem = { taskId: 1, resultId: 100, fileStatus: 'RUNNING', fileProgressPercent: 30 }
|
|
const merged = mergeHistoryItemPreservingLiveProgress(historyMissingProgress, live)
|
|
assert.equal(merged.fileProgressPercent, 30)
|
|
assert.equal(merged.fileProgressCurrent, undefined, 'live 缺失的字段不写入')
|
|
assert.equal(merged.fileProgressTotal, undefined)
|
|
assert.equal(merged.fileStatus, 'RUNNING')
|
|
})
|
|
|
|
test('merge ignores meaningless progress values', () => {
|
|
assert.equal(hasMeaningfulProgress('fileProgressPercent', 0), false, '0% 不算有效进度')
|
|
assert.equal(hasMeaningfulProgress('fileProgressPercent', -1), false)
|
|
assert.equal(hasMeaningfulProgress('fileProgressPercent', 5), true)
|
|
assert.equal(hasMeaningfulProgress('fileProgressCurrent', 0), true, '0 是合法计数')
|
|
assert.equal(hasMeaningfulProgress('fileProgressMessage', null), false)
|
|
assert.equal(hasMeaningfulProgress('fileProgressMessage', undefined), false)
|
|
|
|
const live: HistoryItem = { taskId: 1, resultId: 100, fileProgressPercent: 0 }
|
|
const merged = mergeHistoryItemPreservingLiveProgress(historyMissingProgress, live)
|
|
assert.equal(merged.fileProgressPercent, undefined, '0% 不覆盖 history')
|
|
})
|
|
|
|
test('merge preserves fileReady flag from live', () => {
|
|
const live: HistoryItem = { taskId: 1, resultId: 100, fileReady: true, fileProgressPercent: 100 }
|
|
const merged = mergeHistoryItemPreservingLiveProgress(historyMissingProgress, live)
|
|
assert.equal(merged.fileReady, true)
|
|
assert.equal(merged.fileProgressPercent, 100)
|
|
})
|
|
|
|
test('merge is idempotent', () => {
|
|
const once = mergeHistoryItemPreservingLiveProgress(historyMissingProgress, liveWithProgress)
|
|
const twice = mergeHistoryItemPreservingLiveProgress(once, liveWithProgress)
|
|
assert.deepEqual(twice, once, '重复合并结果一致')
|
|
})
|
|
|
|
test('file progress keys cover the live progress contract', () => {
|
|
assert.deepEqual(
|
|
[...FILE_PROGRESS_KEYS].sort(),
|
|
[
|
|
'fileProgressCurrent',
|
|
'fileProgressMessage',
|
|
'fileProgressPercent',
|
|
'fileProgressTotal',
|
|
'fileReady',
|
|
'fileStatus',
|
|
].sort(),
|
|
)
|
|
})
|
|
|
|
test('canDownloadItem requires result and ready state', () => {
|
|
assert.equal(canDownloadItem({ resultId: 1, fileReady: true }), true)
|
|
assert.equal(canDownloadItem({ resultId: 1, downloadUrl: 'https://x' }), true)
|
|
assert.equal(canDownloadItem({ resultId: 1 }), false)
|
|
assert.equal(canDownloadItem({ fileReady: true }), false, '无 resultId 不可下载')
|
|
assert.equal(canDownloadItem(null), false)
|
|
assert.equal(canDownloadItem(undefined), false)
|
|
})
|