feat: add mqtt raw data management with UTC+8 range UI
All checks were successful
Deploy to Production / deploy (push) Successful in 1m19s
All checks were successful
Deploy to Production / deploy (push) Successful in 1m19s
This commit is contained in:
223
backend/tests/api/routes/test_mqtt_raw.py
Normal file
223
backend/tests/api/routes/test_mqtt_raw.py
Normal file
@@ -0,0 +1,223 @@
|
||||
from datetime import date, datetime, timezone
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlmodel import Session, delete, func, select
|
||||
|
||||
from app.core.config import settings
|
||||
from app.models import TerminalMessageRaw
|
||||
from app.mqtt.repository import insert_raw_message
|
||||
|
||||
|
||||
def _reset_raw_data(db: Session) -> None:
|
||||
db.execute(delete(TerminalMessageRaw))
|
||||
db.commit()
|
||||
|
||||
|
||||
def _count_raw_rows(db: Session) -> int:
|
||||
statement = select(func.count()).select_from(TerminalMessageRaw)
|
||||
return int(db.exec(statement).one())
|
||||
|
||||
|
||||
def test_list_mqtt_raw_days(
|
||||
client: TestClient, superuser_token_headers: dict[str, str], db: Session
|
||||
) -> None:
|
||||
_reset_raw_data(db)
|
||||
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"A1",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 10, 8, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"A2",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 10, 21, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-b",
|
||||
topic="terminal/device-b/raw",
|
||||
payload=b"B1",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 11, 9, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
f"{settings.API_V1_STR}/mqtt-raw/days?skip=0&limit=10",
|
||||
headers=superuser_token_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
content = response.json()
|
||||
assert content["count"] == 2
|
||||
assert content["data"][0]["day"] == "2026-03-11"
|
||||
assert content["data"][0]["message_count"] == 2
|
||||
assert content["data"][1]["day"] == "2026-03-10"
|
||||
assert content["data"][1]["message_count"] == 1
|
||||
|
||||
|
||||
def test_download_mqtt_raw_by_day_or_time_range(
|
||||
client: TestClient, superuser_token_headers: dict[str, str], db: Session
|
||||
) -> None:
|
||||
_reset_raw_data(db)
|
||||
|
||||
target_day = date(2026, 3, 12)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"EARLY\n",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 11, 20, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"MID\n",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 12, 3, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"LATE\n",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 12, 12, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"NEXT_DAY\n",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 12, 18, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
full_day_response = client.get(
|
||||
f"{settings.API_V1_STR}/mqtt-raw/download",
|
||||
headers=superuser_token_headers,
|
||||
params={"day": target_day.isoformat()},
|
||||
)
|
||||
assert full_day_response.status_code == 200
|
||||
assert full_day_response.content == b"EARLY\nMID\nLATE\n"
|
||||
|
||||
range_response = client.get(
|
||||
f"{settings.API_V1_STR}/mqtt-raw/download",
|
||||
headers=superuser_token_headers,
|
||||
params={
|
||||
"day": target_day.isoformat(),
|
||||
"start_seconds": 10 * 3600,
|
||||
"end_seconds": 14 * 3600,
|
||||
},
|
||||
)
|
||||
assert range_response.status_code == 200
|
||||
assert range_response.content == b"MID\n"
|
||||
|
||||
|
||||
def test_delete_mqtt_raw_by_day(
|
||||
client: TestClient, superuser_token_headers: dict[str, str], db: Session
|
||||
) -> None:
|
||||
_reset_raw_data(db)
|
||||
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-x",
|
||||
topic="terminal/device-x/raw",
|
||||
payload=b"X",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 14, 20, 30, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"A",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 15, 1, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-b",
|
||||
topic="terminal/device-b/raw",
|
||||
payload=b"B",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 15, 12, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-c",
|
||||
topic="terminal/device-c/raw",
|
||||
payload=b"C",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 15, 16, 30, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
response = client.delete(
|
||||
f"{settings.API_V1_STR}/mqtt-raw/day/2026-03-15",
|
||||
headers=superuser_token_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
content = response.json()
|
||||
assert content["deleted_count"] == 3
|
||||
assert _count_raw_rows(db) == 1
|
||||
|
||||
|
||||
def test_delete_all_mqtt_raw_requires_confirmation(
|
||||
client: TestClient, superuser_token_headers: dict[str, str], db: Session
|
||||
) -> None:
|
||||
_reset_raw_data(db)
|
||||
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-a",
|
||||
topic="terminal/device-a/raw",
|
||||
payload=b"A",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 15, 1, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
insert_raw_message(
|
||||
session=db,
|
||||
device_id="device-b",
|
||||
topic="terminal/device-b/raw",
|
||||
payload=b"B",
|
||||
qos=1,
|
||||
retain=False,
|
||||
received_at=datetime(2026, 3, 16, 1, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
reject_response = client.delete(
|
||||
f"{settings.API_V1_STR}/mqtt-raw/all",
|
||||
headers=superuser_token_headers,
|
||||
)
|
||||
assert reject_response.status_code == 400
|
||||
assert _count_raw_rows(db) == 2
|
||||
|
||||
confirmed_response = client.delete(
|
||||
f"{settings.API_V1_STR}/mqtt-raw/all?confirm=true",
|
||||
headers=superuser_token_headers,
|
||||
)
|
||||
assert confirmed_response.status_code == 200
|
||||
content = confirmed_response.json()
|
||||
assert content["deleted_count"] == 2
|
||||
assert _count_raw_rows(db) == 0
|
||||
Reference in New Issue
Block a user