frontend layout and infrastructure

This commit is contained in:
2026-03-18 13:53:36 +08:00
parent 88df42fe52
commit 2b1a2f0c28
26 changed files with 986 additions and 460 deletions
+139
View File
@@ -0,0 +1,139 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from '../user'
// Mock the api module
vi.mock('@/utils/request', () => ({
api: {
get: vi.fn(),
post: vi.fn(),
},
}))
describe('useUserStore', () => {
beforeEach(() => {
setActivePinia(createPinia())
localStorage.clear()
vi.restoreAllMocks()
})
describe('initial state', () => {
it('starts with null values when localStorage is empty', () => {
const store = useUserStore()
expect(store.token).toBeNull()
expect(store.refreshToken).toBeNull()
expect(store.user).toBeNull()
expect(store.isLoggedIn).toBe(false)
expect(store.username).toBe('')
})
it('restores token from localStorage', () => {
localStorage.setItem('access_token', 'saved-token')
localStorage.setItem('refresh_token', 'saved-refresh')
const store = useUserStore()
expect(store.token).toBe('saved-token')
expect(store.refreshToken).toBe('saved-refresh')
expect(store.isLoggedIn).toBe(true)
})
it('restores user info from localStorage', () => {
const savedUser = { id: 1, username: 'admin', email: 'a@b.com', role: 'admin', status: 1 }
localStorage.setItem('user', JSON.stringify(savedUser))
const store = useUserStore()
expect(store.user).toEqual(savedUser)
expect(store.username).toBe('admin')
expect(store.isAdmin).toBe(true)
})
it('handles corrupted user data in localStorage', () => {
localStorage.setItem('user', 'invalid-json{')
const store = useUserStore()
expect(store.user).toBeNull()
})
})
describe('setToken', () => {
it('sets tokens in store and localStorage', () => {
const store = useUserStore()
store.setToken('new-access', 'new-refresh')
expect(store.token).toBe('new-access')
expect(store.refreshToken).toBe('new-refresh')
expect(localStorage.getItem('access_token')).toBe('new-access')
expect(localStorage.getItem('refresh_token')).toBe('new-refresh')
expect(store.isLoggedIn).toBe(true)
})
})
describe('setUser', () => {
it('sets user info in store and localStorage', () => {
const store = useUserStore()
const userInfo = { id: 1, username: 'test', email: 't@t.com', role: 'user', status: 1 }
store.setUser(userInfo)
expect(store.user).toEqual(userInfo)
expect(store.username).toBe('test')
expect(store.isAdmin).toBe(false)
expect(JSON.parse(localStorage.getItem('user')!)).toEqual(userInfo)
})
})
describe('logout', () => {
it('clears all state and localStorage', () => {
const store = useUserStore()
store.setToken('tok', 'ref')
store.setUser({ id: 1, username: 'a', email: 'a@a.com', role: 'admin', status: 1 })
store.logout()
expect(store.token).toBeNull()
expect(store.refreshToken).toBeNull()
expect(store.user).toBeNull()
expect(store.isLoggedIn).toBe(false)
expect(localStorage.getItem('access_token')).toBeNull()
expect(localStorage.getItem('refresh_token')).toBeNull()
expect(localStorage.getItem('user')).toBeNull()
})
})
describe('fetchCurrentUser', () => {
it('fetches user from API and updates store', async () => {
const { api } = await import('@/utils/request')
const mockUser = { id: 1, username: 'fetched', email: 'f@f.com', role: 'admin', status: 1 }
vi.mocked(api.get).mockResolvedValueOnce(mockUser)
const store = useUserStore()
const result = await store.fetchCurrentUser()
expect(api.get).toHaveBeenCalledWith('/api/v1/auth/me')
expect(result).toEqual(mockUser)
expect(store.user).toEqual(mockUser)
expect(store.isAdmin).toBe(true)
})
})
describe('computed properties', () => {
it('isAdmin returns true for admin role', () => {
const store = useUserStore()
store.setUser({ id: 1, username: 'a', email: 'a@a.com', role: 'admin', status: 1 })
expect(store.isAdmin).toBe(true)
})
it('isAdmin returns false for non-admin role', () => {
const store = useUserStore()
store.setUser({ id: 1, username: 'u', email: 'u@u.com', role: 'user', status: 1 })
expect(store.isAdmin).toBe(false)
})
})
})