Mobile E2E test author
Local-only Maestro suite for the Kata Code mobile app on the iOS Simulator. The TS
orchestrator owns server lifecycle, isolation, prereq gates, and artifacts; Maestro
YAML owns on-device interaction. Real services only — no mocks.
Current status (2026-06-25)
Verified green on-device (iPhone 17 Pro): @smoke, @pairing, @agent. Open:
@auth (the native NativeClerk.presentAuth modal is not yet driven by Maestro).
Full verified locators and the run inventory live in the
Maestro Studio authoring guide
and the E2E test catalog.
Durable learnings to reuse, not relearn:
clearState: false on launchApp keeps the saved Metro URL so the dev client
loads past the Expo Dev Launcher; pair extendedWaitUntil for Metro bundling and
real provider round-trips.
- Accessibility-id test contracts beat fragile text where the UI has no durable
label — e.g.
connection-status on ConnectionStatusDot, asserted as
connection-status-ready for the pairing ready-state.
- Subflows live in
maestro/shared/ (e.g. open-add-environment.yaml), composed
via runFlow. shared/ is excluded from flow discovery (SUBFLOW_DIRS in
cli/flows.ts) so subflows are never run standalone.
- Model-picker labels are display labels, not raw slugs.
flows/agent.ts derives
them (providerMenuLabel: openai→Codex, anthropic→Claude; modelMenuLabel:
gpt-5.4-mini→GPT-5.4-Mini) mirroring the server's toDisplayName. Keep in sync.
Before writing a flow
Read mobile-e2e/README.md and the design spec
(docs/specs/2026-06-24-mobile-e2e-testing-foundation-design.md).
Read Mobile E2E authoring (Maestro Studio) for the canonical Studio workflow.
Inspect existing flows under mobile-e2e/maestro/ and the TS building blocks in
mobile-e2e/src/harness/ and mobile-e2e/src/flows/.
Explore the live app with Maestro Studio first, then codify locators — do
not guess selectors from product code alone. Full workflow:
Mobile E2E authoring (Maestro Studio).
vp run e2e:mobile:studio # boots the sim, verifies the dev client, opens Studio
Architecture (do not fight this)
| Layer |
Role |
src/harness/ (TS) |
Generic: simulator control, server stack (serve + token + project add), isolated run, Maestro runner, artifacts, prereq gates |
src/flows/ (TS) |
Kata-specific: pairing inputs, Clerk Connect gate, agent expected-text + normalization |
maestro/**/*.yaml |
On-device UI — the only layer that references screen elements |
src/cli/run.ts |
Orchestrates a run: gate → isolate → sim → server → Maestro → manifest → cleanup |
The TS layer injects dynamic values (one-time token, expected agent text, model)
into flows as -e KEY=VALUE (${KEY} in YAML). Keep dynamic plumbing in TS; keep
flows declarative.
Rules
- Compose flows from the harness/flows building blocks — do not duplicate launch,
pairing, isolation, or server logic in YAML.
- Keep generic simulator/process/Maestro concerns in
src/harness/ and Kata UI/product
language in src/flows/ + maestro/.
- Do not mock services: no fake server/provider/Clerk, no HAR/route stubs.
- Store secrets and auth state only under ignored paths (
mobile-e2e/.auth/,
mobile-e2e/test-results/, mobile-e2e/artifacts/, local .env.local).
- Tag every flow with exactly one feature tag in its YAML header (
@smoke, @pairing,
@auth, @agent). New surfaces get new tags; register them in src/config/tags.ts.
- Fail loud with the missing prerequisite when tooling or credentials are absent —
never skip an assertion silently.
- Prefer durable accessible locators (text, label). Add a stable
accessibilityLabel
in product code only when no durable locator exists and it is a deliberate test
contract (e.g. a ConnectionStatusDot ready state).
- The suite drives an already-installed dev client. Do not rebuild per run; if the
app is missing the run fails loud with build instructions (
vp run e2e:mobile:build).
Credentials and deferred flows
@smoke and @pairing need no credentials (bearer loopback path).
@auth needs CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, KATACODE_E2E_GOOGLE_EMAIL.
Mobile sign-in is a native auth modal (NativeClerk.presentAuth); Maestro may
not be able to drive it. Its green runtime pass is a maintainer responsibility.
@agent needs KATACODE_E2E_AGENT_PROVIDER, KATACODE_E2E_AGENT_MODEL, and the
matching provider key. Select the model explicitly; the composer default is not
reliable for deterministic replies. Green runtime pass is a maintainer responsibility.
Verification commands
vp run e2e:mobile --list # list flows + tags
vp run e2e:mobile --include-tags @smoke # smoke launch
vp run e2e:mobile --include-tags @pairing # bearer pairing
vp run e2e:mobile:studio # explore / author locators
vp test run mobile-e2e/src # harness + flow unit tests
vp check mobile-e2e # format + lint
Suggested rollout order: @smoke → @pairing → @auth → @agent, one at a time in
Studio, giving the maintainer the exact verify command after each passes.
1---2name: mobile-e2e-test-author3description: Author local Maestro iOS-Simulator E2E flows for the Kata Code mobile app using the reusable TS orchestrator and Kata-specific flows. Use when adding or updating flows under mobile-e2e/.4---56# Mobile E2E test author78Local-only Maestro suite for the Kata Code mobile app on the iOS Simulator. The TS9orchestrator owns server lifecycle, isolation, prereq gates, and artifacts; Maestro10YAML owns on-device interaction. Real services only — no mocks.1112## Current status (2026-06-25)1314Verified green on-device (iPhone 17 Pro): `@smoke`, `@pairing`, `@agent`. Open:15`@auth` (the native `NativeClerk.presentAuth` modal is not yet driven by Maestro).16Full verified locators and the run inventory live in the17[Maestro Studio authoring guide](../../../docs/guides/e2e-mobile-authoring-maestro-studio.md)18and the [E2E test catalog](../../../docs/guides/e2e-test-catalog.md).1920Durable learnings to reuse, not relearn:2122- **`clearState: false`** on `launchApp` keeps the saved Metro URL so the dev client23 loads past the Expo Dev Launcher; pair `extendedWaitUntil` for Metro bundling and24 real provider round-trips.25- **Accessibility-id test contracts** beat fragile text where the UI has no durable26 label — e.g. `connection-status` on `ConnectionStatusDot`, asserted as27 `connection-status-ready` for the pairing ready-state.28- **Subflows** live in `maestro/shared/` (e.g. `open-add-environment.yaml`), composed29 via `runFlow`. `shared/` is excluded from flow discovery (`SUBFLOW_DIRS` in30 `cli/flows.ts`) so subflows are never run standalone.31- **Model-picker labels are display labels, not raw slugs.** `flows/agent.ts` derives32 them (`providerMenuLabel`: `openai`→`Codex`, `anthropic`→`Claude`; `modelMenuLabel`:33 `gpt-5.4-mini`→`GPT-5.4-Mini`) mirroring the server's `toDisplayName`. Keep in sync.3435## Before writing a flow36371. Read [mobile-e2e/README.md](../../../mobile-e2e/README.md) and the design spec38 (`docs/specs/2026-06-24-mobile-e2e-testing-foundation-design.md`).392. Read [Mobile E2E authoring (Maestro Studio)](../../../docs/guides/e2e-mobile-authoring-maestro-studio.md) for the canonical Studio workflow.403. Inspect existing flows under `mobile-e2e/maestro/` and the TS building blocks in41 `mobile-e2e/src/harness/` and `mobile-e2e/src/flows/`.424. **Explore the live app with Maestro Studio first**, then codify locators — do43 not guess selectors from product code alone. Full workflow:44 [Mobile E2E authoring (Maestro Studio)](../../../docs/guides/e2e-mobile-authoring-maestro-studio.md).4546 ```bash47 vp run e2e:mobile:studio # boots the sim, verifies the dev client, opens Studio48 ```4950## Architecture (do not fight this)5152| Layer | Role |53| ------------------- | ----------------------------------------------------------------------------------------------------------------------------- |54| `src/harness/` (TS) | Generic: simulator control, server stack (serve + token + project add), isolated run, Maestro runner, artifacts, prereq gates |55| `src/flows/` (TS) | Kata-specific: pairing inputs, Clerk Connect gate, agent expected-text + normalization |56| `maestro/**/*.yaml` | On-device UI — the only layer that references screen elements |57| `src/cli/run.ts` | Orchestrates a run: gate → isolate → sim → server → Maestro → manifest → cleanup |5859The TS layer injects dynamic values (one-time token, expected agent text, model)60into flows as `-e KEY=VALUE` (`${KEY}` in YAML). Keep dynamic plumbing in TS; keep61flows declarative.6263## Rules6465- Compose flows from the harness/flows building blocks — do not duplicate launch,66 pairing, isolation, or server logic in YAML.67- Keep generic simulator/process/Maestro concerns in `src/harness/` and Kata UI/product68 language in `src/flows/` + `maestro/`.69- Do **not** mock services: no fake server/provider/Clerk, no HAR/route stubs.70- Store secrets and auth state only under ignored paths (`mobile-e2e/.auth/`,71 `mobile-e2e/test-results/`, `mobile-e2e/artifacts/`, local `.env.local`).72- Tag every flow with exactly one feature tag in its YAML header (`@smoke`, `@pairing`,73 `@auth`, `@agent`). New surfaces get new tags; register them in `src/config/tags.ts`.74- Fail loud with the missing prerequisite when tooling or credentials are absent —75 never skip an assertion silently.76- Prefer durable accessible locators (text, label). Add a stable `accessibilityLabel`77 in product code only when no durable locator exists and it is a deliberate test78 contract (e.g. a `ConnectionStatusDot` ready state).79- The suite drives an **already-installed** dev client. Do not rebuild per run; if the80 app is missing the run fails loud with build instructions (`vp run e2e:mobile:build`).8182## Credentials and deferred flows8384- `@smoke` and `@pairing` need no credentials (bearer loopback path).85- `@auth` needs `CLERK_PUBLISHABLE_KEY`, `CLERK_SECRET_KEY`, `KATACODE_E2E_GOOGLE_EMAIL`.86 Mobile sign-in is a **native auth modal** (`NativeClerk.presentAuth`); Maestro may87 not be able to drive it. Its green runtime pass is a maintainer responsibility.88- `@agent` needs `KATACODE_E2E_AGENT_PROVIDER`, `KATACODE_E2E_AGENT_MODEL`, and the89 matching provider key. Select the model explicitly; the composer default is not90 reliable for deterministic replies. Green runtime pass is a maintainer responsibility.9192## Verification commands9394```bash95vp run e2e:mobile --list # list flows + tags96vp run e2e:mobile --include-tags @smoke # smoke launch97vp run e2e:mobile --include-tags @pairing # bearer pairing98vp run e2e:mobile:studio # explore / author locators99vp test run mobile-e2e/src # harness + flow unit tests100vp check mobile-e2e # format + lint101```102103Suggested rollout order: `@smoke` → `@pairing` → `@auth` → `@agent`, one at a time in104Studio, giving the maintainer the exact verify command after each passes.