20260904232445

This commit is contained in:
oneao committed 2026-09-04 23:24:45 +08:00
1 parent 4e167df0f0
commit 1b01a31252
19 files changed
+1099 -1013

No files matched your search

+150
View File
@@ -0,0 +1,150 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useAuthStore } from '@/stores/auth'
import { useMenuStore } from '@/stores/menus'
// mock 后端数据接口,避免真实网络请求
vi.mock('@/services/api', () => ({
loadDataApi: vi.fn(),
}))
import { loadDataApi } from '@/services/api'
const mockMenus = [
{
b_id: '1',
b_code: 'sys',
b_name: '系统',
b_menu_type: 'directory',
b_parent_id: null,
b_canuse: 1,
},
{
b_id: '2',
b_code: 'module',
b_name: '模块管理',
b_menu_type: 'page',
b_parent_id: '1',
b_route: '/module/module-management',
b_canuse: 1,
},
{
b_id: '3',
b_code: 'menu',
b_name: '菜单管理',
b_menu_type: 'page',
b_parent_id: '1',
b_route: '/module/menu-management',
b_canuse: 1,
},
{
b_id: '4',
b_code: 'i18n',
b_name: '多语言类型',
b_menu_type: 'page',
b_parent_id: '1',
b_route: '/module/i18n-type',
b_canuse: 1,
},
]
function mockSModuleData(menus) {
loadDataApi.mockImplementation((view) =>
Promise.resolve({
data: view === 's_menu' ? menus : [],
code: 0,
success: true,
}),
)
}
function setUser(account, id) {
const auth = useAuthStore()
auth.setSession({ token: 't', user: { id, account } }, 'ORG')
}
/** 冲刷微任务:让 setSession 触发的 watch(clear) 先执行 */
const flush = () => Promise.resolve()
function collectCodes(nodes) {
const codes = []
for (const node of nodes) {
codes.push(String(node.b_code))
if (node.children) codes.push(...collectCodes(node.children))
}
return codes
}
beforeEach(() => {
setActivePinia(createPinia())
loadDataApi.mockReset()
})
describe('menus store(s_menu 动态菜单)', () => {
it('普通用户:隐藏编码 module 的菜单(含空目录剪枝)', async () => {
mockSModuleData(mockMenus)
setUser('u1', 123)
await flush()
const menus = useMenuStore()
await menus.load()
const codes = collectCodes(menus.visibleMenus)
expect(codes).toContain('sys')
expect(codes).toContain('menu')
expect(codes).toContain('i18n')
expect(codes).not.toContain('module')
})
it('普通用户:目录下仅剩 module 子项时,目录整体不渲染', async () => {
// 系统目录下只有「模块管理」这一个可用子菜单
mockSModuleData(mockMenus.filter((m) => m.b_code !== 'menu' && m.b_code !== 'i18n'))
setUser('u1', 123)
await flush()
const menus = useMenuStore()
await menus.load()
expect(menus.visibleMenus).toEqual([])
})
it('g3soft:module 菜单可见', async () => {
mockSModuleData(mockMenus)
setUser('g3soft', 1)
await flush()
const menus = useMenuStore()
await menus.load()
expect(menus.isG3soft).toBe(true)
expect(collectCodes(menus.visibleMenus)).toContain('module')
})
it('同一主体重复 load 不重复发请求', async () => {
mockSModuleData(mockMenus)
setUser('u1', 123)
await flush()
const menus = useMenuStore()
await menus.load()
await menus.load()
expect(loadDataApi).toHaveBeenCalledTimes(1)
})
it('切换账号:缓存清空并重新加载', async () => {
mockSModuleData(mockMenus)
setUser('u1', 123)
await flush()
const menus = useMenuStore()
await menus.load()
expect(menus.rawMenus.length).toBe(mockMenus.length)
// 切换到另一个主体:watch(clear) 清空已加载数据
setUser('u2', 999)
await flush()
await flush()
expect(menus.rawMenus.length).toBe(0)
expect(menus.visibleMenus).toEqual([])
// 新主体 load 重新拉取
loadDataApi.mockClear()
await menus.load()
expect(menus.rawMenus.length).toBe(mockMenus.length)
})
})