45a8161bb2
menu-manage-model.ts 增 menuFormFromNode 回填 + menuParentChangeReason 防环(自身/子孙不可为父);
menu-manage-api.ts 增 updateMenu PUT /api/admin/permission-menus/{id};MenusPage 行内编辑复用
Dialog(新增/编辑切换)校验后提交并刷新。8 用例全过,411 单测 + build 绿。
89 lines
3.9 KiB
TypeScript
89 lines
3.9 KiB
TypeScript
import test from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import { readSource } from './helpers.ts'
|
||
import {
|
||
buildMenuManageTree,
|
||
menuFormFromNode,
|
||
menuParentChangeReason,
|
||
parseMenuManageList,
|
||
toMenuUpdateRequest,
|
||
} from '../src/pages/account/menu-manage-model.ts'
|
||
|
||
test('test_task_056_menu_edit_form_normal_primary_path', () => {
|
||
// 正常主路径:从节点回填可编辑表单(含 parentId/routePath/sort)。
|
||
const node = parseMenuManageList([
|
||
{ id: 4, name: '用户管理', column_key: 'account_users', parent_id: 1, route_path: '/account/users', sort_order: 2, menu_type: 'admin' },
|
||
])[0]
|
||
const form = menuFormFromNode(node)
|
||
assert.equal(form.name, '用户管理')
|
||
assert.equal(form.columnKey, 'account_users')
|
||
assert.equal(form.parentId, 1)
|
||
assert.equal(form.routePath, '/account/users')
|
||
assert.equal(form.sortOrder, 2)
|
||
})
|
||
|
||
test('test_task_056_menu_edit_form_normal_variant_input', () => {
|
||
// 正常变体:根节点回填 parentId=null;序列化到 update 请求体字段对齐。
|
||
const node = parseMenuManageList([{ id: 1, name: '账号', column_key: 'account', parent_id: null, sort_order: 0 }])[0]
|
||
const form = menuFormFromNode(node)
|
||
assert.equal(form.parentId, null)
|
||
assert.deepEqual(toMenuUpdateRequest(form).columnKey, 'account')
|
||
})
|
||
|
||
test('test_task_056_menu_edit_form_normal_repeated_operation_is_idempotent', () => {
|
||
// 正常重复:回填不改节点、结果稳定。
|
||
const node = parseMenuManageList([{ id: 5, name: 'A', column_key: 'a', parent_id: null, sort_order: 1 }])[0]
|
||
assert.deepEqual(menuFormFromNode(node), menuFormFromNode(node))
|
||
assert.equal(node.name, 'A')
|
||
})
|
||
|
||
test('test_task_056_menu_edit_form_boundary_empty_input', () => {
|
||
// 边界空值:仅 id+name 节点回填,其余字段给默认,不崩溃。
|
||
const node = parseMenuManageList([{ id: 7, name: 'Only' }])[0]
|
||
const form = menuFormFromNode(node)
|
||
assert.equal(form.columnKey, '')
|
||
assert.equal(form.routePath, '')
|
||
assert.equal(form.sortOrder, 0)
|
||
})
|
||
|
||
test('test_task_056_menu_edit_form_boundary_single_item', () => {
|
||
// 边界单元素:单根节点可安全改父为根(null)。
|
||
const node = parseMenuManageList([{ id: 9, name: 'Only', column_key: 'only', parent_id: null }])[0]
|
||
assert.equal(menuParentChangeReason(node, null), undefined)
|
||
})
|
||
|
||
test('test_task_056_menu_edit_form_boundary_limit_or_missing_field', () => {
|
||
// 边界上限/越权父:不能把自身/子孙设为父(防环)。
|
||
const tree = buildMenuManageTree(
|
||
parseMenuManageList([
|
||
{ id: 1, name: '根', column_key: 'root', parent_id: null },
|
||
{ id: 2, name: '子', column_key: 'sub', parent_id: 1 },
|
||
{ id: 3, name: '孙', column_key: 'leaf', parent_id: 2 },
|
||
]),
|
||
)
|
||
const root = tree[0]
|
||
const sub = root.children?.[0]!
|
||
const leaf = sub.children?.[0]!
|
||
assert.match(menuParentChangeReason(sub, sub.id) || '', /自身/)
|
||
assert.match(menuParentChangeReason(root, leaf.id) || '', /子菜单/)
|
||
})
|
||
|
||
test('test_task_056_menu_edit_form_invalid_input_rejected', () => {
|
||
// 异常输入:父选自身/子孙被拒;换父到合法节点(自身父=1)允许。
|
||
const node = parseMenuManageList([{ id: 1, name: 'A', column_key: 'a', parent_id: null }])[0]
|
||
assert.ok(menuParentChangeReason(node, 1))
|
||
assert.equal(menuParentChangeReason(node, 99), undefined)
|
||
})
|
||
|
||
test('test_task_056_menu_edit_form_dependency_failure_returns_actionable_message', () => {
|
||
// 依赖失败/编辑走 adapter:PUT permission-menus/{id},页面用 updateMenu + 回填 + 防环校验。
|
||
const api = readSource('src/pages/account/menu-manage-api.ts')
|
||
assert.match(api, /updateMenu/)
|
||
assert.match(api, /http\.put/)
|
||
assert.match(api, /permission-menus/)
|
||
const page = readSource('src/pages/account/MenusPage.vue')
|
||
assert.match(page, /updateMenu/)
|
||
assert.match(page, /menuFormFromNode|menuParentChangeReason/)
|
||
assert.equal(/http\.(get|post|put)|unwrap\(/.test(page), false, '页面不内联请求')
|
||
})
|