# Closer — Private MVP QA Checklist

> Manual testing checklist for the internal MVP build. Covers every top-level flow in the app and notes known gaps discovered during the 2025-06 QA pass.

---

## Environment & Setup

- [ ] Clean install on test device (API 26+).
- [ ] Test device/emulator has network connectivity.
- [ ] Check non-network build: `./gradlew :app:compileDebugKotlin` passes.
- [ ] Verify `RC_API_KEY` in `local.properties` (or a placeholder) so billing build does not fail.
- [ ] Google-services JSON is present for the selected build variant.

---

## 1. Onboarding & First Launch

### 1.1 Splash / App launch
- [ ] App launches to `MainActivity` without crash.
- [ ] `AppNavigation` starts at `AppRoute.ONBOARDING` on fresh install.
- [ ] Theme applies (`CloserTheme`) and status bar / navigation bar insets handled correctly.
- [ ] App name in launcher is "Closer".

### 1.2 Onboarding screen (`OnboardingScreen`)
- [ ] Value proposition visible and not placeholder text.
- [ ] CTA navigates to `CREATE_PROFILE` or `LOGIN` as expected.
- [ ] Secondary sign-in link works.
- [ ] No dead-end: user can always reach either create profile or login.

### 1.3 Create profile (`CreateProfileScreen`)
- [ ] Name input accepts text and reflects in UI.
- [ ] Validation prevents empty submission.
- [ ] Profile creation succeeds and navigates forward (home or pairing flow).
- [ ] Loading / error states handled.

### 1.4 Login / Sign up / Forgot password
- [ ] `LoginScreen`: email/password fields, sign-in call, error shown on failure, success navigates to `HOME`.
- [ ] `SignUpScreen`: account creation, weak-password validation, navigates to profile creation.
- [ ] `ForgotPasswordScreen`: email reset flow, success/error messaging.
- [ ] Back navigation from auth screens returns to onboarding.

### 1.5 Known onboarding gaps (from code scan)
- `AccountScreen` shows "Local profile" and disables "Sign in or create account" and "Export your data" rows. These need real wiring before public release.
- Home header text changes based on `partnerName` presence; confirm both states render.

---

## 2. Pairing

### 2.1 Create invite (`CreateInviteScreen`)
- [ ] Generates 6-character code.
- [ ] Code displays with chunked formatting (e.g., "ABC – 123").
- [ ] Copy button copies raw code to clipboard and shows snackbar.
- [ ] Share button opens system share sheet with correct message.
- [ ] "Partner already has a code? Accept instead" navigates to `ACCEPT_INVITE`.
- [ ] Code expiry note shown ("expires in 24 hours").

### 2.2 Accept invite (`AcceptInviteScreen`)
- [ ] 6-character code entry field with visual chunking and uppercase auto-capitalization.
- [ ] Continue enabled only when code length == 6.
- [ ] Invalid/expired code shows error.
- [ ] Valid code navigates to `INVITE_CONFIRM/{inviteCode}`.
- [ ] "Need to create an invite instead?" link works.
- [ ] Keyboard Done triggers lookup.

### 2.3 Invite confirm (`InviteConfirmScreen`)
- [ ] Inviter name loaded and displayed.
- [ ] Pairing confirmation button shows loading spinner.
- [ ] Success navigates to home.
- [ ] "Not right — enter a different code" returns to accept screen.
- [ ] Error surfaced via snackbar.

### 2.4 Email invite (`EmailInviteScreen`)
- [ ] This is currently a `PlaceholderScreen`. Verify it renders and that primary/secondary actions navigate correctly.
- [ ] **Risk**: placeholder actions reference a hardcoded invite code `ABC123`; replace before public release.

### 2.5 Relationship settings
- [ ] `SettingsScreen` partner card opens `RELATIONSHIP_SETTINGS` when paired.
- [ ] Leave couple confirmation dialog shown.
- [ ] Leave action calls repository and navigates to `CREATE_INVITE` on success.
- [ ] Error shown on failure.

