53 lines
4.6 KiB
Markdown
53 lines
4.6 KiB
Markdown
# 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:
|
||
1. 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.
|
||
2. 45 Middle page: `/media?page=7` -> "Showing 151–175 of 312"; `aria-current="page"` on 7; ellipses.
|
||
3. 46 Last page: `/media?page=13` -> 12 items, "Showing 301–312 of 312"; Next/Last disabled.
|
||
4. Single page: total 12 -> summary, page-size select, no First..Last.
|
||
5. 47 List view: `?view=list&page=2` -> paginator under the table (md) and the card list (below md, the "Page 2 of 13" form).
|
||
6. 48 Loading next page: pending page 2 -> skeleton cards, `aria-busy`, controls disabled, "Loading page 2…"; resolve -> URL `/media?page=2`.
|
||
7. 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.
|
||
8. 50 Out of range: `?page=99` with items [] and total 312 -> URL replaced by `?page=13` (assert `router.replace`, history length unchanged), notice text exact, last-page state.
|
||
9. Total 0 out of range: empty state, URL `/media`; with `q` -> no-results state.
|
||
10. 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.
|
||
11. 51 Page-size menu table: 5, 25, 50, 100 -> request `page=1&size=N`; URLs per the table.
|
||
12. 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.
|
||
13. Controls kept: Next with `size=50&sort=largest&filter=unused` keeps every param.
|
||
14. 52 Focus and keyboard: tab order select, first, previous, pages, next, last; ArrowDown opens, Enter selects, Esc closes and refocuses.
|
||
15. Select all: "25 images", 25 selected, page change clears the selection and the bulk bar.
|
||
16. 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.
|
||
17. Last-image delete: steps back one page and replaces the URL; counts refreshed.
|
||
18. Background refresh after rename/upload/merge: same page, no skeleton.
|
||
19. Hash lookups send `hash=H&page=1&size=100` (`findCopies`, `useMediaUpload`, `ImageUploader`).
|
||
20. Amended existing specs: every spec reading `next_cursor`, `limit=100`, `MEDIA_PAGE_LIMIT` or 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.
|