"""Paging cursor correctness. The subtle invariant: `page.oldest` must be computed over the RAW batch, before the acted-on filter — otherwise a page that is mostly hidden would report a too-recent cursor (or none) and the client would stop early, silently truncating the folder with no error. """ from conftest import login_static def _records(n, start_hour=9): return [ {"date": f"2026-07-14 {start_hour - i:02d}:00:00", "from": "s@x", "rcpts": ["r@y"], "subject": f"m{i}", "guid": f"g{i}", "localguid": f"6:6:{i}", "size": "10"} for i in range(n) ] def test_oldest_from_raw_batch_not_filtered(app_client): login_static(app_client) pps = app_client._pps pps._records = _records(3) # 09,08,07 # Hide the two newest by enqueuing an action on them. q = app_client._queue q.enqueue("delete", "Quarantine", [{"localguid": "6:6:0"}, {"localguid": "6:6:1"}], {}, user="dev@example.invalid") data = app_client.get("/api/messages?folder=Quarantine&limit=1000").get_json() # Only the un-acted message is shown... assert len(data["messages"]) == 1 # ...but the cursor still reflects the oldest RAW record (07:00), not the shown one. assert data["page"]["oldest"] == "2026-07-14 07:00:00" assert data["page"]["raw_count"] == 3 def test_has_more_boundary(app_client): login_static(app_client) pps = app_client._pps pps._records = _records(5) data = app_client.get("/api/messages?folder=Quarantine&limit=5").get_json() assert data["page"]["has_more"] is True # raw_count == page_size data = app_client.get("/api/messages?folder=Quarantine&limit=6").get_json() assert data["page"]["has_more"] is False # raw_count < page_size def test_clamp_limit_edges(app_client): from app import _clamp_limit cfg = {"default_limit": 200} assert _clamp_limit(None, cfg) == 200 assert _clamp_limit("abc", cfg) == 200 assert _clamp_limit("0", cfg) == 1 assert _clamp_limit("-5", cfg) == 1 assert _clamp_limit("99999", cfg) == 1000 assert _clamp_limit("500", cfg) == 500