---

## 3. Home

### 3.1 Home screen (`HomeScreen`)
- [ ] Loads without crash; loading, error, and success states all tested.
- [ ] Header shows correct subtitle for paired vs. unpaired user.
- [ ] Streak pill appears when `streakCount > 0`.
- [ ] Primary action card responds to tap.
- [ ] Secondary action feed renders and navigates.
- [ ] "More doorways" grid shows up to 2 categories; tap navigates to category.
- [ ] "All packs" button navigates to `QUESTION_PACKS`.
- [ ] Pull/refresh or retry on error works.

### 3.2 Partner home (`PartnerHomeScreen`)
- [ ] Renders `PlaceholderScreen` with correct copy.
- [ ] Actions navigate to invite flow or home.
- [ ] **Gap**: screen is a placeholder; not a functional partner dashboard yet.

### 3.3 Moment cue / special dates section
- [ ] `SpecialDatesSection` previews render.
- [ ] Home moment cue card text not placeholder.
- [ ] Hardcoded names ("Jessica", "Mark") and dates in `SpecialDatesSection` must be replaced with real data before public release.

---

## 4. Daily Question

### 4.1 Daily question screen (`DailyQuestionScreen`)
- [ ] Question text loads.
- [ ] Answer input accepts text and respects private/public toggle.
- [ ] Save/submit works, shows feedback.
- [ ] Navigates to answer reveal or answer history appropriately.
- [ ] Discussion section handles un-revealed state gracefully.

### 4.2 Answer input components
- [ ] `QuestionAnswerInput`: empty-state handling, formatting, IME actions.
- [ ] `QuestionHelpExpandable`: expand/collapse works.
- [ ] `QuestionDiscussionThread`: disabled state copy is clear.
- [ ] `QuestionNavigationBar`: previous/next navigation and disabled states.

### 4.3 Question thread (`QuestionThreadScreen`)
- [ ] Loads question and optional `prevId`/`nextId` args.
- [ ] Previous / next navigation works when ids provided.
- [ ] Both partner answers visible after reveal.
- [ ] Comments can be added (if unlocked).
- [ ] Back button returns to prior screen.

---

## 5. Question Packs & Categories

### 5.1 Question pack library (`QuestionPackLibraryScreen`)
- [ ] Loading, error, empty states tested.
- [ ] Categories/packs list scrolls.
- [ ] Free and premium locks indicated.
- [ ] Tap on premium pack navigates to `PAYWALL`.
- [ ] Tap on free/mixed pack navigates to `QUESTION_CATEGORY/{categoryId}`.

### 5.2 Question category (`QuestionCategoryScreen`)
- [ ] Loads questions for `categoryId`.
- [ ] Format and depth filters apply.
- [ ] Question cards navigate to `QUESTION_THREAD`.
- [ ] Locked premium packs route to paywall.
- [ ] Loading/error handled.

### 5.3 Question composer (`QuestionComposerScreen`)
- [ ] User can create a custom question.
- [ ] Category/depth/format options available.
- [ ] Save creates question and returns.
- [ ] Validation prevents empty submission.

---

## 6. Answers & Reveal

### 6.1 Answer reveal (`AnswerRevealScreen`)
- [ ] Loads answer for `questionId`.
- [ ] Private answer shown only to author until reveal.
- [ ] Reveal action updates state and reveals both answers.
- [ ] Loading, error, empty states tested.
- [ ] Navigation to discussion or history works.

### 6.2 Answer history (`AnswerHistoryScreen`)
- [ ] List of answered/revealed questions loads.
- [ ] Empty state shown when no answers.
- [ ] Remove action (if available) works and updates list.
- [ ] Tap navigates to thread/reveal.

---

## 7. Spin Wheel

### 7.1 Category picker (`CategoryPickerScreen`)
- [ ] Categories load; loading, error, empty states tested.
- [ ] Locked categories show lock icon and "Premium" pill.
- [ ] Locked tap routes to `PAYWALL`.
- [ ] Free tap routes to `SPIN_WHEEL/{categoryId}`.

