修复bug
This commit is contained in:
@@ -1,200 +1,27 @@
|
||||
import { beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { nextTick } from 'vue'
|
||||
import { getNavigationLeaves } from '@/navigation/adminNavigation'
|
||||
import { useAdminDataStore } from '@/stores/adminData'
|
||||
import { PREVIEW_ROLE_KEY, useAccessPreviewStore } from '@/stores/accessPreview'
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
import { useAccessPreviewStore } from '@/stores/accessPreview'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
function createMemoryStorage(): Storage {
|
||||
const values = new Map<string, string>()
|
||||
describe('server access store', () => {
|
||||
beforeEach(() => setActivePinia(createPinia()))
|
||||
|
||||
return {
|
||||
get length() {
|
||||
return values.size
|
||||
},
|
||||
clear() {
|
||||
values.clear()
|
||||
},
|
||||
getItem(key) {
|
||||
return values.get(key) ?? null
|
||||
},
|
||||
key(index) {
|
||||
return [...values.keys()][index] ?? null
|
||||
},
|
||||
removeItem(key) {
|
||||
values.delete(key)
|
||||
},
|
||||
setItem(key, value) {
|
||||
values.set(key, value)
|
||||
},
|
||||
}
|
||||
}
|
||||
it('uses only the authenticated permission snapshot', () => {
|
||||
const auth = useAuthStore()
|
||||
auth.token = 'token'
|
||||
auth.permissions = ['platform:warehouse:list']
|
||||
const access = useAccessPreviewStore()
|
||||
access.initializeAfterLogin()
|
||||
|
||||
describe('access preview store', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia())
|
||||
vi.stubGlobal('localStorage', createMemoryStorage())
|
||||
expect(access.can('platform:warehouse:list')).toBe(true)
|
||||
expect(access.can('platform:user:list')).toBe(false)
|
||||
expect(access.firstAccessiblePath).toBe('/warehouses')
|
||||
})
|
||||
|
||||
it('defaults to the enabled super admin with all enabled permissions', () => {
|
||||
const preview = useAccessPreviewStore()
|
||||
|
||||
preview.initializeAfterLogin()
|
||||
|
||||
expect(preview.enabledRoles).toHaveLength(5)
|
||||
expect(preview.currentRole?.code).toBe('SUPER_ADMIN')
|
||||
expect(preview.can('system:permission:write')).toBe(true)
|
||||
expect(preview.firstAccessiblePath).toBe('/customers')
|
||||
expect(localStorage.getItem(PREVIEW_ROLE_KEY)).toBe('R001')
|
||||
})
|
||||
|
||||
it('ignores disabled permission resources even when the selected role still holds their ids', () => {
|
||||
const data = useAdminDataStore()
|
||||
const preview = useAccessPreviewStore()
|
||||
preview.initializeAfterLogin()
|
||||
const customerList = data.permissions.find((item) => item.code === 'platform:customer:list')
|
||||
expect(customerList).toBeDefined()
|
||||
|
||||
if (customerList) customerList.status = '停用'
|
||||
|
||||
expect(preview.can('platform:customer:list')).toBe(false)
|
||||
expect(getNavigationLeaves(preview.filteredNavigation).map((item) => item.path)).not.toContain('/customers')
|
||||
expect(preview.firstAccessiblePath).toBe('/customers/reviews')
|
||||
})
|
||||
|
||||
it('does not cascade a disabled directory to enabled descendant leaves', () => {
|
||||
const data = useAdminDataStore()
|
||||
const preview = useAccessPreviewStore()
|
||||
preview.initializeAfterLogin()
|
||||
const businessDirectory = data.permissions.find((item) => item.code === 'business')
|
||||
expect(businessDirectory).toBeDefined()
|
||||
|
||||
if (businessDirectory) businessDirectory.status = '停用'
|
||||
|
||||
expect(preview.can('business')).toBe(false)
|
||||
expect(preview.can('platform:customer:list')).toBe(true)
|
||||
expect(getNavigationLeaves(preview.filteredNavigation).map((item) => item.path)).toContain('/customers')
|
||||
})
|
||||
|
||||
it('reacts immediately to permission id changes and falls back when the current role is disabled', async () => {
|
||||
const data = useAdminDataStore()
|
||||
const preview = useAccessPreviewStore()
|
||||
preview.initializeAfterLogin()
|
||||
expect(preview.commitRole('R003')).toBe(true)
|
||||
const operator = data.roles.find((item) => item.id === 'R003')
|
||||
expect(operator).toBeDefined()
|
||||
|
||||
if (operator) operator.permissionIds = ['P100']
|
||||
expect(preview.can('first-leg:list')).toBe(false)
|
||||
expect(preview.can('platform:customer:list')).toBe(true)
|
||||
expect(preview.permissionSignature).toBe('platform:customer:list')
|
||||
|
||||
if (operator) operator.status = '停用'
|
||||
await nextTick()
|
||||
|
||||
expect(preview.currentRole?.code).toBe('SUPER_ADMIN')
|
||||
expect(localStorage.getItem(PREVIEW_ROLE_KEY)).toBe('R001')
|
||||
})
|
||||
|
||||
it('falls back from an invalid persisted role and reset clears selection and persistence', () => {
|
||||
localStorage.setItem(PREVIEW_ROLE_KEY, 'missing-role')
|
||||
const preview = useAccessPreviewStore()
|
||||
|
||||
preview.initializeAfterLogin()
|
||||
expect(preview.currentRole?.code).toBe('SUPER_ADMIN')
|
||||
|
||||
preview.reset()
|
||||
expect(preview.initialized).toBe(false)
|
||||
expect(preview.currentRole).toBeNull()
|
||||
expect(localStorage.getItem(PREVIEW_ROLE_KEY)).toBeNull()
|
||||
})
|
||||
|
||||
it('restores an enabled persisted role', () => {
|
||||
localStorage.setItem(PREVIEW_ROLE_KEY, 'R003')
|
||||
const preview = useAccessPreviewStore()
|
||||
|
||||
preview.initializeAfterLogin()
|
||||
|
||||
expect(preview.currentRole?.id).toBe('R003')
|
||||
expect(localStorage.getItem(PREVIEW_ROLE_KEY)).toBe('R003')
|
||||
})
|
||||
|
||||
it('does not reload an initialized role during guarded navigation', () => {
|
||||
const preview = useAccessPreviewStore()
|
||||
preview.initializeAfterLogin()
|
||||
expect(preview.commitRole('R003')).toBe(true)
|
||||
|
||||
localStorage.setItem(PREVIEW_ROLE_KEY, 'R001')
|
||||
preview.initializeAfterLogin()
|
||||
|
||||
expect(preview.currentRole?.id).toBe('R003')
|
||||
})
|
||||
|
||||
it('has no role, permissions, or route when every role is disabled', () => {
|
||||
const data = useAdminDataStore()
|
||||
data.roles.forEach((role) => {
|
||||
role.status = '停用'
|
||||
})
|
||||
const preview = useAccessPreviewStore()
|
||||
|
||||
preview.initializeAfterLogin()
|
||||
|
||||
expect(preview.currentRole).toBeNull()
|
||||
expect([...preview.permissionCodes]).toEqual([])
|
||||
expect(preview.filteredNavigation).toEqual([])
|
||||
expect(preview.firstAccessiblePath).toBeNull()
|
||||
expect(localStorage.getItem(PREVIEW_ROLE_KEY)).toBeNull()
|
||||
})
|
||||
|
||||
it('does not recreate a default preview after reset when role data changes', async () => {
|
||||
const data = useAdminDataStore()
|
||||
const preview = useAccessPreviewStore()
|
||||
preview.initializeAfterLogin()
|
||||
preview.reset()
|
||||
|
||||
data.roles[0].status = '停用'
|
||||
data.roles[1].status = '停用'
|
||||
await nextTick()
|
||||
|
||||
expect(preview.initialized).toBe(false)
|
||||
expect(preview.selectedRoleId).toBeNull()
|
||||
expect(preview.currentRole).toBeNull()
|
||||
expect(localStorage.getItem(PREVIEW_ROLE_KEY)).toBeNull()
|
||||
})
|
||||
|
||||
it('previews candidates without committing and rejects disabled roles', () => {
|
||||
const data = useAdminDataStore()
|
||||
const preview = useAccessPreviewStore()
|
||||
preview.initializeAfterLogin()
|
||||
const candidate = preview.previewRole('R003')
|
||||
|
||||
expect(candidate.codes.has('first-leg:create')).toBe(true)
|
||||
expect(candidate.firstPath).toBe('/warehouses')
|
||||
expect(getNavigationLeaves(candidate.navigation).map((item) => item.path)).toContain('/orders/first-leg')
|
||||
expectTypeOf(candidate.codes).toEqualTypeOf<ReadonlySet<string>>()
|
||||
expectTypeOf(preview.permissionCodes).toEqualTypeOf<ReadonlySet<string>>()
|
||||
expect(preview.currentRole?.id).toBe('R001')
|
||||
|
||||
const finance = data.roles.find((item) => item.id === 'R004')
|
||||
if (finance) finance.status = '停用'
|
||||
expect(preview.commitRole('R004')).toBe(false)
|
||||
expect(preview.previewRole('R004').firstPath).toBeNull()
|
||||
expect(preview.currentRole?.id).toBe('R001')
|
||||
})
|
||||
|
||||
it('does not filter or mutate mock business data when switching data scopes', () => {
|
||||
const data = useAdminDataStore()
|
||||
const preview = useAccessPreviewStore()
|
||||
preview.initializeAfterLogin()
|
||||
const customerSnapshot = JSON.parse(JSON.stringify(data.customers)) as typeof data.customers
|
||||
const orderSnapshot = JSON.parse(JSON.stringify(data.orders)) as typeof data.orders
|
||||
|
||||
expect(preview.commitRole('R003')).toBe(true)
|
||||
expect(preview.currentRole?.dataScope).toBe('本部门数据')
|
||||
expect(preview.commitRole('R005')).toBe(true)
|
||||
expect(preview.currentRole?.dataScope).toBe('本人数据')
|
||||
|
||||
expect(data.customers).toEqual(customerSnapshot)
|
||||
expect(data.orders).toEqual(orderSnapshot)
|
||||
it('exposes no permissions when the server snapshot is empty', () => {
|
||||
const access = useAccessPreviewStore()
|
||||
expect(access.permissionCodes.size).toBe(0)
|
||||
expect(access.filteredNavigation).toHaveLength(0)
|
||||
expect(access.firstAccessiblePath).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user