Files
next-tjwater-server/tests/api/test_scada_timeseries_endpoints.py
T
jiang 1d061f6099
Generic Container CI/CD / test-build-publish (push) Failing after 6s
Server CI/CD v2 / build-test-publish-and-deploy (push) Failing after 6s
feat: add project-scoped operations
2026-10-22 18:40:20 +08:00

149 lines
4.4 KiB
Python

import asyncio
from datetime import datetime, timezone
from unittest.mock import AsyncMock
import pytest
from fastapi import HTTPException
from app.api.v1.endpoints.timeseries import scada as scada_endpoint
def _reading(device_id: str) -> scada_endpoint.ScadaReadingBatchItem:
return scada_endpoint.ScadaReadingBatchItem(
time=datetime(2026, 8, 27, tzinfo=timezone.utc),
device_id=device_id,
monitored_value=12.5,
)
def test_scada_batch_rejects_devices_missing_from_bizdb(monkeypatch):
monkeypatch.setattr(
scada_endpoint.ScadaInfoRepository,
"get_existing_device_ids",
AsyncMock(return_value={"known"}),
)
insert = AsyncMock()
monkeypatch.setattr(scada_endpoint.ScadaRepository, "insert_scada_batch", insert)
with pytest.raises(HTTPException, match="missing") as exc_info:
asyncio.run(
scada_endpoint.insert_scada_data(
[_reading("known"), _reading("missing")],
conn=object(),
postgres_conn=object(),
)
)
assert exc_info.value.status_code == 422
insert.assert_not_awaited()
def test_scada_batch_writes_only_after_bizdb_validation(monkeypatch):
monkeypatch.setattr(
scada_endpoint.ScadaInfoRepository,
"get_existing_device_ids",
AsyncMock(return_value={"known"}),
)
insert = AsyncMock()
monkeypatch.setattr(scada_endpoint.ScadaRepository, "insert_scada_batch", insert)
result = asyncio.run(
scada_endpoint.insert_scada_data(
[_reading(" known ")],
conn=object(),
postgres_conn=object(),
)
)
assert result == {"message": "Inserted 1 records"}
assert insert.await_args.args[1][0]["device_id"] == "known"
def test_latest_scada_readings_join_device_metadata_with_latest_rows(monkeypatch):
observed_at = datetime(2026, 10, 22, 1, 2, tzinfo=timezone.utc)
monkeypatch.setattr(
scada_endpoint.ScadaInfoRepository,
"get_scadas",
AsyncMock(return_value=[
{
"device_id": "PRESSURE-1",
"device_type": "pressure",
"measurement_unit": "MPa",
"transmission_mode": "realtime",
"transmission_frequency": "15min",
},
{
"device_id": "FLOW-2",
"device_type": "pipe_flow",
"measurement_unit": "m3/h",
"transmission_mode": "realtime",
"transmission_frequency": "15min",
},
]),
)
latest = AsyncMock(return_value={
"PRESSURE-1": {
"time": observed_at,
"device_id": "PRESSURE-1",
"monitored_value": 0.31,
"cleaned_value": 0.3,
}
})
monkeypatch.setattr(
scada_endpoint.ScadaRepository,
"get_latest_scada_readings",
latest,
)
result = asyncio.run(
scada_endpoint.get_latest_scada_readings(
limit=100,
offset=0,
conn=object(),
postgres_conn=object(),
)
)
assert result.total == 2
assert result.observed_count == 1
assert result.latest_observed_at == observed_at
assert result.items[0].monitored_value == pytest.approx(0.31)
assert result.items[1].observed_at is None
assert latest.await_args.args[1] == ["PRESSURE-1", "FLOW-2"]
def test_latest_scada_readings_applies_device_page_before_timeseries_query(monkeypatch):
monkeypatch.setattr(
scada_endpoint.ScadaInfoRepository,
"get_scadas",
AsyncMock(return_value=[
{
"device_id": f"D-{index}",
"device_type": "pressure",
"measurement_unit": "MPa",
"transmission_mode": "realtime",
"transmission_frequency": "15min",
}
for index in range(4)
]),
)
latest = AsyncMock(return_value={})
monkeypatch.setattr(
scada_endpoint.ScadaRepository,
"get_latest_scada_readings",
latest,
)
result = asyncio.run(
scada_endpoint.get_latest_scada_readings(
limit=2,
offset=1,
conn=object(),
postgres_conn=object(),
)
)
assert result.total == 4
assert [item.device_id for item in result.items] == ["D-1", "D-2"]
assert latest.await_args.args[1] == ["D-1", "D-2"]