import test from 'node:test' import assert from 'node:assert/strict' import { readSource } from './helpers.ts' import { ADMIN_MENU_TYPE, APP_MENU_TYPE, parseMenuOptionList, parsePermissionMenuItem, } from '../src/pages/account/user-menu-auth.ts' // 验收反馈:用户创建/编辑的菜单权限配置要同时包含 后台(admin) 与 前端客户端(app) 两类菜单, // 并按类型分区落库(internal 不纳入)。 test('align_user_menu_auth_both_types_tree_nodes', () => { // 授权节点携带 type:admin/app 两类菜单都能进同一棵树。 assert.equal(APP_MENU_TYPE, 'app') const admin = parsePermissionMenuItem({ id: 1, name: '账号权限', parent_id: null, sort_order: 1 }, ADMIN_MENU_TYPE) assert.equal(admin?.type, ADMIN_MENU_TYPE) const app = parseMenuOptionList( [{ id: 2, name: '视频', parent_id: null, sort_order: 1, column_key: 'wb' }], APP_MENU_TYPE, ) assert.equal(app[0].type, APP_MENU_TYPE) }) test('align_user_menu_auth_both_types_fetch_and_submit_source', () => { const api = readSource('src/pages/account/user-menu-auth-api.ts') assert.match(api, /APP_MENU_TYPE/, '拉取/回显含客户端类型') assert.match(api, /Promise\.all/, '两类菜单并行拉取') assert.match(api, /normalizeMenuIds/, '两类已授权 id 合并去重') // 提交仍由后端把勾选 id 按类型分区写(user PUT),前端不再限定单类型。 const service = readSource('../backend-java/src/main/java/com/nanri/aiimage/modules/admin/service/AdminUserService.java') assert.match(service, /resolveMenuTypes/, '后端按菜单 id 解析类型') assert.match(service, /MENU_TYPE_ADMIN/, 'admin 分区写') assert.match(service, /MENU_TYPE_APP/, 'app 分区写') const auth = readSource('src/pages/account/user-menu-auth.ts') assert.match(auth, /type: string/, '授权节点携带 type') }) test('align_user_menu_auth_echo_waits_tree_render', () => { // 验收反馈:编辑用户时已授权菜单无回显——load() 在 data 赋值后同步 setCheckedKeys, // el-tree 的 store 异步同步 props.data,勾选作用在空 store 上丢失。 // 修复:data 就绪后先 await nextTick() 再 applyChecked()。 const tree = readSource('src/pages/account/UserMenuAuthTree.vue') const loadBlock = tree.slice(tree.indexOf('async function load'), tree.indexOf('catch {', tree.indexOf('async function load'))) assert.match(loadBlock, /await nextTick\(\).*applyChecked\(\)/s, '树数据就绪后等渲染完成再应用已勾选 id') assert.ok(loadBlock.indexOf('await nextTick') < loadBlock.indexOf('applyChecked()'), 'nextTick 先于 applyChecked') assert.match(tree, /watch\(/, 'checked 变化时仍兜底回显') assert.match(tree, /if \(loaded\.value\) applyChecked\(\)/, '兜底回显仅在树加载完成后') })