from __future__ import annotations from datetime import datetime, timezone from app.ha.client import HaClient, HaClientSettings from app.ha.reader import HaReader class FakeHaClient(HaClient): def __init__(self) -> None: super().__init__(HaClientSettings(url="http://test", token="token")) def list_entities(self) -> list[dict[str, object]]: return [ { "entity_id": "sensor.temperature", "state": "21.5", "attributes": { "state_class": "measurement", "device_class": "temperature", "unit_of_measurement": "°C", }, }, { "entity_id": "light.living_room", "state": "on", "attributes": {}, }, ] def get_history( self, entity_ids: list[str], start_time: datetime, end_time: datetime, ) -> list[object]: return [ [ { "entity_id": entity_ids[0], "state": "21.5", "last_changed": start_time.isoformat(), } ] ] def list_entity_metadata(self, entity_ids: list[str]) -> dict[str, dict[str, str | None]]: return { "sensor.temperature": { "area_id": "kitchen", "area_name": "Kueche", "device_id": "device-1", "device_name": "Thermometer", } } def get_logbook( self, entity_id: str, start_time: datetime, end_time: datetime, ) -> list[object]: return [ { "entity_id": entity_id, "when": start_time.isoformat(), "message": "turned on", "context_user_id": "user-1", } ] def call_service( self, domain: str, service: str, service_data: dict[str, object], ) -> list[object]: return [] def test_ha_reader_returns_summaries() -> None: reader = HaReader(FakeHaClient()) summaries = reader.read_entities() assert len(summaries) == 2 domains = {summary.domain for summary in summaries} assert domains == {"sensor", "light"} sensor = next(item for item in summaries if item.entity_id == "sensor.temperature") assert sensor.unit_of_measurement == "°C" assert sensor.state == "21.5" assert sensor.area_name == "Kueche" assert sensor.device_name == "Thermometer" def test_ha_reader_discovers_learnable_sensors() -> None: reader = HaReader(FakeHaClient()) discovered = reader.discover(learnable=True) assert [entity.entity_id for entity in discovered] == ["sensor.temperature"] def test_ha_reader_normalizes_history() -> None: reader = HaReader(FakeHaClient()) start = datetime(2026, 6, 1, tzinfo=timezone.utc) history = reader.read_history( ["sensor.temperature"], start, datetime(2026, 6, 2, tzinfo=timezone.utc), ) assert history[0].entity_id == "sensor.temperature" assert history[0].points[0].value == 21.5 def test_ha_reader_normalizes_state_history_and_logbook() -> None: reader = HaReader(FakeHaClient()) start = datetime(2026, 6, 1, tzinfo=timezone.utc) end = datetime(2026, 6, 2, tzinfo=timezone.utc) history = reader.read_state_history(["light.living_room"], start, end) logbook = reader.read_logbook("light.living_room", start, end) assert history[0].points[0].state == "21.5" assert logbook[0].context_user_id == "user-1"