Files

88 lines
3.8 KiB
TypeScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readSource } from './helpers.ts'
import {
MENU_TYPE_OPTIONS,
menuParentCandidates,
menuSiblingGroupKey,
menuTypeLabel,
siblingOrderAfterDrop,
toMenuReorderRequest,
type MenuManageNode,
} from '../src/pages/account/menu-manage-model.ts'
/** 对齐 admin.js:6799-6830(全量列/类型文案 后台|软件)与 6882-6964(同级拖拽 + reorder 载荷)。 */
function node(id: number, menuType = 'admin', parentId: number | null = null): MenuManageNode {
return { id, name: `菜单${id}`, columnKey: `k${id}`, parentId, menuType, routePath: `/r/${id}`, sortOrder: id }
}
test('align_menu_type_label_matches_reference', () => {
// 参考:admin → 后台,其余一律 → 软件(含空值)。
assert.equal(menuTypeLabel('admin'), '后台')
assert.equal(menuTypeLabel('app'), '软件')
assert.equal(menuTypeLabel('APP'), '软件')
assert.equal(menuTypeLabel(null), '软件')
assert.equal(menuTypeLabel(undefined), '软件')
})
test('align_menu_type_options_backend_software', () => {
assert.deepEqual(MENU_TYPE_OPTIONS, [
{ value: 'admin', label: '后台' },
{ value: 'app', label: '软件' },
])
})
test('align_menu_sibling_group_key_is_type_plus_parent', () => {
assert.equal(menuSiblingGroupKey(node(1, 'admin', 5)), 'admin|5')
assert.equal(menuSiblingGroupKey(node(2, 'app', null)), 'app|')
assert.equal(menuSiblingGroupKey(node(3, 'app', 5)), 'app|5')
})
test('align_menu_sibling_order_after_drop_before_target', () => {
const group = [1, 2, 3, 4]
assert.deepEqual(siblingOrderAfterDrop(group, 4, 2, false), [1, 4, 2, 3])
})
test('align_menu_sibling_order_after_drop_after_target', () => {
const group = [1, 2, 3, 4]
assert.deepEqual(siblingOrderAfterDrop(group, 4, 2, true), [1, 2, 4, 3])
})
test('align_menu_sibling_order_after_drop_invalid_returns_original', () => {
const group = [1, 2, 3]
assert.deepEqual(siblingOrderAfterDrop(group, 9, 2, false), group)
assert.deepEqual(siblingOrderAfterDrop(group, 1, 9, true), group)
assert.deepEqual(siblingOrderAfterDrop(group, 2, 2, false), group)
assert.deepEqual(siblingOrderAfterDrop([], 1, 2, false), [])
})
test('align_menu_parent_candidates_same_type_only', () => {
const nodes = [node(1, 'admin', null), node(2, 'app', null), node(3, 'admin', 1), node(4, 'app', 2)]
assert.deepEqual(menuParentCandidates(nodes, 'admin').map((n) => n.id), [1, 3])
assert.deepEqual(menuParentCandidates(nodes, 'app').map((n) => n.id), [2, 4])
})
test('align_menu_reorder_request_includes_menu_type', () => {
// 参考 persistColumnOrder 载荷:{ menu_type, ordered_ids }。
assert.deepEqual(toMenuReorderRequest('admin', [1, 2, 3]), { menu_type: 'admin', ordered_ids: [1, 2, 3] })
assert.deepEqual(toMenuReorderRequest('', [1]), { menu_type: 'app', ordered_ids: [1] })
})
test('align_menu_list_loads_all_types_no_filter', () => {
// 参考 loadColumns 拉全量列(无 menuType 过滤),类型由列内区分。
const api = readSource('src/pages/account/menu-manage-api.ts')
assert.doesNotMatch(api, /params:\s*\{\s*menuType/, '列表请求不再按 admin 过滤')
assert.match(api, /ordered_ids/, '重排载荷带 ordered_ids')
assert.match(api, /menu_type/, '重排载荷带 menu_type')
})
test('align_menu_page_drag_and_type_wiring', () => {
const page = readSource('src/pages/account/MenusPage.vue')
assert.match(page, /拖动每行左侧的手柄可调整同级菜单的显示顺序,松开后自动保存/, '顶部拖拽提示文案对齐')
assert.match(page, /draggable/, '行手柄可拖拽')
assert.match(page, /menuSiblingGroupKey/, '拖拽分组按类型+父级')
assert.match(page, /MENU_TYPE_OPTIONS|菜单类型/, '新建/编辑弹窗含菜单类型下拉')
assert.match(page, /menuParentCandidates/, '父菜单候选按类型过滤')
})