M5-T07: add latest-reading cards and Recharts trend charts; readings return most-recent rows
This commit is contained in:
@@ -548,6 +548,7 @@ def test_readings_time_window_filters_correctly(modbus_client):
|
||||
|
||||
|
||||
def test_readings_limit_applied(modbus_client):
|
||||
"""When limit < total rows, exactly *limit* items are returned."""
|
||||
client, engine = modbus_client
|
||||
_login(client)
|
||||
device = _make_device(engine)
|
||||
@@ -564,6 +565,49 @@ def test_readings_limit_applied(modbus_client):
|
||||
assert len(resp.json()["items"]) == 3
|
||||
|
||||
|
||||
def test_readings_limit_returns_most_recent_rows_ascending(modbus_client):
|
||||
"""When window rows > limit, the MOST RECENT limit rows are returned, ascending.
|
||||
|
||||
This is the regression test for REWORK-1: previously the endpoint returned
|
||||
the oldest N rows (ASC + LIMIT), causing 6h/24h charts to show stale data.
|
||||
Now it returns the most recent N rows (DESC + LIMIT, then reversed to ASC).
|
||||
"""
|
||||
client, engine = modbus_client
|
||||
_login(client)
|
||||
device = _make_device(engine)
|
||||
|
||||
now = datetime.now(UTC)
|
||||
# Insert 5 readings spread over the last 5 minutes (newest first, but order shouldn't matter).
|
||||
timestamps = [now - timedelta(minutes=i) for i in range(5)] # t0=now, t1=now-1m, ..., t4=now-4m
|
||||
for idx, ts in enumerate(timestamps):
|
||||
_make_reading(engine, device.id, ts, {"voltage": float(200 + idx)})
|
||||
# Chronologically: t4 < t3 < t2 < t1 < t0
|
||||
# Voltages mapped: 204 203 202 201 200
|
||||
|
||||
# Request only the most recent 3 rows (limit=3).
|
||||
resp = client.get(
|
||||
f"/api/modbus/devices/{device.uuid}/readings",
|
||||
params={"limit": 3},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
items = resp.json()["items"]
|
||||
assert len(items) == 3
|
||||
|
||||
# Response must be in ascending recorded_at order.
|
||||
recorded_ats = [item["recorded_at"] for item in items]
|
||||
assert recorded_ats == sorted(recorded_ats), "Items must be ascending by recorded_at"
|
||||
|
||||
# The 3 most recent are timestamps[0], [1], [2] → voltages 200, 201, 202.
|
||||
voltages = [item["payload"]["voltage"] for item in items]
|
||||
assert voltages == [202.0, 201.0, 200.0], (
|
||||
f"Expected most recent 3 rows (voltages 200/201/202 ascending), got {voltages}"
|
||||
)
|
||||
|
||||
# The oldest row (voltage 204.0, at t4=now-4m) must NOT be in the response.
|
||||
assert 204.0 not in voltages, "Oldest row must not appear when limit truncates the window"
|
||||
assert 203.0 not in voltages, "Second-oldest row must not appear when limit truncates"
|
||||
|
||||
|
||||
def test_readings_limit_exceeds_max_returns_422(modbus_client):
|
||||
"""A limit > 5000 must be rejected by FastAPI query validation (422)."""
|
||||
client, engine = modbus_client
|
||||
|
||||
Reference in New Issue
Block a user