chore: auto-commit after complete-milestone
GSD-Unit: M012
This commit is contained in:
parent
baef500de6
commit
c0df8a7908
8 changed files with 320 additions and 3 deletions
|
|
@ -210,3 +210,15 @@
|
|||
**Context:** CSS `border-image` property overrides `border-radius`, making rounded corners disappear. This is per CSS spec — border-image replaces the entire border rendering including corner shapes.
|
||||
|
||||
**Fix:** If rounded corners are required, use `box-shadow` or pseudo-elements for decorative borders instead of `border-image`. For the featured technique card, box-shadow glow provides the visual distinction even though corners are square.
|
||||
|
||||
## Sort strategy depends on data source homogeneity
|
||||
|
||||
**Context:** Search results come from two sources (Qdrant semantic + keyword SQL). Applying SQL ORDER BY is impossible when results are merged from different backends. Single-source list views (subtopic pages, creator detail) pull exclusively from PostgreSQL.
|
||||
|
||||
**Fix:** Use Python-level sorting (`sorted()` with key functions) for mixed-source result sets. Use SQL `ORDER BY` for single-source endpoints — it's faster and handles NULLs correctly. The sort param flows from the API query string through to whichever strategy applies. Don't try to unify into one approach.
|
||||
|
||||
## Multi-token AND search with partial_matches fallback
|
||||
|
||||
**Context:** Single-pattern ILIKE search (e.g., `%keota snare%`) only matches when the exact phrase appears in one field. Users expect "keota snare" to find content where "keota" matches the creator and "snare" matches the title/tags.
|
||||
|
||||
**Fix:** Tokenize by whitespace. For each token, generate OR conditions across all searchable fields (title, summary, tags, category, creator name). AND all per-token conditions. When a multi-token AND query returns zero results, fall back to partial_matches: query each token separately, score results by token coverage, return top 5 with a muted UI treatment. This gives exact matches priority while still providing useful results for imprecise queries.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
## Current State
|
||||
|
||||
Eleven milestones complete. The system is deployed and running on ub01 at `http://ub01:8096`.
|
||||
Twelve milestones complete. The system is deployed and running on ub01 at `http://ub01:8096`.
|
||||
|
||||
### What's Built
|
||||
|
||||
|
|
@ -44,6 +44,7 @@ Eleven milestones complete. The system is deployed and running on ub01 at `http:
|
|||
- **Empty subtopic handling** — Subtopics with 0 techniques show "Coming soon" badge instead of dead-end links.
|
||||
- **Accessibility & SEO fixes** — Single h1 per page, skip-to-content keyboard link, AA-compliant muted text contrast (#828291), descriptive per-route browser tab titles via useDocumentTitle hook.
|
||||
- **Multi-field composite search** — Search tokenizes multi-word queries, AND-matches each token across creator/title/tags/category/body fields. Partial matches fallback when no exact cross-field match exists. Qdrant embeddings enriched with creator names and topic tags. Admin reindex-all endpoint for re-embedding after changes.
|
||||
- **Sort controls on all list views** — Reusable SortDropdown component on SearchResults, SubTopicPage, and CreatorDetail. Sort options: relevance/newest/oldest/alpha/creator (context-appropriate per page). Preference persists in sessionStorage across navigation.
|
||||
|
||||
### Stack
|
||||
|
||||
|
|
@ -67,4 +68,4 @@ Eleven milestones complete. The system is deployed and running on ub01 at `http:
|
|||
| M009 | Homepage & First Impression | ✅ Complete |
|
||||
| M010 | Discovery, Navigation & Visual Identity | ✅ Complete |
|
||||
| M011 | Interaction Polish, Navigation & Accessibility | ✅ Complete |
|
||||
| M012 | Search & Sort Improvements | 🔄 In Progress |
|
||||
| M012 | Multi-Field Composite Search & Sort Controls | ✅ Complete |
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ Every search input resolves multi-token queries across all metadata fields (crea
|
|||
| ID | Slice | Risk | Depends | Done | After this |
|
||||
|----|-------|------|---------|------|------------|
|
||||
| S01 | Multi-Field Composite Search | high | — | ✅ | Type 'keota snare' in search box → results show only content matching both tokens across creator/title/tags/body fields |
|
||||
| S02 | Sort Controls on All List Views | medium | S01 | ⬜ | Every list view (search results, sub-topic page, creator detail) shows a visible sort dropdown. Changing sort persists across navigation within the session. |
|
||||
| S02 | Sort Controls on All List Views | medium | S01 | ✅ | Every list view (search results, sub-topic page, creator detail) shows a visible sort dropdown. Changing sort persists across navigation within the session. |
|
||||
|
|
|
|||
71
.gsd/milestones/M012/M012-SUMMARY.md
Normal file
71
.gsd/milestones/M012/M012-SUMMARY.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
id: M012
|
||||
title: "Multi-Field Composite Search & Sort Controls"
|
||||
status: complete
|
||||
completed_at: 2026-04-01T06:38:09.561Z
|
||||
key_decisions:
|
||||
- D023: Multi-token AND search architecture — tokenize by whitespace, per-token OR across fields, AND all tokens, partial_matches fallback on zero results
|
||||
- D024: Qdrant embedding text enriched with creator_name + topic_tags, batch-resolved at stage start
|
||||
- Sort applied in Python for mixed-source search results, SQL ORDER BY for single-source endpoints
|
||||
- Shared sessionStorage key across all pages for unified sort preference
|
||||
- Page-specific sort option lists with context-appropriate defaults (relevance for search, alpha for subtopic, newest for creator)
|
||||
key_files:
|
||||
- backend/search_service.py
|
||||
- backend/schemas.py
|
||||
- backend/routers/search.py
|
||||
- backend/routers/topics.py
|
||||
- backend/routers/techniques.py
|
||||
- backend/pipeline/stages.py
|
||||
- backend/pipeline/qdrant_client.py
|
||||
- backend/routers/pipeline.py
|
||||
- frontend/src/components/SortDropdown.tsx
|
||||
- frontend/src/hooks/useSortPreference.ts
|
||||
- frontend/src/pages/SearchResults.tsx
|
||||
- frontend/src/pages/SubTopicPage.tsx
|
||||
- frontend/src/pages/CreatorDetail.tsx
|
||||
- frontend/src/api/public-client.ts
|
||||
- backend/tests/test_search.py
|
||||
lessons_learned:
|
||||
- Reusable SortDropdown + useSortPreference hook pattern: sessionStorage for UI preferences that don't need server persistence, page-specific option lists with shared storage key
|
||||
- Batch-resolve related entity names at stage start to avoid N+1 during embedding loops — resolved creator names once for all technique pages/key moments
|
||||
- Reindex-all admin endpoint pattern: when embedding text composition changes, provide a one-shot re-embedding trigger rather than requiring manual per-video reprocessing
|
||||
- Python-level sorting for mixed-source results (Qdrant + keyword) vs SQL ORDER BY for single-source endpoints — choosing sort strategy based on data source homogeneity
|
||||
---
|
||||
|
||||
# M012: Multi-Field Composite Search & Sort Controls
|
||||
|
||||
**Delivered multi-token AND search across all metadata fields with partial_matches fallback, enriched Qdrant embeddings with creator/tag data, and sort controls on all list views with session-persistent preferences.**
|
||||
|
||||
## What Happened
|
||||
|
||||
M012 addressed two high-value UX gaps: search queries with multiple tokens returned irrelevant results (single ILIKE pattern matching), and list views had no user-controllable sort.
|
||||
|
||||
S01 (Multi-Field Composite Search) rewrote the keyword search engine from single-pattern ILIKE to a multi-token AND architecture. Each whitespace-delimited token generates OR conditions across all entity fields (title, summary, topic_category, topic_tags, creator name via JOIN). All per-token conditions are AND'd so every token must match at least one field. A partial_matches fallback triggers on multi-token queries with zero AND results — individual tokens are queried separately and top-5 results scored by coverage are returned with a muted UI treatment. Stage 6 embedding text was enriched to include creator_name and topic_tags, with batch resolution at stage start to avoid N+1. A reindex-all admin endpoint enables one-shot re-embedding after text composition changes. 19 backend tests pass including 6 new tests for multi-token AND logic. Frontend handles the new partial_matches field with defensive fallback for backward compatibility.
|
||||
|
||||
S02 (Sort Controls) added a sort query parameter to four backend endpoints (search, subtopic, category topics, techniques) supporting relevance/newest/oldest/alpha/creator options. Search results use Python-level sorting (mixed Qdrant + keyword sources), while single-source endpoints use SQL ORDER BY. A reusable SortDropdown component and useSortPreference hook backed by sessionStorage were integrated into SearchResults, SubTopicPage, and CreatorDetail with context-appropriate option lists and defaults. Deployed to ub01 and verified end-to-end.
|
||||
|
||||
## Success Criteria Results
|
||||
|
||||
- **Multi-token queries across all metadata fields with AND logic:** ✅ Met. keyword_search tokenizes by whitespace, generates per-token OR across title/summary/category/tags/creator, AND's all tokens. 19 tests pass including explicit multi-token cross-field scenarios.
|
||||
- **Every list view exposes visible sort control with session-persisted preference:** ✅ Met. SortDropdown integrated into SearchResults (relevance/newest/oldest/alpha), SubTopicPage (alpha/newest/oldest), and CreatorDetail (newest/oldest/alpha). sessionStorage persists preference across navigation. Verified on ub01:8096.
|
||||
|
||||
## Definition of Done Results
|
||||
|
||||
- **S01 complete with summary:** ✅ S01-SUMMARY.md, S01-UAT.md, 3 task summaries present.
|
||||
- **S02 complete with summary:** ✅ S02-SUMMARY.md, S02-UAT.md, 2 task summaries present.
|
||||
- **All slices marked done in roadmap:** ✅ Both S01 and S02 show ✅ in M012-ROADMAP.md.
|
||||
- **Cross-slice integration:** ✅ S02 depends on S01 — sort controls work on search results that use the new multi-token AND engine.
|
||||
|
||||
## Requirement Outcomes
|
||||
|
||||
- **R005 (Search-First Web UI):** Remains validated. Advanced with multi-token AND logic — composite queries like "keota snare" now return targeted results instead of broad single-pattern matches.
|
||||
- **R009 (Qdrant Vector Search):** Remains validated. Advanced with enriched embedding text containing creator_name and topic_tags for broader semantic coverage.
|
||||
- **R015 (30-Second Retrieval Target):** Remains active. Advanced — multi-token AND search significantly reduces result noise for specific queries, shortening time-to-answer. Still needs formal timed test for validation.
|
||||
|
||||
## Deviations
|
||||
|
||||
T02 added creator_name to technique_page Qdrant payload beyond the original plan (only key_moment was specified) — strictly additive. T01 added sort param to the category-level topic endpoint beyond the original plan, for frontend consistency.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
After deploy: rebuild containers on ub01, run POST /admin/pipeline/reindex-all to re-embed all content with creator names and tags. R015 (30-Second Retrieval) still needs a formal timed user test for validation.
|
||||
49
.gsd/milestones/M012/M012-VALIDATION.md
Normal file
49
.gsd/milestones/M012/M012-VALIDATION.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
verdict: needs-attention
|
||||
remediation_round: 0
|
||||
---
|
||||
|
||||
# Milestone Validation: M012
|
||||
|
||||
## Success Criteria Checklist
|
||||
- [x] **Multi-token AND search across all metadata fields** — PASS. S01 summary confirms tokenize-by-whitespace → per-token OR across fields → AND all tokens. Fields covered: title, summary, topic_category, topic_tags (array_to_string), creator name (via JOIN). 19 tests pass including 6 new multi-token AND tests.
|
||||
- [x] **Partial matches fallback on zero AND results** — PASS. S01 implemented `partial_matches` in SearchResponse schema, backend `_keyword_partial_matches` fallback, and frontend three-way rendering (exact → partial → empty). Tests cover partial_matches trigger logic.
|
||||
- [x] **Sort controls on all list views** — PASS. S02 added SortDropdown component to SearchResults, SubTopicPage, and CreatorDetail. Backend sort param on search, subtopic, category topics, and techniques endpoints. SQL ORDER BY for single-source, Python sort for mixed sources.
|
||||
- [x] **Session-persistent sort preference** — PASS. S02 useSortPreference hook backed by sessionStorage with shared key across all pages. Verified: changing sort persists across navigation within session.
|
||||
- [x] **Enriched Qdrant embeddings with creator/tags** — PASS. S01/T02 enriched stage 6 embedding text with creator_name and topic_tags for both technique pages and key moments. Batch creator resolution avoids N+1. Reindex-all admin endpoint added.
|
||||
|
||||
## Slice Delivery Audit
|
||||
| Slice | Claimed Deliverable | Evidence | Verdict |
|
||||
|-------|---------------------|----------|---------|
|
||||
| S01: Multi-Field Composite Search | Type 'keota snare' → results matching both tokens across fields | Backend: multi-token AND with cross-field matching, 19 tests pass (6 new). Frontend: PartialMatchResults component, three-way rendering. Qdrant embeddings enriched with creator_name + topic_tags. Reindex-all endpoint. | ✅ Delivered |
|
||||
| S02: Sort Controls on All List Views | Every list view shows sort dropdown, persists across navigation | Backend: sort param on 4 endpoints. Frontend: SortDropdown + useSortPreference hook on 3 pages. Browser-verified on ub01:8096 — sort changes update results, sessionStorage persists. | ✅ Delivered |
|
||||
|
||||
## Cross-Slice Integration
|
||||
S01 provides multi-field composite search endpoints. S02 depends on S01 and extends the search endpoint with sort param. Integration is clean:
|
||||
- S02's sort param (`backend/routers/search.py`) builds on S01's SearchService changes (`backend/search_service.py`) — `_apply_sort` operates on the enriched result dicts that S01's multi-token logic produces.
|
||||
- S02's frontend SortDropdown integrates into `SearchResults.tsx` which S01 modified for partial_matches — no conflicts reported.
|
||||
- No boundary mismatches detected. Both slices modify overlapping files (search_service.py, search router, SearchResults.tsx, public-client.ts, App.css) and both summaries report clean builds and tests.
|
||||
|
||||
## Requirement Coverage
|
||||
- **R005 (Search-First Web UI):** Advanced by S01 (multi-token AND search improves relevance for composite queries) and S02 (sort controls on all list views improve findability).
|
||||
- **R009 (Qdrant Vector Search Integration):** Advanced by S01/T02 (enriched embeddings with creator_name and topic_tags for better semantic coverage).
|
||||
- **R015 (30-Second Retrieval Target):** Advanced by S01 (multi-token AND reduces result noise, helping users find specific techniques faster).
|
||||
|
||||
All three requirements listed in the unit header are covered by slice deliverables.
|
||||
|
||||
## Verification Class Compliance
|
||||
### Contract Verification
|
||||
**Status: ✅ Addressed.** S01: 19 backend tests pass (13 updated + 6 new) covering multi-token AND, cross-field matching, partial_matches, topic_tags, and creator genres. S02: curl verification of sort params on search, subtopic, and techniques endpoints. Frontend TypeScript compilation and Vite build clean for both slices.
|
||||
|
||||
### Integration Verification
|
||||
**Status: ✅ Addressed.** S01: End-to-end flow verified — frontend search box → API → keyword/semantic → enriched results with partial_matches. S02: Sort dropdown → public-client sort param → API → sorted results, with sessionStorage persistence verified via browser on ub01:8096.
|
||||
|
||||
### Operational Verification
|
||||
**Status: ⚠️ Partially addressed.** All containers healthy on ub01 after deployment (API, worker, web, watcher, qdrant, db, redis, ollama). However, no explicit latency measurement was captured to prove "search latency stays under 500ms". No evidence of regression testing on existing search/browse pages beyond the fact that existing tests pass and builds succeed. The operational verification class is technically unproven for the latency claim, though the deployment is confirmed healthy.
|
||||
|
||||
### UAT Verification
|
||||
**Status: ⚠️ Written but not executed.** Both S01 and S02 have detailed UAT test case documents (10 and 12 test cases respectively). S02 summary reports browser verification on ub01:8096 confirming sort functionality. S01 notes that running deployment needs container rebuild + reindex to pick up new code. UAT documents are comprehensive but formal manual UAT execution against production deployment is deferred to post-merge deploy.
|
||||
|
||||
|
||||
## Verdict Rationale
|
||||
Both slices delivered their claimed outputs with strong evidence: backend tests, TypeScript compilation, Vite builds, and browser verification on ub01. Cross-slice integration is clean. All three requirements (R005, R009, R015) are advanced. Two minor gaps prevent a clean pass: (1) No explicit latency measurement for the "search latency under 500ms" operational criterion — the system is deployed and healthy but the specific metric wasn't captured. (2) UAT test cases are written but formal execution is deferred to post-deploy (S01 notes containers need rebuild + reindex). Neither gap is material enough to block completion — they represent post-deploy verification items, not missing functionality.
|
||||
95
.gsd/milestones/M012/slices/S02/S02-SUMMARY.md
Normal file
95
.gsd/milestones/M012/slices/S02/S02-SUMMARY.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
id: S02
|
||||
parent: M012
|
||||
milestone: M012
|
||||
provides:
|
||||
- Sort query param on search, subtopic, topic, and techniques endpoints
|
||||
- SortDropdown component and useSortPreference hook for reuse
|
||||
requires:
|
||||
- slice: S01
|
||||
provides: Multi-field composite search endpoints
|
||||
affects:
|
||||
[]
|
||||
key_files:
|
||||
- backend/routers/search.py
|
||||
- backend/routers/topics.py
|
||||
- backend/routers/techniques.py
|
||||
- backend/search_service.py
|
||||
- frontend/src/components/SortDropdown.tsx
|
||||
- frontend/src/hooks/useSortPreference.ts
|
||||
- frontend/src/pages/SearchResults.tsx
|
||||
- frontend/src/pages/SubTopicPage.tsx
|
||||
- frontend/src/pages/CreatorDetail.tsx
|
||||
- frontend/src/api/public-client.ts
|
||||
- frontend/src/App.css
|
||||
key_decisions:
|
||||
- Sort applied in Python for search results (mixed Qdrant + keyword sources), SQL ORDER BY for single-source endpoints
|
||||
- Shared sessionStorage key across all pages for unified sort preference
|
||||
- Page-specific option lists with context-appropriate defaults (relevance for search, alpha for subtopic, newest for creator)
|
||||
patterns_established:
|
||||
- Reusable SortDropdown + useSortPreference hook pattern for adding sort controls to any list page
|
||||
- sessionStorage for session-scoped UI preferences that don't need server persistence
|
||||
observability_surfaces:
|
||||
- none
|
||||
drill_down_paths:
|
||||
- .gsd/milestones/M012/slices/S02/tasks/T01-SUMMARY.md
|
||||
- .gsd/milestones/M012/slices/S02/tasks/T02-SUMMARY.md
|
||||
duration: ""
|
||||
verification_result: passed
|
||||
completed_at: 2026-04-01T06:35:19.120Z
|
||||
blocker_discovered: false
|
||||
---
|
||||
|
||||
# S02: Sort Controls on All List Views
|
||||
|
||||
**Added sort dropdown to SearchResults, SubTopicPage, and CreatorDetail with backend sort params and session-persistent preference via sessionStorage.**
|
||||
|
||||
## What Happened
|
||||
|
||||
Two tasks delivered the full sort stack. T01 added a `sort` query parameter to four backend endpoints — search, subtopic, category topics, and techniques — supporting relevance/newest/oldest/alpha/creator options. Search results use Python-level sorting (mixed Qdrant + keyword sources), while single-source endpoints use SQL ORDER BY. Creator sort joins the Creator table. T02 built a reusable SortDropdown component and useSortPreference hook backed by sessionStorage. Integrated into three pages with context-appropriate option lists and defaults (relevance for search, alpha for subtopic, newest for creator). The sort param flows through public-client.ts to the API. Changing sort resets pagination. Deployed to ub01 and verified end-to-end: alphabetical sort on search returns A-Z titles, oldest sort on subtopic returns ascending dates, preference persists across navigation.
|
||||
|
||||
## Verification
|
||||
|
||||
Backend: curl verified search?sort=alpha returns alphabetically ordered titles, topics/sound-design/bass?sort=oldest returns ascending created_at dates, techniques?sort=creator returns creator-grouped results. Frontend: TypeScript compilation clean (npx tsc --noEmit), Vite build successful. Browser verification on ub01:8096 confirmed all three pages show sort dropdown, sort changes update results, sessionStorage persists preference across navigation.
|
||||
|
||||
## Requirements Advanced
|
||||
|
||||
None.
|
||||
|
||||
## Requirements Validated
|
||||
|
||||
None.
|
||||
|
||||
## New Requirements Surfaced
|
||||
|
||||
None.
|
||||
|
||||
## Requirements Invalidated or Re-scoped
|
||||
|
||||
None.
|
||||
|
||||
## Deviations
|
||||
|
||||
T01 added sort param to the category-level topic endpoint (get_topic_techniques) beyond the original plan, for frontend consistency.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
None.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
None.
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `backend/routers/search.py` — Added sort query param, passed to SearchService
|
||||
- `backend/routers/topics.py` — Added sort param to subtopic and category topic endpoints with SQL ORDER BY
|
||||
- `backend/routers/techniques.py` — Extended sort options with oldest/alpha/creator
|
||||
- `backend/search_service.py` — Added _apply_sort for Python-level sorting of enriched results, added created_at to result dicts
|
||||
- `frontend/src/components/SortDropdown.tsx` — New reusable sort dropdown component
|
||||
- `frontend/src/hooks/useSortPreference.ts` — New hook for sessionStorage-backed sort preference
|
||||
- `frontend/src/pages/SearchResults.tsx` — Integrated SortDropdown with search-specific options
|
||||
- `frontend/src/pages/SubTopicPage.tsx` — Integrated SortDropdown with subtopic-specific options
|
||||
- `frontend/src/pages/CreatorDetail.tsx` — Integrated SortDropdown with creator-specific options
|
||||
- `frontend/src/api/public-client.ts` — Added sort param to searchApi and fetchSubTopicTechniques
|
||||
- `frontend/src/App.css` — Dark-theme styles for sort dropdown with custom chevron and focus ring
|
||||
80
.gsd/milestones/M012/slices/S02/S02-UAT.md
Normal file
80
.gsd/milestones/M012/slices/S02/S02-UAT.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# S02: Sort Controls on All List Views — UAT
|
||||
|
||||
**Milestone:** M012
|
||||
**Written:** 2026-04-01T06:35:19.121Z
|
||||
|
||||
# S02 UAT: Sort Controls on All List Views
|
||||
|
||||
## Preconditions
|
||||
- Chrysopedia running at ub01:8096
|
||||
- At least 5 technique pages in the database with different creators and created_at dates
|
||||
- Browser with sessionStorage available (not incognito with storage blocked)
|
||||
|
||||
## Test Cases
|
||||
|
||||
### TC1: Search Results Sort Dropdown Visible
|
||||
1. Navigate to ub01:8096
|
||||
2. Type "bass" in the search bar and submit
|
||||
3. **Expected:** Search results page shows a sort dropdown in the results header area
|
||||
4. **Expected:** Default selection is "Relevance" when arriving from a search query
|
||||
|
||||
### TC2: Search Results Sort by Alphabetical
|
||||
1. From TC1, change sort dropdown to "A → Z"
|
||||
2. **Expected:** Results reorder so titles are in ascending alphabetical order
|
||||
3. Note the first 3 titles — they should be alphabetically sequential
|
||||
|
||||
### TC3: Search Results Sort by Newest
|
||||
1. Change sort dropdown to "Newest"
|
||||
2. **Expected:** Results reorder with most recently created techniques first
|
||||
|
||||
### TC4: Search Results Sort by Creator
|
||||
1. Change sort dropdown to "Creator"
|
||||
2. **Expected:** Results group by creator name in alphabetical order
|
||||
|
||||
### TC5: SubTopic Page Sort Dropdown
|
||||
1. Navigate to Topics → Sound Design → Bass (or any subtopic with multiple techniques)
|
||||
2. **Expected:** Sort dropdown visible, defaulting to "A → Z"
|
||||
3. Change to "Oldest"
|
||||
4. **Expected:** Techniques reorder by ascending created_at date
|
||||
|
||||
### TC6: Creator Detail Page Sort Dropdown
|
||||
1. Navigate to Creators → click any creator with multiple techniques
|
||||
2. **Expected:** Sort dropdown visible, defaulting to "Newest"
|
||||
3. Change to "A → Z"
|
||||
4. **Expected:** Techniques reorder alphabetically by title
|
||||
|
||||
### TC7: Session Persistence Across Navigation
|
||||
1. On search results page, set sort to "A → Z"
|
||||
2. Navigate to Topics page, then to a subtopic
|
||||
3. **Expected:** Subtopic page sort dropdown shows "A → Z" (persisted from search)
|
||||
4. Navigate back to search, search for "snare"
|
||||
5. **Expected:** Sort dropdown still shows "A → Z", not reset to default
|
||||
|
||||
### TC8: Sort Resets Pagination
|
||||
1. On search results with enough results for pagination, navigate to page 2
|
||||
2. Change the sort dropdown value
|
||||
3. **Expected:** Results refresh and pagination resets to page 1/first offset
|
||||
|
||||
### TC9: Sort Options Are Context-Appropriate
|
||||
1. On Search Results page, open sort dropdown
|
||||
2. **Expected:** Options include Relevance, Newest, Oldest, A → Z, Creator
|
||||
3. On SubTopic page, open sort dropdown
|
||||
4. **Expected:** Options include A → Z, Newest, Oldest, Creator (no Relevance)
|
||||
5. On Creator Detail page, open sort dropdown
|
||||
6. **Expected:** Options include Newest, Oldest, A → Z (no Relevance, no Creator)
|
||||
|
||||
### TC10: Backend API Sort Param
|
||||
1. `curl 'http://ub01:8096/api/v1/search?q=bass&sort=alpha'` — verify titles in alphabetical order
|
||||
2. `curl 'http://ub01:8096/api/v1/topics/sound-design/bass?sort=oldest'` — verify ascending dates
|
||||
3. `curl 'http://ub01:8096/api/v1/techniques?sort=creator'` — verify grouped by creator name
|
||||
|
||||
### Edge Cases
|
||||
|
||||
### TC11: Sort with No Results
|
||||
1. Search for a nonsense query like "xyzzy12345"
|
||||
2. **Expected:** Sort dropdown either hidden or present but non-functional (no crash)
|
||||
|
||||
### TC12: Sort on Fresh Session
|
||||
1. Open a new browser tab (or clear sessionStorage)
|
||||
2. Navigate directly to a subtopic page
|
||||
3. **Expected:** Sort defaults to page-specific default (A → Z for subtopic), not undefined
|
||||
9
.gsd/milestones/M012/slices/S02/tasks/T02-VERIFY.json
Normal file
9
.gsd/milestones/M012/slices/S02/tasks/T02-VERIFY.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"taskId": "T02",
|
||||
"unitId": "M012/S02/T02",
|
||||
"timestamp": 1775025229552,
|
||||
"passed": true,
|
||||
"discoverySource": "none",
|
||||
"checks": []
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue