4.6 KiB
QA: Media page pagination (SPA)
Automated (Vitest + Vue Test Utils, task test:web)
Mock /v1/media/ the way web/src/views/__tests__/mediaTestKit.ts does, extended so the mock honours page and size, builds the envelope {items, total, page, size, counts} and has no next_cursor. Use the 312-image fixture (25 per page) from the board's data in docs/design/source/MediaFrame.dc.html. Mount MediaView with a real router and Pinia. Reuse the helpers of ArticlesPagination.spec.ts.
One test per state:
- 44 First page: request
?filter=all&sort=newest&page=1&size=25; "Showing 1–25 of 312"; First/Previous disabled; URL without page or size. - 45 Middle page:
/media?page=7-> "Showing 151–175 of 312";aria-current="page"on 7; ellipses. - 46 Last page:
/media?page=13-> 12 items, "Showing 301–312 of 312"; Next/Last disabled. - Single page: total 12 -> summary, page-size select, no First..Last.
- 47 List view:
?view=list&page=2-> paginator under the table (md) and the card list (below md, the "Page 2 of 13" form). - 48 Loading next page: pending page 2 -> skeleton cards,
aria-busy, controls disabled, "Loading page 2…"; resolve -> URL/media?page=2. - 49 Error (500, network): previous images stay, URL unchanged, notice "Couldn't load page 7. Showing page 6." with Retry; Retry succeeds ->
?page=7, notice gone. - 50 Out of range:
?page=99with items [] and total 312 -> URL replaced by?page=13(assertrouter.replace, history length unchanged), notice text exact, last-page state. - Total 0 out of range: empty state, URL
/media; withq-> no-results state. - Reset to page 1: table of search (120 ms debounce with fake timers on the timer only, never the system date), tab, sort, view, variants filter -> request carries
page=1, URL has no page. - 51 Page-size menu table: 5, 25, 50, 100 -> request
page=1&size=N; URLs per the table. - Invalid URL table (
size=10&page=abc,page=0,page=-2,page=1.5,size=0,size=200): request page=1 size=25, URL replaced, no notice or alert. - Controls kept: Next with
size=50&sort=largest&filter=unusedkeeps every param. - 52 Focus and keyboard: tab order select, first, previous, pages, next, last; ArrowDown opens, Enter selects, Esc closes and refocuses.
- Select all: "25 images", 25 selected, page change clears the selection and the bulk bar.
- Duplicates tab: with 130 duplicates, assert requests page=1 and page=2 at size=100, groups built from all 130, no paginator, URL drops page and size; selecting All returns to the paginated request.
- Last-image delete: steps back one page and replaces the URL; counts refreshed.
- Background refresh after rename/upload/merge: same page, no skeleton.
- Hash lookups send
hash=H&page=1&size=100(findCopies,useMediaUpload,ImageUploader). - Amended existing specs: every spec reading
next_cursor,limit=100,MEDIA_PAGE_LIMITor the old/v1/media/?mocks is migrated to the envelope and page/size requests; list them in the diff.
Visual (task visual:check -- media)
Hard gate: every capture within 10 % at 1440×900 and 390×844, light and dark. Add web/visual/states.ts setups using the board's own sample data (312 images, 25 per page; filenames, sizes, uploaders and dates taken from the frame's script in docs/design/source/MediaFrame.dc.html; counts all 312 / unused 2 / duplicates 2):
| State | Setup |
|---|---|
| 44 Pagination: first page | /media, page 1 of 13 |
| 45 middle page | /media?page=7 |
| 46 last page | /media?page=13, 12 items |
| 47 list view | /media?view=list&page=2 |
| 48 loading next page | page 2 pending |
| 49 error loading a page | page 7 fails, page 6 shown |
| 50 page out of range | /media?page=99 replaced by ?page=13 with the notice |
| 51 page-size menu | select open upward |
| 52 focus-visible | Next focused |
If a frame renders a relative date or greeting, mark that state skip: clock-sensitive and write no date-frozen test. The paginator's placement under the grid or list is checked against the board frame's markup, not components.md prose.
Manual verification
- Keyboard: tab order and focus ring on every paginator control; ArrowDown/Enter/Esc in the page-size list; grid arrow-key navigation still works after a page change; focus is sensible after Next.
- Hover and motion on the paginator and skeleton.
- A real library of 60+ images through
task dev: paging, size change, page past the end replaced with the notice, Duplicates tab loading beyond 100 duplicates. - Screen reader: the summary and "Loading page N…" are announced; selection announcements after a page change.