3.5.3 At-scale interaction E2E — drag-as-transition · snap-back · swimlanes · cross-lane reassign · WIP
Estimate: 25m · Depends on: 3.5.1, 3.2.4, 3.3.5, 3.3.6, 3.8.5
The Playwright spec (tests/e2e/board-at-scale.spec.ts, the interaction half) that proves the combined drag + swimlane + WIP journey holds at scale — the deferral 3.2.7 / 3.3.7 / 4.5.4 send here. Every interaction runs on a card inside a virtualized, bounded board (3.5.1 seed), so it doubles as proof that the 3.8 load model does not break the 3.2/3.3 interaction contracts.
Drag-as-transition deep in a virtualized list. Scroll a tall column, pick a card not in the initial window, drag it to another column → the workflow transition applies (optimistic, then reconciled to the returned BoardCardDto); re-fetch / quick-view shows the new status; counts on both columns update. Proves drag survives virtualization (the dragged card + neighbours stay mounted, 3.2.5/3.8.3).
Illegal-move snap-back (409) at scale. An illegal cross-column move under the restricted workflow → the card snaps back to its origin column and the status is unchanged on re-fetch (the 3.1.5 IllegalBoardMoveError 409 contract), even from deep in the list.
Swimlanes re-lay at scale. Switch group-by to Assignee → the board re-lays into one lane per assignee-with-cards + the "No assignee" catch-all (last), each lane still bounded + virtualized with NO "Load more" (3.8.5); switch to Epic (grouped by ancestor epic) and Priority and back to None. Collapse a lane → its cards hide, header + aggregate count remain, and the collapse persists on reload.
Cross-lane reassign + diagonal. Drag a card into another assignee lane → the assignee is reassigned (confirmed via re-fetch / quick-view), status unchanged; into "No assignee" → unassigned. A diagonal drag (different column AND different lane) applies BOTH the transition and the field reassign, each with independent reconcile (3.3.5) — one rejection does not revert the other.
WIP soft-warning is advisory, not blocking. Set a column's WIP limit below its card count (the [⋯] menu, 3.3.6) → the header shows the n/limit over-limit warning (hue + icon/label, not colour-alone, finding #35); drag another card in → the drop still succeeds and the warning persists (soft = advisory; the 3.2.4 move contract is untouched). A column exactly at the limit (n === limit) is NOT warned (strictly greater).
Acceptance criteria
pnpm test:e2e --grep board-at-scale(this spec) is green: a drag-as-transition on a card scrolled into view deep in a virtualized column applies + reconciles; an illegal cross-column move snaps back (409) with status unchanged.- Switching group-by (Assignee/Epic-ancestor/Priority/None) re-lays the board into bounded, virtualized lanes + catch-all with NO "Load more"; a collapsed lane stays collapsed on reload; a cross-lane drag reassigns the grouped field (status unchanged) and a diagonal drag applies both writes with independent reconcile.
- A column over its WIP limit shows the soft
n/limitwarning (not colour-alone) yet still ACCEPTS a dropped card (advisory, non-blocking); an at-limit column is not warned. - Every interaction runs against the 3.5.1 board-shaped large seed (cards deep in virtualized lists), reuses the real-Postgres/Playwright harness + 3.5.1 helpers, and does NOT duplicate the single-surface drag/swimlane/WIP journeys owned by 3.2.7 / 3.3.7.
Context refs
- Story 3.5.1 — the board-shaped large seed + at-scale helpers; Stories 3.2.7 / 3.3.7 — the single-surface journeys this extends to scale (do not duplicate)
app/(authed)/boards/_components/{BoardContainer,BoardColumn,BoardCard,SwimlaneBoard,LaneCell}.tsx(3.2.4 dnd-kit drag, 3.3.5 swimlanes, 3.3.6 WIP, 3.8.5 bounded swimlane render) — under testlib/services/boardsService.ts(moveCard, swimlane projection, WIP) +lib/boards/errors.ts(IllegalBoardMoveError409,UnmappedColumnTargetError422) — the move + reassign contracts verifiedtests/e2e/_helpers/board.ts(+ 3.5.1 additions) +tests/e2e/_helpers/workflow.ts;design/boards/{board,swimlanes-wip}.mock.html(3.2.1/3.3.1) — the drag/lane/WIP design under test