Phase 4 Stage 5: pairing UX upgrades (searching + match + targeted-wait)

Searching screen: soft-prompt card reskin, pulsing-dots panel replaces
the spinner, inline 5-min timeout panel with `coba cari lagi` (resets
pairing notifier + routes to /payment/entry for a fresh funnel — the
server-side payment is failed_pairing at that point so a stale retry
isn't valid) and `kembali ke home` ghost CTA.

Bestie-found screen: S9 Match-V4 reskin — HaloOrb + status dot +
'halo, aku bestie {name}' + `mulai sesi {N} menit →` with N pulled from
the active session's duration_minutes.

Targeted-wait overlay (new) at /chat/waiting-targeted/:mitraId. Three
sub-states from pairingProvider's PairingTargetedWaitingData:
waiting (20s countdown) / accepted (routes to chat) / declined (stubbed
BestieOfflinePopup with a TODO pointing to Stage 8). Reached via
payment_screen._routeToSearchOnConfirmed when the confirm carried a
targetedMitraId — keeps the mandatory payment-before-pairing invariant.

Dev-only POST /internal/_test/force-pairing-timeout drives the 5-min
timeout shortcut for the Maestro flow without waiting live.

Maestro 05_searching_timeout.yaml + force_pairing_timeout.js helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 16:49:07 +08:00
parent 7ae8f33b2c
commit f170d54535
8 changed files with 800 additions and 93 deletions

View File

@@ -0,0 +1,89 @@
# Stage 5 acceptance: drive the searching screen into the 5-min timeout
# state without waiting 5 minutes, verify the new copy + both CTAs render.
#
# Flow:
# home → tap CTA → payment funnel → confirm → /chat/searching →
# force-timeout via dev endpoint → verify timeout panel + CTAs.
#
# Pre-req:
# 1. Customer is already onboarded + on /home (run flow 01 first).
# 2. At least one mitra is ONLINE on the target backend (so the home
# "Mulai Curhat" CTA is enabled — we then force-timeout server-side
# regardless of mitra availability).
# 3. Backend reachable at BACKEND_INTERNAL_URL with NODE_ENV != 'production'
# (so the _test routes register).
#
# Run:
# maestro test client_app/.maestro/flows/05_searching_timeout.yaml
appId: ${APP_ID_ANDROID}
env:
BACKEND_INTERNAL_URL: http://localhost:3001
---
- launchApp:
clearState: false
- assertVisible: "Mulai Curhat"
# Step 1: enter payment funnel.
- tapOn: "Mulai Curhat"
- extendedWaitUntil:
visible:
text: "pilih cara curhat|sesi pertama|pilih durasi"
timeout: 10000
# Step 2: regardless of branch, end up on /payment/method.
- runFlow:
when:
visible:
text: "pilih cara curhat"
commands:
- tapOn: "chat"
- extendedWaitUntil:
visible:
text: "pilih durasi"
timeout: 5000
- tapOn:
text: "5 menit"
retryTapIfNoChange: true
- tapOn:
text: "bayar"
retryTapIfNoChange: true
- runFlow:
when:
visible:
text: "sesi pertama"
commands:
- tapOn:
text: "mulai"
retryTapIfNoChange: true
# Step 3: cara-bayar → tap bayar → waiting screen.
- extendedWaitUntil:
visible:
text: "cara bayar"
timeout: 10000
- tapOn:
text: "bayar"
retryTapIfNoChange: true
# Step 4: payment confirms via mock; the searching screen opens. The
# soft-prompt copy ships in Stage 5 — we wait for that landmark.
- extendedWaitUntil:
visible:
text: "sambil nunggu"
timeout: 15000
- assertVisible: "lagi nyari bestie..."
# Step 5: force the 5-min timeout server-side; the WS event lands within
# ~1s and the screen flips to the timeout panel.
- runScript:
file: ../scripts/force_pairing_timeout.js
env:
BACKEND_INTERNAL_URL: ${BACKEND_INTERNAL_URL}
# Step 6: verify timeout panel + both CTAs render.
- extendedWaitUntil:
visible:
text: "masih nyari nih"
timeout: 10000
- assertVisible: "coba cari lagi"
- assertVisible: "kembali ke home"