Files
huangzd1997 d189d94c3b fix(更新日志): 面板随指定版本下拉联动;本机已是最新时展示本机条目
- 「指定版本更新」下拉选中版本时日志切到该版本自身的条目(升级/回退统一语义),
  未收录显示"暂无更新说明"(区块不消失),选回空项回默认区间;
  列表加载后自动默认选中第一条不触发切换
- 本机版本==线上最新时回退显示本机版本条目(原来整块消失),灰度/回滚仍隐藏
- 精简 4.0.20/4.0.21 超长文案,修复既有红测试(更新说明限 40 字)
2026-09-16 01:02:13 +08:00

172 lines
6.7 KiB
TypeScript

import { test } from 'node:test'
import assert from 'node:assert/strict'
import {
CLIENT_CHANGELOG,
newestChangelogVersion,
selectChangelogEntries,
selectVersionEntry,
type ClientChangelogEntry,
} from '../src/shared/client-changelog.ts'
const FIXTURE: ClientChangelogEntry[] = [
{ version: '4.1.0', date: '2026-09-20', items: ['新功能甲'] },
{ version: '4.0.11', date: '2026-09-13', items: ['修复乙'] },
{ version: '4.0.9', date: '2026-09-13', items: ['修复丙'] },
{ version: '4.0.4', date: '2026-09-13', items: ['修复丁'] },
]
test('更新日志:数据文件新版本在前且版本号唯一', () => {
const versions = CLIENT_CHANGELOG.map((entry) => entry.version)
assert.ok(versions.length > 0, '更新日志不应为空')
assert.deepEqual(
versions,
[...new Set(versions)],
'版本号不得重复(重复会让面板出现两条同名记录)',
)
const sorted = [...versions].sort((a, b) => {
const pa = a.split('.').map(Number)
const pb = b.split('.').map(Number)
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
const diff = (pa[i] ?? 0) - (pb[i] ?? 0)
if (diff !== 0) return diff
}
return 0
})
assert.deepEqual(versions, sorted.reverse(), '更新日志应按版本号从新到旧排列')
})
test('更新日志:每条都有日期与面向用户的说明', () => {
for (const entry of CLIENT_CHANGELOG) {
assert.match(entry.version, /^\d+(\.\d+)+$/, `版本号格式异常:${entry.version}`)
assert.match(entry.date, /^\d{4}-\d{2}-\d{2}$/, `日期格式异常:${entry.version}`)
assert.ok(entry.items.length > 0, `缺少更新说明:${entry.version}`)
for (const item of entry.items) {
assert.ok(item.trim().length > 0, `更新说明为空:${entry.version}`)
assert.ok(item.length <= 40, `更新说明过长(面板放不下,需精简):${entry.version} -> ${item}`)
}
}
})
test('更新日志:最新版本号取数据文件第一条', () => {
assert.equal(newestChangelogVersion(FIXTURE), '4.1.0')
assert.equal(newestChangelogVersion([]), '')
})
test('更新日志:只给本机版本之后的条目,新版本在前', () => {
const entries = selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.0.11', latestVersion: '4.1.0' })
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0'])
})
test('更新日志:落后多个版本时逐版本列出(含中间版本)', () => {
const entries = selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.0.4', latestVersion: '4.1.0' })
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0', '4.0.11', '4.0.9'])
})
test('更新日志:已是最新版本且不带 includeCurrent 时没有条目(确认框语义)', () => {
assert.deepEqual(
selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.0.11', latestVersion: '4.0.11' }),
[],
)
})
test('更新日志:面板展示(includeCurrent)在本机已是最新时给出本机版本条目', () => {
const entries = selectChangelogEntries({
entries: FIXTURE,
currentVersion: '4.0.11',
latestVersion: '4.0.11',
includeCurrent: true,
})
assert.deepEqual(entries.map((entry) => entry.version), ['4.0.11'])
})
test('更新日志:面板展示在有更新时行为不变(只给本机之后的条目)', () => {
const entries = selectChangelogEntries({
entries: FIXTURE,
currentVersion: '4.0.11',
latestVersion: '4.1.0',
includeCurrent: true,
})
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0'])
})
test('更新日志:面板展示在本机高于线上(灰度/回滚)时仍不列条目', () => {
assert.deepEqual(
selectChangelogEntries({
entries: FIXTURE,
currentVersion: '4.1.0',
latestVersion: '4.0.11',
includeCurrent: true,
}),
[],
)
})
test('更新日志:面板展示在本机版本未被收录时不倒推旧条目', () => {
assert.deepEqual(
selectChangelogEntries({
entries: FIXTURE,
currentVersion: '4.0.10',
latestVersion: '4.0.10',
includeCurrent: true,
}),
[],
)
})
test('更新日志:本机版本高于线上(灰度/回滚)不列条目', () => {
assert.deepEqual(
selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.1.0', latestVersion: '4.0.11' }),
[],
)
})
test('更新日志:线上已发布但日志未收录的新版本不误报旧条目', () => {
const entries = selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.1.0', latestVersion: '4.2.0' })
assert.deepEqual(entries, [], '没有对应版本条目不倒推历史,避免把已装过的改动当成新内容')
})
test('更新日志:拿不到本机版本(旧客户端)时只给最新一条', () => {
const entries = selectChangelogEntries({ entries: FIXTURE, currentVersion: '', latestVersion: '4.1.0' })
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0'])
})
test('更新日志:检测未完成(线上版本为空)时按数据文件最新版本兜底', () => {
const entries = selectChangelogEntries({ entries: FIXTURE, currentVersion: '4.0.4', latestVersion: '' })
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0', '4.0.11', '4.0.9'])
})
test('更新日志:两边版本都拿不到时给数据文件最新一条', () => {
const entries = selectChangelogEntries({ entries: FIXTURE })
assert.deepEqual(entries.map((entry) => entry.version), ['4.1.0'])
})
test('更新日志:空数据不报错', () => {
assert.deepEqual(selectChangelogEntries({ entries: [], currentVersion: '4.0.4' }), [])
})
test('更新日志:版本号前缀 v 不影响筛选', () => {
const entries = selectChangelogEntries({ entries: FIXTURE, currentVersion: 'v4.0.4', latestVersion: 'v4.0.11' })
assert.deepEqual(entries.map((entry) => entry.version), ['4.0.11', '4.0.9'])
})
test('指定版本日志:取选中版本自身的条目(升级/回退/同版统一语义)', () => {
assert.deepEqual(
selectVersionEntry('4.0.9', FIXTURE).map((entry) => entry.version),
['4.0.9'],
'回退到旧版本时也要能看到该版本的更新说明',
)
assert.deepEqual(selectVersionEntry('4.1.0', FIXTURE).map((entry) => entry.version), ['4.1.0'])
})
test('指定版本日志:v 前缀与版本号为空', () => {
assert.deepEqual(selectVersionEntry('v4.0.11', FIXTURE).map((entry) => entry.version), ['4.0.11'])
assert.deepEqual(selectVersionEntry('', FIXTURE), [])
assert.deepEqual(selectVersionEntry('v', FIXTURE), [])
})
test('指定版本日志:未收录的版本不倒推相邻条目', () => {
assert.deepEqual(selectVersionEntry('4.0.10', FIXTURE), [], '4.0.10 未收录,不能拿 4.0.9 的说明顶替')
assert.deepEqual(selectVersionEntry('4.2.0', FIXTURE), [])
})