### 7.2 Spin wheel (`SpinWheelScreen`)
- [ ] Category name displayed.
- [ ] Spin action triggers selection of `SpinWheelViewModel.SESSION_SIZE` questions.
- [ ] Visual spinning animation runs.
- [ ] Error surfaced.
- [ ] Ready state shows count and enables "Start session".
- [ ] "Spin again" re-rolls selection.

### 7.3 Wheel session (`WheelSessionScreen`)
- [ ] Loads session via `sessionId`.
- [ ] Progress indicator updates.
- [ ] Current question displays centered.
- [ ] Next / skip / end session buttons work.
- [ ] Empty session state shown when no active session.
- [ ] Last question button label reads "Finish".
- [ ] Navigates to `WHEEL_COMPLETE/{sessionId}` on finish.

### 7.4 Wheel complete (`WheelCompleteScreen`)
- [ ] Shows category name and answered/total count.
- [ ] Saves session to repository on init.
- [ ] "Back home" navigates to `HOME`.
- [ ] "Spin again" navigates to `CATEGORY_PICKER`.
- [ ] Handles 0-question edge case gracefully.

### 7.5 Wheel history (`WheelHistoryScreen`)
- [ ] Premium lock card shown for non-premium users.
- [ ] Premium users see list of completed sessions.
- [ ] Empty state with "Spin now" action.
- [ ] Error/retry works.
- [ ] Date formatting uses default locale.

---

## 8. Dates

### 8.1 Date match (`DateMatchScreen`)
- [ ] Swipe cards render.
- [ ] Match state shows correctly.
- [ ] Premium gating tested.
- [ ] Error/loading handled.

### 8.2 Date matches (`DateMatchesScreen`)
- [ ] List of matched date ideas loads.
- [ ] Empty state shown.
- [ ] Tap navigates to detail/builder.

### 8.3 Date builder (`DateBuilderScreen`)
- [ ] Fields render: date, time, budget, duration.
- [ ] **Gap**: date and time fields show "TODO: Date picker dialog" / "TODO: Time picker dialog"; they are not interactive yet.
- [ ] Budget input accepts digits only.
- [ ] Duration chips selectable.
- [ ] Save button calls view model.
- [ ] Back navigation works.

### 8.4 Bucket list (`BucketListScreen`)
- [ ] Items load; empty state shown.
- [ ] Category filter chips scroll and filter list.
- [ ] Add item FAB opens dialog.
- [ ] Add dialog: title required, description optional, category selectable.
- [ ] Toggle complete updates card style.
- [ ] Delete removes item.
- [ ] Back navigation works.

---

## 9. Settings

### 9.1 Settings home (`SettingsScreen`)
- [ ] Profile card shows display name / email or local profile note.
- [ ] Partner card shows paired state and partner name, or invite prompt.
- [ ] Tapping profile card opens `ACCOUNT`.
- [ ] Tapping partner card opens `RELATIONSHIP_SETTINGS` (paired) or `CREATE_INVITE` (unpaired).
- [ ] Notifications, Subscription, Privacy & Terms rows open correct screens.
- [ ] Legal links open external URLs.
- [ ] Delete account row opens `DELETE_ACCOUNT`.
- [ ] Sign out button works and shows loading state.

### 9.2 Account (`AccountScreen`)
- [ ] "Local profile" card shown for signed-out state.
- [ ] Disabled rows visually greyed out.
- [ ] Delete account row navigates to `DELETE_ACCOUNT`.
- [ ] Back navigation works.

### 9.3 Notifications (`NotificationSettingsScreen`)
- [ ] All four toggles reflect persisted state.
- [ ] Toggling each calls repository and updates UI.
- [ ] Quiet hours description accurate (10 PM – 8 AM).

### 9.4 Privacy (`PrivacyScreen`)
- [ ] External links open in browser.
- [ ] No browser available case handled via `ExternalLinks.openUrl` Toast fallback.
- [ ] Back navigation works.
- [ ] **Note**: Support URL is `https://couplesconnect.app/support` (legacy domain); should be migrated to `closer.app` before release.

