# Browser QA checklist (AI agents)

Use this checklist when you **open the app in a browser**, **navigate**, **fill
fields**, or **judge UI** after editing Dart.

**Live reload (`r`/`R`) after coding:** see `docs/agent-guidance.md` and
`.cursor/rules/kasy-agent-contract.mdc` (apply when `kasy run` is active).

**Triggers for this checklist:** user asks to test in the browser, validate a
flow, or you will snapshot/screenshot to verify UI after a Dart edit.

## 1. App must be running

- Web: `kasy run --web` on port **5555** (`http://localhost:5555`).
- **Start it yourself** if it is not running and you need the browser (`kasy
  run --web` or MCP `run_app` with web).
- Do **not** start the app for coding tasks with no browser validation.

## 2. After Dart edits, before judging UI

Reloading the **browser tab** (F5, re-navigate) **does not** recompile Dart.

Update the build before snapshot, screenshot, or concluding a fix failed:

| Change | Command |
| --- | --- |
| Layout, colour, padding, text, icons, style | **`r`** hot reload |
| Provider, `initState`, routes, `main()`, wiring a rebuild won't pick up | **`R`** hot restart |
| `r` failed or Flutter asks for restart | **`R`** |

Prefer **`r`** for design tweaks. Do not default to **`R`** (slower, clears state).

**Terminal first:** if you have shell access, type **`r`** or **`R`** in the
terminal running `flutter run` / `kasy run` and **read the output**. If reload
fails, send **`R`**. Do not pretend you lack a terminal; ask the user if blocked.

Otherwise use the **device preview toolbar** `r`/`R` buttons (browser tools).

## 3. Open the app in your browser tool

Open `http://localhost:5555` (Simple Browser, Cursor browser, Playwright, …).

## 4. Browser tools ritual

1. Lock tab → accessibility **snapshot** → click/type by **ref** (named
   buttons/fields) → **screenshot** only at checkpoints (not every step).
2. Prefer controls by accessible **name** (button "Sign in", textbox "Email").
   Wrong or missing labels break automation.

## 5. Typing into fields

1. Read the accessible **name** from the snapshot (label or hint).
2. Prefer `window.__kasyBrowserQa.setTextIn('Label', 'value')` via CDP
   `Runtime.evaluate` (no focus race).
3. Fallback: click the textbox ref → wait ~300–800ms →
   `window.__kasyBrowserQa.setText('value')`.
4. Last resort: `browser_type` with `clear: true` and `slowly: true` after
   focus+wait.
5. Screenshot after filling multi-field forms before submitting.

## 6. Anti-patterns

- Mute canvas / "Enable accessibility": semantics off — hot **restart** after
  `main()` changes, then snapshot again.
- Do **not** rely on pixel coordinates as the primary strategy.
- Do **not** use `browser_fill` alone on Flutter fields (DOM mirror without
  Flutter controller).
- Do **not** type into `document.activeElement` by hand — use `setTextIn` /
  `setText`.
- **Scroll** with PageDown / PageUp (or drag), not HTML `scrollIntoView`.
- **Dropdown / date / time:** click the named **button** in the snapshot, not a
  textbox.

## 7. Suggested smoke

Admin → send push: audience All → `setTextIn` title + message → open target route
→ send → confirm toast / form reset.
