"""Integration tests for the elprisenligenu module.""" from datetime import datetime from zoneinfo import ZoneInfo import pytest from elprisenligenu.api import API from elprisenligenu.dto.hour_data import HourData class TestElprisenLigenIntegration: """Integration tests that make real API calls.""" def setup_method(self) -> None: """Set up test fixtures before each test method.""" self.api = API() self.tz = ZoneInfo("Europe/Copenhagen") @pytest.mark.integration def test_get_current_prices_dk1(self) -> None: """Test fetching current day prices for DK1 (integration test).""" # Act result = self.api.get_daily_prices(zone="DK1") # Assert assert isinstance(result, list) assert all(isinstance(item, HourData) for item in result) if result: # If data is available first_hour = result[0] assert isinstance(first_hour.DKK_per_kWh, float) assert isinstance(first_hour.EUR_per_kWh, float) assert isinstance(first_hour.EXR, float) assert isinstance(first_hour.time_start, datetime) assert isinstance(first_hour.time_end, datetime) # Basic sanity checks assert first_hour.EXR > 0 # Exchange rate should be positive assert first_hour.time_start < first_hour.time_end @pytest.mark.integration def test_get_current_prices_dk2(self) -> None: """Test fetching current day prices for DK2 (integration test).""" # Act result = self.api.get_daily_prices(zone="DK2") # Assert assert isinstance(result, list) assert all(isinstance(item, HourData) for item in result) if result: # If data is available first_hour = result[0] assert isinstance(first_hour.DKK_per_kWh, float) assert isinstance(first_hour.EUR_per_kWh, float) assert isinstance(first_hour.EXR, float) assert isinstance(first_hour.time_start, datetime) assert isinstance(first_hour.time_end, datetime) @pytest.mark.integration def test_get_historical_prices(self) -> None: """Test fetching historical prices (integration test).""" # Arrange - Use a date that should have data (not too far back) historical_date = datetime(2024, 10, 1, tzinfo=self.tz) # Act result = self.api.get_daily_prices(zone="DK1", date=historical_date) # Assert assert isinstance(result, list) if result: # If historical data is available assert len(result) <= 24 # Should be max 24 hours assert all(isinstance(item, HourData) for item in result) # Check that all times are from the requested date for hour_data in result: assert hour_data.time_start.date() == historical_date.date() @pytest.mark.integration def test_price_consistency(self) -> None: """Test that EUR and DKK prices are consistent with exchange rate.""" # Act result = self.api.get_daily_prices(zone="DK1") # Assert if result: for hour_data in result: # Calculate expected DKK price from EUR price and exchange rate expected_dkk = hour_data.EUR_per_kWh * hour_data.EXR # Allow for small floating point differences difference = abs(hour_data.DKK_per_kWh - expected_dkk) assert difference < 0.001, ( f"Price inconsistency: DKK={hour_data.DKK_per_kWh}, " f"EUR={hour_data.EUR_per_kWh}, EXR={hour_data.EXR}, " f"Expected DKK={expected_dkk}" ) @pytest.mark.integration def test_time_ordering(self) -> None: """Test that hours are returned in chronological order.""" # Act result = self.api.get_daily_prices(zone="DK1") # Assert if len(result) > 1: for i in range(1, len(result)): assert result[i - 1].time_start <= result[i].time_start, ( f"Hours not in chronological order: " f"{result[i - 1].time_start} > {result[i].time_start}" ) @pytest.mark.integration def test_hour_duration(self) -> None: """Test that each hour period is exactly 1 hour long.""" # Act result = self.api.get_daily_prices(zone="DK1") # Assert if result: for hour_data in result: duration = hour_data.time_end - hour_data.time_start assert duration.total_seconds() == 3600, ( f"Hour duration is not 1 hour: {duration}" ) @pytest.mark.integration def test_both_zones_same_day(self) -> None: """Test that both zones return data for the same day.""" # Arrange test_date = datetime(2024, 10, 15, tzinfo=self.tz) # Act dk1_result = self.api.get_daily_prices(zone="DK1", date=test_date) dk2_result = self.api.get_daily_prices(zone="DK2", date=test_date) # Assert # Both zones should have data for the same day if dk1_result and dk2_result: assert len(dk1_result) == len(dk2_result) # Times should be the same for dk1_hour, dk2_hour in zip(dk1_result, dk2_result): assert dk1_hour.time_start == dk2_hour.time_start assert dk1_hour.time_end == dk2_hour.time_end # Exchange rates should be the same assert dk1_hour.EXR == dk2_hour.EXR # But prices can be different between zones # (That's the whole point of having two zones!)