import os import sys import pytest from unittest.mock import MagicMock, patch from streamlit.testing.v1 import AppTest from langchain_core.messages import AIMessage # Ensure src is in python path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) @pytest.fixture(autouse=True) def mock_history_manager(): """Globally mock HistoryManager to avoid DB calls during AppTest.""" with patch("ea_chatbot.history.manager.HistoryManager") as mock_cls: instance = mock_cls.return_value instance.create_conversation.return_value = MagicMock(id="conv_123") instance.get_conversations.return_value = [] instance.get_messages.return_value = [] instance.add_message.return_value = MagicMock() instance.update_conversation_summary.return_value = MagicMock() yield instance @pytest.fixture def mock_app_stream(): with patch("ea_chatbot.graph.workflow.app.stream") as mock_stream: # Mock events from app.stream mock_stream.return_value = [ {"query_analyzer": {"next_action": "research"}}, {"researcher": {"messages": [AIMessage(content="Research result")]}} ] yield mock_stream @pytest.fixture def mock_user(): user = MagicMock() user.id = "test_id" user.username = "test@example.com" user.display_name = "Test User" return user def test_app_initial_state(mock_app_stream, mock_user): """Test that the app initializes with the correct title and empty history.""" at = AppTest.from_file("src/ea_chatbot/app.py") # Simulate logged-in user at.session_state["user"] = mock_user at.run() assert not at.exception assert at.title[0].value == "🗳️ Election Analytics Chatbot" # Check session state initialization assert "messages" in at.session_state assert len(at.session_state["messages"]) == 0 def test_app_dev_mode_toggle(mock_app_stream, mock_user): """Test that the dev mode toggle exists in the sidebar.""" with patch.dict(os.environ, {"DEV_MODE": "false"}): at = AppTest.from_file("src/ea_chatbot/app.py") at.session_state["user"] = mock_user at.run() # Check for sidebar toggle (checkbox) assert len(at.sidebar.checkbox) > 0 dev_mode_toggle = at.sidebar.checkbox[0] assert dev_mode_toggle.label == "Dev Mode" assert dev_mode_toggle.value is False def test_app_graph_execution_streaming(mock_app_stream, mock_user, mock_history_manager): """Test that entering a prompt triggers the graph stream and displays response.""" at = AppTest.from_file("src/ea_chatbot/app.py") at.session_state["user"] = mock_user at.run() # Input a question at.chat_input[0].set_value("Test question").run() # Verify graph stream was called assert mock_app_stream.called # Message should be added to history assert len(at.session_state["messages"]) == 2 assert at.session_state["messages"][0]["role"] == "user" assert at.session_state["messages"][1]["role"] == "assistant" assert "Research result" in at.session_state["messages"][1]["content"] # Verify history manager was used assert mock_history_manager.create_conversation.called assert mock_history_manager.add_message.called