"""Test script for ChatManager - Pytest compatible tests""" import sys from pathlib import Path import pytest from unittest.mock import patch, MagicMock # Add project root to Python path sys.path.insert(0, str(Path(__file__).parent.parent)) from backend.managers.chat_manager import ChatManager class TestChatManager: """Test suite for ChatManager functionality.""" @pytest.fixture def chat_manager(self): return ChatManager() def test_initialization(self, chat_manager): """Test that ChatManager initializes correctly.""" assert chat_manager.api_url is not None assert chat_manager.model is not None assert chat_manager.chat_history == [] def test_add_message(self, chat_manager): """Test adding messages to chat history.""" chat_manager.add_message("user", "Hello") assert len(chat_manager.chat_history) == 1 assert chat_manager.chat_history[0]["role"] == "user" assert chat_manager.chat_history[0]["content"] == "Hello" def test_get_history(self, chat_manager): """Test retrieving chat history.""" chat_manager.add_message("user", "Hello") chat_manager.add_message("assistant", "Hi there!") history = chat_manager.get_history() assert len(history) == 2 assert history[0]["role"] == "user" assert history[1]["role"] == "assistant" def test_clear_history(self, chat_manager): """Test clearing chat history.""" chat_manager.add_message("user", "Hello") assert len(chat_manager.chat_history) == 1 chat_manager.clear_history() assert len(chat_manager.chat_history) == 0 def test_send_message_integration(self, chat_manager): """ Integration test for sending message to AI. This test actually communicates with the API. """ try: # Send a simple test message response = chat_manager.send_message("Hello, what is 2+2?") # Verify response is not empty assert isinstance(response, str) assert len(response) > 0 # Verify message was added to history assert len(chat_manager.chat_history) == 2 # user + assistant assert chat_manager.chat_history[0]["role"] == "user" assert chat_manager.chat_history[1]["role"] == "assistant" print(f"API Test Passed") print(f"Response: {response}") except Exception as e: # If API is not reachable, mark as skipped pytest.skip(f"API not reachable: {str(e)}") def test_multiple_messages(self, chat_manager): """Test sending multiple messages in a conversation.""" try: # Send first message response1 = chat_manager.send_message("What is your name?") assert len(response1) > 0 # Send follow-up message response2 = chat_manager.send_message("Tell me more") assert len(response2) > 0 # Verify full conversation is in history assert len(chat_manager.chat_history) == 4 # 2 user + 2 assistant print(f"Conversation Test Passed") print(f"Messages: {len(chat_manager.chat_history)}") except Exception as e: pytest.skip(f"API not reachable: {str(e)}") class TestChatManagerSendMessage: """Unit tests for send_message using mocked HTTP requests.""" @pytest.fixture def chat_manager(self): return ChatManager() def _mock_response(self, content="AI reply", status_code=200): mock = MagicMock() mock.status_code = status_code mock.json.return_value = { "choices": [{"message": {"role": "assistant", "content": content}}] } mock.text = "error text" return mock def test_send_message_adds_user_message_to_history(self, chat_manager): with patch("requests.post", return_value=self._mock_response()): chat_manager.send_message("Hello") assert chat_manager.chat_history[0] == {"role": "user", "content": "Hello"} def test_send_message_adds_assistant_response_to_history(self, chat_manager): with patch("requests.post", return_value=self._mock_response("Hi there")): chat_manager.send_message("Hello") assert chat_manager.chat_history[1] == {"role": "assistant", "content": "Hi there"} def test_send_message_returns_ai_content(self, chat_manager): with patch("requests.post", return_value=self._mock_response("Answer")): response = chat_manager.send_message("Question") assert response == "Answer" def test_send_message_history_grows_with_each_call(self, chat_manager): with patch("requests.post", return_value=self._mock_response()): chat_manager.send_message("First") chat_manager.send_message("Second") assert len(chat_manager.chat_history) == 4 # 2 user + 2 assistant def test_send_message_connection_error_raises(self, chat_manager): import requests with patch("requests.post", side_effect=requests.exceptions.ConnectionError("refused")): with pytest.raises(Exception, match="Connection Error"): chat_manager.send_message("Hello") def test_send_message_api_error_status_raises(self, chat_manager): mock = self._mock_response(status_code=500) with patch("requests.post", return_value=mock): with pytest.raises(Exception, match="API Error 500"): chat_manager.send_message("Hello") def test_send_message_empty_choices_raises(self, chat_manager): mock = MagicMock() mock.status_code = 200 mock.json.return_value = {"choices": []} with patch("requests.post", return_value=mock): with pytest.raises(Exception, match="Invalid API response format"): chat_manager.send_message("Hello") def test_send_message_missing_choices_key_raises(self, chat_manager): mock = MagicMock() mock.status_code = 200 mock.json.return_value = {} with patch("requests.post", return_value=mock): with pytest.raises(Exception): chat_manager.send_message("Hello") def test_send_message_timeout_raises(self, chat_manager): import requests with patch("requests.post", side_effect=requests.exceptions.Timeout()): with pytest.raises(Exception): chat_manager.send_message("Hello") class TestChatManagerGetChatDisplay: """Tests for get_chat_display().""" @pytest.fixture def chat_manager(self): return ChatManager() def test_empty_history_returns_empty_list(self, chat_manager): assert chat_manager.get_chat_display() == [] def test_display_contains_role_and_content_keys(self, chat_manager): chat_manager.add_message("user", "Hello") display = chat_manager.get_chat_display() assert "role" in display[0] assert "content" in display[0] def test_display_preserves_message_order(self, chat_manager): chat_manager.add_message("user", "First") chat_manager.add_message("assistant", "Second") display = chat_manager.get_chat_display() assert display[0]["role"] == "user" assert display[1]["role"] == "assistant" def test_display_matches_history(self, chat_manager): chat_manager.add_message("user", "Hi") chat_manager.add_message("assistant", "Hello!") assert chat_manager.get_chat_display() == chat_manager.get_history() def test_system_message_included_in_display(self, chat_manager): chat_manager.add_message("system", "You are a helper.") display = chat_manager.get_chat_display() assert display[0]["role"] == "system" def test_chat_manager_demo(): """Demo test - Shows interactive chat (can be run manually).""" print("\n" + "=" * 60) print("ChatManager Demo - Interactive Test") print("=" * 60 + "\n") chat_manager = ChatManager() print(f"Connected to API: {chat_manager.api_url}") print(f"Model: {chat_manager.model}\n") # Demo conversation test_messages = ["Hello! What can you do?", "Tell me a joke", "What is Python?"] print("Starting conversation...\n") for message in test_messages: print(f"User: {message}") try: response = chat_manager.send_message(message) print(f"Assistant: {response}\n") except Exception as e: print(f"Error: {str(e)}\n") pytest.skip(f"API not reachable: {str(e)}") # Display full chat history print("=" * 60) print("Chat History:") print("=" * 60) for msg in chat_manager.get_history(): print(f"{msg['role'].upper()}: {msg['content']}\n") if __name__ == "__main__": # Run with: pytest tests/test_chat_manager.py -v -s pytest.main([__file__, "-v", "-s"])