/** * 聊天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; 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'] }); }); }); });