mirror of
https://github.com/truewhile/MeBox.git
synced 2026-11-16 04:44:23 +08:00
优化
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import {
|
||||
ALL_GROUP_ID,
|
||||
UNGROUPED_GROUP_ID,
|
||||
attachBookToGroup,
|
||||
buildBookGroupTabs,
|
||||
dedupeBookGroups,
|
||||
detachBooksFromGroup,
|
||||
filterBooksByGroup,
|
||||
groupIdOfBook,
|
||||
normalizeBookGroups,
|
||||
reorderBookGroups,
|
||||
resolveSelectedGroupId,
|
||||
} from './readerBookGroups'
|
||||
|
||||
// 书架分组的纯逻辑回归测试(对齐 utils/libraryTags.test.ts 的写法)。
|
||||
|
||||
function check(name: string, condition: boolean) {
|
||||
if (!condition) throw new Error(`readerBookGroups: ${name}`)
|
||||
}
|
||||
|
||||
const book = (id: string) => ({ id })
|
||||
|
||||
// ── 清洗 ──
|
||||
check('non-array → empty', normalizeBookGroups(null).length === 0)
|
||||
check('blank name dropped', normalizeBookGroups([{ name: ' ', book_ids: ['a'] }]).length === 0)
|
||||
check('name trimmed and ids deduped', (() => {
|
||||
const got = normalizeBookGroups([{ name: ' 科幻 ', book_ids: ['a', '', 'a', 'b'] }])
|
||||
return got.length === 1 && got[0].name === '科幻' && got[0].book_ids.join(',') === 'a,b'
|
||||
})())
|
||||
check('same name (case-insensitive) merged', (() => {
|
||||
const got = normalizeBookGroups([
|
||||
{ name: 'SciFi', book_ids: ['a'] },
|
||||
{ name: 'scifi', book_ids: ['b'] },
|
||||
])
|
||||
return got.length === 1 && got[0].book_ids.join(',') === 'a,b'
|
||||
})())
|
||||
|
||||
// ── 一书一组 ──
|
||||
const claimed = dedupeBookGroups([
|
||||
{ name: '一', book_ids: ['a', 'b'] },
|
||||
{ name: '二', book_ids: ['b', 'c'] },
|
||||
{ name: '三', book_ids: ['c'] },
|
||||
])
|
||||
check('dedupe keeps first claim', claimed[0].book_ids.join(',') === 'a,b')
|
||||
// 二 原本 [b,c]:b 被 一 抢走后仍留住 c;三 的 [c] 已被 二 认领,因此变空
|
||||
check('dedupe keeps the still-unclaimed member', claimed[1].book_ids.join(',') === 'c')
|
||||
check('dedupe empties the group whose books were all claimed', claimed[2].book_ids.length === 0)
|
||||
|
||||
// ── 过滤 ──
|
||||
const books = [book('a'), book('b'), book('c'), book('d')]
|
||||
const groups = [{ name: '科幻', book_ids: ['a', 'b'] }, { name: '在读', book_ids: ['c'] }]
|
||||
const ids = (list: { id: string }[]) => list.map((x) => x.id).join(',')
|
||||
|
||||
check('ALL returns everything', ids(filterBooksByGroup(books, groups, ALL_GROUP_ID)) === 'a,b,c,d')
|
||||
check('empty id behaves like ALL', ids(filterBooksByGroup(books, groups, '')) === 'a,b,c,d')
|
||||
check('group filter keeps members in input order', ids(filterBooksByGroup(books, groups, '科幻')) === 'a,b')
|
||||
check('unknown group → empty', filterBooksByGroup(books, groups, '不存在').length === 0)
|
||||
check('ungrouped returns unclaimed books', ids(filterBooksByGroup(books, groups, UNGROUPED_GROUP_ID)) === 'd')
|
||||
check('stale ids in a group are ignored', (() => {
|
||||
const withStale = [{ name: '科幻', book_ids: ['a', 'ghost'] }]
|
||||
return ids(filterBooksByGroup(books, withStale, '科幻')) === 'a'
|
||||
})())
|
||||
|
||||
// ── 分组栏 ──
|
||||
const noGroups = buildBookGroupTabs(books, [])
|
||||
check('no groups → only 全部', noGroups.length === 1 && noGroups[0].id === ALL_GROUP_ID && noGroups[0].count === 4)
|
||||
|
||||
const tabs = buildBookGroupTabs(books, groups)
|
||||
check('tabs = 全部 + 未分组 + groups', tabs.map((t) => t.name).join(',') === '全部,未分组,科幻,在读')
|
||||
check('全部 counts all books', tabs[0].count === 4)
|
||||
check('未分组 counts unclaimed', tabs[1].count === 1)
|
||||
check('group counts only existing books', tabs[2].count === 2 && tabs[3].count === 1)
|
||||
check('stale ids do not inflate counts', (() => {
|
||||
const withStale = buildBookGroupTabs(books, [{ name: '科幻', book_ids: ['a', 'ghost', 'ghost2'] }])
|
||||
return withStale[2].count === 1 && withStale[1].count === 3
|
||||
})())
|
||||
|
||||
// ── 排序与选中回落 ──
|
||||
check(
|
||||
'reorder follows the given order',
|
||||
reorderBookGroups(groups, ['在读', '科幻']).map((g) => g.name).join(',') === '在读,科幻',
|
||||
)
|
||||
check(
|
||||
'reorder appends unknown names (never drops)',
|
||||
reorderBookGroups(groups, ['在读']).map((g) => g.name).join(',') === '在读,科幻',
|
||||
)
|
||||
check('selected group falls back to ALL when removed', resolveSelectedGroupId(groups, '已删除') === ALL_GROUP_ID)
|
||||
check('selected group kept when it exists', resolveSelectedGroupId(groups, '科幻') === '科幻')
|
||||
check('ungrouped selection is preserved', resolveSelectedGroupId(groups, UNGROUPED_GROUP_ID) === UNGROUPED_GROUP_ID)
|
||||
|
||||
// ── 归组 ──
|
||||
const moved = attachBookToGroup(groups, 'c', '科幻')
|
||||
check('attach moves the book out of its old group', moved[1].book_ids.length === 0)
|
||||
check('attach appends to the target group', moved[0].book_ids.join(',') === 'a,b,c')
|
||||
check('attach to unknown group is a no-op', attachBookToGroup(groups, 'c', '不存在') === groups)
|
||||
check('detach returns the book to ungrouped', detachBooksFromGroup(groups, ['a'])[0].book_ids.join(',') === 'b')
|
||||
check('groupIdOfBook finds the owner', groupIdOfBook(groups, 'c') === '在读' && groupIdOfBook(groups, 'd') === '')
|
||||
|
||||
console.log('readerBookGroups.test.ts ok')
|
||||
Reference in New Issue
Block a user