--- name: flow-testing description: >- Boot both sides of Balinyaar locally and walk a real user journey end to end — the right seeded account, the right flow doc, and knowing whether you just proved the real path or a mock answering. Use before claiming a fix or feature works, or when asked to test, verify, or demo a flow. --- # Balinyaar Flow Testing Exercising a flow proves something only if you know which half of the stack actually answered. This is the procedure; the facts it points at (ports, accounts, known failure modes) live in [docs/flows/testing-setup.md](../../../docs/flows/testing-setup.md) and are kept current there — don't copy them here, they will drift. --- ## 1. Boot it The five-minute path, verbatim from [testing-setup.md](../../../docs/flows/testing-setup.md#the-five-minute-path): ```bash # API — mock SMS or request_otp 500s cd server Seams__Sms__Provider=mock dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj # client cd client && npm install && npm run dev # http://localhost:3000/fa # read the OTP — the console does NOT print it curl http://localhost:5002/api/v1/dev/last_otp/09120000010 ``` No database setup: the committed dev config points at an already-seeded remote SQL Server. If anything here doesn't match reality when you run it, **testing-setup.md is wrong and needs a fix in the same change** — it carries a `Last verified` stamp for exactly this reason. --- ## 2. Check the mock-vs-real map *before* you conclude anything A flow "working" through a mocked domain proves the UI, not the server. Before testing: 1. Open [docs/integration/domains/index.md](../../../docs/integration/domains/index.md) — the census table names which of the 22 client `services/` domains are real vs **mock** (currently 15 real, 7 mock: `admin`, `bnpl`, `partnerCenter`, `patientRecords`, `payouts`, `refunds`, `verification`). 2. A mocked domain is a `USE__MOCK` flag in `client/src/services//constants.ts` — check it directly if you need certainty for the exact domain you're touching. 3. State your finding in terms of which one you exercised: "the booking flow works end-to-end against the real server" is a different claim from "the admin console renders correctly against its mock" — never report the second as if it were the first. --- ## 3. Pick the right seeded account Demo accounts, their roles, and what each one demonstrates are tabulated in [testing-setup.md](../../../docs/flows/testing-setup.md#demo-accounts) — read it there rather than assuming a phone number. One standing gap to route around: **the seeded admin accounts (`…020` `super_admin`, `…021` `finance`) get 403 on every real admin endpoint** (a `DynamicPermission` / role-literal mismatch). The admin backoffice is only testable against the client's mock; don't spend time trying to walk it against the real API without first checking whether that gap has been closed. --- ## 4. Walk the flow [docs/flows/index.md](../../../docs/flows/index.md) is the atlas — one file per user-meaningful journey, each answering exactly three questions: what it does, what's mocked *for that journey specifically*, and how to test it. Open the one file that matches what you're testing rather than guessing the steps; it's the one place gap numbers and REQ references for that journey are tracked. --- ## 5. Two things that will silently invalidate your test - **The scheduler is live while you test.** `booking_request_expiry` runs every 60 seconds (hardcoded) and flips an un-actioned request to `expired_no_response` / `payment_deadline_expired` out from under you. Act on a request promptly, or create a fresh one rather than trying to reuse an old test artifact. - **The OTP endpoints are rate-limited together.** `request_otp` and `verify_otp` share one bucket, 5 calls per 60 s per IP — a login is 2 calls, so that's **two logins per minute, total**. Space scripted logins ≥ 40 s apart (see [testing-setup.md](../../../docs/flows/testing-setup.md#scripting-logins) for a working script) or you'll 429 and misread it as a bug. --- ## 6. When the seeded world has aged out There is no in-app reseed — both seeders guard on natural keys, so re-running never refreshes stale dates. If the scenario you need (an "upcoming" booking, an open dispute window, a pending request) no longer exists because the world was seeded days ago: - **Fastest fix:** create the scenario fresh yourself (customer → search → booking request → accept → pay) — this is the intended way to exercise booking-request and checkout-and-payment anyway. - **Full reseed:** only against a **local** database — `docker compose down -v && docker compose up -d` under `server/`, then boot. **Never drop the shared remote database** casually; it backs the live demo deployment and other people's sessions. --- ## 7. Report what you actually saw Name the account you used, the domain's mock/real status, and the exact response (status code, error message) rather than "it worked" — the troubleshooting table in [testing-setup.md](../../../docs/flows/testing-setup.md#troubleshooting) exists because several failure modes here look identical to an unrelated bug (a rate limit looks like a crash; `/healthz/ready` failing on Windows looks like the app is down). Check it before filing something as a new defect.