"""Test Suite for Dispatcher Tests for event routing and agent execution. """ import os import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "tools", "ai-review")) from unittest.mock import MagicMock, Mock, patch import pytest class TestDispatcherCreation: """Test dispatcher initialization.""" def test_create_dispatcher(self): """Test creating dispatcher.""" from dispatcher import Dispatcher dispatcher = Dispatcher() assert dispatcher is not None assert dispatcher.agents == [] def test_create_dispatcher_with_config(self): """Test creating dispatcher with config.""" from dispatcher import Dispatcher config = {"dispatcher": {"max_workers": 4}} dispatcher = Dispatcher(config=config) assert dispatcher.config == config class TestAgentRegistration: """Test agent registration.""" def test_register_agent(self): """Test registering an agent.""" from agents.base_agent import AgentContext, AgentResult, BaseAgent from dispatcher import Dispatcher class MockAgent(BaseAgent): def can_handle(self, event_type, event_data): return event_type == "test" def execute(self, context): return AgentResult(success=True, message="done") dispatcher = Dispatcher() agent = MockAgent(config={}, gitea_client=None, llm_client=None) dispatcher.register_agent(agent) assert len(dispatcher.agents) == 1 assert dispatcher.agents[0] == agent def test_register_multiple_agents(self): """Test registering multiple agents.""" from agents.base_agent import AgentContext, AgentResult, BaseAgent from dispatcher import Dispatcher class MockAgent1(BaseAgent): def can_handle(self, event_type, event_data): return event_type == "type1" def execute(self, context): return AgentResult(success=True, message="agent1") class MockAgent2(BaseAgent): def can_handle(self, event_type, event_data): return event_type == "type2" def execute(self, context): return AgentResult(success=True, message="agent2") dispatcher = Dispatcher() dispatcher.register_agent( MockAgent1(config={}, gitea_client=None, llm_client=None) ) dispatcher.register_agent( MockAgent2(config={}, gitea_client=None, llm_client=None) ) assert len(dispatcher.agents) == 2 class TestEventRouting: """Test event routing to agents.""" def test_route_to_matching_agent(self): """Test that events are routed to matching agents.""" from agents.base_agent import AgentContext, AgentResult, BaseAgent from dispatcher import Dispatcher class MockAgent(BaseAgent): def can_handle(self, event_type, event_data): return event_type == "issues" def execute(self, context): return AgentResult(success=True, message="handled") dispatcher = Dispatcher() agent = MockAgent(config={}, gitea_client=None, llm_client=None) dispatcher.register_agent(agent) result = dispatcher.dispatch( event_type="issues", event_data={"action": "opened"}, owner="test", repo="repo", ) assert len(result.agents_run) == 1 assert result.results[0].success is True def test_no_matching_agent(self): """Test dispatch when no agent matches.""" from agents.base_agent import AgentContext, AgentResult, BaseAgent from dispatcher import Dispatcher class MockAgent(BaseAgent): def can_handle(self, event_type, event_data): return event_type == "issues" def execute(self, context): return AgentResult(success=True, message="handled") dispatcher = Dispatcher() agent = MockAgent(config={}, gitea_client=None, llm_client=None) dispatcher.register_agent(agent) result = dispatcher.dispatch( event_type="pull_request", # Different event type event_data={"action": "opened"}, owner="test", repo="repo", ) assert len(result.agents_run) == 0 def test_multiple_matching_agents(self): """Test dispatch when multiple agents match.""" from agents.base_agent import AgentContext, AgentResult, BaseAgent from dispatcher import Dispatcher class MockAgent1(BaseAgent): def can_handle(self, event_type, event_data): return event_type == "issues" def execute(self, context): return AgentResult(success=True, message="agent1") class MockAgent2(BaseAgent): def can_handle(self, event_type, event_data): return event_type == "issues" def execute(self, context): return AgentResult(success=True, message="agent2") dispatcher = Dispatcher() dispatcher.register_agent( MockAgent1(config={}, gitea_client=None, llm_client=None) ) dispatcher.register_agent( MockAgent2(config={}, gitea_client=None, llm_client=None) ) result = dispatcher.dispatch( event_type="issues", event_data={"action": "opened"}, owner="test", repo="repo", ) assert len(result.agents_run) == 2 class TestDispatchResult: """Test dispatch result structure.""" def test_result_structure(self): """Test DispatchResult has correct structure.""" from dispatcher import DispatchResult result = DispatchResult( agents_run=["Agent1", "Agent2"], results=[], errors=[], ) assert result.agents_run == ["Agent1", "Agent2"] assert result.results == [] assert result.errors == [] def test_result_with_errors(self): """Test DispatchResult with errors.""" from dispatcher import DispatchResult result = DispatchResult( agents_run=["Agent1"], results=[], errors=["Error 1", "Error 2"], ) assert len(result.errors) == 2 class TestAgentExecution: """Test agent execution through dispatcher.""" def test_agent_receives_context(self): """Test that agents receive proper context.""" from agents.base_agent import AgentContext, AgentResult, BaseAgent from dispatcher import Dispatcher received_context = None class MockAgent(BaseAgent): def can_handle(self, event_type, event_data): return True def execute(self, context): nonlocal received_context received_context = context return AgentResult(success=True, message="done") dispatcher = Dispatcher() dispatcher.register_agent( MockAgent(config={}, gitea_client=None, llm_client=None) ) dispatcher.dispatch( event_type="issues", event_data={"action": "opened", "issue": {"number": 123}}, owner="testowner", repo="testrepo", ) assert received_context is not None assert received_context.owner == "testowner" assert received_context.repo == "testrepo" assert received_context.event_type == "issues" assert received_context.event_data["action"] == "opened" def test_agent_failure_captured(self): """Test that agent failures are captured in results.""" from agents.base_agent import AgentContext, AgentResult, BaseAgent from dispatcher import Dispatcher class FailingAgent(BaseAgent): def can_handle(self, event_type, event_data): return True def execute(self, context): raise Exception("Test error") dispatcher = Dispatcher() dispatcher.register_agent( FailingAgent(config={}, gitea_client=None, llm_client=None) ) result = dispatcher.dispatch( event_type="issues", event_data={}, owner="test", repo="repo", ) # Agent should still be in agents_run assert len(result.agents_run) == 1 # Result should indicate failure assert result.results[0].success is False class TestGetDispatcher: """Test get_dispatcher factory function.""" def test_get_dispatcher_returns_singleton(self): """Test that get_dispatcher returns configured dispatcher.""" from dispatcher import get_dispatcher dispatcher = get_dispatcher() assert dispatcher is not None def test_get_dispatcher_with_config(self): """Test get_dispatcher with custom config.""" from dispatcher import get_dispatcher config = {"test": "value"} dispatcher = get_dispatcher(config=config) assert dispatcher.config.get("test") == "value" if __name__ == "__main__": pytest.main([__file__, "-v"])