# S05: Search-First Web UI — UAT

**Milestone:** M001
**Written:** 2026-03-30T00:19:49.898Z

## UAT: S05 — Search-First Web UI

### Preconditions
- Docker Compose stack running (`docker compose up -d`) with PostgreSQL, API, and frontend services
- At least 1 creator, 1 source video, 2+ technique pages, and 3+ key moments in the database (from S03 pipeline processing)
- Qdrant running at configured endpoint with embeddings collection populated
- Frontend accessible at configured URL (e.g., http://localhost:5173 for dev, or via Docker)

---

### TC-01: Landing Page Search with Typeahead
1. Navigate to `/` (landing page)
2. **Expected:** Search bar is auto-focused, nav cards for "Topics" and "Creators" visible, "Recently Added" section shows up to 5 technique pages
3. Type "comp" into search bar and wait 300ms
4. **Expected:** Typeahead dropdown appears with up to 5 matching results after 2+ characters typed
5. Press Enter or click "See all results"
6. **Expected:** Browser navigates to `/search?q=comp`, full search results page loads

### TC-02: Search Results Grouped by Type
1. Navigate to `/search?q=reverb`
2. **Expected:** Results grouped by type — technique pages section first, then key moments section
3. Each result shows: title (clickable link), summary snippet, creator name, category/tags
4. **Expected:** If Qdrant was used, `fallback_used` is false; if Qdrant unreachable, banner shows "Showing keyword results"

### TC-03: Search with Empty Query
1. Navigate to `/search?q=`
2. **Expected:** No results shown, no errors, page loads cleanly

### TC-04: Search Keyword Fallback
1. Stop Qdrant service (or disconnect embedding API)
2. Navigate to `/search?q=compression`
3. **Expected:** Results still appear (from keyword ILIKE search), fallback banner "Showing keyword results" visible
4. Restart Qdrant service

### TC-05: Technique Page Full Detail
1. From search results, click on a technique page title
2. **Expected:** Browser navigates to `/techniques/{slug}`
3. **Expected:** Page shows:
   - Header: title, topic_category badge, topic_tags pills, creator name (clickable link to `/creators/{slug}`), source_quality indicator
   - If source_quality is "unstructured": amber banner warning displayed
   - Study guide prose: body_sections rendered as `<h2>` headings with paragraph text
   - Key moments index: ordered list with title, time range, content_type badge, summary
   - Signal chains section (if present): named chains with ordered steps
   - Plugins referenced (if present): pill list
   - Related techniques (if present): linked list

### TC-06: Technique Page 404
1. Navigate to `/techniques/nonexistent-slug-12345`
2. **Expected:** 404 error state shown — not a blank page, not a crash

### TC-07: Creators Browse — Randomized Default Sort (R014)
1. Navigate to `/creators`
2. Note the order of creators displayed
3. Refresh the page (F5)
4. **Expected:** Creator order differs from step 2 (randomized sort)
5. **Expected:** All creators have equal visual weight — no featured/highlighted/larger treatment

### TC-08: Creators Browse — Sort Toggle
1. On `/creators`, click "A-Z" sort toggle
2. **Expected:** Creators re-sort alphabetically
3. Click "Views" sort toggle
4. **Expected:** Creators re-sort by view count (highest first)
5. Click "Random" sort toggle
6. **Expected:** Creators return to randomized order

### TC-09: Creators Browse — Genre Filter
1. On `/creators`, click a genre filter pill (e.g., "Bass music")
2. **Expected:** Only creators matching that genre are shown
3. Click the same genre pill again (or clear filter)
4. **Expected:** All creators shown again

### TC-10: Creators Browse — Name Filter
1. On `/creators`, type a partial creator name in the filter input
2. **Expected:** Creator list narrows to only matching names (client-side filter)
3. Clear the input
4. **Expected:** All creators shown again

### TC-11: Creator Detail Page
1. From `/creators`, click on a creator row
2. **Expected:** Browser navigates to `/creators/{slug}`
3. **Expected:** Page shows creator name, genres, video count
4. **Expected:** Technique pages list shows technique pages by this creator, each with title (linked to `/techniques/{slug}`), category, tags

### TC-12: Creator Detail 404
1. Navigate to `/creators/nonexistent-creator-slug`
2. **Expected:** 404 error state shown

### TC-13: Topics Browse — Two-Level Hierarchy (R008)
1. Navigate to `/topics`
2. **Expected:** 6 top-level categories visible (Sound design, Mixing, Synthesis, Arrangement, Workflow, Mastering)
3. Each category shows expandable sub-topics
4. **Expected:** Each sub-topic shows technique_count and creator_count numbers

### TC-14: Topics Browse — Sub-Topic Navigation
1. On `/topics`, click a sub-topic name
2. **Expected:** Navigates to search results filtered by that topic (e.g., `/search?q={sub_topic}&scope=topics`)

### TC-15: Topics Browse — Filter
1. On `/topics`, type a partial topic name in the filter input
2. **Expected:** Categories and sub-topics narrow to matching entries
3. Clear filter
4. **Expected:** Full hierarchy restored

### TC-16: Navigation Header
1. On any page, observe the navigation header
2. **Expected:** "Chrysopedia" title (not "Chrysopedia Admin"), nav links to Home, Topics, Creators, Admin
3. Click each nav link
4. **Expected:** Each navigates to the correct page

### TC-17: Admin Routes Still Work
1. Navigate to `/admin/review`
2. **Expected:** Review queue admin page loads (from S04)
3. Navigate to `/` then back to `/admin/review`
4. **Expected:** Admin page still accessible — public routes don't break admin routes

### TC-18: Search Observability
1. Execute a search via API: `curl localhost:8001/api/v1/search?q=test`
2. **Expected:** JSON response with `items`, `total`, `query`, `fallback_used` fields
3. Check API server logs
4. **Expected:** INFO log line with format: `Search query='test' scope=all results=N fallback=False latency_ms=X.X`

### Edge Cases
- **Long query:** Search with a query > 500 characters → should be truncated, no error
- **Special characters:** Search with `q=a+b&c` → handled without crash
- **Empty database:** Topics page with no technique pages → zero counts shown, no crash
- **Concurrent requests:** Multiple rapid searches → debounce prevents flooding, no race conditions in typeahead
