user.spec.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { describe, it, expect, vi, beforeEach } from 'vitest'
  2. import { setActivePinia, createPinia } from 'pinia'
  3. import { useUserStore } from '@/store/user'
  4. import * as loginApi from '@/api/login'
  5. import * as auth from '@/utils/auth'
  6. import { mockLoginResponse, mockAdminInfo, wrapResponse, wrapErrorResponse } from '../../fixtures'
  7. // Mock modules
  8. vi.mock('@/api/login', () => ({
  9. login: vi.fn(),
  10. getInfo: vi.fn(),
  11. logout: vi.fn()
  12. }))
  13. vi.mock('@/utils/auth', () => ({
  14. getToken: vi.fn(() => ''),
  15. setToken: vi.fn(),
  16. removeToken: vi.fn()
  17. }))
  18. describe('User Store', () => {
  19. beforeEach(() => {
  20. setActivePinia(createPinia())
  21. vi.clearAllMocks()
  22. })
  23. describe('loginAction', () => {
  24. it('should login successfully and store token', async () => {
  25. const mockResponse = wrapResponse(mockLoginResponse)
  26. vi.mocked(loginApi.login).mockResolvedValue(mockResponse)
  27. const store = useUserStore()
  28. const result = await store.loginAction({ username: 'admin', password: 'password' })
  29. expect(result.code).toBe(200)
  30. expect(store.token).toBe(mockLoginResponse.token)
  31. expect(store.userInfo?.username).toBe(mockLoginResponse.admin.username)
  32. // setToken now takes (token, expiresIn)
  33. expect(auth.setToken).toHaveBeenCalledWith(mockLoginResponse.token, mockLoginResponse.expiresIn)
  34. })
  35. it('should not store token on login failure', async () => {
  36. const mockResponse = wrapErrorResponse('用户名或密码错误', 401) as any
  37. vi.mocked(loginApi.login).mockResolvedValue(mockResponse)
  38. const store = useUserStore()
  39. const result = await store.loginAction({ username: 'wrong', password: 'wrong' })
  40. expect(result.code).toBe(401)
  41. expect(store.token).toBe('')
  42. expect(auth.setToken).not.toHaveBeenCalled()
  43. })
  44. })
  45. describe('getUserInfo', () => {
  46. it('should fetch and store user info', async () => {
  47. const mockResponse = wrapResponse(mockAdminInfo)
  48. vi.mocked(loginApi.getInfo).mockResolvedValue(mockResponse)
  49. const store = useUserStore()
  50. const result = await store.getUserInfo()
  51. expect(result.code).toBe(200)
  52. expect(store.userInfo?.username).toBe(mockAdminInfo.username)
  53. expect(store.userInfo?.role).toBe(mockAdminInfo.role)
  54. })
  55. })
  56. describe('logoutAction', () => {
  57. it('should clear token and user info on logout', async () => {
  58. vi.mocked(loginApi.logout).mockResolvedValue(wrapResponse(null))
  59. const store = useUserStore()
  60. // Set initial state
  61. store.token = mockLoginResponse.token
  62. store.userInfo = mockAdminInfo
  63. await store.logoutAction()
  64. expect(store.token).toBe('')
  65. expect(store.userInfo).toBeNull()
  66. expect(auth.removeToken).toHaveBeenCalled()
  67. })
  68. it('should clear state in finally block even if logout API fails', async () => {
  69. vi.mocked(loginApi.logout).mockRejectedValue(new Error('Network error'))
  70. const store = useUserStore()
  71. store.token = mockLoginResponse.token
  72. store.userInfo = mockAdminInfo
  73. // logoutAction now catches errors internally and still clears state
  74. await store.logoutAction()
  75. // State should be cleared in finally block
  76. expect(store.token).toBe('')
  77. expect(store.userInfo).toBeNull()
  78. expect(auth.removeToken).toHaveBeenCalled()
  79. })
  80. })
  81. describe('resetToken', () => {
  82. it('should clear all auth state', () => {
  83. const store = useUserStore()
  84. store.token = mockLoginResponse.token
  85. store.userInfo = mockAdminInfo
  86. store.resetToken()
  87. expect(store.token).toBe('')
  88. expect(store.userInfo).toBeNull()
  89. expect(auth.removeToken).toHaveBeenCalled()
  90. })
  91. })
  92. })