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

@@ -0,0 +1,101 @@
# TS-07 — Returning user with existing display_name skips set-name screen
# (requirement/phase4-customer-flow.md → Test Scenarios → TS-07).
#
# Inverse of TS-01..TS-06: those flows wipe the customer (drop_customer=true)
# so every OTP path hits the new-user set-name branch. TS-07 instead seeds
# an EXISTING customer row with phone + display_name, then verifies the
# OTP sign-in returns the existing row unchanged (via
# resolveCustomerForIdentity branch 1) and the client routes directly to
# /home without showing /auth/set-name.
#
# Pre-reqs:
# - Backend reachable, NODE_ENV != 'production'.
# - (No mitra requirement — flow stops at /home.)
#
# Run:
# maestro test client_app/.maestro/flows/ts-07_returning_existing_name_skips_setname.yaml
appId: com.halobestie.client.client_app
env:
TEST_PHONE: "+6281234567890"
EXISTING_NAME: "Returning User"
BACKEND_INTERNAL_URL: http://localhost:3001
---
# --- Setup: wipe the phone, then re-seed an identified customer with name ---
- runScript:
file: ../scripts/reset_phone.js
env:
TEST_PHONE: ${TEST_PHONE}
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
- runScript:
file: ../scripts/seed_customer.js
env:
TEST_PHONE: ${TEST_PHONE}
DISPLAY_NAME: ${EXISTING_NAME}
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
- launchApp:
clearState: true
# --- Welcome carousel → home (anon) ---
- extendedWaitUntil:
visible:
text: "Mulai"
timeout: 15000
- tapOn:
text: "Mulai"
retryTapIfNoChange: true
# Home anon view shows the `masuk →` banner.
- extendedWaitUntil:
visible:
text: "(?s).*udah pernah pakai HaloBestie.*"
timeout: 30000
# --- Tap masuk → register → phone → OTP ---
- tapOn:
text: "(?s).*masuk →.*"
- extendedWaitUntil:
visible:
text: "(?s).*nomor wa-mu.*"
timeout: 10000
- tapOn:
point: "60%, 47%"
- inputText: "81234567890"
- hideKeyboard
- tapOn:
text: "(?s).*kirim kode.*"
- extendedWaitUntil:
visible:
text: "Masukkan OTP"
timeout: 15000
- runScript:
file: ../scripts/peek_otp.js
env:
TEST_PHONE: ${TEST_PHONE}
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
- inputText: ${output.OTP}
# --- KEY ASSERTIONS ---
# 1. OTP entry should disappear (auto-submit on 6th digit).
- extendedWaitUntil:
notVisible:
text: "Masukkan OTP"
timeout: 15000
# 2. Home renders directly. Identified (verified) users land on the
# `_SHomeReturningView` regardless of chat history: greeting becomes
# "halo, <name>" and CTA flips to "curhat sama bestie baru". The
# 1st-time view ("aku mau curhat") is the anon-user variant only.
- extendedWaitUntil:
visible:
text: "(?s).*halo, ${EXISTING_NAME}.*"
timeout: 20000
- assertVisible: "(?s).*curhat sama bestie baru.*"
# 3. The "Siapa namamu?" set-name screen must NOT have been shown —
# if it had, the assertion above would have failed at the set-name
# intermediate. This belt-and-braces assert catches the case where
# the set-name screen briefly flashes then auto-redirects.
- assertNotVisible:
text: "(?s).*Siapa namamu.*"

View File

@@ -0,0 +1,20 @@
// Upsert a customer row with TEST_PHONE + DISPLAY_NAME via the dev-only
// /internal/_test/seed-customer endpoint. Used by TS-07 to set up the
// "returning user already has a name" precondition, so the OTP sign-in
// path can verify the set-name screen is skipped for existing identified
// customers.
const phone = TEST_PHONE
const displayName = DISPLAY_NAME
const url = BACKEND_INTERNAL_URL || 'http://localhost:3001'
if (!phone) throw new Error('TEST_PHONE env not set')
if (!displayName) throw new Error('DISPLAY_NAME env not set')
const resp = http.post(`${url}/internal/_test/seed-customer`, {
body: JSON.stringify({ phone, display_name: displayName }),
headers: { 'Content-Type': 'application/json' },
})
if (resp.status !== 200) {
throw new Error(`seed-customer failed (${resp.status}): ${resp.body}`)
}
const data = json(resp.body)
output.CUSTOMER_ID = data.id
output.CUSTOMER_DISPLAY_NAME = data.display_name