- 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
6.4 KiB
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; it is the desktop companion to the
Android doc in 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):
- connects a
StudioRemoteClientto an already running Makepad Studio instance at127.0.0.1:8001 - sends
ListBuilds, thenClearBuildfor any existing build of the same mount + package (so you get a fresh run tab) - sends a
Runfor the current package and waits forBuildStarted+AppStarted - 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
-
Build the Studio remote tool:
cargo build --release -p cargo-makepad -
Start Studio (it stays running for the whole interaction):
target/release/cargo-makepad studio --studio=127.0.0.1:8001Keep that process running in its own terminal.
-
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 — includingmakepad-example-counter— as a runnable item on themakepadmount.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-gluedep 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:
MAKEPAD_TEST_VISIBLE=1 cargo test --release -p makepad-example-counter --test ui -- --test-threads=1
Watchable run (slow, so each interaction is visible):
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:
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 getfailure.txt,failure-screenshot.png,widget-tree.txt, etc. undertarget/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=1for 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