37 lines
4.2 KiB
Markdown
37 lines
4.2 KiB
Markdown
# QA: Paginated media listing (API)
|
|
|
|
## HTTP-level (Go, `test/`, `task test`)
|
|
|
|
Build `media.NewHandler(...)` over the real `ListMediaUseCase` and in-memory fakes of `image.Repository`, `article.Repository`, `user.Repository` and `image.VariantFileRepository` (extend the existing media fakes, keeping type names unique across files). Mount on a fresh `chi.NewRouter()` mirroring the media router in `api/router.go` (GET / inside `jwtauth.Verifier` + `jwtauth.Authenticator`, test `jwtauth.New("HS256", ...)`, valid `jwt` cookie with a `user_id` claim of a verified user). Call `validator.InitValidator()`. No live server, no SQLite file.
|
|
|
|
Helper: decode into {items []map, total, page, size int, counts {all, unused, duplicates}}; also assert the raw JSON contains `"items":[` (never null) and does not contain `next_cursor`.
|
|
|
|
1. Bare request: 30 images -> object, page 1, size 25, total 30, 25 items, no `next_cursor`.
|
|
2. Defaults table: page=2, page=3, size=5, size=50, size=100 on 60 images.
|
|
3. Partition: 12 images, pages 1-3 of size 5 -> 5, 5, 2; 12 distinct ids.
|
|
4. Order: equal-timestamp case -> ids 3,2,1. Sort table (newest, oldest, name, largest, total_size): 12 images, three pages, concatenation equals the full ordered list, no repeat. Ties break on id.
|
|
5. Filter/variants/q: unused -> total 6, counts unchanged; variants=with -> total 3; q=wall&size=5&page=2 -> total 7, 2 items, counts.all 27.
|
|
6. Hash: hash=H&page=1&size=100 -> 3 copies; hash=H alone -> page 1, size 25, 3 items.
|
|
7. Out of range: page=99&size=5 -> 200, raw `"items":[]`, total 12.
|
|
8. Empty library -> items [], total 0, counts 0/0/0.
|
|
9. counts library-wide: q=zzzz&page=3&size=5 -> items [], total 0, counts.all 30.
|
|
10. cursor/limit ignored: rows `cursor=abc`, `limit=5`, `limit=0`, `limit=abc`, a valid-looking old cursor -> 200, page 1, size 25, 25 items.
|
|
11. Invalid table (all rows): each -> 400, body exactly "The media query is invalid.", repository call counters stay 0.
|
|
12. Repository failure -> 500 "Internal server error".
|
|
13. Missing or invalid jwt cookie -> the auth group's 401, use case counter 0.
|
|
14. Use-case tests: `ListMediaUseCase.List` returns items, total, page, size and counts; slices after sorting; propagates a repository error (`errors.Is` on a sentinel); `Describe` is unchanged; `ListQuery.Validate` rejects page < 1 and sizes outside 5/25/50/100 with `ErrInvalidQuery`. `image.ListQuery.Cursor` and `.Limit`, `MediaPage.NextCursor`, `encodeCursor` and `decodeCursor` no longer exist.
|
|
15. Existing tests that read `next_cursor`, send `limit` or `cursor`, or call `NewListQuery` (media tests in `test/`, `features/media_library.qa.md`, `features/media_browse.qa.md`) are amended to the envelope; list them in the diff.
|
|
|
|
## Docs (verified by reading the diff)
|
|
|
|
- `docs/api.md` lines 99-103: replace `cursor` and `limit` with `page` (default 1) and `size` (5, 25, 50, 100; default 25); state the envelope (`items`, `total`, `page`, `size`, `counts`), that `counts` stays library-wide, that invalid values answer 400 "The media query is invalid.", and a "Breaking change" note: `next_cursor` is gone, `cursor` and `limit` are ignored.
|
|
- `docs/api/*.md`: grep for `/v1/media/` and `cursor`; update the media listing section if one exists.
|
|
- `web/src/data/apiCatalogue.ts` `med-list`: add `page`, `size`, `q`, `filter`, `sort`, `variants`, `hash` query entries, the 400 error, and a paged example (`total`, `page`, `size`, no `next_cursor`). Remove the `next_cursor` rule (line ~129, with its French entry in `web/src/i18n/messages.ts` line ~1606) if it is only used by media. Integration specs asserting the catalogue are amended.
|
|
- Flag for the user (read-only to agents): `docs/design/screens/integration.md` and `docs/design/source/IntegrationPage.dc.html` (med-list with no params), `docs/design/screens/media.md`, `routes.md`, `change-list.md` item 13b, `README.md` line 92 and `screens/media-picker.md`: all still say "array body" and "X-Total-Count".
|
|
- A release note under `docs/releases/` is the maintainer's call: flag it.
|
|
|
|
## Manual verification
|
|
|
|
- Real SQLite file via `task dev`: seed 60 images, check page=2&size=25, ordering by each sort and counts; the same on MySQL/PostgreSQL if available (no live DB in tests).
|
|
- An authenticated curl returns the envelope with no `next_cursor`.
|