develop #2
@@ -0,0 +1,167 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest'
|
||||||
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
|
import { usePermissionStore } from '@/stores/permission'
|
||||||
|
|
||||||
|
describe('Permission Store', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia())
|
||||||
|
localStorage.clear()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('基础功能', () => {
|
||||||
|
it('应该正确初始化状态', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
|
||||||
|
expect(store.roles).toEqual([])
|
||||||
|
expect(store.permissions).toEqual([])
|
||||||
|
expect(store.menus).toEqual([])
|
||||||
|
expect(store.loaded).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('应该正确设置权限数据', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: ['admin'],
|
||||||
|
permissions: ['user:read', 'user:delete'],
|
||||||
|
menus: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '仪表盘',
|
||||||
|
path: '/dashboard',
|
||||||
|
icon: 'Odometer',
|
||||||
|
sort: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.roles).toEqual(['admin'])
|
||||||
|
expect(store.permissions).toEqual(['user:read', 'user:delete'])
|
||||||
|
expect(store.menus).toHaveLength(1)
|
||||||
|
expect(store.loaded).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('应该正确清除权限数据', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: ['admin'],
|
||||||
|
permissions: ['user:read'],
|
||||||
|
menus: []
|
||||||
|
})
|
||||||
|
|
||||||
|
store.clearPermissionData()
|
||||||
|
|
||||||
|
expect(store.roles).toEqual([])
|
||||||
|
expect(store.permissions).toEqual([])
|
||||||
|
expect(store.menus).toEqual([])
|
||||||
|
expect(store.loaded).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('权限检查方法', () => {
|
||||||
|
it('应该正确检查单个角色', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: ['admin', 'user'],
|
||||||
|
permissions: [],
|
||||||
|
menus: []
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.hasRole('admin')).toBe(true)
|
||||||
|
expect(store.hasRole('manager')).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('应该正确检查多个角色(满足任一即可)', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: ['user'],
|
||||||
|
permissions: [],
|
||||||
|
menus: []
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.hasRole(['admin', 'user'])).toBe(true)
|
||||||
|
expect(store.hasRole(['admin', 'manager'])).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('应该正确检查单个权限', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: [],
|
||||||
|
permissions: ['user:read', 'user:delete'],
|
||||||
|
menus: []
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.hasPermission('user:read')).toBe(true)
|
||||||
|
expect(store.hasPermission('user:create')).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('应该正确检查多个权限(满足任一即可)', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: [],
|
||||||
|
permissions: ['user:read'],
|
||||||
|
menus: []
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.hasPermission(['user:read', 'user:create'])).toBe(true)
|
||||||
|
expect(store.hasPermission(['user:create', 'user:update'])).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('localStorage 持久化', () => {
|
||||||
|
it('应该正确保存到 localStorage', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: ['admin'],
|
||||||
|
permissions: ['user:read'],
|
||||||
|
menus: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '仪表盘',
|
||||||
|
path: '/dashboard',
|
||||||
|
sort: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const stored = localStorage.getItem('permission')
|
||||||
|
expect(stored).toBeTruthy()
|
||||||
|
|
||||||
|
const data = JSON.parse(stored!)
|
||||||
|
expect(data.roles).toEqual(['admin'])
|
||||||
|
expect(data.permissions).toEqual(['user:read'])
|
||||||
|
expect(data.menus).toHaveLength(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('应该正确从 localStorage 恢复', () => {
|
||||||
|
localStorage.setItem('permission', JSON.stringify({
|
||||||
|
roles: ['user'],
|
||||||
|
permissions: ['user:read:self'],
|
||||||
|
menus: []
|
||||||
|
}))
|
||||||
|
|
||||||
|
const store = usePermissionStore()
|
||||||
|
store.initFromStorage()
|
||||||
|
|
||||||
|
expect(store.roles).toEqual(['user'])
|
||||||
|
expect(store.permissions).toEqual(['user:read:self'])
|
||||||
|
expect(store.loaded).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('清除数据时应该同时清除 localStorage', () => {
|
||||||
|
const store = usePermissionStore()
|
||||||
|
|
||||||
|
store.setPermissionData({
|
||||||
|
roles: ['admin'],
|
||||||
|
permissions: [],
|
||||||
|
menus: []
|
||||||
|
})
|
||||||
|
|
||||||
|
store.clearPermissionData()
|
||||||
|
|
||||||
|
expect(localStorage.getItem('permission')).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export interface MenuItem {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
path: string
|
||||||
|
icon?: string
|
||||||
|
parentId?: number
|
||||||
|
sort: number
|
||||||
|
children?: MenuItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PermissionState {
|
||||||
|
roles: string[]
|
||||||
|
permissions: string[]
|
||||||
|
menus: MenuItem[]
|
||||||
|
loaded: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePermissionStore = defineStore('permission', {
|
||||||
|
state: (): PermissionState => ({
|
||||||
|
roles: [],
|
||||||
|
permissions: [],
|
||||||
|
menus: [],
|
||||||
|
loaded: false
|
||||||
|
}),
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
hasRole: (state) => (role: string | string[]) => {
|
||||||
|
if (Array.isArray(role)) {
|
||||||
|
return role.some(r => state.roles.includes(r))
|
||||||
|
}
|
||||||
|
return state.roles.includes(role)
|
||||||
|
},
|
||||||
|
|
||||||
|
hasPermission: (state) => (permission: string | string[]) => {
|
||||||
|
if (Array.isArray(permission)) {
|
||||||
|
return permission.some(p => state.permissions.includes(p))
|
||||||
|
}
|
||||||
|
return state.permissions.includes(permission)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
setPermissionData(data: {
|
||||||
|
roles: string[]
|
||||||
|
permissions: string[]
|
||||||
|
menus: MenuItem[]
|
||||||
|
}) {
|
||||||
|
this.roles = data.roles
|
||||||
|
this.permissions = data.permissions
|
||||||
|
this.menus = data.menus
|
||||||
|
this.loaded = true
|
||||||
|
|
||||||
|
this.saveToStorage()
|
||||||
|
},
|
||||||
|
|
||||||
|
clearPermissionData() {
|
||||||
|
this.roles = []
|
||||||
|
this.permissions = []
|
||||||
|
this.menus = []
|
||||||
|
this.loaded = false
|
||||||
|
|
||||||
|
localStorage.removeItem('permission')
|
||||||
|
},
|
||||||
|
|
||||||
|
saveToStorage() {
|
||||||
|
const data = {
|
||||||
|
roles: this.roles,
|
||||||
|
permissions: this.permissions,
|
||||||
|
menus: this.menus
|
||||||
|
}
|
||||||
|
localStorage.setItem('permission', JSON.stringify(data))
|
||||||
|
},
|
||||||
|
|
||||||
|
initFromStorage() {
|
||||||
|
const stored = localStorage.getItem('permission')
|
||||||
|
if (stored) {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(stored)
|
||||||
|
this.roles = data.roles || []
|
||||||
|
this.permissions = data.permissions || []
|
||||||
|
this.menus = data.menus || []
|
||||||
|
this.loaded = true
|
||||||
|
} catch (error) {
|
||||||
|
console.error('从 localStorage 恢复权限数据失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -20,20 +20,42 @@ Object.defineProperty(window, 'matchMedia', {
|
|||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const localStorageMock = (() => {
|
||||||
|
let store: Record<string, string> = {}
|
||||||
|
return {
|
||||||
|
getItem: vi.fn((key: string) => store[key] || null),
|
||||||
|
setItem: vi.fn((key: string, value: string) => {
|
||||||
|
store[key] = value
|
||||||
|
}),
|
||||||
|
removeItem: vi.fn((key: string) => {
|
||||||
|
delete store[key]
|
||||||
|
}),
|
||||||
|
clear: vi.fn(() => {
|
||||||
|
store = {}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
Object.defineProperty(window, 'localStorage', {
|
Object.defineProperty(window, 'localStorage', {
|
||||||
value: {
|
value: localStorageMock,
|
||||||
getItem: vi.fn(),
|
|
||||||
setItem: vi.fn(),
|
|
||||||
removeItem: vi.fn(),
|
|
||||||
clear: vi.fn(),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const sessionStorageMock = (() => {
|
||||||
|
let store: Record<string, string> = {}
|
||||||
|
return {
|
||||||
|
getItem: vi.fn((key: string) => store[key] || null),
|
||||||
|
setItem: vi.fn((key: string, value: string) => {
|
||||||
|
store[key] = value
|
||||||
|
}),
|
||||||
|
removeItem: vi.fn((key: string) => {
|
||||||
|
delete store[key]
|
||||||
|
}),
|
||||||
|
clear: vi.fn(() => {
|
||||||
|
store = {}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
Object.defineProperty(window, 'sessionStorage', {
|
Object.defineProperty(window, 'sessionStorage', {
|
||||||
value: {
|
value: sessionStorageMock,
|
||||||
getItem: vi.fn(),
|
|
||||||
setItem: vi.fn(),
|
|
||||||
removeItem: vi.fn(),
|
|
||||||
clear: vi.fn(),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user