Files
knowai/test/unit/api/modules/user.test.ts
tobegold574 6a81b7bb13
Some checks reported errors
continuous-integration/drone/push Build was killed
feat(image): 新建 knowai-core:1.0.0 镜像并完成推送
- 搭建 api、auth、utils 等逻辑模块
- 通过 tsc、eslint、vitest 测试验证

BREAKING CHANGE: 新镜像分支
2025-11-10 20:20:25 +08:00

334 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 用户API模块测试
* 测试用户相关的API调用包括登录、注册、刷新令牌、获取/更新用户档案、关注/取消关注用户等功能
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { userApi } from '@/api/modules/user';
import { createMockAxios } from '@/test/mocks/http-client';
import {
createMockUser,
createMockUserProfile
} from '@/test/mocks/data-factory';
import type { ApiClient } from '@/api/client';
import type {
LoginRequest,
LoginResponse,
RegisterRequest,
RegisterResponse,
RefreshTokenRequest,
RefreshTokenResponse,
UserProfileUpdateRequest,
UserProfileUpdateResponse,
UserFollowRequest,
UserFollowResponse
} from '@/types/user';
describe('用户API模块', () => {
let mockClient: ApiClient;
let userApiInstance: ReturnType<typeof userApi>;
beforeEach(() => {
// 创建模拟的API客户端
mockClient = {
get: vi.fn(),
post: vi.fn(),
put: vi.fn(),
delete: vi.fn(),
patch: vi.fn(),
request: vi.fn(),
getWithResponse: vi.fn(),
postWithResponse: vi.fn(),
putWithResponse: vi.fn(),
deleteWithResponse: vi.fn(),
patchWithResponse: vi.fn(),
requestWithResponse: vi.fn(),
addRequestInterceptor: vi.fn(),
addResponseInterceptor: vi.fn(),
removeRequestInterceptor: vi.fn(),
removeResponseInterceptor: vi.fn(),
setDefaults: vi.fn(),
setBaseURL: vi.fn(),
createInstance: vi.fn(),
} as unknown as ApiClient;
// 创建用户API实例
userApiInstance = userApi(mockClient);
});
describe('用户登录功能', () => {
it('应该能够成功登录', async () => {
const loginRequest: LoginRequest = {
username: 'test@example.com',
password: 'password123'
};
const mockUser = createMockUser({ username: loginRequest.username });
const mockResponse: LoginResponse = {
user: mockUser,
sessionId: 'session-123'
};
mockClient.post.mockResolvedValue(mockResponse);
const result = await userApiInstance.login(loginRequest);
expect(mockClient.post).toHaveBeenCalledWith('/auth/login', loginRequest);
expect(result).toEqual(mockResponse);
});
it('应该处理登录失败的情况', async () => {
const loginRequest: LoginRequest = {
username: 'wrong@example.com',
password: 'wrongpassword'
};
const errorResponse = {
success: false,
data: null,
message: '用户名或密码错误',
code: 401
};
mockClient.post.mockRejectedValue(errorResponse);
await expect(userApiInstance.login(loginRequest)).rejects.toEqual(errorResponse);
expect(mockClient.post).toHaveBeenCalledWith('/auth/login', loginRequest);
});
});
describe('用户注册功能', () => {
it('应该能够成功注册', async () => {
const registerRequest: RegisterRequest = {
username: 'newuser',
email: 'newuser@example.com',
password: 'password123'
};
const mockUser = createMockUser({
username: registerRequest.username,
email: registerRequest.email
});
const mockResponse: RegisterResponse = {
user: mockUser,
sessionId: 'session-456'
};
mockClient.post.mockResolvedValue(mockResponse);
const result = await userApiInstance.register(registerRequest);
expect(mockClient.post).toHaveBeenCalledWith('/auth/register', registerRequest);
expect(result).toEqual(mockResponse);
});
it('应该处理注册失败的情况', async () => {
const registerRequest: RegisterRequest = {
username: '',
email: 'invalid-email',
password: '123' // 密码太短
};
const errorResponse = {
success: false,
data: null,
message: '用户名不能为空邮箱格式不正确密码长度至少为6位',
code: 400
};
mockClient.post.mockRejectedValue(errorResponse);
await expect(userApiInstance.register(registerRequest)).rejects.toEqual(errorResponse);
expect(mockClient.post).toHaveBeenCalledWith('/auth/register', registerRequest);
});
});
describe('刷新令牌功能', () => {
it('应该能够成功刷新令牌', async () => {
const refreshTokenRequest: RefreshTokenRequest = {
sessionId: 'session-456'
};
const mockResponse: RefreshTokenResponse = {
sessionId: 'new-session-789'
};
mockClient.post.mockResolvedValue(mockResponse);
const result = await userApiInstance.refreshToken(refreshTokenRequest);
expect(mockClient.post).toHaveBeenCalledWith('/auth/refresh', refreshTokenRequest);
expect(result).toEqual(mockResponse);
});
it('应该处理刷新令牌失败的情况', async () => {
const refreshTokenRequest: RefreshTokenRequest = {
sessionId: 'invalid-session'
};
const errorResponse = {
success: false,
data: null,
message: '会话无效或已过期',
code: 401
};
mockClient.post.mockRejectedValue(errorResponse);
await expect(userApiInstance.refreshToken(refreshTokenRequest)).rejects.toEqual(errorResponse);
expect(mockClient.post).toHaveBeenCalledWith('/auth/refresh', refreshTokenRequest);
});
});
describe('获取用户档案功能', () => {
it('应该能够获取用户档案', async () => {
const mockUserProfile = createMockUserProfile();
const mockResponse: UserProfileUpdateResponse = {
success: true,
data: mockUserProfile,
message: '获取用户档案成功',
code: 200
};
mockClient.get.mockResolvedValue(mockResponse);
const result = await userApiInstance.getProfile();
expect(mockClient.get).toHaveBeenCalledWith('/user/profile');
expect(result).toEqual(mockResponse);
});
it('应该处理获取用户档案失败的情况', async () => {
const errorResponse = {
success: false,
data: null,
message: '用户未登录',
code: 401
};
mockClient.get.mockRejectedValue(errorResponse);
await expect(userApiInstance.getProfile()).rejects.toEqual(errorResponse);
expect(mockClient.get).toHaveBeenCalledWith('/user/profile');
});
});
describe('更新用户档案功能', () => {
it('应该能够更新用户档案', async () => {
const updateRequest: UserProfileUpdateRequest = {
username: 'updateduser',
bio: '这是我的个人简介',
avatar: 'https://example.com/avatar.jpg'
};
const mockUserProfile = createMockUserProfile(updateRequest);
const mockResponse: UserProfileUpdateResponse = {
success: true,
data: mockUserProfile,
message: '用户档案更新成功',
code: 200
};
mockClient.put.mockResolvedValue(mockResponse);
const result = await userApiInstance.updateProfile(updateRequest);
expect(mockClient.put).toHaveBeenCalledWith('/user/profile', updateRequest);
expect(result).toEqual(mockResponse);
});
it('应该处理更新用户档案失败的情况', async () => {
const updateRequest: UserProfileUpdateRequest = {
username: '', // 用户名不能为空
bio: '',
avatar: ''
};
const errorResponse = {
success: false,
data: null,
message: '用户名不能为空',
code: 400
};
mockClient.put.mockRejectedValue(errorResponse);
await expect(userApiInstance.updateProfile(updateRequest)).rejects.toEqual(errorResponse);
expect(mockClient.put).toHaveBeenCalledWith('/user/profile', updateRequest);
});
});
describe('关注用户功能', () => {
it('应该能够关注用户', async () => {
const followRequest: UserFollowRequest = {
userId: 'user-123'
};
const mockResponse: UserFollowResponse = {
success: true,
data: {
isFollowing: true,
followersCount: 101
},
message: '关注成功',
code: 200
};
mockClient.put.mockResolvedValue(mockResponse);
const result = await userApiInstance.followUser(followRequest);
expect(mockClient.put).toHaveBeenCalledWith('/user/follow/user-123');
expect(result).toEqual(mockResponse);
});
it('应该处理关注不存在的用户的情况', async () => {
const followRequest: UserFollowRequest = {
userId: 'non-existent-user'
};
const errorResponse = {
success: false,
data: null,
message: '用户不存在',
code: 404
};
mockClient.put.mockRejectedValue(errorResponse);
await expect(userApiInstance.followUser(followRequest)).rejects.toEqual(errorResponse);
expect(mockClient.put).toHaveBeenCalledWith('/user/follow/non-existent-user');
});
});
describe('取消关注用户功能', () => {
it('应该能够取消关注用户', async () => {
const unfollowRequest: UserFollowRequest = {
userId: 'user-123'
};
const mockResponse: UserFollowResponse = {
success: true,
data: {
isFollowing: false,
followersCount: 99
},
message: '取消关注成功',
code: 200
};
mockClient.delete.mockResolvedValue(mockResponse);
const result = await userApiInstance.unfollowUser(unfollowRequest);
expect(mockClient.delete).toHaveBeenCalledWith('/user/follow/user-123');
expect(result).toEqual(mockResponse);
});
it('应该处理取消关注不存在的用户的情况', async () => {
const unfollowRequest: UserFollowRequest = {
userId: 'non-existent-user'
};
const errorResponse = {
success: false,
data: null,
message: '用户不存在',
code: 404
};
mockClient.delete.mockRejectedValue(errorResponse);
await expect(userApiInstance.unfollowUser(unfollowRequest)).rejects.toEqual(errorResponse);
expect(mockClient.delete).toHaveBeenCalledWith('/user/follow/non-existent-user');
});
});
});