Files
halobestie-clone/client_app/.maestro/flows/09_chat_tab.yaml
ramadhan sjamsani 1908e98012 Phase 4 Stage 10 Maestro: 09_chat_tab.yaml + seed-pending-payment endpoint
Closes the Stage 10 acceptance criterion §10.11 #13 (Maestro coverage).

- New dev-only `POST /internal/_test/seed-pending-payment` — inserts a
  payment_sessions row in `pending` status with expires_at 20m out, so
  the Pembayaran sub-tab has a deterministic row to render. Body
  accepts { phone, isExtension?, amount?, durationMinutes?, mode? }.
  Gated on NODE_ENV != 'production' like the other test routes.

- New Maestro helper script `seed_pending_payment.js` mirrors the
  existing seed_history_session pattern.

- New flow `09_chat_tab.yaml`:
    cold-start onboarding → home (returning view) →
    seed completed session + seed pending payment →
    tap "💬 chat" bottom-nav → lands on /chat/aktif via redirect →
    assert "aktif" / "pembayaran" / "selesai" pills + empty-state copy →
    tap pembayaran → assert "menunggu pembayaran sesi" + "bayar Rp..." →
    tap selesai → assert "X menit" duration row → tap row → assert
    "Transkrip Chat" appbar → back → still on /chat/selesai.

  Maestro parsed the YAML cleanly and started executing against the
  device; full run requires backend + online mitra in dev DB (same
  pre-reqs as flows 03/05/06/08).

- TECH_DEBT entry: Stage 10 retired the standalone bestie-history list
  screen, which means (a) the "curhat lagi" targeted-payment entry
  point has no UI affordance anywhere in the app — its plumbing in
  payment_notifier / payment_screen is now orphaned, and (b) the
  Stage 8 flow `08_returning_targeted.yaml` will fail at
  `assertVisible: "Riwayat Chat"` because it expects the deleted
  screen. Three fix paths listed in the entry for product to pick.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 20:24:50 +08:00

162 lines
4.5 KiB
YAML

# Stage 10 acceptance: Chat tab (3 sub-tabs).
#
# Flow:
# 1. Cold-start onboarding (abbreviated; mirrors 01_smoke) → home with a
# phone-verified customer so the dev seed endpoints can find them.
# 2. Seed a completed chat_sessions row → Selesai sub-tab has data.
# 3. Seed a pending payment_sessions row → Pembayaran sub-tab has data
# AND the bottom-nav chat tab should render a red dot (visual; not
# asserted because Maestro can't reliably introspect small pixel state).
# 4. Tap the "💬 chat" bottom-nav icon → /chat redirects to /chat/aktif.
# 5. Aktif sub-tab: no active session, so empty state copy shows.
# 6. Tap "pembayaran" pill → row with preview "menunggu pembayaran sesi"
# and the "bayar Rp..." chip.
# 7. Tap "selesai" pill → row with seeded mitra name. Tap the row →
# transcript screen opens.
# 8. Back → still on /chat/selesai (URL is source of truth for the sub-tab).
#
# Pre-req: client_app debug APK installed, backend reachable on
# BACKEND_INTERNAL_URL with NODE_ENV != 'production' so /internal/_test/*
# routes are registered, AND at least one mitra is online in the dev DB.
#
# Run:
# maestro test client_app/.maestro/flows/09_chat_tab.yaml
appId: com.halobestie.client.client_app
env:
TEST_PHONE: "+628155556678"
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 carousel → splash → home (1st time view).
- extendedWaitUntil:
visible:
text: "Mulai"
timeout: 15000
- tapOn:
text: "Mulai"
retryTapIfNoChange: true
# Verif choice sheet → "Lanjut sebagai Tamu" → name → phone OTP
- 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
# Returning users land on SHomeReturning with "Mulai Curhat".
- extendedWaitUntil:
visible:
text: "Mulai Curhat"
timeout: 20000
# Seed a completed session → Selesai sub-tab populated.
- runScript:
file: ../scripts/seed_history_session.js
env:
TEST_PHONE: ${TEST_PHONE}
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
# Seed a pending payment → Pembayaran sub-tab populated + red dot eligibility.
- runScript:
file: ../scripts/seed_pending_payment.js
env:
TEST_PHONE: ${TEST_PHONE}
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
# Tap "💬 chat" in the bottom nav → /chat → redirected to /chat/aktif.
- tapOn:
text: "chat"
retryTapIfNoChange: true
- extendedWaitUntil:
visible:
text: "aktif"
timeout: 10000
# Sub-tab pills visible; the heading "chat" duplicates with the nav label
# so assert what's unique to the chat-tab shell.
- assertVisible: "aktif"
- assertVisible: "pembayaran"
- assertVisible: "selesai"
# Aktif default body: empty state since no active session was seeded.
- assertVisible: "belum ada chat di sini"
# Pembayaran sub-tab → seeded pending initial payment is visible.
- tapOn:
text: "pembayaran"
- extendedWaitUntil:
visible:
text: "menunggu pembayaran sesi"
timeout: 5000
- assertVisible:
text: "bayar Rp.*"
# Selesai sub-tab → seeded completed session is visible.
- tapOn:
text: "selesai"
- extendedWaitUntil:
visible:
text: ".* menit"
timeout: 5000
# Tap the row → opens the read-only transcript screen.
- tapOn:
text: ".* menit"
- extendedWaitUntil:
visible:
text: "Transkrip Chat"
timeout: 10000
# Back returns us to /chat/selesai (URL preserves sub-tab state).
- back
- extendedWaitUntil:
visible:
text: "selesai"
timeout: 5000
- assertVisible: "selesai"