Test: TS-07 returning user with existing display_name skips set-name

Inverse coverage for the auth path: TS-01..TS-06 all wipe the customer
row (drop_customer=true) so every OTP path lands on the new-user
set-name branch. TS-07 instead seeds an existing identified customer
(phone + display_name + is_anonymous=false) and verifies the OTP
sign-in returns the existing row unchanged via
resolveCustomerForIdentity branch 1, so /auth/set-name is never shown.

Adds:
* /internal/_test/seed-customer endpoint — upserts a customer with
  phone + display_name + is_anonymous=false.
* client_app/.maestro/scripts/seed_customer.js helper.
* client_app/.maestro/flows/ts-07_returning_existing_name_skips_setname.yaml.
* TS-07 scenario doc + coverage-map row in
  requirement/phase4-customer-flow.md.

The flow asserts the "halo, <name>" greeting on the returning-user home
variant (identified users always land on _SHomeReturningView regardless
of chat history) plus an explicit notVisible on "Siapa namamu" as a
belt-and-braces check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 20:50:40 +08:00
parent e09f76ceb6
commit 93fa5f113a
4 changed files with 198 additions and 1 deletions

View File

@@ -608,7 +608,7 @@ Manual reproduction checklists for Phase 4 customer flows. Tick boxes as
verified. Cluster tag `[C]` = client_app, `[BE]` = backend setup.
> **Coverage map** — these scenarios collectively exercise every branching
> point in §4 of `flow_customer.mermaid.md`:
> point in §4 of `flow_customer.mermaid.md`, plus one §2 (auth) edge:
>
> | Branching point | Scenario(s) |
> |---|---|
@@ -618,6 +618,7 @@ verified. Cluster tag `[C]` = client_app, `[BE]` = backend setup.
> | PayStat: `paid` vs `timeout 20 min` | TS-01/02/04/06 vs TS-05 |
> | PairRoute: `lama (Targeted)` vs `baru / cari lain (BlastFlow)` | TS-01/05/06 vs TS-02/04 |
> | TargetedRes: `accept` vs `reject/timeout` | TS-01/05 vs TS-06 |
> | §2 post-OTP: new user (set-name) vs existing user with name (skip) | TS-01..06 vs TS-07 |
## TS-01 — Returning user re-pays an online bestie (lama happy path)
@@ -878,3 +879,55 @@ escape (same shape as TS-03), but post-payment — the customer has already
paid, so this is effectively abandoning a paid session. Worth confirming
the UX (probably a confirmation prompt) and whether the payment is
refunded / converted to credit.
---
## TS-07 — Returning user with existing display_name skips set-name screen
**Flow:** §2 (verified path) `Choice → "verif WA" → OTP → user lookup → existing account (display_name set, has_transacted=false) → /home`. Verifies the existing-user-with-name branch of `resolveCustomerForIdentity`.
**Affects:** `client_app`, `backend`.
**Goal:** Confirm a phone-OTP sign-in for a customer who already has a
non-empty `display_name` in `customers` does NOT re-show the
"Siapa namamu?" set-name screen. Routes directly from OTP success
to /home with the stored display_name. This is the inverse of TS-01..TS-06,
all of which use `drop_customer:true` (wiping the row) and therefore always
land on the new-user set-name branch.
**Pre-reqs**
- [ ] **[BE]** Backend reachable; NODE_ENV != 'production'.
**Steps**
1. [ ] **[BE]** Wipe phone state via `/internal/_test/reset-phone`
`{ phone, drop_customer: true }` — clears any prior customer row.
2. [ ] **[BE]** Seed an identified customer via
`/internal/_test/seed-customer` `{ phone, display_name }` —
inserts a row with `is_anonymous=false` and the chosen display_name.
3. [ ] **[C]** Cold-launch `client_app` with clearState → welcome
carousel → tap `Mulai` → home (anonymous view, shows `masuk →` banner).
4. [ ] **[C]** Tap `masuk →` → `/auth/register` → input phone digits
(after the `+62` chip) → tap `kirim kode` → OTP screen.
5. [ ] **[C]** Peek OTP from the stub, input it — auto-submits on the
6th digit.
**Expected result**
- [ ] **[C]** App routes directly to `/home`, CTA `aku mau curhat`
visible (the `_SHome1stView` no-history variant). The customer's
stored display_name is loaded into the profile state.
- [ ] **[C]** The `Siapa namamu?` set-name screen is **never shown**.
An `assertNotVisible` for the set-name title at the home-arrival point
acts as a belt-and-braces check against a brief flash-then-redirect.
- [ ] **[BE]** No new `customers` row created — the seeded row is the
same one returned by `getCustomerByPhone` → `resolveCustomerForIdentity`
branch 1 (existing identity, no anon prefix). `customers.id` after the
flow equals the seeded `CUSTOMER_ID`.
**Why this needs its own test:** TS-01..TS-06 all begin with
`reset_phone` `drop_customer:true`, which makes every OTP path land in
`resolveCustomerForIdentity` branch 4 (no existing + no anon → create
new with display_name=null → client routes to set-name). That covers
the new-user surface but never exercises the "existing user with name"
path. TS-07 is the symmetric coverage for the same auth code, ensuring
the set-name screen isn't accidentally re-shown for known users (which
would be a real UX regression — name re-entry every login).