### 9.5 Subscription (`SubscriptionScreen`)
- [ ] Renders placeholder with paywall and settings actions.
- [ ] **Gap**: subscription management is placeholder; needs real UI before release.

### 9.6 Relationship settings / Delete account
- [ ] See pairing section for leave-couple flow.
- [ ] Delete account confirmation dialog requires acknowledgment checkbox.
- [ ] Delete action calls `AuthRepository.deleteAccount()` and navigates to onboarding.
- [ ] Loading and error states shown.

---

## 10. Paywall

### 10.1 Paywall screen (`PaywallScreen`)
- [ ] Loads RevenueCat packages; loading/error handled.
- [ ] Benefits list accurate.
- [ ] Selecting plan updates selection state.
- [ ] Purchase button enabled only when plan selected.
- [ ] Purchase call uses current activity context.
- [ ] Restore purchases button works.
- [ ] Legal links open externally.
- [ ] Thank-you overlay shown on success; dismiss returns to previous screen.
- [ ] **Note**: Requires real RevenueCat API key and product configuration to fully test.

---

## 11. Notifications

### 11.1 FCM service (`AppMessagingService`)
- [ ] App receives push when in foreground and background.
- [ ] Quiet hours suppression works (10 PM – 8 AM).
- [ ] Notification channel created on Android O+.
- [ ] Tap action navigates to relevant screen.

### 11.2 Token registrar
- [ ] Token updates sent to backend/user document.
- [ ] Handles sign-out / re-sign-in correctly.

---

## 12. General UX / Edge Cases

### 12.1 Navigation
- [ ] Bottom nav shows on top-level routes only.
- [ ] System back from top-level routes does not exit unexpectedly (navigate back within app).
- [ ] Shell top bar appears on `shellBackRoutes` and uses route title.
- [ ] Deep links / invite-confirm route handled: `invite_confirm/{inviteCode}`.

### 12.2 Input / Accessibility
- [ ] Text fields have proper keyboard options (email, ASCII, capitalization).
- [ ] Labels / placeholders readable.
- [ ] Touch targets >= 48 dp for all clickable surfaces.
- [ ] Max lines and ellipses used to prevent overflow clipping.

### 12.3 Theming
- [ ] Light theme renders consistently (current primary theme).
- [ ] Dark theme colors defined but not wired to system dark mode (`isSystemInDarkTheme()` not used). Verify this is intentional for MVP.
- [ ] No stale Next.js / React Native references in resources or manifests.

### 12.4 Data / Offline
- [ ] App does not crash when offline (graceful error cards).
- [ ] Local answer repository persists data.
- [ ] Firebase calls fail cleanly and retry available where exposed.

---

## 13. Release Blockers Logged from This QA Pass

These findings came from the static review and should be fixed before public or store release. Do **not** block internal MVP on these unless explicitly required.

| # | Area | Issue | Severity |
|---|------|-------|----------|
| 1 | Date builder | Date/time picker TODOs — fields are not interactive | High |
| 2 | Special dates | Hardcoded names/dates in `SpecialDatesSection` | High |
| 3 | Email invite | Placeholder screen with hardcoded `ABC123` code | Medium |
| 4 | Subscription | Placeholder screen, not real management | Medium |
| 5 | Partner home | Placeholder screen only | Medium |
| 6 | Settings | Account rows disabled ("Auth coming soon", "Export coming soon") | Medium |
| 7 | External links | Support URL points to `couplesconnect.app/support` | Low |
| 8 | Strings | 100+ hardcoded display strings; should move to `strings.xml` for localization | Low |
| 9 | Logging | `android.util.Log.e` used in `QuestionJsonParser` — acceptable for errors, but confirm no verbose/debug logs remain in release builds | Low |

---

## Sign-off

| Tester | Date | Build | Result |
|--------|------|-------|--------|
|        |      |       |        |
