# 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///` ## 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