""" Mock factories for creating test doubles and mocks. """ from unittest.mock import Mock, AsyncMock, MagicMock from typing import Dict, Any, List, Optional, Callable import asyncio from datetime import datetime, timezone class MockRepositoryFactory: """Factory for creating mock repository objects.""" @staticmethod def create_issue_repository() -> Mock: """Create a mock issue repository.""" repo = AsyncMock() repo.get_issue = AsyncMock() repo.create_issue = AsyncMock() repo.update_issue = AsyncMock() repo.delete_issue = AsyncMock() repo.list_issues = AsyncMock() repo.search_issues = AsyncMock() return repo @staticmethod def create_project_repository() -> Mock: """Create a mock project repository.""" repo = AsyncMock() repo.get_project = AsyncMock() repo.create_project = AsyncMock() repo.update_project = AsyncMock() repo.delete_project = AsyncMock() repo.list_projects = AsyncMock() repo.get_issue_project_info = AsyncMock() return repo @staticmethod def create_document_repository() -> Mock: """Create a mock document repository.""" repo = AsyncMock() repo.store_document = AsyncMock() repo.get_document = AsyncMock() repo.update_document = AsyncMock() repo.delete_document = AsyncMock() repo.list_documents = AsyncMock() repo.search_content = AsyncMock() return repo class MockServiceFactory: """Factory for creating mock service objects.""" @staticmethod def create_http_client() -> Mock: """Create a mock HTTP client.""" client = AsyncMock() # Default successful response mock_response = AsyncMock() mock_response.status = 200 mock_response.json = AsyncMock(return_value={"status": "success"}) mock_response.text = AsyncMock(return_value='{"status": "success"}') mock_response.headers = {"Content-Type": "application/json"} client.get.return_value = mock_response client.post.return_value = mock_response client.put.return_value = mock_response client.delete.return_value = mock_response client.close = AsyncMock() return client @staticmethod def create_database_connection() -> Mock: """Create a mock database connection.""" conn = Mock() cursor = Mock() conn.cursor.return_value = cursor conn.execute.return_value = cursor conn.commit = Mock() conn.rollback = Mock() conn.close = Mock() # Default empty results cursor.fetchone.return_value = None cursor.fetchall.return_value = [] cursor.fetchmany.return_value = [] cursor.lastrowid = 1 cursor.rowcount = 0 return conn @staticmethod def create_cache_manager() -> Mock: """Create a mock cache manager.""" cache = AsyncMock() cache.get = AsyncMock(return_value=None) cache.set = AsyncMock() cache.delete = AsyncMock() cache.clear = AsyncMock() cache.exists = AsyncMock(return_value=False) cache.expire = AsyncMock() return cache @staticmethod def create_file_system() -> Mock: """Create a mock file system.""" fs = Mock() fs.read_file = Mock(return_value="mock file content") fs.write_file = Mock() fs.delete_file = Mock() fs.exists = Mock(return_value=True) fs.list_files = Mock(return_value=[]) fs.create_directory = Mock() fs.delete_directory = Mock() return fs class MockConfigFactory: """Factory for creating mock configuration objects.""" @staticmethod def create_test_config(overrides: Optional[Dict[str, Any]] = None) -> Mock: """Create a mock configuration object.""" config = Mock() # Default configuration values defaults = { "workspace_dir": "/tmp/test-workspace", "database_path": "/tmp/test.db", "cache_dir": "/tmp/test-cache", "gitea_url": "http://test-gitea.com", "gitea_token": "test-token", "repo_owner": "test", "repo_name": "repo", "log_level": "DEBUG", "max_retries": 3, "timeout": 30, "batch_size": 100 } if overrides: defaults.update(overrides) for key, value in defaults.items(): setattr(config, key, value) return config class MockEventFactory: """Factory for creating mock event objects and event handlers.""" @staticmethod def create_event_emitter() -> Mock: """Create a mock event emitter.""" emitter = Mock() emitter.emit = Mock() emitter.on = Mock() emitter.off = Mock() emitter.once = Mock() emitter.listeners = Mock(return_value=[]) return emitter @staticmethod def create_event_handler() -> Mock: """Create a mock event handler.""" handler = Mock() handler.handle = AsyncMock() handler.can_handle = Mock(return_value=True) handler.priority = 1 return handler class MockNetworkFactory: """Factory for creating network-related mocks.""" @staticmethod def create_rate_limiter() -> Mock: """Create a mock rate limiter.""" limiter = AsyncMock() limiter.acquire = AsyncMock() limiter.release = AsyncMock() limiter.is_available = AsyncMock(return_value=True) limiter.reset = AsyncMock() return limiter @staticmethod def create_circuit_breaker() -> Mock: """Create a mock circuit breaker.""" breaker = Mock() breaker.call = AsyncMock() breaker.is_open = Mock(return_value=False) breaker.is_closed = Mock(return_value=True) breaker.is_half_open = Mock(return_value=False) breaker.reset = Mock() return breaker class MockTimeFactory: """Factory for creating time-related mocks.""" @staticmethod def create_timer() -> Mock: """Create a mock timer.""" timer = Mock() timer.start = Mock() timer.stop = Mock() timer.elapsed = 0.1 timer.reset = Mock() return timer @staticmethod def create_scheduler() -> Mock: """Create a mock task scheduler.""" scheduler = AsyncMock() scheduler.schedule = AsyncMock() scheduler.cancel = AsyncMock() scheduler.is_scheduled = Mock(return_value=False) scheduler.start = AsyncMock() scheduler.stop = AsyncMock() return scheduler class MockResponseBuilder: """Builder for creating mock HTTP responses.""" def __init__(self): self.status = 200 self.headers = {"Content-Type": "application/json"} self.body = {"status": "success"} self.delay = 0.0 self.exception = None def with_status(self, status: int) -> "MockResponseBuilder": """Set response status code.""" self.status = status return self def with_headers(self, headers: Dict[str, str]) -> "MockResponseBuilder": """Set response headers.""" self.headers.update(headers) return self def with_json_body(self, body: Dict[str, Any]) -> "MockResponseBuilder": """Set JSON response body.""" self.body = body self.headers["Content-Type"] = "application/json" return self def with_text_body(self, body: str) -> "MockResponseBuilder": """Set text response body.""" self.body = body self.headers["Content-Type"] = "text/plain" return self def with_delay(self, delay: float) -> "MockResponseBuilder": """Add delay to response.""" self.delay = delay return self def with_exception(self, exception: Exception) -> "MockResponseBuilder": """Make response raise an exception.""" self.exception = exception return self def build(self) -> Mock: """Build the mock response.""" if self.exception: # Create a coroutine that raises the exception async def raise_exception(): await asyncio.sleep(self.delay) raise self.exception return raise_exception() response = AsyncMock() response.status = self.status response.headers = self.headers if isinstance(self.body, dict): response.json = AsyncMock(return_value=self.body) response.text = AsyncMock(return_value=str(self.body)) else: response.text = AsyncMock(return_value=self.body) response.json = AsyncMock(side_effect=ValueError("Not JSON")) # Add delay if specified if self.delay > 0: original_json = response.json original_text = response.text async def delayed_json(): await asyncio.sleep(self.delay) return await original_json() async def delayed_text(): await asyncio.sleep(self.delay) return await original_text() response.json = delayed_json response.text = delayed_text return response # Convenience functions def create_failing_mock(exception: Exception) -> Mock: """Create a mock that always raises the specified exception.""" mock = Mock() mock.side_effect = exception return mock def create_async_failing_mock(exception: Exception) -> AsyncMock: """Create an async mock that always raises the specified exception.""" mock = AsyncMock() mock.side_effect = exception return mock def create_sequence_mock(values: List[Any]) -> Mock: """Create a mock that returns values in sequence.""" mock = Mock() mock.side_effect = values return mock def create_async_sequence_mock(values: List[Any]) -> AsyncMock: """Create an async mock that returns values in sequence.""" mock = AsyncMock() mock.side_effect = values return mock def create_conditional_mock(condition: Callable[..., bool], true_value: Any, false_value: Any) -> Mock: """Create a mock that returns different values based on a condition.""" def side_effect(*args, **kwargs): if condition(*args, **kwargs): return true_value return false_value mock = Mock() mock.side_effect = side_effect return mock