Files
crawler-plugin/admin-frontend-vue/tests/task-38.test.ts
T

68 lines
3.4 KiB
TypeScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readSource } from './helpers.ts'
import { parseMenuTree } from '../src/api/session-model.ts'
import { toSidebarEntries } from '../src/layout/menu-mapper.ts'
test('test_task_038_menu_sort_and_empty_route_normal_primary_path', () => {
// 正常主路径:前端保后端顺序,不按 sort 二次重排。
const payload = { data: { items: [
{ key: 'b', name: '乙', route: '/b', sort: 1 },
{ key: 'a', name: '甲', route: '/a', sort: 0 },
] } }
const tree = parseMenuTree(payload)
assert.equal(tree[0].key, 'b', '先出现者排前,不按 sort 值重排')
})
test('test_task_038_menu_sort_and_empty_route_normal_variant_input', () => {
// 正常变体:分组(无 route) 下带 route 的子页正常进分组。
const tree = parseMenuTree({ items: [{ key: 'g', name: '组', route: undefined, children: [{ key: 'p', name: '页', route: '/p' }] }] })
const entries = toSidebarEntries(tree)
assert.equal(entries[0].kind, 'group')
})
test('test_task_038_menu_sort_and_empty_route_normal_repeated_operation_is_idempotent', () => {
// 正常重复:排序稳定、解析不修改输入。
const payload = { items: [{ key: 'a', name: 'A', route: '/a', sort: 2 }] }
assert.deepEqual(parseMenuTree(payload), parseMenuTree(payload))
assert.equal((payload.items as Array<{ sort: number }>)[0].sort, 2)
})
test('test_task_038_menu_sort_and_empty_route_boundary_empty_input', () => {
// 边界空值:无路由的子节点被侧边栏过滤(点不进去不展示)。
const entries = toSidebarEntries([{ key: 'g', name: '组', children: [{ key: 'p', name: '页' }] }])
assert.equal(entries.length, 0, '组内无任何可路由子项则整组不展示')
})
test('test_task_038_menu_sort_and_empty_route_boundary_single_item', () => {
// 边界单元素:顶级无子但有 route 的叶节点作为单页项展示。
const entries = toSidebarEntries([{ key: 's', name: '单页', route: '/solo' }])
assert.equal(entries.length, 1)
assert.equal(entries[0].kind, 'item')
})
test('test_task_038_menu_sort_and_empty_route_boundary_limit_or_missing_field', () => {
// 边界上限/缺字段:既有可路由子项又有不可路由子项时只保留可路由子项。
const entries = toSidebarEntries([{ key: 'g', name: '组', children: [
{ key: 'ok', name: '可进', route: '/ok' },
{ key: 'bad', name: '占位' },
] }])
assert.equal(entries[0].kind, 'group')
if (entries[0].kind === 'group') assert.equal(entries[0].children.length, 1)
})
test('test_task_038_menu_sort_and_empty_route_invalid_input_rejected', () => {
// 异常输入:整树失败信封抛错而非空树;空路由不是合法的页面进入理由。
assert.throws(() => parseMenuTree({ success: false, message: '菜单失败' }), /菜单失败/)
const tree = parseMenuTree({ items: [{ key: 'p', name: '页' }] })
assert.equal(toSidebarEntries(tree).length, 0, '无 route 的顶级节点不进侧边栏')
})
test('test_task_038_menu_sort_and_empty_route_dependency_failure_returns_actionable_message', () => {
// 依赖失败:store/路由保存菜单后不二次排序(按后端下发顺序渲染)。
const store = readSource('src/stores/admin-session.ts')
assert.equal(/\bsort\(\)/.test(store), false, 'store 不对菜单树调用 sort()')
const helpers = readSource('src/router/helpers.ts')
assert.equal(/\bsort\(\)/.test(helpers), false, 'helpers 不对菜单树调用 sort()')
})