5.2 KiB
QA procedure: Integration page search (jump-to palette)
No Go test: SPA only, no /v1 call, no API change. Counts and sample rows follow the real catalogue, not the board's sample data. The search index is built from the in-repo catalogue, so tests use the real API_GROUPS, SESSION_GROUPS, PUBLIC_AUTH_ROWS and ERROR_ROWS.
Automated SPA (Vitest + Vue Test Utils, task test:web)
Suggested files: web/src/views/__tests__/IntegrationSearch.spec.ts (palette), web/src/lib/__tests__/apiSearch.spec.ts (pure matcher), plus additions to IntegrationView.spec.ts for the trigger and the hash.
Setup:
- Mount IntegrationView like the existing spec (router at
/integration, attached to the document body for focus checks). - No
/v1mocks: assert no API call is made. - Stub
scrollTo,scrollIntoViewandgetBoundingClientRectas the existing spec does; fake timers for the 1.5 s flash class. No test freezes the system date. - Mock
matchMedia('(prefers-reduced-motion: reduce)')for the reduced-motion case, and the viewport for desktop vs mobile.
Cases (one it per scenario or Examples row; it.each for outlines):
- Trigger: desktop button has placeholder, "/" kbd, aria-label, aria-keyshortcuts; mobile icon button sits beside "Jump to".
- Shortcuts:
/, Ctrl+K and Cmd+K open;/ignored in input, textarea and contenteditable and not typed into the palette input; Ctrl+K opens from inside an input and calls preventDefault; listeners removed on unmount; Ctrl/Cmd+S in the editor is not affected. - Open focus: input focused; close returns focus to the opener; Cancel on mobile.
- Empty query: the 5 Suggested rows in order, first selected, "5 suggestions" in footer and live region; no recent searches stored.
- "media": 6 endpoint rows of 16, Sections row Media "11 routes", cap line "10 more endpoints. Keep typing to narrow the list.", "17 results", live "17 results, showing 7", highlight marks.
- "404": 6 rows with "Error" second line, Errors section, cap line "17 more endpoints. Keep typing to narrow the list.", "24 results", live "24 results, showing 7".
- "keep_id": one row, "Body field keep_id", "1 result". "page": GET /v1/site/{key}/sitemap shows "Query parameter page"; GET /v1/article/ matches in its description and has no second line.
- "login": dashed chip with lock, weight 400, Session only section row "37 routes, not available to API keys" with lock icon, "2 results".
- "xyz": empty copy, "0 results", live "No results".
- Matcher unit table: multi-term AND, case-insensitive, substring, "mdia" no match, extra spaces trimmed, path/description matches first then catalogue order, no search over code samples or response examples.
- Keyboard: ArrowDown/ArrowUp wrap, Home, End, typing resets to row 1, Enter selects, Esc closes with no scroll and no hash change.
- ARIA: combobox attributes, aria-activedescendant follows selection, listbox, group labelling, option aria-label, polite live region.
- Select endpoint: palette closed, scroll helper called with the card, card expanded, focus on the card button, flash class present then removed after 1500 ms, hash
#ep-<id>set throughhistory.replaceState(history length unchanged), other cards unchanged, index at "Media". - Select section: heading focused, hash is the section id, no flash, no expansion.
- Select session-only route: Session only heading focused, no card expanded.
- Reduced motion: static ring class, no animation class.
- Deep link: mount with
#ep-<id>runs case 13 without opening the palette;#ep-nopedoes nothing. - Never filtered: after typing, the number of cards and sections in the page DOM is unchanged.
- Regression: existing
IntegrationView.spec.tscases (section hash, scroll-spy, Jump to) still pass.
Visual (task visual:check -- integration, desktop and mobile, light and dark)
References: docs/design/screens/integration.md "Search (jump-to palette)", docs/design/source/IntegrationSearch.dc.html, states 8a to 8h of RenewCMS Screens Back-office.dc.html, and AppFrame.dc.html. Add each state to web/visual/states.ts with no /v1 mocks.
| state | setup | notes |
|---|---|---|
| 8a Trigger focused | focus the trigger | |
| 8b Open, empty | open the palette | 5 Suggested rows |
| 8c "media" | type "media" | 6 of 16 endpoints, Media section, 17 results |
| 8d "404", third row selected | type "404", ArrowDown x2 | cap line, 24 results |
| 8e "keep_id" | type "keep_id" | 1 result |
| 8f "login" | type "login" | session-only styling |
| 8g no results | type "xyz" | |
| 8h After selecting | select POST /v1/media/merge | capture after the flash with its animation disabled in the setup; the flash itself is not checked |
Queries and rows use the board's sample data exactly as in the table.
Manual checks (screenshots cannot cover)
- Keyboard and focus order: Tab reaches the trigger; "/" and Ctrl/Cmd+K open from the page; focus is trapped in the modal; Esc returns focus to the trigger.
- Flash motion: the 1.5 s fade is visible, and the OS reduced-motion setting swaps it for a static ring.
- Hover on rows and the trigger.
- Real browsers: Ctrl+K / Cmd+K does not open the address-bar search in Chrome, Firefox and Safari.
- Scroll offsets under the sticky bar on mobile and desktop for several groups.