"""Tests for ChatClient.""" from unittest.mock import Mock, patch import pytest import httpx from fastgpt_client.client import ChatClient from fastgpt_client.exceptions import ValidationError class TestChatClientCreateChatCompletion: """Test suite for ChatClient.create_chat_completion method.""" def test_create_chat_completion_basic(self, api_key, sample_chat_response): """Test basic chat completion creation.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 mock_response.json = Mock(return_value=sample_chat_response) with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], stream=False ) assert response.status_code == 200 mock_send.assert_called_once() call_args = mock_send.call_args assert call_args[0][0] == "POST" assert call_args[0][1] == "/api/v1/chat/completions" assert call_args[1]['json']['messages'] == [{"role": "user", "content": "Hello"}] assert call_args[1]['stream'] is False def test_create_chat_completion_with_chat_id(self, api_key): """Test chat completion with chatId parameter.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], chatId="chat-123" ) assert response.status_code == 200 assert mock_send.call_args[1]['json']['chatId'] == "chat-123" def test_create_chat_completion_with_variables(self, api_key): """Test chat completion with variables parameter.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], variables={"name": "John", "city": "NYC"} ) assert response.status_code == 200 assert mock_send.call_args[1]['json']['variables'] == {"name": "John", "city": "NYC"} def test_create_chat_completion_with_detail(self, api_key): """Test chat completion with detail enabled.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], detail=True ) assert response.status_code == 200 assert mock_send.call_args[1]['json']['detail'] is True def test_create_chat_completion_with_response_chat_item_id(self, api_key): """Test chat completion with custom responseChatItemId.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], responseChatItemId="custom-id-123" ) assert response.status_code == 200 assert mock_send.call_args[1]['json']['responseChatItemId'] == "custom-id-123" def test_create_chat_completion_streaming(self, api_key, mock_stream_response): """Test streaming chat completion.""" client = ChatClient(api_key) with patch.object(client, '_send_request', return_value=mock_stream_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], stream=True ) assert response.status_code == 200 assert mock_send.call_args[1]['stream'] is True def test_create_chat_completion_all_parameters(self, api_key): """Test chat completion with all parameters.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], stream=True, chatId="chat-123", detail=True, variables={"key": "value"}, responseChatItemId="custom-id" ) assert response.status_code == 200 json_data = mock_send.call_args[1]['json'] assert json_data['chatId'] == "chat-123" assert json_data['detail'] is True assert json_data['variables'] == {"key": "value"} assert json_data['responseChatItemId'] == "custom-id" def test_create_chat_completion_parameter_validation(self, api_key): """Test that parameter validation works for known fields.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 # Test with valid chatId (should pass validation) with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.create_chat_completion( messages=[{"role": "user", "content": "Hello"}], chatId="valid-chat-id" ) # Verify the request was sent successfully assert response.status_code == 200 mock_send.assert_called_once() class TestChatClientGetChatHistories: """Test suite for ChatClient.get_chat_histories method.""" def test_get_chat_histories_basic(self, api_key, sample_chat_histories_response): """Test getting chat histories with basic parameters.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 mock_response.json = Mock(return_value=sample_chat_histories_response) with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_histories(appId="app-123") assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "POST" assert call_args[0][1] == "/api/core/chat/getHistories" assert call_args[1]['json']['appId'] == "app-123" def test_get_chat_histories_with_pagination(self, api_key): """Test getting chat histories with pagination.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_histories( appId="app-123", offset=10, pageSize=50 ) json_data = mock_send.call_args[1]['json'] assert json_data['offset'] == 10 assert json_data['pageSize'] == 50 def test_get_chat_histories_with_source(self, api_key): """Test getting chat histories with source filter.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_histories( appId="app-123", source="online" ) assert mock_send.call_args[1]['json']['source'] == "online" def test_get_chat_histories_all_parameters(self, api_key): """Test getting chat histories with all parameters.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_histories( appId="app-123", offset=5, pageSize=25, source="share" ) json_data = mock_send.call_args[1]['json'] assert json_data == { "appId": "app-123", "offset": 5, "pageSize": 25, "source": "share" } class TestChatClientGetChatInit: """Test suite for ChatClient.get_chat_init method.""" def test_get_chat_init(self, api_key): """Test getting chat initialization.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_init(appId="app-123", chatId="chat-123") assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "GET" assert call_args[0][1] == "/api/core/chat/init" assert call_args[1]['params'] == {"appId": "app-123", "chatId": "chat-123"} class TestChatClientGetChatRecords: """Test suite for ChatClient.get_chat_records method.""" def test_get_chat_records_basic(self, api_key, sample_chat_records_response): """Test getting chat records with basic parameters.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 mock_response.json = Mock(return_value=sample_chat_records_response) with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_records(appId="app-123", chatId="chat-123") assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "POST" assert call_args[0][1] == "/api/core/chat/getPaginationRecords" json_data = call_args[1]['json'] assert json_data['appId'] == "app-123" assert json_data['chatId'] == "chat-123" def test_get_chat_records_with_pagination(self, api_key): """Test getting chat records with pagination.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_records( appId="app-123", chatId="chat-123", offset=20, pageSize=30 ) json_data = mock_send.call_args[1]['json'] assert json_data['offset'] == 20 assert json_data['pageSize'] == 30 def test_get_chat_records_with_custom_feedbacks(self, api_key): """Test getting chat records with custom feedbacks loaded.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_records( appId="app-123", chatId="chat-123", loadCustomFeedbacks=True ) assert mock_send.call_args[1]['json']['loadCustomFeedbacks'] is True def test_get_chat_records_all_parameters(self, api_key): """Test getting chat records with all parameters.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_chat_records( appId="app-123", chatId="chat-123", offset=10, pageSize=20, loadCustomFeedbacks=True ) json_data = mock_send.call_args[1]['json'] assert json_data == { "appId": "app-123", "chatId": "chat-123", "offset": 10, "pageSize": 20, "loadCustomFeedbacks": True } class TestChatClientGetRecordDetail: """Test suite for ChatClient.get_record_detail method.""" def test_get_record_detail(self, api_key): """Test getting record detail.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_record_detail( appId="app-123", chatId="chat-123", dataId="data-123" ) assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "GET" assert call_args[0][1] == "/api/core/chat/getResData" assert call_args[1]['params'] == { "appId": "app-123", "chatId": "chat-123", "dataId": "data-123" } class TestChatClientUpdateChatHistory: """Test suite for ChatClient.update_chat_history method.""" def test_update_chat_history_title(self, api_key): """Test updating chat history title.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.update_chat_history( appId="app-123", chatId="chat-123", customTitle="New Title" ) assert response.status_code == 200 json_data = mock_send.call_args[1]['json'] assert json_data['appId'] == "app-123" assert json_data['chatId'] == "chat-123" assert json_data['customTitle'] == "New Title" assert 'top' not in json_data def test_update_chat_history_pin(self, api_key): """Test pinning chat history.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.update_chat_history( appId="app-123", chatId="chat-123", top=True ) json_data = mock_send.call_args[1]['json'] assert json_data['top'] is True assert 'customTitle' not in json_data def test_update_chat_history_both_parameters(self, api_key): """Test updating both title and pin status.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.update_chat_history( appId="app-123", chatId="chat-123", customTitle="Important Chat", top=True ) json_data = mock_send.call_args[1]['json'] assert json_data['customTitle'] == "Important Chat" assert json_data['top'] is True class TestChatClientDeleteChatHistory: """Test suite for ChatClient.delete_chat_history method.""" def test_delete_chat_history(self, api_key): """Test deleting a chat history.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.delete_chat_history(appId="app-123", chatId="chat-123") assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "DELETE" assert call_args[0][1] == "/api/core/chat/delHistory" assert call_args[1]['params'] == {"appId": "app-123", "chatId": "chat-123"} class TestChatClientClearChatHistories: """Test suite for ChatClient.clear_chat_histories method.""" def test_clear_chat_histories(self, api_key): """Test clearing all chat histories.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.clear_chat_histories(appId="app-123") assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "DELETE" assert call_args[0][1] == "/api/core/chat/clearHistories" assert call_args[1]['params'] == {"appId": "app-123"} class TestChatClientDeleteChatRecord: """Test suite for ChatClient.delete_chat_record method.""" def test_delete_chat_record(self, api_key): """Test deleting a single chat record.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.delete_chat_record( appId="app-123", chatId="chat-123", contentId="content-123" ) assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "DELETE" assert call_args[0][1] == "/api/core/chat/item/delete" assert call_args[1]['json'] == { "appId": "app-123", "chatId": "chat-123", "contentId": "content-123" } class TestChatClientSendFeedback: """Test suite for ChatClient.send_feedback method.""" def test_send_feedback_good(self, api_key): """Test sending positive feedback.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.send_feedback( appId="app-123", chatId="chat-123", dataId="data-123", userGoodFeedback="Great response!" ) assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "POST" assert call_args[0][1] == "/api/core/chat/feedback/updateUserFeedback" json_data = call_args[1]['json'] assert json_data['userGoodFeedback'] == "Great response!" assert 'userBadFeedback' not in json_data def test_send_feedback_bad(self, api_key): """Test sending negative feedback.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.send_feedback( appId="app-123", chatId="chat-123", dataId="data-123", userBadFeedback="Not helpful" ) json_data = mock_send.call_args[1]['json'] assert json_data['userBadFeedback'] == "Not helpful" assert 'userGoodFeedback' not in json_data def test_send_feedback_cancel_good(self, api_key): """Test canceling positive feedback by passing empty string.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.send_feedback( appId="app-123", chatId="chat-123", dataId="data-123", userGoodFeedback="" ) # Empty string is still sent (to cancel the feedback) json_data = mock_send.call_args[1]['json'] assert 'userGoodFeedback' in json_data def test_send_feedback_only_required_params(self, api_key): """Test sending feedback with only required parameters.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.send_feedback( appId="app-123", chatId="chat-123", dataId="data-123" ) json_data = mock_send.call_args[1]['json'] assert json_data == { "appId": "app-123", "chatId": "chat-123", "dataId": "data-123" } class TestChatClientGetSuggestedQuestions: """Test suite for ChatClient.get_suggested_questions method.""" def test_get_suggested_questions_basic(self, api_key): """Test getting suggested questions.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_suggested_questions( appId="app-123", chatId="chat-123" ) assert response.status_code == 200 call_args = mock_send.call_args assert call_args[0][0] == "POST" assert call_args[0][1] == "/api/core/ai/agent/v2/createQuestionGuide" json_data = call_args[1]['json'] assert json_data['appId'] == "app-123" assert json_data['chatId'] == "chat-123" assert 'questionGuide' not in json_data def test_get_suggested_questions_with_guide(self, api_key): """Test getting suggested questions with custom question guide.""" client = ChatClient(api_key) mock_response = Mock(spec=httpx.Response) mock_response.status_code = 200 question_guide = { "maxQuestions": 5, "contextWindow": 10 } with patch.object(client, '_send_request', return_value=mock_response) as mock_send: response = client.get_suggested_questions( appId="app-123", chatId="chat-123", questionGuide=question_guide ) json_data = mock_send.call_args[1]['json'] assert json_data['questionGuide'] == question_guide