An easy-to-host PDS on the ATProtocol, iPhone and MacOS. Maintain control of your keys and data, always.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: add test plan for MM-150 wallet home screen

authored by

Malpercio and committed by
Tangled
2461a175 84d0cfb3

+196
+196
docs/test-plans/2026-03-27-MM-150.md
··· 1 + # MM-150 Human Test Plan 2 + 3 + **Ticket:** MM-150 — Wallet Home Screen: Identity Overview + Session Status 4 + **Implementation plan:** `docs/implementation-plans/2026-03-27-MM-150/` 5 + **Generated:** 2026-03-27 6 + 7 + --- 8 + 9 + ## Prerequisites 10 + 11 + - macOS with Xcode installed 12 + - iOS Simulator platform installed (Xcode → Settings → Platforms → iOS) 13 + - Nix dev shell active from the workspace root: `nix develop --impure --accept-flake-config` 14 + - Frontend dependencies installed: `cd apps/identity-wallet && pnpm install` 15 + - Xcode project generated: `cargo tauri ios init` 16 + - A relay instance running and accessible from the simulator (local at `localhost:8080` for debug builds) 17 + - `cargo test -p identity-wallet` passing (all Phase 1 automated tests green) 18 + 19 + --- 20 + 21 + ## Phase 2: DIDAvatar Component 22 + 23 + | Step | Action | Expected | 24 + |------|--------|----------| 25 + | 2.1 (AC1.5) | Launch the app from a fresh simulator. Complete the full onboarding flow. After the `complete` step, observe the avatar circle in the identity card on the home screen. | A solid-color circle is displayed (not white, not black, not transparent). The color is derived from the DID. | 26 + | 2.2 (AC1.5) | Note the exact color of the avatar circle. Force-quit the app completely. Relaunch the app. | The avatar circle color is identical to what was observed before the force-quit. The hue is deterministic and stable. | 27 + | 2.3 (AC1.6) | On the home screen, read the letter displayed inside the avatar circle. Compare it to the handle shown in the identity card. | The avatar letter is the first character of the handle, uppercased. For example, if the handle is `testuser.test`, the avatar displays `T`. | 28 + | 2.4 (AC1.7) | Create an account where the relay returns `handle.invalid` as the handle (requires mocking or a test account without a registered handle). Navigate to the home screen. | The avatar displays `?` instead of a letter. | 29 + 30 + --- 31 + 32 + ## Phase 3: HomeScreen Component 33 + 34 + | Step | Action | Expected | 35 + |------|--------|----------| 36 + | 3.1 (AC1.1) | Complete onboarding with a known handle (e.g., `testuser.test`). On the home screen, read the handle in the identity card. | The identity card shows `@testuser.test` (the handle prefixed with `@`). | 37 + | 3.2 (AC1.2) | On the home screen, read the DID string in the identity card. | The DID is displayed as `did:plc:XXXXXXXX…XXXXXX` — the full `did:plc:` prefix is visible, followed by 8 characters, an ellipsis, and 6 characters. | 38 + | 3.3 (AC1.3) | On the home screen, tap the "Copy" button next to the DID. | The button text changes to "Copied!" for approximately 2 seconds, then reverts to "Copy". | 39 + | 3.4 (AC1.3) | After tapping "Copy", switch to the Notes app and paste. | The pasted text is the full, untruncated DID (e.g., `did:plc:abcdefghijklmnopqrstuvwx`), not the truncated display string. | 40 + | 3.5 (AC1.4) | On the home screen, read the email address in the identity card. | The displayed email matches the email used during registration. | 41 + | 3.6 (AC1.8) | Force-quit and relaunch the app (or tap the refresh button). | A loading spinner with "Loading…" text appears briefly before the identity card data renders. | 42 + | 3.7 (AC3.2) | On the home screen, tap "Log Out". | The app navigates to the welcome screen. No identity data is visible on the welcome screen. | 43 + | 3.8 (AC3.8) | After completing standard onboarding (which publishes a DID document), observe the home screen. | The "View DID Document" button is visible. | 44 + | 3.9 (AC3.8) | If `didDoc` is null in the `getSession` response (no published DID document), observe the home screen. | The "View DID Document" button is hidden (not rendered). | 45 + 46 + --- 47 + 48 + ## Phase 4: State Machine Wiring 49 + 50 + | Step | Action | Expected | 51 + |------|--------|----------| 52 + | 4.1 (AC3.4) | On the home screen, tap "View DID Document" (requires `didDoc` to be non-null). | The app transitions to the DID Document screen. The header reads "DID Document". | 53 + | 4.2 (AC3.9) | On the DID Document screen, tap the "Back" button. | The app returns to the home screen. All identity card data is intact and unchanged. | 54 + | 4.3 (AC3.10) | On the home screen, tap "Recovery Info". | The app transitions to the Recovery Info screen. The header reads "Recovery Info". | 55 + | 4.4 (AC3.14) | On the Recovery Info screen, tap the "Back" button. | The app returns to the home screen. All identity card data is intact and unchanged. | 56 + | 4.5 (AC5.1) | Complete onboarding so OAuth tokens are stored in Keychain. Force-quit the app completely. Relaunch the app. | The app opens directly to the home screen (not the welcome screen). | 57 + | 4.6 (AC5.2 — entry via onboarding) | Complete onboarding. After the `complete` step, the app navigates to home. | The identity card is fully populated (handle, DID, email, avatar, status indicators all present). | 58 + | 4.7 (AC5.2 — entry via relaunch) | Force-quit and relaunch the app after onboarding is complete. | The identity card is fully populated on the home screen (loaded on mount regardless of entry path). | 59 + 60 + --- 61 + 62 + ## Phase 5: DIDDocumentScreen Component 63 + 64 + | Step | Action | Expected | 65 + |------|--------|----------| 66 + | 5.1 (AC3.5) | Navigate to the DID Document screen (tap "View DID Document" from home). | The screen displays sections: "Identifier" (full DID), "Also Known As" (`at://handle` entries if present), "Verification Keys" (type + truncated `publicKeyMultibase`), "Services" (type + endpoint URL). | 67 + | 5.2 (AC3.6) | On the DID Document screen, tap "Show Raw JSON". | A monospace code block appears showing the full DID document JSON with proper indentation. | 68 + | 5.3 (AC3.6) | Tap "Hide Raw JSON". | The monospace JSON block disappears. The structured view remains. | 69 + | 5.4 (AC3.7) | On the DID Document screen, tap the "Copy" button next to a verification key's `publicKeyMultibase` value. | The button text changes to "Copied!" for approximately 2 seconds. | 70 + | 5.5 (AC3.7) | Switch to Notes or another text-input app and paste. | The pasted text is the full `publicKeyMultibase` string (e.g., `zDnae…`), not the truncated display value. | 71 + 72 + --- 73 + 74 + ## Phase 6: RecoveryInfoScreen Component 75 + 76 + | Step | Action | Expected | 77 + |------|--------|----------| 78 + | 6.1 (AC3.11) | Complete onboarding (which stores `recovery-share-1` in Keychain). Navigate to Recovery Info from the home screen. | Share 1 row shows a green checkmark icon and text "Saved to iCloud Keychain". | 79 + | 6.2 (AC3.12) | Manually delete `recovery-share-1` from the Keychain (using Xcode Keychain debugging or a test helper). Return to the home screen, refresh, then navigate to Recovery Info. | Share 1 row shows a red X icon and text "Not found in Keychain". | 80 + | 6.3 (AC3.13) | Navigate to Recovery Info. | Share 2 row always shows a green checkmark icon and text "Held by the relay". | 81 + 82 + --- 83 + 84 + ## End-to-End Scenarios 85 + 86 + ### E2E-1: Full Onboarding to Home Screen 87 + 88 + **Purpose:** Full user journey from first launch through account creation to the home screen. 89 + 90 + | Step | Action | Expected | 91 + |------|--------|----------| 92 + | 1 | Reset the iOS Simulator (Device → Erase All Content and Settings). Launch the app with `cargo tauri ios dev`. | The welcome screen appears. | 93 + | 2 | Complete the full onboarding flow (claim code, email, handle, password, DID ceremony, Shamir backup). | Each step transitions correctly. | 94 + | 3 | After the `complete` step, observe the transition. | The app navigates to the home screen automatically. | 95 + | 4 | Verify the identity card. | Handle (`@handle`), truncated DID (`did:plc:XXXXXXXX…XXXXXX`), email, and colored avatar with handle initial are all displayed. | 96 + | 5 | Verify the status indicators. | Relay shows "Connected" (green dot). Session shows "Active" (green dot). | 97 + | 6 | Verify the action buttons. | "View DID Document", "Recovery Info", and "Log Out" are all visible. | 98 + 99 + ### E2E-2: Home Screen to DID Document and Back 100 + 101 + **Purpose:** DID Document navigation round-trip. 102 + 103 + | Step | Action | Expected | 104 + |------|--------|----------| 105 + | 1 | From the home screen, tap "View DID Document". | DID Document screen appears with "DID Document" header. | 106 + | 2 | Verify structured content. | Identifier, verification keys, and services sections are populated. | 107 + | 3 | Tap "Show Raw JSON". | Monospace JSON block appears. | 108 + | 4 | Tap "Hide Raw JSON". | JSON block disappears. | 109 + | 5 | Tap the "Copy" button on a verification key. | Button text changes to "Copied!". | 110 + | 6 | Tap "Back". | Returns to the home screen with all data intact. | 111 + 112 + ### E2E-3: Home Screen to Recovery Info and Back 113 + 114 + **Purpose:** Recovery Info navigation round-trip. 115 + 116 + | Step | Action | Expected | 117 + |------|--------|----------| 118 + | 1 | From the home screen, tap "Recovery Info". | Recovery Info screen appears with "Recovery Info" header. | 119 + | 2 | Verify Share 1. | Green checkmark, "Saved to iCloud Keychain". | 120 + | 3 | Verify Share 2. | Green checkmark, "Held by the relay". | 121 + | 4 | Verify Share 3. | Clipboard icon, "Your manual backup". | 122 + | 5 | Tap "Back". | Returns to the home screen with all data intact. | 123 + 124 + ### E2E-4: Logout and Re-authentication 125 + 126 + **Purpose:** Logout clears tokens and returns app to clean state. 127 + 128 + | Step | Action | Expected | 129 + |------|--------|----------| 130 + | 1 | From the home screen, tap "Log Out". | App navigates to the welcome screen. | 131 + | 2 | Force-quit and relaunch the app. | Welcome screen appears (not home), confirming tokens were cleared. | 132 + | 3 | Complete the OAuth login flow again. | App navigates to the home screen with fresh session data. | 133 + 134 + ### E2E-5: App Relaunch with Existing Session 135 + 136 + **Purpose:** App launches to home when already onboarded (AC5.1). 137 + 138 + | Step | Action | Expected | 139 + |------|--------|----------| 140 + | 1 | Start from a state where onboarding is complete and the home screen is showing. | Home screen displayed. | 141 + | 2 | Force-quit the app. | App terminated. | 142 + | 3 | Relaunch the app. | App opens directly to the home screen (not the welcome screen). | 143 + | 4 | Verify identity card is populated. | Handle, DID, email, and avatar all displayed. | 144 + 145 + ### E2E-6: Refresh Button 146 + 147 + **Purpose:** Refresh button re-fetches data without navigating away. 148 + 149 + | Step | Action | Expected | 150 + |------|--------|----------| 151 + | 1 | On the home screen, note the current identity card data. | Data is displayed. | 152 + | 2 | Tap the refresh button (top-right corner). | Loading spinner appears briefly, then data re-renders. | 153 + | 3 | Verify data is unchanged. | Same handle, DID, email, and status indicators as before. | 154 + 155 + --- 156 + 157 + ## Traceability Matrix 158 + 159 + | Acceptance Criterion | Automated Test | Manual Step | 160 + |----------------------|----------------|-------------| 161 + | MM-150.AC1.1 | — | 3.1 | 162 + | MM-150.AC1.2 | — | 3.2 | 163 + | MM-150.AC1.3 | — | 3.3, 3.4 | 164 + | MM-150.AC1.4 | — | 3.5 | 165 + | MM-150.AC1.5 | — | 2.1, 2.2 | 166 + | MM-150.AC1.6 | — | 2.3 | 167 + | MM-150.AC1.7 | — | 2.4 | 168 + | MM-150.AC1.8 | — | 3.6 | 169 + | MM-150.AC2.1 | `load_home_data_relay_healthy_true_when_health_returns_200` | — | 170 + | MM-150.AC2.2 | `load_home_data_relay_healthy_false_when_health_fails` | — | 171 + | MM-150.AC2.3 | `load_home_data_session_populated_when_get_session_succeeds` | — | 172 + | MM-150.AC2.4 | `load_home_data_session_null_when_get_session_fails` | — | 173 + | MM-150.AC2.5 | `relay_healthy_false_when_health_fails` + `session_null_when_get_session_fails` | — | 174 + | MM-150.AC3.1 | `log_out_deletes_oauth_and_did_from_keychain` | — | 175 + | MM-150.AC3.2 | — | 3.7 | 176 + | MM-150.AC3.3 | `log_out_preserves_device_and_dpop_keys` | — | 177 + | MM-150.AC3.4 | — | 4.1 | 178 + | MM-150.AC3.5 | — | 5.1 | 179 + | MM-150.AC3.6 | — | 5.2, 5.3 | 180 + | MM-150.AC3.7 | — | 5.4, 5.5 | 181 + | MM-150.AC3.8 | — | 3.8, 3.9 | 182 + | MM-150.AC3.9 | — | 4.2 | 183 + | MM-150.AC3.10 | — | 4.3 | 184 + | MM-150.AC3.11 | — | 6.1 | 185 + | MM-150.AC3.12 | — | 6.2 | 186 + | MM-150.AC3.13 | — | 6.3 | 187 + | MM-150.AC3.14 | — | 4.4 | 188 + | MM-150.AC4.1 | `load_home_data_relay_healthy_true_when_health_returns_200` | — | 189 + | MM-150.AC4.2 | `load_home_data_session_populated_when_get_session_succeeds` | — | 190 + | MM-150.AC4.3 | `load_home_data_relay_healthy_false_when_health_fails` | — | 191 + | MM-150.AC4.4 | `load_home_data_session_null_when_get_session_fails` | — | 192 + | MM-150.AC4.5 | `load_home_data_no_session_returns_not_authenticated` | — | 193 + | MM-150.AC4.6 | `log_out_deletes_oauth_and_did_from_keychain` | — | 194 + | MM-150.AC4.7 | `log_out_succeeds_when_keychain_items_absent` | — | 195 + | MM-150.AC5.1 | — | 4.5 | 196 + | MM-150.AC5.2 | — | 4.6, 4.7 |