from __future__ import annotations import pytest from domain.fuel_rates.fuel import Fuel, UnpricedFuel from domain.fuel_rates.fuel_rates import FuelRate, FuelRates, OffPeakRate def _rates() -> FuelRates: return FuelRates( period="test", seg_export_p_per_kwh=15.0, rates={Fuel.MAINS_GAS: FuelRate(unit_rate_p_per_kwh=5.74, standing_charge_p_per_day=29.09)}, ) def _off_peak_rates() -> FuelRates: return FuelRates( period="test", seg_export_p_per_kwh=15.0, rates={}, off_peak=OffPeakRate( day_p_per_kwh=29.73, night_p_per_kwh=13.89, standing_charge_p_per_day=56.99 ), ) def test_off_peak_blended_rate_at_zero_high_fraction_is_the_night_rate() -> None: # Arrange — an all-night load (storage heating, high-rate fraction 0.0). rates = _off_peak_rates() # Act blended = rates.off_peak_blended_p_per_kwh(high_rate_fraction=0.0) # Assert — every kWh bills at the cheap night rate. assert blended == 13.89 def test_off_peak_blended_rate_at_full_high_fraction_is_the_day_rate() -> None: # Arrange — an all-day load (high-rate fraction 1.0). rates = _off_peak_rates() # Act / Assert — every kWh bills at the dearer day rate. assert rates.off_peak_blended_p_per_kwh(high_rate_fraction=1.0) == 29.73 def test_off_peak_blended_rate_blends_day_and_night_linearly() -> None: # Arrange — 25% of the load at the day rate, 75% at night. rates = _off_peak_rates() # Act / Assert — 0.25 * 29.73 + 0.75 * 13.89 = 17.85 assert rates.off_peak_blended_p_per_kwh(high_rate_fraction=0.25) == pytest.approx(17.85) def test_off_peak_blend_without_a_snapshot_off_peak_entry_raises_unpriced_fuel() -> None: # Arrange — a snapshot that carries no off-peak entry at all. rates = _rates() # Act / Assert with pytest.raises(UnpricedFuel) as excinfo: rates.off_peak_blended_p_per_kwh(high_rate_fraction=0.5) assert excinfo.value.fuel is Fuel.ELECTRICITY_OFF_PEAK def test_off_peak_meter_standing_charge_reads_back() -> None: # Arrange — the bill adds the off-peak meter's standing charge once per meter. rates = _off_peak_rates() # Act / Assert assert rates.standing_charge_p_per_day(Fuel.ELECTRICITY_OFF_PEAK) == 56.99 def test_unit_rate_and_standing_charge_read_back_for_a_priced_fuel() -> None: # Arrange rates = _rates() # Act / Assert assert rates.unit_rate_p_per_kwh(Fuel.MAINS_GAS) == 5.74 assert rates.standing_charge_p_per_day(Fuel.MAINS_GAS) == 29.09 def test_a_fuel_absent_from_the_snapshot_raises_unpriced_fuel() -> None: # Arrange — LPG is not in this snapshot. rates = _rates() # Act / Assert — the raise carries the offending fuel for the operator. with pytest.raises(UnpricedFuel) as excinfo: rates.unit_rate_p_per_kwh(Fuel.LPG) assert excinfo.value.fuel is Fuel.LPG