"""HTTP boundary checks without project database access.""" from datetime import datetime, timezone from types import SimpleNamespace from unittest.mock import AsyncMock from uuid import uuid4 import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from app.api.v1.endpoints.timeseries import scada from app.domain.schemas.scada import ScadaRawPage @pytest.fixture def raw_api(monkeypatch): app = FastAPI() app.include_router(scada.router) project = uuid4() app.dependency_overrides[scada.get_timescale_connection] = lambda: object() app.dependency_overrides[scada.get_postgres_connection] = lambda: object() app.dependency_overrides[scada.get_project_context] = lambda: SimpleNamespace(project_id=project) devices = AsyncMock(return_value={"P1"}) monkeypatch.setattr(scada.ScadaInfoRepository, "get_existing_device_ids", devices) read = AsyncMock(return_value=ScadaRawPage(items=[], next_cursor=None, scanned_through=datetime(2026, 10, 2, tzinfo=timezone.utc))) monkeypatch.setattr(scada, "read_raw_page", read) with TestClient(app) as client: yield client, devices, read, project def test_raw_http_returns_only_read_projection_and_binds_project(raw_api): client, devices, read, project = raw_api response = client.get("/timeseries/scada-readings/raw", params={ "start_time": "2026-10-01T00:00:00Z", "end_time": "2026-10-02T00:00:00Z", "device_ids": "P1,P1", }) assert response.status_code == 200 assert response.json()["items"] == [] assert read.await_args.kwargs["project_id"] == str(project) assert read.await_args.kwargs["device_ids"] == ["P1"] devices.assert_awaited_once() def test_raw_http_rejects_naive_time_before_replay_lookup(raw_api): client, devices, read, _ = raw_api response = client.get("/timeseries/scada-readings/raw", params={ "start_time": "2026-10-01T00:00:00", "end_time": "2026-10-02T00:00:00Z", "device_ids": "P1", "replay_id": str(uuid4()), }) assert response.status_code == 422 devices.assert_not_awaited() read.assert_not_awaited() def test_raw_http_rejects_cross_project_device_before_tsdb(raw_api): client, _, read, _ = raw_api response = client.get("/timeseries/scada-readings/raw", params={ "start_time": "2026-10-01T00:00:00Z", "end_time": "2026-10-02T00:00:00Z", "device_ids": "other", }) assert response.status_code == 422 read.assert_not_awaited()