| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import { describe, it, expect, vi, beforeEach } from 'vitest'
- import { setActivePinia, createPinia } from 'pinia'
- import { useUserStore } from '@/store/user'
- import * as loginApi from '@/api/login'
- import * as auth from '@/utils/auth'
- import { mockLoginResponse, mockAdminInfo, wrapResponse, wrapErrorResponse } from '../../fixtures'
- // Mock modules
- vi.mock('@/api/login', () => ({
- login: vi.fn(),
- getInfo: vi.fn(),
- logout: vi.fn()
- }))
- vi.mock('@/utils/auth', () => ({
- getToken: vi.fn(() => ''),
- setToken: vi.fn(),
- removeToken: vi.fn(),
- setRefreshToken: vi.fn(),
- removeRefreshToken: vi.fn()
- }))
- describe('User Store', () => {
- beforeEach(() => {
- setActivePinia(createPinia())
- vi.clearAllMocks()
- })
- describe('loginAction', () => {
- it('should login successfully and store token', async () => {
- const mockResponse = wrapResponse(mockLoginResponse)
- vi.mocked(loginApi.login).mockResolvedValue(mockResponse)
- const store = useUserStore()
- const result = await store.loginAction({ username: 'admin', password: 'password' })
- expect(result.code).toBe(200)
- expect(store.token).toBe(mockLoginResponse.token)
- expect(store.userInfo?.username).toBe(mockLoginResponse.admin.username)
- expect(auth.setToken).toHaveBeenCalledWith(mockLoginResponse.token)
- expect(auth.setRefreshToken).toHaveBeenCalledWith(mockLoginResponse.refreshToken)
- })
- it('should not store token on login failure', async () => {
- const mockResponse = wrapErrorResponse('用户名或密码错误', 401)
- vi.mocked(loginApi.login).mockResolvedValue(mockResponse)
- const store = useUserStore()
- const result = await store.loginAction({ username: 'wrong', password: 'wrong' })
- expect(result.code).toBe(401)
- expect(store.token).toBe('')
- expect(auth.setToken).not.toHaveBeenCalled()
- })
- })
- describe('getUserInfo', () => {
- it('should fetch and store user info', async () => {
- const mockResponse = wrapResponse(mockAdminInfo)
- vi.mocked(loginApi.getInfo).mockResolvedValue(mockResponse)
- const store = useUserStore()
- const result = await store.getUserInfo()
- expect(result.code).toBe(200)
- expect(store.userInfo?.username).toBe(mockAdminInfo.username)
- expect(store.userInfo?.role).toBe(mockAdminInfo.role)
- })
- })
- describe('logoutAction', () => {
- it('should clear token and user info on logout', async () => {
- vi.mocked(loginApi.logout).mockResolvedValue(wrapResponse(null))
- const store = useUserStore()
- // Set initial state
- store.token = mockLoginResponse.token
- store.userInfo = mockAdminInfo
- await store.logoutAction()
- expect(store.token).toBe('')
- expect(store.userInfo).toBeNull()
- expect(auth.removeToken).toHaveBeenCalled()
- expect(auth.removeRefreshToken).toHaveBeenCalled()
- })
- it('should clear state in finally block even if logout API fails', async () => {
- vi.mocked(loginApi.logout).mockRejectedValue(new Error('Network error'))
- const store = useUserStore()
- store.token = mockLoginResponse.token
- store.userInfo = mockAdminInfo
- // logoutAction uses try/finally without catch, so error will propagate
- // but finally block still clears the state
- try {
- await store.logoutAction()
- } catch {
- // Expected to throw
- }
- // State should be cleared in finally block
- expect(store.token).toBe('')
- expect(store.userInfo).toBeNull()
- expect(auth.removeToken).toHaveBeenCalled()
- expect(auth.removeRefreshToken).toHaveBeenCalled()
- })
- })
- describe('resetToken', () => {
- it('should clear all auth state', () => {
- const store = useUserStore()
- store.token = mockLoginResponse.token
- store.userInfo = mockAdminInfo
- store.resetToken()
- expect(store.token).toBe('')
- expect(store.userInfo).toBeNull()
- expect(auth.removeToken).toHaveBeenCalled()
- expect(auth.removeRefreshToken).toHaveBeenCalled()
- })
- })
- })
|