import asyncio from contextlib import contextmanager from datetime import datetime, timezone from app.infra.db.timescaledb.repositories.realtime import RealtimeRepository class _FakeCursor: def __init__(self): self.calls: list[tuple[str, tuple]] = [] async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): return False async def execute(self, query, params): self.calls.append((str(query), params)) async def fetchall(self): return [] class _FakeConnection: def __init__(self): self.cursor_instance = _FakeCursor() def cursor(self): return self.cursor_instance def test_get_links_by_time_range_normalizes_inputs_to_utc(): conn = _FakeConnection() asyncio.run( RealtimeRepository.get_links_by_time_range( conn, datetime.fromisoformat("2026-06-01T08:00:00+08:00"), datetime.fromisoformat("2026-06-01T09:00:00+08:00"), ) ) assert len(conn.cursor_instance.calls) == 1 _, params = conn.cursor_instance.calls[0] assert params == ( datetime(2026, 6, 1, 0, 0, tzinfo=timezone.utc), datetime(2026, 6, 1, 1, 0, tzinfo=timezone.utc), ) def test_get_nodes_by_time_range_normalizes_inputs_to_utc(): conn = _FakeConnection() asyncio.run( RealtimeRepository.get_nodes_by_time_range( conn, datetime.fromisoformat("2026-06-01T08:00:00+08:00"), datetime.fromisoformat("2026-06-01T09:00:00+08:00"), ) ) assert len(conn.cursor_instance.calls) == 1 _, params = conn.cursor_instance.calls[0] assert params == ( datetime(2026, 6, 1, 0, 0, tzinfo=timezone.utc), datetime(2026, 6, 1, 1, 0, tzinfo=timezone.utc), ) class _SyncTransactionConnection: def __init__(self): self.transactions = 0 @contextmanager def transaction(self): self.transactions += 1 yield def test_realtime_node_and_link_replacement_share_outer_transaction(monkeypatch): conn = _SyncTransactionConnection() calls: list[str] = [] monkeypatch.setattr( RealtimeRepository, "insert_nodes_batch_sync", lambda _conn, _data: calls.append("nodes"), ) monkeypatch.setattr( RealtimeRepository, "insert_links_batch_sync", lambda _conn, _data: calls.append("links"), ) RealtimeRepository.store_realtime_simulation_result_sync( conn, [{"node": "N1", "result": [{"pressure": 1.0}]}], [{"link": "L1", "result": [{"flow": 2.0}]}], "2026-06-01T00:00:00Z", ) assert conn.transactions == 1 assert calls == ["nodes", "links"]