4.9 KiB
QA: The editor's Library tab
Automated (Vitest + Vue Test Utils, task test:web)
Mock request for GET /v1/media/ by parsed query. Use the 12-image fixture from media_browse.feature as items, with total: 48, page, size: 25 and counts: {all: 48, unused: 2, duplicates: 2} (amended by features/media_pagination_api.feature: next_cursor, cursor and limit are gone). Mount EditorPage at /article/12/edit with a body containing <img data-image-id="1"> and <img data-image-id="4">. Use fake timers for the 150 ms and 120 ms steps.
- Opens on Library with images - first response has items; assert Library selected and skeleton tiles only after 150 ms.
- Opens on Upload when empty - empty first response; assert Upload selected; then click Library and assert the empty panel.
- Drop sends no list request - drop a file; assert no
?page=1&size=25request until Library is clicked. - Nothing selected - assert the line, 12 tiles in order, the "In this article" tag on exactly ids 1 and 4, "Load more", "Insert image" disabled.
- Active search hides the count - the line reads "Newest first".
- Last page - a total equal to the loaded count (for example 12) hides "Load more".
- Accessible names - the three Examples.
- Selection - click, Enter and Space each select; check, outline, "Insert image" enabled.
- Panel copy - kitchen-after.webp panel, placeholder and help text exact; "Load more" hidden; SVG reads "Vector · 8 KB".
- Single selection resets alt; reactivating keeps it selected.
- Insert - alt "A kitchen with new oak worktops and white tiles" gives
insertImage("/static/uploadedImages/2.webp", alt, 2), SaveStatus "Unsaved changes", the toast, the dialog closed, no non-GET request. Empty alt gives"". - Cancel, x and Escape change nothing.
- Search - type "wall"; at 119 ms no request, at 120 ms the request has
q=wall&page=1&size=25; the selection is cleared. The field's x and "Clear search" send a request with noq. - No results and Empty copy; "Upload an image" switches to the Upload tab.
- Load more - request has
page=2&size=25; button "Loading…" and disabled; skeleton row of 4 (3 below md); focus on the button, then on the first new tile after resolve; combinedqandpage=2. - Failed to load, Examples 500 and network - alert copy; "Try again" repeats the request; success replaces the alert.
Visual: task visual:check -- media-picker
Add a setup in web/visual/states.ts for each of the 13 states in docs/design/screens/media-picker.md, from the board's script (RenewCMS Screens Back-office.dc.html lines 239 to 253). Every capture must be within 10 % at 1440×900 and 390×844, light and dark. The sample data to reuse:
- Library mock: the 12-image fixture,
counts.all48,total48; images 1 and 4 in the article. The dialog is opened on the editor "How we price a bathroom renovation". - "Upload tab": Upload selected, idle drop zone.
- "Upload tab: already in your library": a chosen file named
north-wall.jpg; the hash lookup returns id 1 (12 Sep 2026, Marta Alves); the thumbnail is 72 × 54. - "Library: loading": skeleton tiles.
- "Library: nothing selected": the 12 tiles, tags on ids 1 and 4, "Load more".
- "Library: selected": id 2 (kitchen-after.webp, 2400 × 1600 · 1.2 MB), empty alt.
- "Library: alt text entered": id 2 with alt "A kitchen with new oak worktops and white tiles".
- "Library: loading more": 12 tiles plus one skeleton row, button "Loading…".
- "Library: empty": a mock with zero items. "Library: no results": search "wall" and zero items.
- "Library: failed to load": a 500.
- "Inserted": the editor with an image (id 1 as the board draws it) and the toast "Image added" / "Save to keep it in the article.".
- "Remove image: confirm": the confirm over the editor, image id 1 (north-wall.jpg, 3.9 MB). See
editor_image_removal.qa.md. - "Removed": the editor without the image and the toast "Image removed" / "It's still in your library.".
Clock-sensitive: none. Dates are absolute. Nothing is skipped.
Layout facts the mocks must hit (from the frame): the dialog is 640 px at 40 px from the top; the tabs row has a 20 px gap and 24 px side padding; the body has 16 px top padding and 24 px side padding; the search field is 32 px (44 px on mobile); the grid gap is 12 px (8 px between columns on mobile).
Manual checks the screenshots can't cover:
- Focus order is tabs, search, tiles, "Load more", footer. Enter and Space select a tile. Focus returns to the toolbar's image button when the dialog closes.
- Hover on a tile and on "Load more", and the focus ring.
- Motion: the dialog follows the standard 240 ms timing.
- A real library of more than 25 images through
task dev: "Load more" and the page numbers. - A screen reader reads the tile names and the alt text help.
Manual verification
Real GET /v1/media/ with q, page and size against task dev with a live SQLite file.