from __future__ import annotations from collections.abc import Callable import pytest from sqlalchemy import Engine from sqlmodel import Session from datatypes.epc.domain.epc import Epc from domain.property_baseline.property_baseline_performance import PropertyBaselinePerformance from domain.property_baseline.performance import Performance from repositories.postgres_unit_of_work import PostgresUnitOfWork def _session_factory(db_engine: Engine) -> Callable[[], Session]: return lambda: Session(db_engine) def _baseline() -> PropertyBaselinePerformance: perf = Performance( sap_score=72, epc_band=Epc.C, co2_emissions=1.8, primary_energy_intensity=180 ) return PropertyBaselinePerformance( lodged=perf, effective=perf, rebaseline_reason="none", space_heating_kwh=5000.0, water_heating_kwh=2000.0, ) def test_committed_work_is_visible_to_a_later_unit(db_engine: Engine) -> None: # Arrange new_unit = lambda: PostgresUnitOfWork(_session_factory(db_engine)) baseline = _baseline() # Act with new_unit() as uow: uow.property_baseline.save(baseline, property_id=10) uow.commit() # Assert — a fresh unit reads back what the first one committed. with new_unit() as uow: loaded = uow.property_baseline.get_for_property(10) assert loaded == baseline def test_an_exception_in_the_block_rolls_the_batch_back(db_engine: Engine) -> None: # Arrange new_unit = lambda: PostgresUnitOfWork(_session_factory(db_engine)) # Act — a property mid-batch raises after a write but before commit. with pytest.raises(RuntimeError, match="boom"): with new_unit() as uow: uow.property_baseline.save(_baseline(), property_id=10) raise RuntimeError("boom") # Assert — nothing from the aborted batch is persisted. with new_unit() as uow: assert uow.property_baseline.get_for_property(10) is None def test_leaving_the_block_without_commit_persists_nothing(db_engine: Engine) -> None: # Arrange new_unit = lambda: PostgresUnitOfWork(_session_factory(db_engine)) # Act — write but never commit. with new_unit() as uow: uow.property_baseline.save(_baseline(), property_id=10) # Assert with new_unit() as uow: assert uow.property_baseline.get_for_property(10) is None