- Add ChatManager class for OpenAI-compatible API communication (silicon.fhgr.ch:7080) - Add SystemPrompter for intelligent prompt generation with file context - Integrate ChatManager into frontend chat component - Add comprehensive pytest tests (40+ tests covering unit and integration scenarios) - Implement error handling for API failures, timeouts, and connection issues - Add environment variable-based configuration for API credentials - Update frontend state initialization to include ChatManager - All tests passing with mock/patch isolation for API calls
243 lines
8.8 KiB
Python
243 lines
8.8 KiB
Python
"""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"])
|