Phase 4 Stage 8: returning-user shell + Tanya Admin sheet
Bestie Choice Sheet on home Mulai Curhat CTA. When the user has at least one prior session (bestieHistoryHasItemsProvider hits the chat- sessions history endpoint), the CTA opens a HaloBottomSheet with two cards: 'bestie yang udah kenal' -> /chat/history, 'bestie baru' -> /payment/entry. Empty history -> direct to /payment/entry. Bestie history list visual upgrade: HaloOrb (mitraId seed) + name + last-session date + topic pills + sessions count + ONLINE pill. Backend getCustomerHistory now returns topics, mitra_is_online, sessions_count in a single payload (no per-row presence round-trip). BestieOfflinePopup with two variants (returning | new_) replacing the legacy BestieUnavailableDialog. tanya admin ghost CTA on both variants opens the new TanyaAdminSheet. Stage 5's targeted-wait declined stub + Stage 7's chat-screen 409 stub + searching-screen call site all migrated to the real component. TanyaAdminSheet: HaloBottomSheet with WA + Telegram buttons, deeplinks fetched via supportHandlesProvider (CC-config-driven). url_launcher added to client_app; ios LSApplicationQueriesSchemes covers https/http/whatsapp/tg. Stage 2's OTP-blocked popup hubungi admin SnackBar stub also migrated to TanyaAdminSheet. Dev-only POST /internal/_test/seed-history-session lets Maestro 08 flow seed a history row before exercising the choice sheet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
132
client_app/.maestro/flows/08_returning_targeted.yaml
Normal file
132
client_app/.maestro/flows/08_returning_targeted.yaml
Normal file
@@ -0,0 +1,132 @@
|
||||
# Stage 8 acceptance: returning-user shell.
|
||||
#
|
||||
# Flow:
|
||||
# 1. Cold-start onboarding flow (mirrors 01_smoke) lands customer on home.
|
||||
# 2. Seed a completed chat_sessions row so the bestie history list isn't empty.
|
||||
# 3. Tap "Mulai Curhat" → Bestie Choice Sheet appears.
|
||||
# 4. Tap "bestie yang udah kenal" → bestie history list appears.
|
||||
# 5. Verify ONLINE pill renders for the seeded (online) mitra.
|
||||
# 6. Tap "curhat lagi" on the row → targeted-wait screen appears with 20s
|
||||
# countdown overlay, then matches via the running mitra.
|
||||
#
|
||||
# Pre-req: client_app debug APK installed, backend reachable, NODE_ENV != 'production'
|
||||
# so the dev-only /internal/_test routes are registered, AND a mitra is currently
|
||||
# online in the dev DB (see backend/src/db/seed.js or run mitra_app to sign in).
|
||||
#
|
||||
# Run:
|
||||
# maestro test client_app/.maestro/flows/08_returning_targeted.yaml
|
||||
appId: com.halobestie.client.client_app
|
||||
env:
|
||||
TEST_PHONE: "+628155556677"
|
||||
BACKEND_INTERNAL_URL: http://localhost:3001
|
||||
---
|
||||
# Wipe prior state for TEST_PHONE so the run is hermetic.
|
||||
- runScript:
|
||||
file: ../scripts/reset_phone.js
|
||||
env:
|
||||
TEST_PHONE: ${TEST_PHONE}
|
||||
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
|
||||
- launchApp:
|
||||
clearState: true
|
||||
|
||||
# Onboarding → welcome → display name → force-register → OTP → home (matches 01_smoke).
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Mulai"
|
||||
timeout: 15000
|
||||
- tapOn:
|
||||
text: "Mulai"
|
||||
retryTapIfNoChange: true
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Lanjut sebagai Tamu"
|
||||
timeout: 10000
|
||||
- tapOn:
|
||||
text: "Lanjut sebagai Tamu"
|
||||
retryTapIfNoChange: true
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Nama panggilan"
|
||||
timeout: 10000
|
||||
- tapOn:
|
||||
text: "Nama panggilan"
|
||||
- inputText: "Maestro"
|
||||
- hideKeyboard
|
||||
- tapOn:
|
||||
text: "Lanjut"
|
||||
retryTapIfNoChange: true
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Verifikasi Akun"
|
||||
timeout: 15000
|
||||
- tapOn:
|
||||
text: "Nomor HP"
|
||||
- inputText: ${TEST_PHONE}
|
||||
- hideKeyboard
|
||||
- tapOn:
|
||||
text: "Kirim OTP"
|
||||
retryTapIfNoChange: true
|
||||
- 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}
|
||||
- extendedWaitUntil:
|
||||
notVisible:
|
||||
text: "Masukkan OTP"
|
||||
timeout: 15000
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Nama panggilan"
|
||||
timeout: 10000
|
||||
- tapOn:
|
||||
text: "Nama panggilan"
|
||||
- inputText: "Maestro"
|
||||
- hideKeyboard
|
||||
- tapOn:
|
||||
text: "Lanjut"
|
||||
retryTapIfNoChange: true
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Mulai Curhat"
|
||||
timeout: 20000
|
||||
|
||||
# Seed a prior session against an online mitra.
|
||||
- runScript:
|
||||
file: ../scripts/seed_history_session.js
|
||||
env:
|
||||
TEST_PHONE: ${TEST_PHONE}
|
||||
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
|
||||
|
||||
# Tap "Mulai Curhat" → Bestie Choice Sheet (returning-user variant).
|
||||
- tapOn:
|
||||
text: "Mulai Curhat"
|
||||
retryTapIfNoChange: true
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "mau curhat sama siapa?"
|
||||
timeout: 5000
|
||||
- assertVisible: "bestie yang udah kenal"
|
||||
- assertVisible: "bestie baru"
|
||||
|
||||
# Choose the known bestie path → history list with v4 layout.
|
||||
- tapOn: "bestie yang udah kenal"
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Riwayat Chat"
|
||||
timeout: 5000
|
||||
- assertVisible: "ONLINE"
|
||||
- assertVisible: "curhat lagi"
|
||||
|
||||
# Tap "curhat lagi" → /payment (legacy targeted-payment route). Verify the
|
||||
# screen title; the targeted-payment flow itself is covered by Stage 5.
|
||||
- tapOn: "curhat lagi"
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "Chat lagi dengan"
|
||||
timeout: 10000
|
||||
18
client_app/.maestro/scripts/seed_history_session.js
Normal file
18
client_app/.maestro/scripts/seed_history_session.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// Seed a completed chat_sessions row for TEST_PHONE so the bestie history
|
||||
// list isn't empty when the Stage 8 flow opens it. Pairs the customer with
|
||||
// the most-recently-online mitra in the dev DB.
|
||||
//
|
||||
// Hits the dev-only /internal/_test/seed-history-session endpoint.
|
||||
const phone = TEST_PHONE
|
||||
const url = BACKEND_INTERNAL_URL || 'http://localhost:3001'
|
||||
const resp = http.post(`${url}/internal/_test/seed-history-session`, {
|
||||
body: JSON.stringify({ phone }),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
if (resp.status !== 200) {
|
||||
throw new Error(`seed-history-session failed (${resp.status}): ${resp.body}`)
|
||||
}
|
||||
const data = json(resp.body)
|
||||
output.SESSION_ID = data.session_id
|
||||
output.MITRA_ID = data.mitra_id
|
||||
output.MITRA_NAME = data.mitra_name
|
||||
Reference in New Issue
Block a user