- 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
149 lines
6.4 KiB
Markdown
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
|