Files
RenewCMS/features/integration_search.qa.md
T

59 lines
5.2 KiB
Markdown

# 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 `/v1` mocks: assert no API call is made.
- Stub `scrollTo`, `scrollIntoView` and `getBoundingClientRect` as 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):
1. Trigger: desktop button has placeholder, "/" kbd, aria-label, aria-keyshortcuts; mobile icon button sits beside "Jump to".
2. 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.
3. Open focus: input focused; close returns focus to the opener; Cancel on mobile.
4. Empty query: the 5 Suggested rows in order, first selected, "5 suggestions" in footer and live region; no recent searches stored.
5. "media": 6 endpoint rows of 11, Sections row Media "11 routes", cap line "5 more endpoints. Keep typing to narrow the list.", "12 results", live "12 results, showing 7", highlight marks.
6. "404": 6 rows with "Error" second line, Errors section, cap line "8 more endpoints. Keep typing to narrow the list.", "15 results", live "15 results, showing 7".
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.
8. "login": dashed chip with lock, weight 400, Session only section row "25 routes, not available to API keys" with lock icon, "2 results".
9. "xyz": empty copy, "0 results", live "No results".
10. 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.
11. Keyboard: ArrowDown/ArrowUp wrap, Home, End, typing resets to row 1, Enter selects, Esc closes with no scroll and no hash change.
12. ARIA: combobox attributes, aria-activedescendant follows selection, listbox, group labelling, option aria-label, polite live region.
13. 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 through `history.replaceState` (history length unchanged), other cards unchanged, index at "Media".
14. Select section: heading focused, hash is the section id, no flash, no expansion.
15. Select session-only route: Session only heading focused, no card expanded.
16. Reduced motion: static ring class, no animation class.
17. Deep link: mount with `#ep-<id>` runs case 13 without opening the palette; `#ep-nope` does nothing.
18. Never filtered: after typing, the number of cards and sections in the page DOM is unchanged.
19. Regression: existing `IntegrationView.spec.ts` cases (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 11 endpoints, Media section, 12 results |
| 8d "404", third row selected | type "404", ArrowDown x2 | cap line, 15 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.