You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/pubky-profile-manual-e2e.md
+35-11Lines changed: 35 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Pubky profile & contacts — manual E2E charter
2
2
3
-
Charter for QA around profile creation, Pubky Ring import, and contacts. Use while the feature is landing; automate later via WebdriverIO + `ciIt()` when flows and infra are stable.
3
+
Charter for QA around profile creation, Pubky Ring import, and contacts. Use alongside the WebdriverIO `@pubky_profile` specs: keep high-value stable flows automated and use the remaining checklist for manual / exploratory coverage while the feature is landing.
@@ -73,7 +73,7 @@ With no profile created yet, every entry point should funnel into the choice scr
73
73
4. Character limits (if enforced by the UI) prevent oversize inputs without crashing.
74
74
5.**Delete Profile** lives at the bottom of this Edit screen (the only entry point in the normal UI). Covered by B.8.
75
75
76
-
### B.4 Add contact (manual)
76
+
### B.4 Add contact
77
77
78
78
1. Contacts → **Add contact** → paste a valid pubky → Continue → contact is added; opening detail shows the remote profile snapshot (name, image, links).
79
79
2. Scan-QR path (if exposed): scan a pubky QR → same flow.
@@ -82,21 +82,36 @@ With no profile created yet, every entry point should funnel into the choice scr
82
82
5.**Self-add guard**: pasting your own pubky shows an explicit error (Android string: `contacts__add_error_self`); contact is **not** created.
83
83
6.**Duplicate add** (same pubky already in contacts) → de-duplicated or clear message.
84
84
85
+
> **`@pubky_profile_2`** adds one staging contact after editing the profile, then verifies the row persists after app relaunch and wallet restore. **`@pubky_profile_3`** covers malformed pubky and self-add inline validation, then adds both staging contacts. Scan-QR, paste-from-clipboard, duplicate-add handling, and full remote snapshot assertions (avatar/links) remain manual.
86
+
85
87
### B.5 Edit contact (local snapshot)
86
88
87
89
1. Contacts → open a contact → Edit.
88
90
2. Edits to **Notes** and any local fields **persist locally** and **do not** update the remote Pubky profile of that contact — this is a local snapshot.
89
91
3. Name field behavior: verify whether the app allows renaming or is display-only; whichever is shipped should match across Android and iOS.
90
92
4. Manual refresh / pull-to-refresh (if present) re-fetches the remote snapshot; local Notes are preserved.
91
93
94
+
> **`@pubky_profile_4`** creates Wallet A, creates Wallet B, adds Wallet A as a contact on Wallet B, edits Wallet A's contact name/notes on Wallet B, verifies the edited contact detail locally, then restores Wallet A and verifies Wallet A's own profile is unchanged. Manual refresh / pull-to-refresh behavior and local note preservation after refresh are not automated.
95
+
92
96
### B.6 Contacts list
93
97
94
98
1. Header: single flat **CONTACTS** section header (no A/B/C alphabetical section headers — this was the Figma-compliant design).
95
99
2. "My profile" row is shown at the top when a profile exists.
96
100
3. Tapping a contact opens detail; tapping "My profile" opens own profile.
97
101
4. Empty state (profile exists, no contacts) shows the empty copy and an Add-contact CTA.
98
102
99
-
### B.7 Delete profile (homeserver wipe)
103
+
> **`@pubky_profile_2`** / **`@pubky_profile_3`** verify contact rows can be found by `Contact_<pubkey>`. **`@pubky_profile_3`** also verifies rows are gone after delete. Header copy, `ContactsMyProfile`, tapping My Profile, and empty-state copy remain manual.
104
+
105
+
### B.7 Delete contact
106
+
107
+
1. Contacts → open a contact → Edit → Delete Contact → confirmation → **Yes, Delete**.
108
+
2. Success toast appears ("Contact deleted") and the contact row is removed.
109
+
3. Deleting the last contact returns to the empty contacts state without a stale header/list state.
110
+
4. Error path: if delete fails, show a clear error and keep the contact available.
111
+
112
+
> **`@pubky_profile_3`** deletes both staging contacts, waits for `ContactDeletedToast`, and verifies each contact row is absent. Delete failure/error handling remains manual.
113
+
114
+
### B.8 Delete profile (homeserver wipe)
100
115
101
116
1. Profile → Edit → scroll to the bottom → **Delete Profile** → confirmation ("Delete Profile?" / "This will delete your current Pubky profile data. You can create a new profile for this pubky later.") → confirm.
102
117
2. After delete: gated back to `PubkyChoice` (same as **section A**).
@@ -105,12 +120,12 @@ With no profile created yet, every entry point should funnel into the choice scr
105
120
106
121
> **`@pubky_profile_2`** also ends with delete → recreate and asserts the same seed-derived pubky. Homeserver error path in (4) is manual.
107
122
108
-
### B.8 Wipe wallet
123
+
### B.9 Wipe wallet
109
124
110
125
1. Settings → reset/wipe wallet → onboard a **new seed** → no profile, different pubky → repeat **section A**.
111
126
2. Onboard the **same seed** on a fresh install → profile and contacts should be recovered from the homeserver (if not Deleted first).
112
127
113
-
> **`@pubky_profile_2`** exercises **(2) in part**: it runs the standard E2E **backup → `restoreWallet(seed)`** flow (after profile exists), then checks profile **details and pubkey** and **pubky (copy)** still match. It is not a full “fresh install from IPA” story.
128
+
> **`@pubky_profile_2`** exercises **(2) in part**: it runs the standard E2E **backup → `restoreWallet(seed)`** flow (after profile and one contact exist), then checks profile **details**, **pubky copy**, and the added contact row still match. It is not a full “fresh install from IPA” story.
114
129
115
130
---
116
131
@@ -166,9 +181,9 @@ Use this table to verify persistence expectations. Fill in observed behavior if
| Disconnect from empty state + reconnect | same | same | preserved | re-synced | preserved |
168
183
| Delete profile + recreate (same wallet) | same | same | wiped then new | tbd — verify | tbd — verify |
169
-
| Wipe wallet, restore same seed | same | same | preserved | re-synced | tbd — verify |
184
+
| Wipe wallet, restore same seed | same | same | preserved | re-synced (`@pubky_profile_2`)| tbd — verify |
170
185
| Wipe wallet, new seed | new | new | none | none | none |
171
-
| App reinstall, same seed | same | same | preserved | re-synced | tbd — verify |
186
+
| App reinstall, same seed | same | same | preserved | re-synced (`@pubky_profile_2`)| tbd — verify |
172
187
173
188
---
174
189
@@ -197,9 +212,14 @@ Use this table to verify persistence expectations. Fill in observed behavior if
197
212
198
213
## H. Automation strategy
199
214
200
-
-**Spec**: `test/specs/pubky-profile.e2e.ts` — profile-only for now; contacts and Ring stay manual here until more specs exist. How/whether it runs in automation is a pipeline concern (`AGENTS.md`); this section only describes the spec’s intent.
215
+
-**Spec**: `test/specs/pubky-profile.e2e.ts` — covers profile creation/edit/delete, contact add/delete/edit basics, and persistence. Ring import remains manual until reliable automation exists. How/whether it runs in automation is a pipeline concern (`AGENTS.md`); this section only describes the spec’s intent.
201
216
-**Isolation**: `beforeEach` uses `reinstallApp()` and `completeOnboarding()` so a single `ciIt` can be run alone via `--mochaOpts.grep "@pubky_profile_N"`.
202
-
-**What the two tests do**: `@pubky_profile_1` — section A gating (no profile). `@pubky_profile_2` — one chained flow: create → copy/verify pubky → update profile, verify on screen → `launchFreshApp`, verify again → **wait for backup, restore wallet from seed**, verify details + pubky → remove link and tag, save, verify → delete profile → create profile again, same pubky. Does not cover Ring, full contacts tests, or avatar.
217
+
-**What the tests do**:
218
+
-`@pubky_profile_1` — section A gating (no profile).
219
+
-`@pubky_profile_2` — create → copy/verify pubky → update profile → add one staging contact → `launchFreshApp`, verify profile + contact → **wait for backup, restore wallet from seed**, verify profile + pubky + contact → remove link and tag → delete profile → create profile again, same pubky.
220
+
-`@pubky_profile_3` — invalid pubky and self-add validation → add both staging contacts → delete both contacts and verify rows are absent.
221
+
-`@pubky_profile_4` — Wallet A profile edited as a contact on Wallet B remains a local contact edit; restoring Wallet A verifies its own profile was not changed.
222
+
-**Known gaps in automation**: Ring import, avatar add/remove, scan-QR contact add, paste-from-clipboard contact add, duplicate-add behavior, contacts list header/My Profile row/empty copy, contact refresh behavior, profile/contact field-boundary behavior, and network/error paths.
203
223
-**Tags**: suite `@pubky_profile`; tests `@pubky_profile_1`, `@pubky_profile_2`, …; reserve e.g. `@pubky_ring_required` if you add Ring-specific specs later.
204
224
-**Use `ciIt()`** instead of `it()` in this suite so it matches the repo’s `ci_run_*` / lockfile retry pattern when you wire runs up.
205
225
- Shared test IDs: **H.1** below. Implementation lives under `test/helpers/` next to other E2E specs.
@@ -216,11 +236,15 @@ Use the **same string** on Android and iOS so specs stay platform-agnostic (`ele
| Profile (presentation) |**`ProfileViewName`**, **`ProfileViewNotes`** (own profile only; `CenteredProfileHeader` passes tags on **Profile** screen). **`QRCode`** — same test id as Receive; pubky is read in E2E via **`getUriFromQRCode()`** in `test/helpers/actions.ts` (shared with receive flows). Links: **`ProfileLinkLabel_0`**, **`ProfileLinkValue_0`**, … (index matches link order). Tags section header: **`ProfileViewTagsHeader`**. Each tag chip text: **`Tag-<tagtext>`** (e.g. `Tag-ere`) on the label `Text` / `BodySSB`. |
239
+
| Profile (presentation) |**`ProfileViewName`**, **`ProfileViewNotes`** (own profile only; `CenteredProfileHeader` passes tags on **Profile** screen). **`ProfileQRCode`** is read in E2E via **`getUriFromQRCode()`** in `test/helpers/actions.ts` (shared with receive flows). Links: **`ProfileLinkLabel_0`**, **`ProfileLinkValue_0`**, … (index matches link order). Tags section header: **`ProfileViewTagsHeader`**. Each tag chip text: **`Tag-<tagtext>`** (e.g. `Tag-ere`) on the label `Text` / `BodySSB`. |
Contacts list rows: `ContactsMyProfile`, `Contact_<pubkey>` (existing) — verify in app if still current when adding contact specs.
250
+
Contacts intro note: after a profile exists, first opening **Contacts** shows `ContactsIntro`; its `ContactsIntro-button` now behaves as an add-contact entry point. `ContactsEmptyAddButton` appears only after the intro is gone and the user has zero contacts.
0 commit comments