feat(image): 新建 knowai-core:1.0.0 镜像并完成推送
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
- 搭建 api、auth、utils 等逻辑模块 - 通过 tsc、eslint、vitest 测试验证 BREAKING CHANGE: 新镜像分支
This commit is contained in:
345
test/unit/api/modules/chat.test.ts
Normal file
345
test/unit/api/modules/chat.test.ts
Normal file
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* 聊天API模块测试
|
||||
* 测试聊天相关的API调用,包括创建/更新聊天会话、发送消息、获取聊天会话列表、获取聊天消息、标记消息已读等功能
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { chatApi } from '@/api/modules/chat';
|
||||
import { createMockAxios } from '@/test/mocks/http-client';
|
||||
import {
|
||||
createMockChatSession,
|
||||
createMockChatMessage,
|
||||
createMockUser
|
||||
} from '@/test/mocks/data-factory';
|
||||
import type { ApiClient } from '@/api/client';
|
||||
import type {
|
||||
CreateChatSessionRequest,
|
||||
UpdateChatSessionRequest,
|
||||
SendMessageRequest,
|
||||
GetChatSessionsRequest,
|
||||
GetChatSessionsResponse,
|
||||
GetChatMessagesRequest,
|
||||
GetChatMessagesResponse,
|
||||
MarkMessagesAsReadRequest,
|
||||
MarkMessagesAsReadResponse
|
||||
} from '@/types/chat/api';
|
||||
|
||||
describe('聊天API模块', () => {
|
||||
let mockClient: ApiClient;
|
||||
let chatApiInstance: ReturnType<typeof chatApi>;
|
||||
|
||||
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实例
|
||||
chatApiInstance = chatApi(mockClient);
|
||||
});
|
||||
|
||||
describe('创建聊天会话功能', () => {
|
||||
it('应该能够创建新的聊天会话', async () => {
|
||||
const createRequest: CreateChatSessionRequest = {
|
||||
title: '测试聊天会话',
|
||||
modelId: 'model-123',
|
||||
systemPrompt: '你是一个有用的助手'
|
||||
};
|
||||
const mockSession = createMockChatSession({
|
||||
title: createRequest.title,
|
||||
modelId: createRequest.modelId
|
||||
});
|
||||
const mockResponse = { session: mockSession };
|
||||
|
||||
mockClient.post.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await chatApiInstance.createSession(createRequest);
|
||||
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/chat/sessions', createRequest);
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理创建聊天会话失败的情况', async () => {
|
||||
const createRequest: CreateChatSessionRequest = {
|
||||
title: '',
|
||||
modelId: '',
|
||||
systemPrompt: ''
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '标题和模型ID不能为空',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.post.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(chatApiInstance.createSession(createRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/chat/sessions', createRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('更新聊天会话功能', () => {
|
||||
it('应该能够更新聊天会话', async () => {
|
||||
const updateRequest: UpdateChatSessionRequest = {
|
||||
sessionId: 'session-123',
|
||||
title: '更新后的标题'
|
||||
};
|
||||
const mockSession = createMockChatSession({
|
||||
id: updateRequest.sessionId,
|
||||
title: updateRequest.title
|
||||
});
|
||||
const mockResponse = { session: mockSession };
|
||||
|
||||
mockClient.put.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await chatApiInstance.updateSession(updateRequest);
|
||||
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/chat/sessions/session-123', { title: '更新后的标题' });
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理更新不存在会话的情况', async () => {
|
||||
const updateRequest: UpdateChatSessionRequest = {
|
||||
sessionId: 'non-existent-session',
|
||||
title: '更新后的标题'
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '会话不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.put.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(chatApiInstance.updateSession(updateRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/chat/sessions/non-existent-session', { title: '更新后的标题' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('发送消息功能', () => {
|
||||
it('应该能够发送消息', async () => {
|
||||
const sendMessageRequest: SendMessageRequest = {
|
||||
sessionId: 'session-123',
|
||||
content: '这是一条测试消息',
|
||||
role: 'user'
|
||||
};
|
||||
const mockMessage = createMockChatMessage({
|
||||
sessionId: sendMessageRequest.sessionId,
|
||||
content: sendMessageRequest.content,
|
||||
role: sendMessageRequest.role
|
||||
});
|
||||
const mockResponse = { message: mockMessage };
|
||||
|
||||
mockClient.post.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await chatApiInstance.sendMessage(sendMessageRequest);
|
||||
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/chat/sessions/session-123/messages', sendMessageRequest);
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理发送消息失败的情况', async () => {
|
||||
const sendMessageRequest: SendMessageRequest = {
|
||||
sessionId: 'session-123',
|
||||
content: '',
|
||||
role: 'user'
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '消息内容不能为空',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.post.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(chatApiInstance.sendMessage(sendMessageRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/chat/sessions/session-123/messages', sendMessageRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取聊天会话列表功能', () => {
|
||||
it('应该能够获取聊天会话列表', async () => {
|
||||
const getRequest: GetChatSessionsRequest = {
|
||||
page: 1,
|
||||
limit: 10
|
||||
};
|
||||
const mockSessions = [
|
||||
createMockChatSession({ id: 'session-1' }),
|
||||
createMockChatSession({ id: 'session-2' })
|
||||
];
|
||||
const mockResponse: GetChatSessionsResponse = {
|
||||
sessions: mockSessions,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 20,
|
||||
totalPages: 2
|
||||
}
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await chatApiInstance.getSessions(getRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/chat/sessions', { params: getRequest });
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该能够在不带参数的情况下获取聊天会话列表', async () => {
|
||||
const mockSessions = [
|
||||
createMockChatSession({ id: 'session-1' }),
|
||||
createMockChatSession({ id: 'session-2' })
|
||||
];
|
||||
const mockResponse: GetChatSessionsResponse = {
|
||||
sessions: mockSessions,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
total: 2,
|
||||
totalPages: 1
|
||||
}
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await chatApiInstance.getSessions();
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/chat/sessions', {});
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取聊天会话列表失败的情况', async () => {
|
||||
const getRequest: GetChatSessionsRequest = {
|
||||
page: -1, // 无效的页码
|
||||
limit: 10
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '页码必须大于0',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(chatApiInstance.getSessions(getRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/chat/sessions', { params: getRequest });
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取聊天消息功能', () => {
|
||||
it('应该能够获取聊天消息', async () => {
|
||||
const getRequest: GetChatMessagesRequest = {
|
||||
sessionId: 'session-123',
|
||||
page: 1,
|
||||
limit: 10
|
||||
};
|
||||
const mockMessages = [
|
||||
createMockChatMessage({ id: 'message-1', sessionId: 'session-123' }),
|
||||
createMockChatMessage({ id: 'message-2', sessionId: 'session-123' })
|
||||
];
|
||||
const mockResponse: GetChatMessagesResponse = {
|
||||
messages: mockMessages,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 30,
|
||||
totalPages: 3
|
||||
}
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await chatApiInstance.getMessages(getRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/chat/sessions/session-123/messages', {
|
||||
params: { page: 1, limit: 10 }
|
||||
});
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取不存在会话的消息的情况', async () => {
|
||||
const getRequest: GetChatMessagesRequest = {
|
||||
sessionId: 'non-existent-session',
|
||||
page: 1,
|
||||
limit: 10
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '会话不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(chatApiInstance.getMessages(getRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/chat/sessions/non-existent-session/messages', {
|
||||
params: { page: 1, limit: 10 }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('标记消息已读功能', () => {
|
||||
it('应该能够标记消息为已读', async () => {
|
||||
const markReadRequest: MarkMessagesAsReadRequest = {
|
||||
sessionId: 'session-123',
|
||||
messageIds: ['message-1', 'message-2', 'message-3']
|
||||
};
|
||||
const mockResponse: MarkMessagesAsReadResponse = {
|
||||
success: true,
|
||||
readCount: 3
|
||||
};
|
||||
|
||||
mockClient.post.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await chatApiInstance.markMessagesAsRead(markReadRequest);
|
||||
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/chat/sessions/session-123/read', {
|
||||
messageIds: ['message-1', 'message-2', 'message-3']
|
||||
});
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理标记不存在的消息为已读的情况', async () => {
|
||||
const markReadRequest: MarkMessagesAsReadRequest = {
|
||||
sessionId: 'session-123',
|
||||
messageIds: ['non-existent-message']
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '消息不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.post.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(chatApiInstance.markMessagesAsRead(markReadRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/chat/sessions/session-123/read', {
|
||||
messageIds: ['non-existent-message']
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
239
test/unit/api/modules/model.test.ts
Normal file
239
test/unit/api/modules/model.test.ts
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* AI模型API模块测试
|
||||
* 测试AI模型相关的API调用,包括获取AI模型广场、获取模型详情、获取模型评论等功能
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { modelApi } from '@/api/modules/model';
|
||||
import { createMockAxios } from '@/test/mocks/http-client';
|
||||
import {
|
||||
createMockAIModel,
|
||||
createMockModelComment,
|
||||
createMockUser
|
||||
} from '@/test/mocks/data-factory';
|
||||
import type { ApiClient } from '@/api/client';
|
||||
import type {
|
||||
GetAIPlazaRequest,
|
||||
GetAIPlazaResponse,
|
||||
GetModelDetailRequest,
|
||||
GetModelDetailResponse,
|
||||
GetModelCommentsRequest,
|
||||
GetModelCommentsResponse
|
||||
} from '@/types/model/api';
|
||||
|
||||
describe('AI模型API模块', () => {
|
||||
let mockClient: ApiClient;
|
||||
let modelApiInstance: ReturnType<typeof modelApi>;
|
||||
|
||||
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;
|
||||
|
||||
// 创建AI模型API实例
|
||||
modelApiInstance = modelApi(mockClient);
|
||||
});
|
||||
|
||||
describe('获取AI模型广场功能', () => {
|
||||
it('应该能够获取AI模型广场数据', async () => {
|
||||
const getRequest: GetAIPlazaRequest = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
category: 'text-generation'
|
||||
};
|
||||
const mockModels = [
|
||||
createMockAIModel({ id: 'model-1', category: 'text-generation' }),
|
||||
createMockAIModel({ id: 'model-2', category: 'text-generation' })
|
||||
];
|
||||
const mockResponse: GetAIPlazaResponse = {
|
||||
models: mockModels,
|
||||
categories: [
|
||||
{ id: 'text-generation', name: '文本生成', count: 50 },
|
||||
{ id: 'image-generation', name: '图像生成', count: 30 }
|
||||
],
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 50,
|
||||
totalPages: 5
|
||||
}
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await modelApiInstance.getAIPlaza(getRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/models/plaza', { params: getRequest });
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该能够在不带参数的情况下获取AI模型广场数据', async () => {
|
||||
const mockModels = [
|
||||
createMockAIModel({ id: 'model-1' }),
|
||||
createMockAIModel({ id: 'model-2' })
|
||||
];
|
||||
const mockResponse: GetAIPlazaResponse = {
|
||||
models: mockModels,
|
||||
categories: [
|
||||
{ id: 'text-generation', name: '文本生成', count: 50 },
|
||||
{ id: 'image-generation', name: '图像生成', count: 30 }
|
||||
],
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
total: 2,
|
||||
totalPages: 1
|
||||
}
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await modelApiInstance.getAIPlaza();
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/models/plaza', {});
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取AI模型广场失败的情况', async () => {
|
||||
const getRequest: GetAIPlazaRequest = {
|
||||
page: -1, // 无效的页码
|
||||
limit: 10
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '页码必须大于0',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(modelApiInstance.getAIPlaza(getRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/models/plaza', { params: getRequest });
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取模型详情功能', () => {
|
||||
it('应该能够获取模型详情', async () => {
|
||||
const getRequest: GetModelDetailRequest = {
|
||||
modelId: 'model-123'
|
||||
};
|
||||
const mockModel = createMockAIModel({ id: 'model-123' });
|
||||
const mockResponse: GetModelDetailResponse = {
|
||||
model: mockModel,
|
||||
relatedModels: [
|
||||
createMockAIModel({ id: 'related-1' }),
|
||||
createMockAIModel({ id: 'related-2' })
|
||||
]
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await modelApiInstance.getModelDetail(getRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/models/model-123', { params: {} });
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取不存在模型详情的情况', async () => {
|
||||
const getRequest: GetModelDetailRequest = {
|
||||
modelId: 'non-existent-model'
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '模型不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(modelApiInstance.getModelDetail(getRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/models/non-existent-model', { params: {} });
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取模型评论功能', () => {
|
||||
it('应该能够获取模型评论', async () => {
|
||||
const getRequest: GetModelCommentsRequest = {
|
||||
modelId: 'model-123',
|
||||
page: 1,
|
||||
limit: 10,
|
||||
sortBy: 'newest'
|
||||
};
|
||||
const mockComments = [
|
||||
createMockModelComment({ id: 'comment-1', modelId: 'model-123' }),
|
||||
createMockModelComment({ id: 'comment-2', modelId: 'model-123' })
|
||||
];
|
||||
const mockResponse: GetModelCommentsResponse = {
|
||||
comments: mockComments,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 25,
|
||||
totalPages: 3
|
||||
},
|
||||
statistics: {
|
||||
averageRating: 4.5,
|
||||
totalComments: 25,
|
||||
ratingDistribution: {
|
||||
5: 15,
|
||||
4: 7,
|
||||
3: 2,
|
||||
2: 1,
|
||||
1: 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await modelApiInstance.getModelComments(getRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/models/model-123/comments', {
|
||||
params: { page: 1, limit: 10, sortBy: 'newest' }
|
||||
});
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取不存在模型的评论的情况', async () => {
|
||||
const getRequest: GetModelCommentsRequest = {
|
||||
modelId: 'non-existent-model',
|
||||
page: 1,
|
||||
limit: 10
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '模型不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(modelApiInstance.getModelComments(getRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/models/non-existent-model/comments', {
|
||||
params: { page: 1, limit: 10 }
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
408
test/unit/api/modules/post.test.ts
Normal file
408
test/unit/api/modules/post.test.ts
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* 帖子API模块测试
|
||||
* 测试帖子相关的API调用,包括创建帖子、获取帖子列表、点赞、评论等功能
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { postApi } from '@/api/modules/post';
|
||||
import { createMockAxios } from '@/test/mocks/http-client';
|
||||
import {
|
||||
createMockPost,
|
||||
createMockUser,
|
||||
createMockPostComment
|
||||
} from '@/test/mocks/data-factory';
|
||||
import type { ApiClient } from '@/api/client';
|
||||
import type {
|
||||
CreatePostRequest,
|
||||
CreatePostResponse,
|
||||
GetPostsRequest,
|
||||
GetPostsResponse,
|
||||
GetPostRequest,
|
||||
GetPostResponse,
|
||||
LikePostRequest,
|
||||
LikePostResponse,
|
||||
BookmarkPostRequest,
|
||||
BookmarkPostResponse,
|
||||
CreateCommentRequest,
|
||||
CreateCommentResponse,
|
||||
GetCommentsRequest,
|
||||
GetCommentsResponse,
|
||||
LikeCommentRequest,
|
||||
LikeCommentResponse
|
||||
} from '@/types/post/api';
|
||||
|
||||
describe('帖子API模块', () => {
|
||||
let mockClient: ApiClient;
|
||||
let postApiInstance: ReturnType<typeof postApi>;
|
||||
|
||||
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实例
|
||||
postApiInstance = postApi(mockClient);
|
||||
});
|
||||
|
||||
describe('创建帖子功能', () => {
|
||||
it('应该能够创建新帖子', async () => {
|
||||
const createRequest: CreatePostRequest = {
|
||||
title: '测试帖子标题',
|
||||
content: '这是一个测试帖子的内容',
|
||||
tags: ['测试', 'API'],
|
||||
isPublic: true
|
||||
};
|
||||
const mockPost = createMockPost({
|
||||
title: createRequest.title,
|
||||
content: createRequest.content,
|
||||
tags: createRequest.tags
|
||||
});
|
||||
const mockResponse: CreatePostResponse = {
|
||||
success: true,
|
||||
data: mockPost,
|
||||
message: '帖子创建成功',
|
||||
code: 201
|
||||
};
|
||||
|
||||
mockClient.post.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.createPost(createRequest);
|
||||
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/posts', createRequest);
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理创建帖子失败的情况', async () => {
|
||||
const createRequest: CreatePostRequest = {
|
||||
title: '',
|
||||
content: '',
|
||||
tags: [],
|
||||
isPublic: true
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '标题和内容不能为空',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.post.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.createPost(createRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/posts', createRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取帖子列表功能', () => {
|
||||
it('应该能够获取帖子列表', async () => {
|
||||
const getRequest: GetPostsRequest = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
tag: '测试'
|
||||
};
|
||||
const mockPosts = [
|
||||
createMockPost({ id: 'post-1' }),
|
||||
createMockPost({ id: 'post-2' })
|
||||
];
|
||||
const mockResponse: GetPostsResponse = {
|
||||
success: true,
|
||||
data: {
|
||||
posts: mockPosts,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 100,
|
||||
totalPages: 10
|
||||
}
|
||||
},
|
||||
message: '获取帖子列表成功',
|
||||
code: 200
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.getPosts(getRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/posts', { params: getRequest });
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取帖子列表失败的情况', async () => {
|
||||
const getRequest: GetPostsRequest = {
|
||||
page: -1, // 无效的页码
|
||||
limit: 10
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '页码必须大于0',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.getPosts(getRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/posts', { params: getRequest });
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取帖子详情功能', () => {
|
||||
it('应该能够获取帖子详情', async () => {
|
||||
const getRequest: GetPostRequest = { postId: 'post-123' };
|
||||
const mockPost = createMockPost({ id: 'post-123' });
|
||||
const mockResponse: GetPostResponse = {
|
||||
success: true,
|
||||
data: mockPost,
|
||||
message: '获取帖子详情成功',
|
||||
code: 200
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.getPost(getRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/posts/post-123');
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取不存在帖子的情况', async () => {
|
||||
const getRequest: GetPostRequest = { postId: 'non-existent-post' };
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '帖子不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.getPost(getRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/posts/non-existent-post');
|
||||
});
|
||||
});
|
||||
|
||||
describe('点赞帖子功能', () => {
|
||||
it('应该能够点赞帖子', async () => {
|
||||
const likeRequest: LikePostRequest = { postId: 'post-123' };
|
||||
const mockResponse: LikePostResponse = {
|
||||
success: true,
|
||||
message: '点赞成功',
|
||||
code: 200
|
||||
};
|
||||
|
||||
mockClient.put.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.likePost(likeRequest);
|
||||
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/posts/post-123/like');
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理点赞不存在帖子的情况', async () => {
|
||||
const likeRequest: LikePostRequest = { postId: 'non-existent-post' };
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '帖子不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.put.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.likePost(likeRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/posts/non-existent-post/like');
|
||||
});
|
||||
});
|
||||
|
||||
describe('收藏帖子功能', () => {
|
||||
it('应该能够收藏帖子', async () => {
|
||||
const bookmarkRequest: BookmarkPostRequest = { postId: 'post-123' };
|
||||
const mockResponse: BookmarkPostResponse = {
|
||||
success: true,
|
||||
message: '收藏成功',
|
||||
code: 200
|
||||
};
|
||||
|
||||
mockClient.put.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.bookmarkPost(bookmarkRequest);
|
||||
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/posts/post-123/bookmark');
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理收藏不存在帖子的情况', async () => {
|
||||
const bookmarkRequest: BookmarkPostRequest = { postId: 'non-existent-post' };
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '帖子不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.put.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.bookmarkPost(bookmarkRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/posts/non-existent-post/bookmark');
|
||||
});
|
||||
});
|
||||
|
||||
describe('创建评论功能', () => {
|
||||
it('应该能够创建评论', async () => {
|
||||
const commentRequest: CreateCommentRequest = {
|
||||
postId: 'post-123',
|
||||
content: '这是一个测试评论',
|
||||
parentId: 'parent-comment-123'
|
||||
};
|
||||
const mockComment = createMockPostComment({
|
||||
postId: commentRequest.postId,
|
||||
content: commentRequest.content,
|
||||
parentId: commentRequest.parentId
|
||||
});
|
||||
const mockResponse: CreateCommentResponse = {
|
||||
success: true,
|
||||
data: mockComment,
|
||||
message: '评论创建成功',
|
||||
code: 201
|
||||
};
|
||||
|
||||
mockClient.post.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.createComment(commentRequest);
|
||||
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/posts/post-123/comments', commentRequest);
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理创建评论失败的情况', async () => {
|
||||
const commentRequest: CreateCommentRequest = {
|
||||
postId: 'post-123',
|
||||
content: '', // 空评论内容
|
||||
parentId: 'parent-comment-123'
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '评论内容不能为空',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.post.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.createComment(commentRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.post).toHaveBeenCalledWith('/posts/post-123/comments', commentRequest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('获取评论列表功能', () => {
|
||||
it('应该能够获取评论列表', async () => {
|
||||
const commentsRequest: GetCommentsRequest = {
|
||||
postId: 'post-123',
|
||||
page: 1,
|
||||
limit: 10,
|
||||
sortBy: 'createdAt',
|
||||
sortOrder: 'desc'
|
||||
};
|
||||
const mockComments = [
|
||||
createMockPostComment({ id: 'comment-1', postId: 'post-123' }),
|
||||
createMockPostComment({ id: 'comment-2', postId: 'post-123' })
|
||||
];
|
||||
const mockResponse: GetCommentsResponse = {
|
||||
success: true,
|
||||
data: {
|
||||
comments: mockComments,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 50,
|
||||
totalPages: 5
|
||||
}
|
||||
},
|
||||
message: '获取评论列表成功',
|
||||
code: 200
|
||||
};
|
||||
|
||||
mockClient.get.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.getComments(commentsRequest);
|
||||
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/posts/post-123/comments', {
|
||||
params: { page: 1, limit: 10, sortBy: 'createdAt', sortOrder: 'desc' }
|
||||
});
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理获取评论列表失败的情况', async () => {
|
||||
const commentsRequest: GetCommentsRequest = {
|
||||
postId: 'post-123',
|
||||
page: -1, // 无效的页码
|
||||
limit: 10
|
||||
};
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '页码必须大于0',
|
||||
code: 400
|
||||
};
|
||||
|
||||
mockClient.get.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.getComments(commentsRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.get).toHaveBeenCalledWith('/posts/post-123/comments', {
|
||||
params: { page: -1, limit: 10 }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('点赞评论功能', () => {
|
||||
it('应该能够点赞评论', async () => {
|
||||
const likeCommentRequest: LikeCommentRequest = { commentId: 'comment-123' };
|
||||
const mockResponse: LikeCommentResponse = {
|
||||
success: true,
|
||||
message: '点赞评论成功',
|
||||
code: 200
|
||||
};
|
||||
|
||||
mockClient.put.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await postApiInstance.likeComment(likeCommentRequest);
|
||||
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/comments/comment-123/like');
|
||||
expect(result).toEqual(mockResponse);
|
||||
});
|
||||
|
||||
it('应该处理点赞不存在评论的情况', async () => {
|
||||
const likeCommentRequest: LikeCommentRequest = { commentId: 'non-existent-comment' };
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
data: null,
|
||||
message: '评论不存在',
|
||||
code: 404
|
||||
};
|
||||
|
||||
mockClient.put.mockRejectedValue(errorResponse);
|
||||
|
||||
await expect(postApiInstance.likeComment(likeCommentRequest)).rejects.toEqual(errorResponse);
|
||||
expect(mockClient.put).toHaveBeenCalledWith('/comments/non-existent-comment/like');
|
||||
});
|
||||
});
|
||||
})
|
||||
334
test/unit/api/modules/user.test.ts
Normal file
334
test/unit/api/modules/user.test.ts
Normal file
@@ -0,0 +1,334 @@
|
||||
/**
|
||||
* 用户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');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user