""" Integration tests for Phase 1 components. These tests require a running PostgreSQL database with the test schema. """ import pytest import pytest_asyncio from typing import Dict, Any from src.database.client import DatabaseClient from src.core.auto_discovery import AutoDiscovery from src.core.safety import SafetyLimitEnforcer from config.settings import settings @pytest.mark.integration @pytest.mark.database class TestPhase1Integration: """Integration tests for Phase 1 components.""" @pytest_asyncio.fixture(scope="class") async def integration_db_client(self): """Create database client for integration tests.""" client = DatabaseClient( database_url=settings.database_url, min_connections=1, max_connections=3 ) await client.connect() yield client await client.disconnect() @pytest.mark.asyncio async def test_database_connection_integration(self, integration_db_client): """Test database connection and basic operations.""" # Test health check assert integration_db_client.health_check() is True # Test connection stats stats = integration_db_client.get_connection_stats() assert stats["pool_status"] == "active" @pytest.mark.asyncio async def test_database_queries_integration(self, integration_db_client): """Test database queries with real database.""" # Test getting pump stations stations = integration_db_client.get_pump_stations() assert isinstance(stations, list) # Test getting pumps pumps = integration_db_client.get_pumps() assert isinstance(pumps, list) # Test getting safety limits safety_limits = integration_db_client.get_safety_limits() assert isinstance(safety_limits, list) # Test getting pump plans pump_plans = integration_db_client.get_latest_pump_plans() assert isinstance(pump_plans, list) @pytest.mark.asyncio async def test_auto_discovery_integration(self, integration_db_client): """Test auto-discovery with real database.""" auto_discovery = AutoDiscovery(integration_db_client, refresh_interval_minutes=5) await auto_discovery.discover() # Verify discovery was successful stations = auto_discovery.get_stations() pumps = auto_discovery.get_pumps() assert isinstance(stations, dict) assert isinstance(pumps, list) # Verify discovery status status = auto_discovery.get_discovery_status() assert status["last_discovery"] is not None assert status["station_count"] >= 0 assert status["pump_count"] >= 0 # Validate discovery data validation = auto_discovery.validate_discovery() assert isinstance(validation, dict) assert "valid" in validation assert "issues" in validation @pytest.mark.asyncio async def test_safety_framework_integration(self, integration_db_client): """Test safety framework with real database.""" safety_enforcer = SafetyLimitEnforcer(integration_db_client) await safety_enforcer.load_safety_limits() # Verify limits were loaded limits_count = safety_enforcer.get_loaded_limits_count() assert limits_count >= 0 # Test setpoint enforcement if we have limits if limits_count > 0: # Get first pump with safety limits auto_discovery = AutoDiscovery(integration_db_client) await auto_discovery.discover() pumps = auto_discovery.get_pumps() if pumps: pump = pumps[0] station_id = pump['station_id'] pump_id = pump['pump_id'] # Test setpoint enforcement enforced, violations = safety_enforcer.enforce_setpoint( station_id, pump_id, 35.0 ) assert isinstance(enforced, float) assert isinstance(violations, list) @pytest.mark.asyncio async def test_component_interaction(self, integration_db_client): """Test interaction between Phase 1 components.""" # Initialize all components auto_discovery = AutoDiscovery(integration_db_client) safety_enforcer = SafetyLimitEnforcer(integration_db_client) # Perform discovery await auto_discovery.discover() await safety_enforcer.load_safety_limits() # Get discovered pumps pumps = auto_discovery.get_pumps() # Test setpoint enforcement for discovered pumps for pump in pumps[:2]: # Test first 2 pumps station_id = pump['station_id'] pump_id = pump['pump_id'] # Test setpoint enforcement enforced, violations = safety_enforcer.enforce_setpoint( station_id, pump_id, pump['default_setpoint_hz'] ) # Verify results assert isinstance(enforced, float) assert isinstance(violations, list) # If we have safety limits, the enforced setpoint should be valid if safety_enforcer.has_safety_limits(station_id, pump_id): limits = safety_enforcer.get_safety_limits(station_id, pump_id) assert limits.hard_min_speed_hz <= enforced <= limits.hard_max_speed_hz @pytest.mark.asyncio async def test_error_handling_integration(self, integration_db_client): """Test error handling with real database.""" # Test invalid query with pytest.raises(Exception): integration_db_client.execute_query("SELECT * FROM non_existent_table") # Test auto-discovery with invalid station filter auto_discovery = AutoDiscovery(integration_db_client) await auto_discovery.discover() # Get pumps for non-existent station pumps = auto_discovery.get_pumps("NON_EXISTENT_STATION") assert pumps == [] # Get non-existent pump pump = auto_discovery.get_pump("NON_EXISTENT_STATION", "NON_EXISTENT_PUMP") assert pump is None # Test safety enforcement for non-existent pump safety_enforcer = SafetyLimitEnforcer(integration_db_client) await safety_enforcer.load_safety_limits() enforced, violations = safety_enforcer.enforce_setpoint( "NON_EXISTENT_STATION", "NON_EXISTENT_PUMP", 35.0 ) assert enforced == 0.0 assert violations == ["NO_SAFETY_LIMITS_DEFINED"]