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:
@@ -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.*"
|
||||
20
client_app/.maestro/scripts/seed_customer.js
Normal file
20
client_app/.maestro/scripts/seed_customer.js
Normal 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
|
||||
Reference in New Issue
Block a user