import { describe, it, expect, beforeEach, vi } from 'vitest' import { setActivePinia, createPinia } from 'pinia' import { useAuthStore } from '@/stores/auth' import { usePermissionStore } from '@/stores/permissions' // mock 后端数据接口,避免真实网络请求 vi.mock('@/services/api', () => ({ loadDataApi: vi.fn(), })) import { loadDataApi } from '@/services/api' const mockModules = [ { b_id: '1', b_code: 'm1', b_name: 'M1', b_canuse: 1, b_canmenu: 1, b_module_type: 'directory', b_parent_id: null, b_icon: '', b_route: '', }, ] const mockUserModules = [{ b_id: '1', b_module_id: '1', b_user_id: '123' }] const mockUserPowers = [] const mockPowers = [] function mockApiResponses() { loadDataApi.mockImplementation((view) => { const data = view === 's_module' ? mockModules : view === 'b_user_module' ? mockUserModules : view === 'b_user_power' ? mockUserPowers : view === 's_module_power' ? mockPowers : [] return Promise.resolve({ data, code: 0, success: true }) }) } function setLoggedInUser() { const auth = useAuthStore() auth.setSession({ token: 't', user: { id: 123, account: 'u1', name: 'U' } }, 'ORG') } // 冲刷微任务:让 setSession 触发的 watch(clear) 先执行,隔离“手动 clear”的断言 const flush = () => Promise.resolve() beforeEach(() => { setActivePinia(createPinia()) loadDataApi.mockReset() }) describe('permissions store', () => { it('load 成功后写入 modules 且记录 loadedPrincipalKey', async () => { mockApiResponses() setLoggedInUser() const perm = usePermissionStore() await perm.load() expect(perm.modules.length).toBe(1) }) it('同一主体重复 load 不重复发请求(按主体去重)', async () => { mockApiResponses() setLoggedInUser() const perm = usePermissionStore() await perm.load() await perm.load() // 首次发 4 个接口调用;第二次因主体已加载直接 return expect(loadDataApi).toHaveBeenCalledTimes(4) }) it('登录场景:load 进行中触发 clear(主体相同)不作废结果', async () => { mockApiResponses() setLoggedInUser() await flush() // 先让 watch(clear) 跑完(清空空状态,不作废) const perm = usePermissionStore() const p = perm.load() // loadingPrincipalKey = 'ORG:123' // 模拟登录后 setSession 触发的 watch(clear):当前主体与进行中请求主体相同 perm.clear() await p // 关键修复:clear 未作废进行中请求,modules 正常写入 expect(perm.modules.length).toBe(1) }) it('切换账号:load 进行中触发 clear(主体不同)作废旧请求', async () => { mockApiResponses() setLoggedInUser() await flush() const perm = usePermissionStore() const p = perm.load() // 主体 ORG:123 进行中 // 模拟切换账号:authStore 变为另一主体,watch 触发 clear const auth = useAuthStore() auth.setSession({ token: 't2', user: { id: 999, account: 'u2', name: 'U2' } }, 'ORG2') perm.clear() await p // 旧请求被作废:结果丢弃,modules 仍为空(且未触发新主体的 load) expect(perm.modules.length).toBe(0) }) it('g3soft 提权:仅加载全部启用模块', async () => { loadDataApi.mockImplementation((view) => Promise.resolve({ data: view === 's_module' ? mockModules : [], code: 0, success: true, }), ) const auth = useAuthStore() auth.setSession({ token: 't', user: { id: 1, account: 'g3soft', name: 'G' } }, 'ORG') const perm = usePermissionStore() await perm.load() expect(perm.isG3soft).toBe(true) expect(perm.modules.length).toBe(1) }) })