Files
FabledSteward/tests/core/test_paging.py
T
bvandeusenandClaude Opus 5.5 7275fad767
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 51s
CI / unit (push) Successful in 1m13s
CI / publish (push) Successful in 1m7s
feat(ui): audit log, alert history and Ansible runs load as you scroll (#5211)
#5211 "Lists load as you scroll: audit, alert history, Ansible runs"
(milestone 477), per preference 172.

- core/paging.py: keyset paging over (time, id), newest first, with an
  opaque "<iso>|<id>" cursor; a page reads one row past itself to know
  whether another follows. No OFFSET, so rows added while someone scrolls
  never shift the pages after them.
- _macros.html scroll_more / scroll_end and static/scroll-more.js, written
  once: an IntersectionObserver with a 600px margin fetches the next page
  before the reader reaches the end; "Loading more…" while in flight,
  "End of the list." at the end, and a failed page says so with a Retry
  button instead of re-firing on every scroll.
- Audit log: no "Load more" link and no 500-row cap.
- Alert history: no 200-row stop with "pick a shorter range";
  alert_svc.history takes the cursor, so the MCP tool and the page share
  one query.
- Ansible runs: no silent cap of 50.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:10:53 -04:00

35 lines
1.7 KiB
Python

"""Keyset paging for lists that load as you scroll (#5211): a cursor round-trips,
a mangled one starts over, and a page says whether another follows."""
from datetime import datetime, timezone
from types import SimpleNamespace as NS
from sqlalchemy import Column, DateTime, MetaData, String, Table, select
from sqlalchemy.dialects import postgresql
from steward.core.paging import cursor, keyset, next_page, parse_cursor
AT = datetime(2026, 10, 7, 3, 0, 5, 123456, tzinfo=timezone.utc)
def test_a_cursor_round_trips_and_a_mangled_one_starts_over():
assert parse_cursor(cursor(AT, "0190ab|cd")) == (AT, "0190ab|cd") # an id may hold the separator
assert parse_cursor(None) is None and parse_cursor("") is None
assert parse_cursor("not a cursor") is None and parse_cursor("yesterday|x") is None
def test_a_page_says_whether_another_follows():
rows = [NS(at=AT, id=str(i)) for i in range(5)]
page, after = next_page(rows, lambda r: (r.at, r.id), size=3)
assert [r.id for r in page] == ["0", "1", "2"] and after == cursor(AT, "2")
page, after = next_page(rows[:3], lambda r: (r.at, r.id), size=3)
assert len(page) == 3 and after is None # exactly a page: the end
def test_the_query_reads_one_row_past_the_page_older_than_the_cursor():
t = Table("t", MetaData(), Column("at", DateTime(timezone=True)), Column("id", String))
first = str(keyset(select(t), t.c.at, t.c.id, None, size=10).compile(dialect=postgresql.dialect()))
assert "WHERE" not in first and "ORDER BY t.at DESC, t.id DESC" in first and "LIMIT" in first
later = str(keyset(select(t), t.c.at, t.c.id, cursor(AT, "x"), size=10)
.compile(dialect=postgresql.dialect()))
assert "WHERE (t.at, t.id) < (" in later