import { test } from 'node:test' import assert from 'node:assert/strict' import { classifyTargetVersion, describeTargetVersion, parseVersionList, } from '../src/shared/utils/version-picker.ts' /** /api/version/list 响应样例:接口按 created_at DESC 返回(旧版本重传会排最前) */ function listResponse(items: Array>) { return { items } } test('版本列表解析:同一版本重复上传只保留先出现(最新)的一条记录', () => { const items = parseVersionList(listResponse([ { id: 9, version: '4.0.13', file_url: 'https://oss/4.0.13-new.zip', created_at: '2026-09-14 10:00' }, { id: 5, version: '4.0.14', file_url: 'https://oss/4.0.14.zip', created_at: '2026-09-14 09:00' }, { id: 2, version: '4.0.13', file_url: 'https://oss/4.0.13-old.zip', created_at: '2026-09-13 10:00' }, ])) assert.equal(items.length, 2) const reuploaded = items.find((item) => item.version === '4.0.13') assert.equal(reuploaded?.fileUrl, 'https://oss/4.0.13-new.zip', '同版本应取最新上传的包') }) test('版本列表解析:无下载地址或空版本号的行被丢弃(选了也装不了)', () => { const items = parseVersionList(listResponse([ { id: 1, version: '4.0.14', file_url: 'https://oss/4.0.14.zip', created_at: '2026-09-14 10:36' }, { id: 2, version: '4.0.13', file_url: '', created_at: '2026-09-13 20:00' }, { id: 3, version: ' ', file_url: 'https://oss/blank.zip', created_at: '2026-09-13 19:00' }, { id: 4, version: null, file_url: 'https://oss/null.zip', created_at: '2026-09-13 18:00' }, null, 'not-an-object', ])) assert.deepEqual(items.map((item) => item.version), ['4.0.14']) }) test('版本列表解析:按版本号从高到低排序,旧版本重传不会排到最前', () => { const items = parseVersionList(listResponse([ // 旧版本刚重传:created_at 最新,但版本号最低 { id: 30, version: '4.0.9', file_url: 'https://oss/4.0.9.zip', created_at: '2026-09-14 11:00' }, { id: 29, version: '4.0.14', file_url: 'https://oss/4.0.14.zip', created_at: '2026-09-14 10:00' }, { id: 28, version: '4.0.13', file_url: 'https://oss/4.0.13.zip', created_at: '2026-09-13 20:00' }, ])) assert.deepEqual(items.map((item) => item.version), ['4.0.14', '4.0.13', '4.0.9']) }) test('版本列表解析:兼容驼峰字段、v 前缀与空/异常响应', () => { const items = parseVersionList(listResponse([ { id: 1, version: 'v4.0.14', fileUrl: 'https://oss/4.0.14.zip', createdAt: '2026-09-14 10:36' }, ])) assert.deepEqual(items, [ { id: 1, version: '4.0.14', fileUrl: 'https://oss/4.0.14.zip', createdAt: '2026-09-14 10:36' }, ]) assert.deepEqual(parseVersionList(null), []) assert.deepEqual(parseVersionList({}), []) assert.deepEqual(parseVersionList({ items: 'oops' }), []) }) test('目标版本判定:高于本机=更新,相等=同版,低于本机=回退', () => { assert.equal(classifyTargetVersion('4.0.12', '4.0.14'), 'newer') assert.equal(classifyTargetVersion('4.0.14', '4.0.14'), 'same') assert.equal(classifyTargetVersion('4.0.14', '4.0.13'), 'older') // 多段补零后仍相等 assert.equal(classifyTargetVersion('4.0.14', '4.0.14.0'), 'same') }) test('目标版本判定:本机版本未知时返回 unknown,不误判为升级', () => { assert.equal(classifyTargetVersion('', '4.0.14'), 'unknown') assert.equal(classifyTargetVersion(undefined as unknown as string, '4.0.14'), 'unknown') assert.equal(classifyTargetVersion('4.0.14', ''), 'unknown') }) test('回退文案必须写明低于当前版本(回退是显式操作,不得静默降级)', () => { const text = describeTargetVersion('older', '4.0.14', '4.0.13') assert.ok(text.includes('4.0.13'), '文案要带目标版本号') assert.ok(text.includes('低于当前版本'), '回退必须明确提示低于本机版本') assert.ok(text.includes('4.0.14'), '文案要带本机版本号') }) test('同版与更新文案各自说明动作,本机版本未知时如实说明无法比较', () => { assert.ok(describeTargetVersion('same', '4.0.14', '4.0.14').includes('与当前版本相同')) const newer = describeTargetVersion('newer', '4.0.12', '4.0.14') assert.ok(newer.includes('4.0.12') && newer.includes('4.0.14')) assert.ok(describeTargetVersion('unknown', '', '4.0.14').includes('未读到本机版本')) })