Files
knowai/test/unit/api/modules/chat.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

345 lines
11 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 { 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']
});
});
});
});