122 lines
3.7 KiB
JavaScript
122 lines
3.7 KiB
JavaScript
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)
|
|
})
|
|
})
|