makepad/libs/makepad_test/DESKTOP_VISIBLE.md
andodeki 477421e314 nigig: NIGIG test-mode forwarding, custom manifest hook, ortho camera support
- makepad_test/runtime.rs: forward NIGIG_TEST_MODE from host env to the
  Android app via 'am start' intent extra; add wait_timeout (60s) used by
  wait_visible/wait_hidden/wait_count; make query_widgets tolerant of
  snapshot timeouts; grant READ_CONTACTS during adb setup
- makepad-platform android_jni.rs: read makepad.NIGIG_TEST_MODE intent
  extra and surface it as the NIGIG_TEST_MODE env var via apply_studio_env
- cargo_makepad compile.rs: support verbatim custom AndroidManifest.xml in
  addition to the templated variant
- makepad-xr xr_root.rs: add ortho camera controls (ortho, ortho_height,
  min/max), derive Debug on XrCamera
- docs: ANDROID.md and DESKTOP_VISIBLE.md for makepad_test
2026-09-03 10:55:00 +03:00

149 lines
6.4 KiB
Markdown

# makepad_test on Desktop (Visible Studio Mode)
How to run the same `makepad_test` UI tests in **visible** mode, where the
app opens a real window on your desktop and you can watch every UI response
as the test drives it. This is the opposite of the default headless mode
documented in [GUIDE.md](./GUIDE.md); it is the desktop companion to the
Android doc in [ANDROID.md](./ANDROID.md).
## What this mode is for
- you want to *see* the app react to the test (clicks, typing, widget state)
- you want to debug a flaky interaction by watching it happen in real time
- you want to inspect screenshots / widget dumps as the test progresses
The test body is identical to headless mode — same `TestApp`, `Locator`,
`Selector`, `screenshot()`, and `widget_dump()` APIs. Only the launch
transport changes.
## How it works
When `MAKEPAD_TEST_VISIBLE=1` is set, the runtime (`start_visible_app` in
`libs/makepad_test/src/runtime.rs`):
1. connects a `StudioRemoteClient` to an **already running** Makepad Studio
instance at `127.0.0.1:8001`
2. sends `ListBuilds`, then `ClearBuild` for any existing build of the same
mount + package (so you get a fresh run tab)
3. sends a `Run` for the current package and waits for `BuildStarted` +
`AppStarted`
4. drives the test over the Studio protocol — the app runs with a real,
visible window, and clicks / typing / screenshots / widget dumps go
through Studio
No in-process hub is used here: the hub is the real Studio desktop process,
which mounts its working directory as `makepad`. The test just talks to it
like any Studio remote bridge client.
## Prerequisites
1. Build the Studio remote tool:
```bash
cargo build --release -p cargo-makepad
```
2. Start Studio (it stays running for the whole interaction):
```bash
target/release/cargo-makepad studio --studio=127.0.0.1:8001
```
Keep that process running in its own terminal.
3. **Launch Studio from the makepad repo root.** Studio mounts its current
working directory as the default mount named `makepad`
(`studio/desktop/src/app_backend.rs`), so starting it from the makepad repo
exposes every workspace package — including `makepad-example-counter` — as
a runnable item on the `makepad` mount.
The makepad repo is fully self-contained: the nigig-org parent workspace
excludes `makepad-native-glue/makepad`, and no crate in the makepad
workspace references an out-of-repo path (the counter example's old
`../../../makepad-native-glue` dep was dropped). So **nigig-org is not
mounted and not required** — Studio just needs the makepad repo as its
working directory.
If your Studio session uses a different mount name, set
`MAKEPAD_TEST_STUDIO_MOUNT`.
## Environment variables
| Variable | Purpose | Default |
|----------|---------|---------|
| `MAKEPAD_TEST_VISIBLE` | enable visible mode (truthy: `1` / `true` / `yes` / `on`) | unset (headless) |
| `MAKEPAD_TEST_STUDIO` | Studio remote address | `127.0.0.1:8001` |
| `MAKEPAD_TEST_STUDIO_MOUNT` | Studio mount name of the app | `makepad` |
| `MAKEPAD_TEST_STARTUP_DELAY_MS` | pause after the app appears before the test starts | `0` |
| `MAKEPAD_TEST_ACTION_DELAY_MS` | pause after each interaction (click/type) so you can watch it | `0` |
| `MAKEPAD_TEST_KEEP_OPEN_MS` | keep the app open this long before the test shuts it down | `0` |
The delay variables are the key to "seeing the responses": with a large
`ACTION_DELAY_MS` the test walks through the UI slowly and you can follow
every step.
## Running
Basic visible run:
```bash
MAKEPAD_TEST_VISIBLE=1 cargo test --release -p makepad-example-counter --test ui -- --test-threads=1
```
Watchable run (slow, so each interaction is visible):
```bash
MAKEPAD_TEST_VISIBLE=1 \
MAKEPAD_TEST_STARTUP_DELAY_MS=1000 \
MAKEPAD_TEST_ACTION_DELAY_MS=750 \
MAKEPAD_TEST_KEEP_OPEN_MS=3000 \
cargo test --release -p makepad-example-counter --test ui -- --test-threads=1
```
If Studio is not on `8001` (or you started it on `8002`), point the test at
it:
```bash
MAKEPAD_TEST_VISIBLE=1 MAKEPAD_TEST_STUDIO=127.0.0.1:8002 \
cargo test --release -p makepad-example-counter --test ui -- --test-threads=1
```
`--test-threads=1` is required: the suite is serial and each test takes over
the visible app session.
## What you see
- the app opens in a normal desktop window (not a Studio overlay — the real
app process)
- each click, key press, and text entry happens in that window, paced by
`MAKEPAD_TEST_ACTION_DELAY_MS`
- Studio shows the run in its runview/log tab (BuildStarted / AppStarted /
BuildStopped, query results)
- `screenshot()` / `widget_dump()` / `widget_snapshot()` results still work
and are written to the failure-artifact dir; on a failing test you get
`failure.txt`, `failure-screenshot.png`, `widget-tree.txt`, etc. under
`target/makepad_test/<package>/<test>/`
## Notes
- Studio must already be running before the test starts; the test does not
spawn Studio.
- Older builds of the same package are cleared first, so the app you watch is
always the fresh run the test launched.
- Visible mode uses the normal Studio launch path, so it does **not** use the
direct-stdio script that headless mode uses — the app is connected through
Studio's websocket gateway and windowed normally.
- You can combine this with `MAKEPAD_STUDIO_HUB_DEBUG=1` for protocol-level
diagnostics (only meaningful for the in-process/hub side; in visible mode
the interesting debug output is in Studio itself).
## Troubleshooting
| Symptom | Likely cause / fix |
|---------|--------------------|
| connection refused / no response from Studio | Studio is not running; start `cargo-makepad studio --studio=127.0.0.1:8001` first |
| `request errors with no active websocket` | the app was not connected yet; wait for startup, retry the query |
| app launches but the test times out waiting for `AppStarted` | wrong mount name or Studio started from the wrong directory; launch Studio from the makepad repo root, or set `MAKEPAD_TEST_STUDIO_MOUNT` |
| wrong Studio instance | set `MAKEPAD_TEST_STUDIO` to the correct `ip:port` (use `8002` if Studio reported `8001` occupied) |
| test passes headless but fails visibly | visible runs go through Studio's build/run path (different target dir / fingerprint state); verify with `MAKEPAD_STUDIO_HUB_DEBUG=1` and check the Studio runview log tab |
## Current limitations
- requires a manually started Studio instance
- one visible app session per test (serial suite)
- no visual diffing; screenshot/artifact inspection is manual