test_paging.py 2.1 KB

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