61 lines
2.4 KiB
Python
61 lines
2.4 KiB
Python
"""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()
|