""" Tests for the in-memory DeviceStore. """ from __future__ import annotations import asyncio import pytest from app.device_store import DeviceStore, SensorReading @pytest.mark.asyncio async def test_get_all_devices(store: DeviceStore): """All registered devices are returned.""" devices = await store.get_all_devices() assert len(devices) == 3 @pytest.mark.asyncio async def test_get_enabled_devices(store: DeviceStore): """Only enabled devices are returned.""" devices = await store.get_enabled_devices() assert len(devices) == 2 ids = {d.config.id for d in devices} assert "test-disabled" not in ids @pytest.mark.asyncio async def test_get_device_by_id(store: DeviceStore): """Lookup by device ID.""" device = await store.get_device("test-plant-01") assert device is not None assert device.config.name == "Test Plant" missing = await store.get_device("nonexistent") assert missing is None @pytest.mark.asyncio async def test_get_device_by_ip(store: DeviceStore): """Lookup by IP address.""" device = await store.get_device_by_ip("192.168.1.100") assert device is not None assert device.config.id == "test-plant-01" @pytest.mark.asyncio async def test_update_reading(store: DeviceStore): """Recording a reading updates value and marks device online.""" await store.update_reading("test-plant-01", "sensors/soil_moisture", 42.5, "percent") device = await store.get_device("test-plant-01") assert device.online is True assert "sensors/soil_moisture" in device.readings assert device.readings["sensors/soil_moisture"].value == 42.5 assert device.readings["sensors/soil_moisture"].unit == "percent" @pytest.mark.asyncio async def test_update_reading_unknown_device(store: DeviceStore): """Readings for unknown devices are silently ignored.""" await store.update_reading("unknown-device", "sensors/x", 99, "unit") device = await store.get_device("unknown-device") assert device is None @pytest.mark.asyncio async def test_mark_offline(store: DeviceStore): """Marking offline sets flag and marks readings stale.""" await store.update_reading("test-plant-01", "sensors/temperature", 24.0, "celsius") await store.mark_offline("test-plant-01") device = await store.get_device("test-plant-01") assert device.online is False assert device.readings["sensors/temperature"].stale is True @pytest.mark.asyncio async def test_mark_online(store: DeviceStore): """Marking online resets the flag.""" await store.mark_offline("test-plant-01") await store.mark_online("test-plant-01") device = await store.get_device("test-plant-01") assert device.online is True @pytest.mark.asyncio async def test_snapshot(store: DeviceStore): """Snapshot returns a serializable dict of all devices.""" await store.update_reading("test-plant-01", "sensors/temperature", 23.5, "celsius") snap = await store.snapshot() assert "test-plant-01" in snap assert snap["test-plant-01"]["readings"]["sensors/temperature"]["value"] == 23.5 def test_sensor_reading_age(): """SensorReading.age_seconds returns meaningful values.""" import time reading = SensorReading(value=42, unit="percent", timestamp=time.time() - 10) assert 9.5 < reading.age_seconds() < 11.0 stale = SensorReading(value=0, timestamp=0) assert stale.age_seconds() == float("inf")