# Test Plan: Account Pages (Workstream I) ## Overview Manual test plan for the account management pages: Profile, Authentication, Devices, and Sessions. ## Prerequisites - Dev server running: `bun run --cwd apps/publisher-dashboard dev` - Logged-in user account - Access to multiple devices/browsers for session testing --- ## 1. Account Navigation ### 1.1 Navigation Tabs | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Navigate to `/account` | Profile tab is highlighted | | 2 | Click "Authentication" tab | Navigate to `/account/auth`, tab highlighted | | 3 | Click "Devices" tab | Navigate to `/account/devices`, tab highlighted | | 4 | Click "Sessions" tab | Navigate to `/account/sessions`, tab highlighted | | 5 | Resize to mobile width | Tab labels hidden, only icons visible | --- ## 2. Profile Page (`/account`) ### 2.1 Profile Loading | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Navigate to `/account` | Loading spinner shown briefly | | 2 | Wait for data | Form populated with current user data | | 3 | Refresh page | Data persists correctly | ### 2.2 Avatar URL | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Enter valid image URL | Avatar preview updates | | 2 | Enter invalid URL (e.g., "not-a-url") | Error: "Please enter a valid URL" on blur | | 3 | Enter URL without http/https | Error shown | | 4 | Clear URL | Avatar shows initials fallback | | 5 | Enter URL to non-image | Preview attempts to load, falls back gracefully | ### 2.3 Display Name (Required) | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Clear display name | Save button disabled | | 2 | Enter valid name (1-100 chars) | Save button enabled | | 3 | Enter name > 100 chars | Input enforces maxlength | ### 2.4 Full Name (Optional) | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Leave empty | Form valid | | 2 | Enter value | Form valid | | 3 | Save with value | Value persists after refresh | ### 2.5 Phone Number | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Enter valid phone: "+1 555 123 4567" | Auto-formats to E.164 on blur | | 2 | Enter invalid phone: "abc123" | Error: "Please enter a valid phone number" | | 3 | Leave empty | Form valid (optional field) | | 4 | Enter international number | Formats correctly | ### 2.6 Save Profile | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Make no changes | Save button disabled | | 2 | Change any field | Save button enabled | | 3 | Click Save | Loading state, success toast | | 4 | Refresh page | Changes persisted | | 5 | Save with validation error | Button disabled, cannot submit | ### 2.7 Delete Account | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Click "Delete account" button | Confirmation dialog opens | | 2 | Dialog shows warning icon | Red/destructive styling | | 3 | Enter wrong password | Error message shown | | 4 | Enter correct password | Account deleted, redirected to login | | 5 | Click Cancel | Dialog closes, no action | --- ## 3. Authentication Page (`/account/auth`) ### 3.1 Email Display | Step | Action | Expected Result | |------|--------|-----------------| | 1 | View email section | Email displayed (read-only) | | 2 | Verified user | "Verified" badge shown | | 3 | Unverified user | No badge (or "Unverified" indicator) | ### 3.2 Password - No Existing Password | Step | Action | Expected Result | |------|--------|-----------------| | 1 | User without password | Shows "No password set" | | 2 | Click "Set password" | Dialog opens | | 3 | No "Current password" field | Only new password fields shown | | 4 | Enter weak password (<8 chars) | Submit disabled | | 5 | Enter mismatched passwords | Submit disabled | | 6 | Enter valid matching passwords | Submit enabled | | 7 | Submit | Success toast, status updates to "Password is set" | ### 3.3 Password - Existing Password | Step | Action | Expected Result | |------|--------|-----------------| | 1 | User with password | Shows "Password is set" | | 2 | Click "Change password" | Dialog opens with current password field | | 3 | Leave current password empty | Submit disabled | | 4 | Enter wrong current password | Error message on submit | | 5 | Enter correct current + valid new | Success toast | ### 3.4 Passkeys List | Step | Action | Expected Result | |------|--------|-----------------| | 1 | No passkeys | Empty state message | | 2 | Has passkeys | List with name, created date, last used | | 3 | Each passkey | Rename and Delete buttons visible | ### 3.5 Add Passkey | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Click "+ Add passkey" | Dialog opens | | 2 | Browser doesn't support WebAuthn | Message shown, form disabled | | 3 | Enter passkey name | Create button enabled | | 4 | Click Create | Browser WebAuthn prompt appears | | 5 | Complete WebAuthn ceremony | Success toast, passkey appears in list | | 6 | Cancel WebAuthn prompt | Error: "Passkey creation was cancelled" | | 7 | Verify passkey name | Name matches what user entered | ### 3.6 Rename Passkey | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Click rename icon | Dialog opens with current name | | 2 | Enter same name | Save disabled | | 3 | Enter new name | Save enabled | | 4 | Save | Success toast, list updates | ### 3.7 Delete Passkey | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Click delete icon | Confirmation dialog | | 2 | Confirm deletion | Success toast, passkey removed | | 3 | Only 1 passkey, no password | Delete button disabled with tooltip | | 4 | Has password or 2+ passkeys | Delete enabled | --- ## 4. Devices Page (`/account/devices`) ### 4.1 Trusted Devices List | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Navigate to page | List of trusted devices shown | | 2 | Current device | Marked with "Current" badge | | 3 | Each device shows | Name, location, last used date | | 4 | No trusted devices | Empty state message | ### 4.2 Remove Trust | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Click "Remove trust" on any device | Confirmation dialog | | 2 | Confirm | Success toast, device removed from list | | 3 | Cancel | Dialog closes, no change | ### 4.3 Remove All Trusted Devices | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Only 1 device | "Remove all" button not shown | | 2 | 2+ devices | "Remove all trusted devices" button shown | | 3 | Click remove all | Confirmation dialog | | 4 | Confirm | All devices removed, empty state shown | --- ## 5. Sessions Page (`/account/sessions`) ### 5.1 Active Sessions | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Navigate to page | Active sessions listed | | 2 | Current session | Marked with "Current" badge | | 3 | Each session shows | Browser/OS, location, auth method, start date | | 4 | Passkey session | Shows "via passkey" with key icon | | 5 | Password session | Shows "via password" | ### 5.2 Revoke Session | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Current session | No revoke button | | 2 | Other session | Revoke button visible | | 3 | Click Revoke | Confirmation dialog | | 4 | Confirm | Session moved to past sessions | ### 5.3 Revoke All Sessions | Step | Action | Expected Result | |------|--------|-----------------| | 1 | Only current session | "Revoke all" button not shown | | 2 | Multiple sessions | "Revoke all other sessions" shown | | 3 | Confirm revoke all | All other sessions revoked | ### 5.4 Past Sessions | Step | Action | Expected Result | |------|--------|-----------------| | 1 | No past sessions | Section not shown | | 2 | Has past sessions | Section shows with grayed styling | | 3 | Past session shows | Browser/OS, location, date range, "Logged out" | | 4 | More than 10 | Shows "Showing 10 of X" message | --- ## 6. Cross-Cutting Concerns ### 6.1 Loading States | Page | Expected | |------|----------| | All pages | Spinner while loading data | | Form submissions | Button shows loading state | | Dialogs | Buttons disabled during submission | ### 6.2 Error Handling | Scenario | Expected | |----------|----------| | Network error | Error alert shown | | API error | Error message from server displayed | | Validation error | Inline error message | ### 6.3 Accessibility | Test | Expected | |------|----------| | Keyboard navigation | All interactive elements focusable | | Screen reader | ARIA labels present on icons/buttons | | Dialog close button | Has aria-label="Close dialog" | | Navigation tabs | Has aria-current="page" on active | ### 6.4 Mobile Responsiveness | Breakpoint | Expected | |------------|----------| | Desktop (>640px) | Full navigation labels | | Mobile (<640px) | Icon-only navigation | | All sizes | Forms remain usable | --- ## 7. Integration Tests ### 7.1 Full Passkey Flow 1. Navigate to `/account/auth` 2. Add new passkey with custom name 3. Verify passkey appears in list with correct name 4. Rename passkey 5. Delete passkey (if not last auth method) ### 7.2 Password Change Flow 1. Set initial password (if none) 2. Change password with correct current password 3. Verify can log in with new password ### 7.3 Multi-Device Session Test 1. Log in on Device A 2. Log in on Device B 3. On Device A, view sessions - see both 4. Revoke Device B session 5. Verify Device B is logged out --- ## 8. Edge Cases | Scenario | Expected Behavior | |----------|-------------------| | Last auth method | Cannot delete (button disabled) | | Very long passkey name | Truncated in UI, full in tooltip | | Many sessions (>10 past) | Pagination/truncation message | | Slow network | Loading states visible | | Session expired mid-action | Redirected to login | | Concurrent passkey creation | Correct passkey gets renamed (race condition fixed) | --- ## Sign-Off | Tester | Date | Status | |--------|------|--------| | | | |