Phase 3.7: paid pairing flow + returning chat + extension flip
- Backend: payment_sessions + pairing_failures tables; payment.service.js and pairing-failure.service.js (new); rewritten pairing.service.js (payment-gated blast + targeted "Curhat lagi" + cancel + fallback); rewritten extension.service.js (data-driven auto-approve with offline safeguard, charge-at-approval); pricing.service.js (extension tiers without free trial); mitra-status.service.js (countAvailableMitras cached path); 60s sweeper for stale payment sessions - Backend routes: client.payment.routes, client.mitra-availability.routes, internal/failed-pairings.routes; client.chat.routes rewritten for payment-gated start + /returning + /cancel + /fallback-to-blast; internal/config.routes adds 4 new keys with Valkey invalidate publish - client_app: mitra-availability poll, payment screen + notifier, pairing notifier rewrite (PairingTargetedWaiting + PairingFailed states), targeted-waiting overlay + bestie-unavailable dialog, "Curhat lagi" CTA, failed-pairing terminal, extension via payment-session - mitra_app: PairingRequestType enum, returning-chat 20s countdown auto-dismiss, extension card "otomatis disetujui" copy - control_center: 4 new config rows in Settings, Failed Pairings page (filter + paginate + action menu), sidebar + route registered - Test infrastructure: Vitest backend (7/7 pass), Playwright CC (4/4 pass), Maestro mobile scaffold (CLI install pending) - Bugs found via Playwright + fixed: LoginPage labels not associated with inputs (a11y); backend internal CORS missing PATCH/PUT/DELETE in allow-methods (silent settings breakage in browsers since Stage 4) - Docs: phase3.7.md PRD, phase3.7-plan.md, phase3.7-questions.md (Q&A), phase3.7-testing.md (E2E checklist), phase3.7-test-run-2026-05-03.md (today's run results) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
14
client_app/.maestro/flows/01_smoke.yaml
Normal file
14
client_app/.maestro/flows/01_smoke.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
# Smoke test: launch the app and assert the home screen renders.
|
||||
# Use this flow first to verify Maestro can talk to your device/emulator at all.
|
||||
#
|
||||
# Run:
|
||||
# maestro test client_app/.maestro/flows/01_smoke.yaml
|
||||
#
|
||||
# Pre-req: client_app debug APK installed on the connected device, signed in as a customer.
|
||||
appId: ${APP_ID_ANDROID} # Maestro uses APP_ID_IOS automatically when running against an iOS device
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false # keep existing auth — set to true to test cold-start onboarding
|
||||
- assertVisible:
|
||||
text: "Mulai Curhat"
|
||||
timeout: 10000 # 10s — give Riverpod time to hydrate the home screen
|
||||
21
client_app/.maestro/flows/02_cta_disabled_when_no_mitra.yaml
Normal file
21
client_app/.maestro/flows/02_cta_disabled_when_no_mitra.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
# Verifies the home CTA is disabled and shows the "no bestie available" subtitle
|
||||
# when no mitra is online.
|
||||
#
|
||||
# Pre-req: NO mitras are online on the target backend. Use the helper script to
|
||||
# force everyone offline before running:
|
||||
# bash client_app/.maestro/scripts/force_all_mitras_offline.sh
|
||||
#
|
||||
# Run:
|
||||
# maestro test client_app/.maestro/flows/02_cta_disabled_when_no_mitra.yaml
|
||||
appId: ${APP_ID_ANDROID}
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
- assertVisible: "Mulai Curhat"
|
||||
- assertVisible: "Belum ada bestie tersedia"
|
||||
# CTA is disabled — tapping it should be a no-op.
|
||||
- tapOn: "Mulai Curhat"
|
||||
# We should still be on the home screen, NOT on the payment screen.
|
||||
- assertNotVisible: "Bayar"
|
||||
- assertNotVisible: "Mulai"
|
||||
- assertVisible: "Mulai Curhat"
|
||||
42
client_app/.maestro/flows/03_payment_to_chat_happy.yaml
Normal file
42
client_app/.maestro/flows/03_payment_to_chat_happy.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
# Happy-path golden flow: customer taps CTA → payment screen → confirm →
|
||||
# searching → mitra accepts (via curl harness) → chat screen.
|
||||
#
|
||||
# This is the canonical demonstration of the "single-emulator + curl-as-mitra"
|
||||
# pattern. The customer side is real Maestro; the mitra side is a backend API call
|
||||
# fired from a runScript step.
|
||||
#
|
||||
# Pre-req:
|
||||
# 1. At least one mitra is ONLINE on the target backend
|
||||
# 2. TEST_MITRA_ID and TEST_MITRA_JWT in .maestro/config.yaml point at that mitra
|
||||
# 3. The mitra has spare capacity (active_session_count < max_customers_per_mitra)
|
||||
#
|
||||
# Run:
|
||||
# maestro test client_app/.maestro/flows/03_payment_to_chat_happy.yaml
|
||||
appId: ${APP_ID_ANDROID}
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
- assertVisible: "Mulai Curhat"
|
||||
|
||||
# Step 1: customer taps CTA → payment screen
|
||||
- tapOn: "Mulai Curhat"
|
||||
- assertVisible:
|
||||
text: "Bayar|Mulai" # "Bayar" for paid tier, "Mulai" for free trial
|
||||
timeout: 5000
|
||||
|
||||
# Step 2: customer confirms payment → searching screen
|
||||
- tapOn:
|
||||
text: "Bayar|Mulai"
|
||||
- assertVisible:
|
||||
text: "Mencari Bestie"
|
||||
timeout: 5000
|
||||
|
||||
# Step 3: simulate mitra accepting via backend API (the "curl-as-mitra" trick).
|
||||
# This avoids needing a second emulator — the backend treats mitra interactions as
|
||||
# REST calls regardless of whether they originate from the mitra app or a script.
|
||||
- runScript: ../scripts/mitra_accept_latest.sh
|
||||
|
||||
# Step 4: customer screen transitions to "found" then chat
|
||||
- assertVisible:
|
||||
text: "Bestie Ditemukan"
|
||||
timeout: 10000 # blast→accept→WS round-trip takes a few seconds
|
||||
Reference in New Issue
Block a user