from __future__ import annotations from datetime import UTC, datetime from host_agent.history import ConsoleHistoryStore def test_history_store_records_assignment_and_heartbeat_newest_first(tmp_path) -> None: store = ConsoleHistoryStore(tmp_path / "history.sqlite3") store.record_assignment( task_id="task-a", attempt=1, status="done", failure_reason=None, device_id="device-a", ) store.record_heartbeat(device_count=2) entries = store.list_recent() assert len(entries) == 2 assert entries[0] == { "kind": "heartbeat", "occurred_at": entries[0]["occurred_at"], "summary": "heartbeat: 2 devices", "detail": {"device_count": 2}, } assert entries[1] == { "kind": "assignment", "occurred_at": entries[1]["occurred_at"], "summary": "task-a attempt 1 on device-a: done", "detail": { "task_id": "task-a", "attempt": 1, "status": "done", "failure_reason": None, "device_id": "device-a", }, } def test_history_store_prunes_oldest_entries_beyond_limit(tmp_path) -> None: store = ConsoleHistoryStore(tmp_path / "history.sqlite3", limit=3) for index in range(5): store.record_heartbeat(device_count=index) entries = store.list_recent() assert len(entries) == 3 assert [entry["detail"]["device_count"] for entry in entries] == [4, 3, 2] def test_history_store_returns_empty_list_when_no_entries(tmp_path) -> None: store = ConsoleHistoryStore(tmp_path / "history.sqlite3") assert store.list_recent() == [] def test_history_store_uses_injected_now_for_occurred_at(tmp_path) -> None: fixed_now = datetime(2026, 1, 1, 12, 0, 0, tzinfo=UTC) store = ConsoleHistoryStore(tmp_path / "history.sqlite3", now=lambda: fixed_now) store.record_heartbeat(device_count=1) entries = store.list_recent() assert entries[0]["occurred_at"] == fixed_now.isoformat()