From 0c2e1a353449d482e0b774ec6c67a7b755ae40e3 Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Wed, 19 Mar 2025 23:09:32 +0100 Subject: [PATCH 1/6] Update chat endpoint in ChatService to new API path Replaced '/ask' with '/api/v1/chats' to align with updated API specifications. This ensures compatibility with the latest backend changes and avoids potential request failures. --- src/services/ChatService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/ChatService.ts b/src/services/ChatService.ts index 88039b1..9b4b334 100644 --- a/src/services/ChatService.ts +++ b/src/services/ChatService.ts @@ -40,7 +40,7 @@ export class ChatService extends APIClient { } async sendMessage(payload: ChatPayload): Promise> { - return this.fetchWithError('/ask', { + return this.fetchWithError('/api/v1/chats', { method: 'POST', body: JSON.stringify(payload), }); From d6a0466ed887f1dc7c4198e4f5c4f8050f5f975e Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Wed, 19 Mar 2025 23:44:41 +0100 Subject: [PATCH 2/6] Add chat UUID handling from API response headers Added support for extracting and handling `X-Chat-Uuid` from API response headers. Updated `ChatService` to pass chat UUID to a callback, and `ChatContainer` to set it when not already defined. Enhanced `APIClient` to merge custom headers and enforce CORS mode. --- .../ChatContainer/ChatContainer.tsx | 10 +++++++++ src/services/APIClient.ts | 6 ++++- src/services/ChatService.ts | 22 ++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/components/ChatContainer/ChatContainer.tsx b/src/components/ChatContainer/ChatContainer.tsx index 816c0e3..831aa67 100644 --- a/src/components/ChatContainer/ChatContainer.tsx +++ b/src/components/ChatContainer/ChatContainer.tsx @@ -164,6 +164,11 @@ export const ChatContainer: React.FC = ({ }) }; + if (chatUuid) { + payload.chat_uuid = chatUuid; + } + + if (config.streamResponse) { await handleStreamingResponse(chatService, payload); } else { @@ -209,6 +214,11 @@ export const ChatContainer: React.FC = ({ return newMessages; }); } + }, + (headerChatUuid) => { + if (headerChatUuid && !chatUuid) { + setChatUuid(headerChatUuid); + } } ); }; diff --git a/src/services/APIClient.ts b/src/services/APIClient.ts index 265c4dc..0843b53 100644 --- a/src/services/APIClient.ts +++ b/src/services/APIClient.ts @@ -54,7 +54,11 @@ export class APIClient { ): Promise { const response = await fetch(`${this.baseUrl}${endpoint}`, { ...options, - headers: this.getHeaders(), + headers: { + ...this.getHeaders(), + ...options.headers + }, + mode: 'cors', }); if (!response.ok) { diff --git a/src/services/ChatService.ts b/src/services/ChatService.ts index 9b4b334..199dd2b 100644 --- a/src/services/ChatService.ts +++ b/src/services/ChatService.ts @@ -52,7 +52,8 @@ export class ChatService extends APIClient { async sendStreamMessage( payload: ChatPayload, - onChunk: (chunk: StreamChunk) => void + onChunk: (chunk: StreamChunk) => void, + onHeaderChatUuid?: (chatUuid: string) => void ): Promise { try { const response = await this.fetchStream('/api/v1/chats/stream', { @@ -60,6 +61,25 @@ export class ChatService extends APIClient { body: JSON.stringify(payload), }); + //const chatUuid = response.headers.get('X-Chat-Uuid'); + // Debug: Log all available headers + console.log('All response headers:'); + response.headers.forEach((value, name) => { + console.log(`${name}: ${value}`); + }); + + // Try both casing variants + const chatUuid = response.headers.get('X-Chat-Uuid'); + const chatUUID = response.headers.get('x-chat-uuid'); // Try lowercase + console.log('Chat UUID (X-Chat-Uuid):', chatUuid); + console.log('Chat UUID (x-chat-uuid):', chatUUID); + + + if (chatUuid && onHeaderChatUuid) { + onHeaderChatUuid(chatUuid); + } + + const reader = response.body?.getReader(); if (!reader) { throw new Error('Response body is not readable'); From 4f709e8a0310ec298bd70de3c90c3d7a7992460c Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Thu, 20 Mar 2025 00:07:16 +0100 Subject: [PATCH 3/6] Add unit tests for ChatService API client This commit introduces unit tests for the ChatService API client, including both streaming and synchronous message handling. The tests verify proper callback handling, chat UUID extraction, and payload processing. Mocking is used to simulate service behavior effectively. --- src/services/api-client.test.ts | 113 ++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/services/api-client.test.ts diff --git a/src/services/api-client.test.ts b/src/services/api-client.test.ts new file mode 100644 index 0000000..d398571 --- /dev/null +++ b/src/services/api-client.test.ts @@ -0,0 +1,113 @@ +// Mock ChatService +import {ChatService} from "./ChatService.ts"; +import {ChatPayload} from "../types/chat.ts"; + +jest.mock("./ChatService", () => { + return { + ChatService: jest.fn().mockImplementation(() => ({ + sendStreamMessage: jest.fn().mockImplementation((_payload, onChunk, onHeaderChatUuid) => { + // Simulate response with chat UUID + const mockChatUuid = "123e4567-e89b-12d3-a456-426614174000"; + + // Call the callbacks as the real service would + onHeaderChatUuid(mockChatUuid); + onChunk({ content: "Hello, " }); + onChunk({ content: "world!" }); + onChunk({ content: "", done: true }); + + return Promise.resolve(); + }), + + sendMessage: jest.fn().mockImplementation((payload) => { + // Simulate response with chat UUID + const mockChatUuid = payload.chat_uuid || "123e4567-e89b-12d3-a456-426614174000"; + + return Promise.resolve({ + data: { + chat_uuid: mockChatUuid, + answer: "Mock response", + input_token: 10, + output_token: 5 + } + }); + }) + })) + }; +}); + +describe('Chat API Client', () => { + let chatService: any; + + beforeEach(() => { + jest.clearAllMocks(); + chatService = new ChatService('mock-token'); + }); + + // Helper function to create sample payload + const createSamplePayload = (question: string, chatUuid: string = ""): ChatPayload => ({ + question, + selectedTools: [], + modelSettings: { + temperature: 0.5, + maxTokens: 2000, + topP: 0.5, + topK: 50 + }, + chat_uuid: chatUuid, + llmProvider: { + provider: "Anthropic", + modelId: "claude-3-5-haiku-latest" + }, + stream_settings: { + chunk_size: 1, + delay_ms: 10 + } + }); + + describe('Chat Streaming', () => { + it('should handle stream response and extract UUID', async () => { + // Create mock callbacks + const onChunk = jest.fn(); + const onHeaderChatUuid = jest.fn(); + + // Create payload + const payload = createSamplePayload("Hello"); + + // Call the mocked service + await chatService.sendStreamMessage(payload, onChunk, onHeaderChatUuid); + + // Verify callbacks were called + expect(onHeaderChatUuid).toHaveBeenCalledWith("123e4567-e89b-12d3-a456-426614174000"); + expect(onChunk).toHaveBeenCalledTimes(3); + expect(onChunk).toHaveBeenNthCalledWith(1, { content: "Hello, " }); + expect(onChunk).toHaveBeenNthCalledWith(2, { content: "world!" }); + expect(onChunk).toHaveBeenNthCalledWith(3, { content: "", done: true }); + }); + }); + + describe('Chat Synchronous API', () => { + it('should send and receive message with chat UUID', async () => { + // Create payload without UUID (new chat) + const payload = createSamplePayload("Hello"); + + // Call the mocked service + const result = await chatService.sendMessage(payload); + + // Verify response contains chat UUID + expect(result.data).toHaveProperty('chat_uuid'); + expect(result.data.chat_uuid).toBe("123e4567-e89b-12d3-a456-426614174000"); + }); + + it('should preserve existing chat UUID in subsequent requests', async () => { + // Create payload with existing UUID + const existingUuid = "existing-uuid-123"; + const payload = createSamplePayload("Follow-up question", existingUuid); + + // Call the mocked service + const result = await chatService.sendMessage(payload); + + // Verify same UUID is returned + expect(result.data.chat_uuid).toBe(existingUuid); + }); + }); +}); \ No newline at end of file From e2639cfcea6612b645bc576a420dadfe810d01a3 Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Thu, 20 Mar 2025 00:15:34 +0100 Subject: [PATCH 4/6] Expand and refactor ChatService test suite for better coverage Added comprehensive tests to cover streaming, chat history, UUID handling, and error scenarios. Refactored mocks to simulate more realistic behaviors and ensure clarity. This improves the reliability and robustness of ChatService unit tests. --- src/services/api-client.test.ts | 215 +++++++++++++++++++++++++++----- 1 file changed, 186 insertions(+), 29 deletions(-) diff --git a/src/services/api-client.test.ts b/src/services/api-client.test.ts index d398571..cbfc2d9 100644 --- a/src/services/api-client.test.ts +++ b/src/services/api-client.test.ts @@ -1,40 +1,83 @@ -// Mock ChatService -import {ChatService} from "./ChatService.ts"; -import {ChatPayload} from "../types/chat.ts"; +// api-client.test.ts +import { ChatService } from "./ChatService"; +import { ChatPayload } from "../types/chat"; +// Mock ChatService jest.mock("./ChatService", () => { + const streamMessageMock = jest.fn().mockImplementation((payload, onChunk, onHeaderChatUuid) => { + // Use the chat_uuid from payload if provided + const mockChatUuid = payload.chat_uuid || "123e4567-e89b-12d3-a456-426614174000"; + + // Call the onHeaderChatUuid callback with the UUID + onHeaderChatUuid(mockChatUuid); + + // Simulate streaming chunks + onChunk({ content: "Hello, " }); + onChunk({ content: "world!" }); + onChunk({ content: "", done: true }); + + return Promise.resolve(); + }); + + const sendMessageMock = jest.fn().mockImplementation((payload) => { + // Use the chat_uuid from payload if provided + const mockChatUuid = payload.chat_uuid || "123e4567-e89b-12d3-a456-426614174000"; + + return Promise.resolve({ + data: { + chat_uuid: mockChatUuid, + answer: "Mock response", + input_token: 10, + output_token: 5 + } + }); + }); + + const loadChatHistoryMock = jest.fn().mockImplementation((chatUuid) => { + // Use the provided chatUuid in response for clearer testing + return Promise.resolve({ + data: { + chatUuid: chatUuid, // Use the parameter + messages: [ + { Text: "Hello", IsUser: true }, + { Text: "Hi there! How can I help you?", IsUser: false } + ] + } + }); + }); + + const getChatHistoriesMock = jest.fn().mockImplementation(() => { + return Promise.resolve({ + data: [ + { chatUuid: "123e4567-e89b-12d3-a456-426614174000", title: "Chat 1", timestamp: "2023-07-01T12:00:00Z" }, + { chatUuid: "223e4567-e89b-12d3-a456-426614174001", title: "Chat 2", timestamp: "2023-07-02T12:00:00Z" } + ] + }); + }); + + const deleteChatMock = jest.fn().mockImplementation((chatUuid) => { + // Use the provided chatUuid in response for clearer testing + return Promise.resolve({ + status: 200, + data: { + success: true, + deletedChatUuid: chatUuid // Use the parameter + } + }); + }); + return { ChatService: jest.fn().mockImplementation(() => ({ - sendStreamMessage: jest.fn().mockImplementation((_payload, onChunk, onHeaderChatUuid) => { - // Simulate response with chat UUID - const mockChatUuid = "123e4567-e89b-12d3-a456-426614174000"; - - // Call the callbacks as the real service would - onHeaderChatUuid(mockChatUuid); - onChunk({ content: "Hello, " }); - onChunk({ content: "world!" }); - onChunk({ content: "", done: true }); - - return Promise.resolve(); - }), - - sendMessage: jest.fn().mockImplementation((payload) => { - // Simulate response with chat UUID - const mockChatUuid = payload.chat_uuid || "123e4567-e89b-12d3-a456-426614174000"; - - return Promise.resolve({ - data: { - chat_uuid: mockChatUuid, - answer: "Mock response", - input_token: 10, - output_token: 5 - } - }); - }) + sendStreamMessage: streamMessageMock, + sendMessage: sendMessageMock, + loadChatHistory: loadChatHistoryMock, + getChatHistories: getChatHistoriesMock, + deleteChat: deleteChatMock })) }; }); + describe('Chat API Client', () => { let chatService: any; @@ -83,6 +126,22 @@ describe('Chat API Client', () => { expect(onChunk).toHaveBeenNthCalledWith(2, { content: "world!" }); expect(onChunk).toHaveBeenNthCalledWith(3, { content: "", done: true }); }); + + it('should preserve existing chat UUID in stream requests', async () => { + // Create mock callbacks + const onChunk = jest.fn(); + const onHeaderChatUuid = jest.fn(); + + // Create payload with existing UUID + const existingUuid = "existing-uuid-123"; + const payload = createSamplePayload("Follow-up question", existingUuid); + + // Call the mocked service + await chatService.sendStreamMessage(payload, onChunk, onHeaderChatUuid); + + // Verify the same UUID is returned + expect(onHeaderChatUuid).toHaveBeenCalledWith(existingUuid); + }); }); describe('Chat Synchronous API', () => { @@ -110,4 +169,102 @@ describe('Chat API Client', () => { expect(result.data.chat_uuid).toBe(existingUuid); }); }); + + describe('Chat History Management', () => { + it('should load chat history for a given UUID', async () => { + const chatUuid = "123e4567-e89b-12d3-a456-426614174000"; + + // Load chat history + const result = await chatService.loadChatHistory(chatUuid); + + // Verify the response contains messages + expect(result.data).toHaveProperty('messages'); + expect(result.data.messages).toHaveLength(2); + expect(result.data.messages[0].Text).toBe("Hello"); + expect(result.data.messages[0].IsUser).toBe(true); + expect(result.data.messages[1].Text).toBe("Hi there! How can I help you?"); + expect(result.data.messages[1].IsUser).toBe(false); + }); + + it('should retrieve list of chat histories', async () => { + // Get chat histories + const result = await chatService.getChatHistories(); + + // Verify the response contains list of chats + expect(Array.isArray(result.data)).toBe(true); + expect(result.data).toHaveLength(2); + expect(result.data[0].chatUuid).toBe("123e4567-e89b-12d3-a456-426614174000"); + expect(result.data[1].chatUuid).toBe("223e4567-e89b-12d3-a456-426614174001"); + }); + + it('should delete a chat by UUID', async () => { + const chatUuid = "123e4567-e89b-12d3-a456-426614174000"; + + // Delete chat + const result = await chatService.deleteChat(chatUuid); + + // Verify the response indicates success + expect(result.data.success).toBe(true); + }); + }); + + describe('End-to-End Chat Flow', () => { + it('should maintain consistent UUID across multiple operations', async () => { + // Create initial payload (no UUID) + const initialPayload = createSamplePayload("What is AI?"); + + // 1. Create a new chat with syncMessage + const syncResult = await chatService.sendMessage(initialPayload); + const chatUuid = syncResult.data.chat_uuid; + + // 2. Continue the conversation with streaming + const onChunk = jest.fn(); + const onHeaderChatUuid = jest.fn(); + const streamPayload = createSamplePayload("Tell me more", chatUuid); + + await chatService.sendStreamMessage(streamPayload, onChunk, onHeaderChatUuid); + + // Verify UUID consistency across operations + expect(chatUuid).toBe("123e4567-e89b-12d3-a456-426614174000"); + expect(onHeaderChatUuid).toHaveBeenCalledWith(chatUuid); + }); + + it('should handle switching between chats', async () => { + // Get list of existing chats + const chatListResult = await chatService.getChatHistories(); + const existingChatUuid = chatListResult.data[0].chatUuid; + + // Continue the conversation with that chat + const continuePayload = createSamplePayload("Continue this conversation", existingChatUuid); + const syncResult = await chatService.sendMessage(continuePayload); + + // Verify the same UUID is maintained + expect(syncResult.data.chat_uuid).toBe(existingChatUuid); + }); + }); + + describe('Error Handling', () => { + it('should handle errors when chat UUID is invalid', async () => { + // Mock an implementation that rejects the promise + const originalImplementation = chatService.loadChatHistory; + chatService.loadChatHistory = jest.fn().mockRejectedValueOnce({ + response: { + status: 404, + data: { error: "Chat not found" } + } + }); + + // Try to load a non-existent chat + try { + await chatService.loadChatHistory("non-existent-uuid"); + fail("Expected an error but none was thrown"); + } catch (error: any) { + expect(error.response.status).toBe(404); + expect(error.response.data.error).toBe("Chat not found"); + } + + // Restore the original implementation + chatService.loadChatHistory = originalImplementation; + }); + }); }); \ No newline at end of file From bf954c4fdbfbe334c55447cbb6085cce894f2e01 Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Thu, 20 Mar 2025 00:32:38 +0100 Subject: [PATCH 5/6] Remove legacy tests for ChatService API client The file `api-client.test.ts` containing tests for the ChatService API client has been removed, likely as part of codebase cleanup or migration efforts. These tests are no longer necessary and have been entirely deleted to maintain a leaner codebase. --- src/services/api-client.test.ts | 270 -------------------------------- 1 file changed, 270 deletions(-) delete mode 100644 src/services/api-client.test.ts diff --git a/src/services/api-client.test.ts b/src/services/api-client.test.ts deleted file mode 100644 index cbfc2d9..0000000 --- a/src/services/api-client.test.ts +++ /dev/null @@ -1,270 +0,0 @@ -// api-client.test.ts -import { ChatService } from "./ChatService"; -import { ChatPayload } from "../types/chat"; - -// Mock ChatService -jest.mock("./ChatService", () => { - const streamMessageMock = jest.fn().mockImplementation((payload, onChunk, onHeaderChatUuid) => { - // Use the chat_uuid from payload if provided - const mockChatUuid = payload.chat_uuid || "123e4567-e89b-12d3-a456-426614174000"; - - // Call the onHeaderChatUuid callback with the UUID - onHeaderChatUuid(mockChatUuid); - - // Simulate streaming chunks - onChunk({ content: "Hello, " }); - onChunk({ content: "world!" }); - onChunk({ content: "", done: true }); - - return Promise.resolve(); - }); - - const sendMessageMock = jest.fn().mockImplementation((payload) => { - // Use the chat_uuid from payload if provided - const mockChatUuid = payload.chat_uuid || "123e4567-e89b-12d3-a456-426614174000"; - - return Promise.resolve({ - data: { - chat_uuid: mockChatUuid, - answer: "Mock response", - input_token: 10, - output_token: 5 - } - }); - }); - - const loadChatHistoryMock = jest.fn().mockImplementation((chatUuid) => { - // Use the provided chatUuid in response for clearer testing - return Promise.resolve({ - data: { - chatUuid: chatUuid, // Use the parameter - messages: [ - { Text: "Hello", IsUser: true }, - { Text: "Hi there! How can I help you?", IsUser: false } - ] - } - }); - }); - - const getChatHistoriesMock = jest.fn().mockImplementation(() => { - return Promise.resolve({ - data: [ - { chatUuid: "123e4567-e89b-12d3-a456-426614174000", title: "Chat 1", timestamp: "2023-07-01T12:00:00Z" }, - { chatUuid: "223e4567-e89b-12d3-a456-426614174001", title: "Chat 2", timestamp: "2023-07-02T12:00:00Z" } - ] - }); - }); - - const deleteChatMock = jest.fn().mockImplementation((chatUuid) => { - // Use the provided chatUuid in response for clearer testing - return Promise.resolve({ - status: 200, - data: { - success: true, - deletedChatUuid: chatUuid // Use the parameter - } - }); - }); - - return { - ChatService: jest.fn().mockImplementation(() => ({ - sendStreamMessage: streamMessageMock, - sendMessage: sendMessageMock, - loadChatHistory: loadChatHistoryMock, - getChatHistories: getChatHistoriesMock, - deleteChat: deleteChatMock - })) - }; -}); - - -describe('Chat API Client', () => { - let chatService: any; - - beforeEach(() => { - jest.clearAllMocks(); - chatService = new ChatService('mock-token'); - }); - - // Helper function to create sample payload - const createSamplePayload = (question: string, chatUuid: string = ""): ChatPayload => ({ - question, - selectedTools: [], - modelSettings: { - temperature: 0.5, - maxTokens: 2000, - topP: 0.5, - topK: 50 - }, - chat_uuid: chatUuid, - llmProvider: { - provider: "Anthropic", - modelId: "claude-3-5-haiku-latest" - }, - stream_settings: { - chunk_size: 1, - delay_ms: 10 - } - }); - - describe('Chat Streaming', () => { - it('should handle stream response and extract UUID', async () => { - // Create mock callbacks - const onChunk = jest.fn(); - const onHeaderChatUuid = jest.fn(); - - // Create payload - const payload = createSamplePayload("Hello"); - - // Call the mocked service - await chatService.sendStreamMessage(payload, onChunk, onHeaderChatUuid); - - // Verify callbacks were called - expect(onHeaderChatUuid).toHaveBeenCalledWith("123e4567-e89b-12d3-a456-426614174000"); - expect(onChunk).toHaveBeenCalledTimes(3); - expect(onChunk).toHaveBeenNthCalledWith(1, { content: "Hello, " }); - expect(onChunk).toHaveBeenNthCalledWith(2, { content: "world!" }); - expect(onChunk).toHaveBeenNthCalledWith(3, { content: "", done: true }); - }); - - it('should preserve existing chat UUID in stream requests', async () => { - // Create mock callbacks - const onChunk = jest.fn(); - const onHeaderChatUuid = jest.fn(); - - // Create payload with existing UUID - const existingUuid = "existing-uuid-123"; - const payload = createSamplePayload("Follow-up question", existingUuid); - - // Call the mocked service - await chatService.sendStreamMessage(payload, onChunk, onHeaderChatUuid); - - // Verify the same UUID is returned - expect(onHeaderChatUuid).toHaveBeenCalledWith(existingUuid); - }); - }); - - describe('Chat Synchronous API', () => { - it('should send and receive message with chat UUID', async () => { - // Create payload without UUID (new chat) - const payload = createSamplePayload("Hello"); - - // Call the mocked service - const result = await chatService.sendMessage(payload); - - // Verify response contains chat UUID - expect(result.data).toHaveProperty('chat_uuid'); - expect(result.data.chat_uuid).toBe("123e4567-e89b-12d3-a456-426614174000"); - }); - - it('should preserve existing chat UUID in subsequent requests', async () => { - // Create payload with existing UUID - const existingUuid = "existing-uuid-123"; - const payload = createSamplePayload("Follow-up question", existingUuid); - - // Call the mocked service - const result = await chatService.sendMessage(payload); - - // Verify same UUID is returned - expect(result.data.chat_uuid).toBe(existingUuid); - }); - }); - - describe('Chat History Management', () => { - it('should load chat history for a given UUID', async () => { - const chatUuid = "123e4567-e89b-12d3-a456-426614174000"; - - // Load chat history - const result = await chatService.loadChatHistory(chatUuid); - - // Verify the response contains messages - expect(result.data).toHaveProperty('messages'); - expect(result.data.messages).toHaveLength(2); - expect(result.data.messages[0].Text).toBe("Hello"); - expect(result.data.messages[0].IsUser).toBe(true); - expect(result.data.messages[1].Text).toBe("Hi there! How can I help you?"); - expect(result.data.messages[1].IsUser).toBe(false); - }); - - it('should retrieve list of chat histories', async () => { - // Get chat histories - const result = await chatService.getChatHistories(); - - // Verify the response contains list of chats - expect(Array.isArray(result.data)).toBe(true); - expect(result.data).toHaveLength(2); - expect(result.data[0].chatUuid).toBe("123e4567-e89b-12d3-a456-426614174000"); - expect(result.data[1].chatUuid).toBe("223e4567-e89b-12d3-a456-426614174001"); - }); - - it('should delete a chat by UUID', async () => { - const chatUuid = "123e4567-e89b-12d3-a456-426614174000"; - - // Delete chat - const result = await chatService.deleteChat(chatUuid); - - // Verify the response indicates success - expect(result.data.success).toBe(true); - }); - }); - - describe('End-to-End Chat Flow', () => { - it('should maintain consistent UUID across multiple operations', async () => { - // Create initial payload (no UUID) - const initialPayload = createSamplePayload("What is AI?"); - - // 1. Create a new chat with syncMessage - const syncResult = await chatService.sendMessage(initialPayload); - const chatUuid = syncResult.data.chat_uuid; - - // 2. Continue the conversation with streaming - const onChunk = jest.fn(); - const onHeaderChatUuid = jest.fn(); - const streamPayload = createSamplePayload("Tell me more", chatUuid); - - await chatService.sendStreamMessage(streamPayload, onChunk, onHeaderChatUuid); - - // Verify UUID consistency across operations - expect(chatUuid).toBe("123e4567-e89b-12d3-a456-426614174000"); - expect(onHeaderChatUuid).toHaveBeenCalledWith(chatUuid); - }); - - it('should handle switching between chats', async () => { - // Get list of existing chats - const chatListResult = await chatService.getChatHistories(); - const existingChatUuid = chatListResult.data[0].chatUuid; - - // Continue the conversation with that chat - const continuePayload = createSamplePayload("Continue this conversation", existingChatUuid); - const syncResult = await chatService.sendMessage(continuePayload); - - // Verify the same UUID is maintained - expect(syncResult.data.chat_uuid).toBe(existingChatUuid); - }); - }); - - describe('Error Handling', () => { - it('should handle errors when chat UUID is invalid', async () => { - // Mock an implementation that rejects the promise - const originalImplementation = chatService.loadChatHistory; - chatService.loadChatHistory = jest.fn().mockRejectedValueOnce({ - response: { - status: 404, - data: { error: "Chat not found" } - } - }); - - // Try to load a non-existent chat - try { - await chatService.loadChatHistory("non-existent-uuid"); - fail("Expected an error but none was thrown"); - } catch (error: any) { - expect(error.response.status).toBe(404); - expect(error.response.data.error).toBe("Chat not found"); - } - - // Restore the original implementation - chatService.loadChatHistory = originalImplementation; - }); - }); -}); \ No newline at end of file From e605c036feb6b7171ec4b7058c0f417110e16c1e Mon Sep 17 00:00:00 2001 From: Shaharia Azam Date: Thu, 20 Mar 2025 00:38:13 +0100 Subject: [PATCH 6/6] Update header key for Chat UUID retrieval Replaced "X-Chat-Uuid" with "X-MKit-Chat-UUID" for consistency with updated API response headers. Removed redundant lowercase header check and related console logs to streamline the code. --- src/services/ChatService.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/services/ChatService.ts b/src/services/ChatService.ts index 199dd2b..8760b74 100644 --- a/src/services/ChatService.ts +++ b/src/services/ChatService.ts @@ -69,11 +69,7 @@ export class ChatService extends APIClient { }); // Try both casing variants - const chatUuid = response.headers.get('X-Chat-Uuid'); - const chatUUID = response.headers.get('x-chat-uuid'); // Try lowercase - console.log('Chat UUID (X-Chat-Uuid):', chatUuid); - console.log('Chat UUID (x-chat-uuid):', chatUUID); - + const chatUuid = response.headers.get('X-MKit-Chat-UUID'); if (chatUuid && onHeaderChatUuid) { onHeaderChatUuid(chatUuid);