# client_app Maestro flows

End-to-end UI automation for the customer Flutter app using [Maestro](https://maestro.mobile.dev). Single-emulator + curl-as-mitra pattern — the customer app is driven by real Maestro touches; the mitra side is simulated via backend API calls fired from `runScript` steps.

## One-time install

Maestro is a global CLI (not a project dependency). Install on your dev machine once:

```bash
curl -Ls "https://get.maestro.mobile.dev" | bash
```

Verify with `maestro --version`. See the [Maestro install docs](https://maestro.mobile.dev/getting-started/installing-maestro) for Homebrew / chocolatey / Docker alternatives.

You also need:
- `adb` on your PATH (comes with Android Studio's platform-tools)
- `jq` for the helper scripts (`apt install jq` / `brew install jq`)
- One Android emulator OR one connected device — **only one at a time** (per project decision)

## Folder layout

```
.maestro/
├── README.md                 # this file
├── config.yaml               # shared env: app IDs, backend URL, test credentials
├── flows/                    # the YAML test scripts
│   ├── 01_smoke.yaml
│   ├── 02_cta_disabled_when_no_mitra.yaml
│   └── 03_payment_to_chat_happy.yaml
└── scripts/                  # bash helpers invoked by `runScript` steps
    ├── mitra_accept_latest.sh
    └── force_all_mitras_offline.sh
```

## Configure for your environment

Edit `.maestro/config.yaml` and fill in:
- `BACKEND_URL` — must match the `--dart-define=API_BASE_URL=...` value the installed APK was built with
- `TEST_MITRA_ID` and `TEST_MITRA_JWT` — used by the curl harness to "accept" requests from the customer's blast

The config file is committed because the values are dev-environment defaults. Sensitive credentials (real JWTs, CC operator tokens) should be passed at runtime instead — see "Per-machine overrides" below.

## Run a flow

Single emulator (typical case — Maestro auto-picks the only attached device):

```bash
# from repo root or anywhere
maestro test client_app/.maestro/flows/01_smoke.yaml

# or run all flows in the directory
maestro test client_app/.maestro/flows/
```

If both an emulator and a real device happen to be connected, list them and pick one explicitly:

```bash
adb devices                                       # list attached devices
maestro --device emulator-5554 test client_app/.maestro/flows/01_smoke.yaml
```

## Per-machine overrides

Override any config.yaml value at runtime with `--env`:

```bash
maestro test \
  --env BACKEND_URL=http://192.168.99.10:3000 \
  --env TEST_MITRA_JWT=eyJhbGc... \
  client_app/.maestro/flows/03_payment_to_chat_happy.yaml
```

Or export shell variables — `runScript` steps inherit them:

```bash
export CC_JWT=eyJhbGc...
maestro test client_app/.maestro/flows/02_cta_disabled_when_no_mitra.yaml
```

## Single-emulator + curl pattern

Phase 3.7 flows often need a customer + a mitra acting in concert. Instead of running two emulators (RAM-heavy, flaky), the flows drive the customer side with Maestro and **simulate the mitra via backend curl calls**:

1. Maestro flow drives customer up to the "Mencari Bestie..." state
2. `runScript: ../scripts/mitra_accept_latest.sh` fires `POST /api/mitra/chat-requests/:id/accept` against the backend, using a pre-minted mitra JWT
3. Maestro flow asserts the customer screen transitions to "Bestie Ditemukan" via the WS round-trip

This works for ~90% of multi-actor scenarios — including all the Section D ("Curhat lagi") and Section J ("Mitra goes offline mid-session") tests in [phase3.7-testing.md](../../requirement/phase3.7-testing.md). The 10% that needs both UIs running (e.g., asserting the mitra-side overlay countdown displays correctly) is in [`mitra_app/.maestro/`](../../mitra_app/.maestro/) and runs separately.

## Adding a new flow

Pick a Phase 3.7 testing checklist scenario (see [phase3.7-testing.md](../../requirement/phase3.7-testing.md)), then:

1. Copy an existing flow as a template (e.g., `03_payment_to_chat_happy.yaml`)
2. Update the pre-req comment, the steps, and the assertions
3. If you need a "second actor" action, add a bash helper under `scripts/` and call it via `runScript:`
4. If you need new env vars, add them to `config.yaml` with sensible defaults

## Tips

- **Find the right text to tap on** — `maestro studio` opens a live UI inspector showing every visible label/widget. Run it while the app is on the screen you care about.
- **Slow it down for debugging** — `maestro test --debug-output ./debug flows/foo.yaml` saves screenshots + logs per step.
- **Add flows incrementally** — Maestro's reload-on-save in `maestro studio` makes iteration fast.
- **Don't commit screenshots / debug output** — add `.maestro/output/` and `.maestro/screenshots/` to `.gitignore` if you generate them locally.

## Troubleshooting

- `maestro: device not found` → run `adb devices`; if empty, start an emulator (`emulator -avd <name>`) or plug in a USB device with debugging enabled.
- `Element not visible` errors → use `maestro studio` to inspect actual labels — they may have changed since the flow was written.
- Flow hangs at `assertVisible` waiting for backend → check `BACKEND_URL` matches the APK's build-time value (`grep API_BASE_URL build.gradle`).
- `runScript` exits non-zero → run the script directly to see its error: `bash client_app/.maestro/scripts/mitra_accept_latest.sh`. Most often a missing env var or stale JWT.
