3.5.2 At-scale load-model E2E — bounded load, virtualization, over-cap banner, Done-age window
Estimate: 22m · Depends on: 3.5.1, 3.8.3, 3.8.4, 3.8.5
The Playwright spec (tests/e2e/board-at-scale.spec.ts) that proves the Story-3.8 load model holds at scale — the stub's explicit mandate: "NO per-column 'Load more'; the board loads the filtered set + virtualizes + shows the over-cap 'refine filter' warning + the Done-age window (not the retired cursor paging)". Runs against the board-shaped large seed (3.5.1) over the real stack.
Bounded whole-set load, no "Load more" (flat). Open /boards on the BIG project: columns render their cards with NO per-column "Load more" button and NO scroll-sentinel footer anywhere (the 3.8.3 retirement) — assert the affordance is absent. Each column's count badge shows its full totalCount.
Virtualization keeps the DOM bounded. A tall column (seeded past the row window) renders far fewer card DOM nodes than its total; scrolling it reveals later cards while the rendered node count stays bounded (useRowWindow) — assert rendered-count ≪ total, and that a card deep in the list becomes reachable by scrolling (not by paging).
Over-cap "refine your filter" banner. With the cap lowered below the seeded board total (the 3.5.1 env seam), the OverCapBanner shows above the board — text names the cap, paired with the alert-triangle (not colour-alone, finding #35), role="status" — for both the flat AND the swimlane layout (3.8.4). Raise the cap above the total (or seed under it): the banner is absent (truncated === false).
Done-age window. The terminal (Done) column shows only issues resolved within the Done-age window (the 3.5.1 seed places some resolvedAt inside and some outside); the older resolved issues are absent from the rendered column while the column's count badge still reflects the full total. Shrinking the window via the 3.5.1 seam trims more — proving the window is age-based (3.8.2), not the retired count-based cap.
No retired contract. Assert the dead per-column load-more route (GET /api/board/columns/[id]/cards) is not called by the board at scale (no cursor paging) — the bound is the cap, the render is virtualized.
Acceptance criteria
pnpm test:e2e --grep board-at-scale(this spec) is green: against the board-shaped large seed, the flat board loads the whole bounded set with NO "Load more"/sentinel footer, and a tall column renders a bounded DOM node count that grows by scrolling (not paging).- The over-cap "refine your filter" banner shows above the board (flat AND swimlane) when the seeded total exceeds the (lowered) cap and is absent when under it; it pairs hue with the alert-triangle + copy (not colour-alone) and is announced (
role="status"). - The Done column shows only issues resolved inside the Done-age window while its count badge shows the full total; shrinking the window (3.5.1 seam) trims more (age-based, not count-based).
- The spec asserts NO per-column cursor/"Load more" affordance or route call anywhere (flat or swimlane); reuses the 3.5.1 helpers + the real-Postgres/Playwright harness; does NOT duplicate 3.8.6's unit-level load-model assertions.
Context refs
- Story 3.5.1 — the board-shaped large seed + cap/Done-age seam + at-scale helpers this consumes
app/(authed)/boards/_components/{BoardContainer,BoardColumn,SwimlaneBoard,LaneCell,OverCapBanner}.tsx(3.8.3/3.8.4/3.8.5) +components/ui/useRowWindow.ts— the surfaces under testlib/services/boardsService.ts(getBoardcap/truncated/Done-age) +lib/dto/boards.ts(cap/truncated) — the load-model contract being verifiedtests/e2e/board-projection.spec.ts(3.1.7) — the board E2E pattern;tests/e2e/_helpers/board.ts;design/boards/board-scale.mock.html(3.8.1) — the over-cap/Done-age design under test