freshyo/e2e/README.md
2026-09-14 23:34:10 +05:30

125 lines
5.8 KiB
Markdown

# Maestro E2E — apps/user-ui (Android only)
Maestro flows that drive the **user-ui** app through placing an order:
home → product → add to cart (choose delivery slot) → cart → checkout
(address if needed, Cash on Delivery) → **Place Order** → confirmation.
Everything here targets **Android only** (`appId: in.freshyo.app`), and `run.sh`
always passes `--platform android` — it will never use an iOS simulator.
## Prerequisites
- Maestro CLI installed (`maestro --version`; installed here at `~/.maestro/bin/maestro`).
- A running **Android emulator/device** with the user-ui dev build installed:
```bash
cd apps/user-ui
npx expo run:android
```
- A **test account with a password set**. OTP login can't be automated (the OTP
is server-issued, no dev bypass). The flow reaches the login screen by tapping
**Checkout** as a guest — checkout is behind `useAuthenticatedRoute`, so the app
bounces there — then signs in via `other ways to login` → `Username` +
`Password` and returns to the cart. Alternatively, sign in once by hand and the
subflow becomes a no-op; `launchApp` uses `clearState: false` so the session and
the first-run onboarding survive.
- A catalog with at least one **in-stock product that has a future delivery slot**.
Note: in a dev build the "Open debugger to view warnings" toast overlays the bottom
of the screen and swallows taps on the bottom tab bar — the flows avoid the tab bar
and use `centerElement: true` where a control can land under it.
## Running
**Recommended — one command, values from a gitignored file.** Create `e2e/.env`
(see `.env.example`) and then, from the repo root:
```bash
bun run e2e # or: bash e2e/run.sh
```
`e2e/run.sh` sources `e2e/.env`, runs `maestro test e2e --platform android`, and
falls back to `~/.maestro/bin/maestro` when `maestro` isn't on `PATH`. Extra flags
pass through, and flow paths are relative to `e2e/`:
```bash
bash e2e/run.sh flows/place-order.yaml # one flow
bash e2e/run.sh --format junit # junit report
bash e2e/run.sh --device emulator-5554 # pick an emulator (needed if several are connected)
```
To see which emulators are available: `adb devices -l`.
### How values are supplied
Maestro resolves `${VAR}` from three places:
1. **`config.yaml` → `env:`** — committed, non-secret defaults shared by all flows
(`ADDRESS_NAME`, `ADDRESS_PHONE`, `ADDRESS_LINE1` live here).
2. **`e2e/.env`** (gitignored) — loaded by `run.sh`; put `TEST_IDENTIFIER` /
`TEST_PASSWORD` here so secrets stay out of git and off the command line.
3. **Shell / CLI** — `MAESTRO_`-prefixed env vars or `-e KEY=VALUE`, good for CI:
```bash
MAESTRO_TEST_IDENTIFIER=... MAESTRO_TEST_PASSWORD=... bash e2e/run.sh
# or
maestro test e2e -e TEST_IDENTIFIER=... -e TEST_PASSWORD=...
```
Need more than one setup (e.g. CI vs local)? Maestro supports alternate configs:
`maestro test --config e2e/ci-config.yaml e2e`.
Useful flags: `--include-tags`, `--format junit`, `--test-output-dir`.
Reports/screenshots land in `e2e/.maestro-output/`.
## Layout
```
e2e/
config.yaml # workspace config (flows, execution order, env defaults)
subflows/login.yaml # reusable login (runs only if the login screen is visible)
flows/smoke.yaml # app launches, home renders
flows/place-order.yaml # the order flow
```
## What place-order covers
1. Home → add a product from the card's cart icon → pick a delivery slot in the
"Select Delivery Slot" dialog → add to cart.
(The icon sits inside the card's touchable, so the tap can fall through to the
card; the flow then adds from the product detail page instead.)
2. Cart → checkout. A guest is bounced to login (checkout is behind
`useAuthenticatedRoute`), signs in, and the flow re-enters the cart.
3. Address (only when the account has none) → Cash on Delivery → **Place Order**.
4. **Home glimpse**: `Continue Shopping` returns home; the flow scrolls to the
`NextOrderGlimpse` card and captures it with `takeScreenshot`, so each run
leaves a picture of the upcoming-order card. Maestro writes it under
`~/.maestro/tests/<timestamp>/place-order/takeScreenshot/home-upcoming-order-glimpse.png`.
5. **Cancel**: taps the glimpse card (which routes to
`/(drawer)/(tabs)/me/my-orders/{id}`), scrolls to **Cancel Order**, fills the
reason, confirms, dismisses the success alert, and asserts the
**Cancellation Reason** panel renders.
## Notes
- **These flows place real orders** on whatever backend the app points at, and
then cancel the one they placed. Point the app at a non-production backend /
use a throwaway account.
- The product is chosen as **the first card** (`id: product-card`, `index: 0`).
If that item is out of stock or has no future slot, change the index or seed a
known product.
- The address step is conditional: it only runs when `No addresses found` is
visible, so an account with a saved address skips it.
- Payment defaults to **Cash on Delivery**, so the flow just asserts it's visible.
- Controls below the fold need `scrollUntilVisible`; the home glimpse sits below
**Our Stores**, and **Cancel Order** below the bill summary.
- `launchApp` uses `clearState: false`, so the session and (on the first run) the
onboarding survive. The trade-off is that the app resumes wherever the previous
run left it — the flow taps the **Home** tab (`optional: true`) to get back.
- Maestro taps can be eaten by a dismissing keyboard or the dev-warning toast, so
the flow waits for animations and retries the confirm tap once.
- Stable `testID` anchors used by the flows live in user-ui:
`product-card`, `add-to-cart-icon`, `slot-option`, `add-to-cart-confirm`,
`go-to-cart`, `checkout-button`, `address-name`, `address-phone`,
`address-line1`, `address-submit`, `place-order-button`, `cancel-reason`.