--- phase: 10 slug: ux-interaction status: draft nyquist_compliant: false wave_0_complete: false created: 2026-06-14 --- # Phase 10 — Validation Strategy > Per-phase validation contract for feedback sampling during execution. --- ## Test Infrastructure | Property | Value | |----------|-------| | **Framework** | Vitest ^4.1.7 | | **Config file** | `frontend/vite.config.js` | | **Quick run command** | `cd frontend && npm run test -- --run` | | **Full suite command** | `cd frontend && npm run test` | | **Estimated runtime** | ~30 seconds | --- ## Sampling Rate - **After every task commit:** Run `cd frontend && npm run test -- --run [component-name]` - **After every plan wave:** Run `cd frontend && npm run test -- --run` - **Before `/gsd:verify-work`:** Full suite must be green - **Max feedback latency:** 30 seconds --- ## Per-Task Verification Map | Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status | |---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------| | AppIcon foundation | W0 | 0 | CODE-05 | — | Unknown names warn; render nothing | unit | `npm run test -- --run AppIcon` | ❌ | pending | | EmptyState foundation | W0 | 0 | UX-01 | — | Props render; CTA slot optional | unit | `npm run test -- --run EmptyState` | ❌ | pending | | BreadcrumbBar foundation | W0 | 0 | UX-12 | — | Last segment non-clickable; navigate emitted | unit | `npm run test -- --run BreadcrumbBar` | ❌ | pending | | Toast store + container | W0 | 0 | UX-10 | — | auto-dismiss 4s; dismiss on click | unit | `npm run test -- --run toast` | ❌ | pending | | StorageBrowser skeleton | W1 | 1 | UX-02 | — | skeleton renders when loading=true | unit | `npm run test -- --run StorageBrowser` | ❌ | pending | | AppSidebar skeleton + empty | W1 | 1 | UX-03 | — | skeleton rows replace Loading text | unit | `npm run test -- --run AppSidebar` | ❌ | pending | | Admin table skeletons | W1 | 1 | UX-04 | — | skeleton rows in users + audit | unit | `npm run test -- --run Admin` | ❌ | pending | | EmptyState wiring | W1 | 1 | UX-01 | — | EmptyState shown in all 7+ contexts | unit | `npm run test -- --run EmptyState` | ❌ | pending | | Toast call sites | W1 | 1 | UX-10 | — | show() called on upload/delete/move | unit | `npm run test -- --run toast` | ❌ | pending | | BreadcrumbBar wiring | W1 | 1 | UX-12 | — | admin/settings views pass static segments | unit | `npm run test -- --run BreadcrumbBar` | ❌ | pending | | UX-14 sidebar removal | W1 | 1 | UX-14 | — | "New" button absent from AppSidebar | unit | `npm run test -- --run AppSidebar` | ❌ | pending | | Keyboard shortcuts | W2 | 2 | UX-05..08 | — | guard fires; no input bleed | unit | `npm run test -- --run keyboard` | ❌ | pending | | OS drag overlay | W2 | 2 | UX-09 | — | overlay on Files dragenter; hide on leave | unit | `npm run test -- --run OsDragOverlay` | ❌ | pending | | Drag-to-move toast | W3 | 3 | UX-11 | — | ring-2 ring-inset ring-amber-300 on hover | unit | `npm run test -- --run StorageBrowser` | ❌ | pending | | Dropdown clipping fixes | W3 | 3 | UX-13 | — | picker renders via Teleport at correct pos | unit | `npm run test -- --run dropdown` | ❌ | pending | | SVG migration | W3 | 3 | CODE-05 | — | all 29 files use AppIcon; no inline svg | unit | `npm run test -- --run AppIcon` | ❌ | pending | --- ## Key Behavioral Contracts | Contract | Value | Test Type | |---|---|---| | Toast auto-dismiss timing | 4000ms (locked by Phase 8 stub) | unit (mock timers) | | Toast manual dismiss | click anywhere on toast | unit | | Keyboard guard: `/` inside focused input | does NOT redirect to search | unit | | Keyboard guard: `N` inside focused input | does NOT trigger folder creation | unit | | Breadcrumb last segment | non-clickable (no @click/@navigate on last) | unit | | OS drag detection | `dataTransfer.types.includes('Files')` required | unit | | Drag-to-move ring highlight | `ring-2 ring-inset ring-amber-300` class on hover | unit | | AppIcon unknown name | `console.warn` in dev; renders nothing | unit | --- ## Wave 0 Test Stubs (REQUIRED — create before implementation) - [ ] `frontend/src/components/ui/AppIcon.test.js` — covers CODE-05 (name→path, unknown name warn) - [ ] `frontend/src/components/ui/EmptyState.test.js` — covers UX-01 (props, CTA slot) - [ ] `frontend/src/components/ui/BreadcrumbBar.test.js` — covers UX-12 (last segment, navigate emit) - [ ] `frontend/src/stores/toast.test.js` — covers UX-10 (show, auto-dismiss, dismiss on click) - [ ] `frontend/src/components/ui/ToastContainer.test.js` — covers UX-10 visual rendering --- ## Manual Validation Checkpoints These require human observation: - UX-03: Sidebar skeleton visual appearance (match TreeItem indent level) - UX-04: Admin table skeleton row column alignment - Toast stacking with multiple simultaneous toasts - OS drag-and-drop actual file upload end-to-end - Keyboard `N` in cloud folder view (must no-op silently) - Human checkpoint UAT: all 15 requirements exercised by a real user