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()') })