import { describe, it, expect, vi, beforeEach } from 'vitest'; import { AuthService, User, UserService } from '../../src/auth.service.js'; import { EnableStatus } from '@d8d/shared-types'; describe('认证服务', () => { let authService: AuthService; let mockUserService: UserService; const mockUser: User = { id: 1, username: 'testuser', nickname: '测试用户', isDisabled: EnableStatus.ENABLED, roles: [{ name: 'user' }] }; beforeEach(() => { mockUserService = { getUserByUsername: vi.fn(), verifyPassword: vi.fn(), createUser: vi.fn() }; authService = new AuthService(mockUserService); vi.stubEnv('JWT_SECRET', 'test-secret'); }); describe('登录', () => { it('应该成功登录', async () => { vi.mocked(mockUserService.getUserByUsername).mockResolvedValue(mockUser); vi.mocked(mockUserService.verifyPassword).mockResolvedValue(true); const result = await authService.login('testuser', 'password'); expect(result.token).toBeDefined(); expect(result.user).toEqual(mockUser); expect(mockUserService.getUserByUsername).toHaveBeenCalledWith('testuser'); expect(mockUserService.verifyPassword).toHaveBeenCalledWith(mockUser, 'password'); }); it('用户不存在时应该抛出错误', async () => { vi.mocked(mockUserService.getUserByUsername).mockResolvedValue(null); await expect(authService.login('nonexistent', 'password')) .rejects .toThrow('用户不存在'); }); it('用户被禁用时应该抛出错误', async () => { const disabledUser = { ...mockUser, isDisabled: EnableStatus.DISABLED }; vi.mocked(mockUserService.getUserByUsername).mockResolvedValue(disabledUser); await expect(authService.login('testuser', 'password')) .rejects .toThrow('用户账户已被禁用'); }); it('密码错误时应该抛出错误', async () => { vi.mocked(mockUserService.getUserByUsername).mockResolvedValue(mockUser); vi.mocked(mockUserService.verifyPassword).mockResolvedValue(false); await expect(authService.login('testuser', 'wrongpassword')) .rejects .toThrow('密码错误'); }); }); describe('生成token', () => { it('应该成功生成token', () => { const token = authService.generateToken(mockUser); expect(token).toBeDefined(); expect(typeof token).toBe('string'); }); it('应该使用自定义过期时间生成token', () => { const token = authService.generateToken(mockUser, '2h'); expect(token).toBeDefined(); }); }); describe('验证token', () => { it('应该成功验证token', () => { const token = authService.generateToken(mockUser); const payload = authService.verifyToken(token); expect(payload.id).toBe(mockUser.id); expect(payload.username).toBe(mockUser.username); }); it('无效token应该抛出错误', () => { const invalidToken = 'invalid.token.here'; expect(() => { authService.verifyToken(invalidToken); }).toThrow('无效的token'); }); }); describe('权限验证', () => { it('应该验证用户有权限', () => { const hasPermission = authService.hasPermission(mockUser, 'user'); expect(hasPermission).toBe(true); }); it('应该验证用户没有权限', () => { const hasPermission = authService.hasPermission(mockUser, 'admin'); expect(hasPermission).toBe(false); }); it('应该验证用户有任意一个权限', () => { const hasAnyPermission = authService.hasAnyPermission(mockUser, ['user', 'admin']); expect(hasAnyPermission).toBe(true); }); it('应该验证用户没有任意一个权限', () => { const hasAnyPermission = authService.hasAnyPermission(mockUser, ['admin', 'superuser']); expect(hasAnyPermission).toBe(false); }); }); describe('登出', () => { it('应该成功登出', async () => { const token = authService.generateToken(mockUser); await expect(authService.logout(token)).resolves.toBeUndefined(); }); it('无效token登出时应该抛出错误', async () => { const invalidToken = 'invalid.token.here'; await expect(authService.logout(invalidToken)) .rejects .toThrow('无效的token'); }); }); });