test(maestro): one mock daemon, not three #47

Merged
naps62-yolo merged 1 commits from lithuanians into main 2026-08-22 14:55:43 +01:00
Collaborator

Three answers to "how do I test against a daemon", and the CLI — the thinnest client — had none, so its formatting and error handling were exercised by compiling and forking the real binary plus tmux.

New crates/maestro-testing holds a MockDaemon that serves the real /api/* surface from maestro-protocol types, backed by a Vec<Session>. It replaces two ad-hoc stubs:

  • maestro-web/tests/proxy.rs returned [{"id": "session-1"}] — not even a valid Session, so the test could not have caught a wire-shape change
  • maestro-tui/tests/catalog_ws.rs was a scripted socket with a hardcoded timeline and a sleep(2s) to stop the client reconnecting

maestro-cli gets its first tests against a daemon — six cases, 10ms: reading the catalog, that DaemonInfo carries the version and presets its old private copy silently dropped, that a structured failure surfaces the daemon's own message, and that connection-refused stays distinguishable from an HTTP rejection.

maestro-web's proxy suite gains an end-to-end check I didn't expect to need. My first attempt asserted the upgrade fails for an unknown session; it doesn't — the proxy upgrades the client before dialing upstream, so a rejection has to arrive as a close code. The test now asserts the browser gets a 4502 close carrying the daemon's own message, which is the end-to-end counterpart to upstream_close_reason (unit-tested only until now).

maestro-e2e keeps the tmux-shaped tests and loses the rest:

  • cli_list_reads_from_daemon still runs the shipped binary as a subprocess — that's the point of it — but against MockDaemon rather than a real daemon and tmux
  • tui_integration.rs is deleted. Its three cases asserted that CatalogStore works against a real daemon; the real daemon's /api/events contract is now covered by maestro-daemon/tests/local_api.rs (added in #43) and the client reducer by catalog_ws.rs. Keeping them meant paying for tmux to test a reducer.

The e2e suite drops from ~32s to ~20s.

One thing I left alone: maestro-tui/tests/session_task_ws.rs still has its own stub. It needs a server that produces PTY bytes unprompted, and MockDaemon's attach endpoint echoes. Making it scriptable is a reasonable follow-up, not something to bolt on here.

Verification
cargo fmt --all -- --check                   ok
cargo clippy --all-targets -- -D warnings    0
cargo test --all                             308 passed, 0 failed

308 rather than 304: +6 CLI, +1 web, +1 tui, −4 from deleting tui_integration.rs.

Eighth of nine from the architecture review (#40–#46 merged).

Three answers to "how do I test against a daemon", and the CLI — the thinnest client — had none, so its formatting and error handling were exercised by compiling and forking the real binary *plus* tmux. New `crates/maestro-testing` holds a `MockDaemon` that serves the real `/api/*` surface from `maestro-protocol` types, backed by a `Vec<Session>`. It replaces two ad-hoc stubs: - `maestro-web/tests/proxy.rs` returned `[{"id": "session-1"}]` — not even a valid `Session`, so the test could not have caught a wire-shape change - `maestro-tui/tests/catalog_ws.rs` was a scripted socket with a hardcoded timeline and a `sleep(2s)` to stop the client reconnecting **`maestro-cli` gets its first tests against a daemon** — six cases, 10ms: reading the catalog, that `DaemonInfo` carries the `version` and `presets` its old private copy silently dropped, that a structured failure surfaces the daemon's own message, and that connection-refused stays distinguishable from an HTTP rejection. `maestro-web`'s proxy suite gains an end-to-end check I didn't expect to need. My first attempt asserted the upgrade fails for an unknown session; it doesn't — the proxy upgrades the client *before* dialing upstream, so a rejection has to arrive as a close code. The test now asserts the browser gets a 4502 close carrying the daemon's own message, which is the end-to-end counterpart to `upstream_close_reason` (unit-tested only until now). `maestro-e2e` keeps the tmux-shaped tests and loses the rest: - `cli_list_reads_from_daemon` still runs the shipped binary as a subprocess — that's the point of it — but against `MockDaemon` rather than a real daemon and tmux - `tui_integration.rs` is deleted. Its three cases asserted that `CatalogStore` works against a real daemon; the real daemon's `/api/events` contract is now covered by `maestro-daemon/tests/local_api.rs` (added in #43) and the client reducer by `catalog_ws.rs`. Keeping them meant paying for tmux to test a reducer. **The e2e suite drops from ~32s to ~20s.** One thing I left alone: `maestro-tui/tests/session_task_ws.rs` still has its own stub. It needs a server that *produces* PTY bytes unprompted, and `MockDaemon`'s attach endpoint echoes. Making it scriptable is a reasonable follow-up, not something to bolt on here. <details> <summary>Verification</summary> ``` cargo fmt --all -- --check ok cargo clippy --all-targets -- -D warnings 0 cargo test --all 308 passed, 0 failed ``` 308 rather than 304: +6 CLI, +1 web, +1 tui, −4 from deleting `tui_integration.rs`. </details> Eighth of nine from the architecture review (#40–#46 merged).
naps62-yolo added 1 commit 2026-08-22 14:51:50 +01:00
test(maestro): one mock daemon instead of three answers
ci / web (pull_request) Successful in 29s
ci / rust (pull_request) Successful in 3m17s
ci / web (push) Successful in 30s
ci / rust (push) Successful in 2m39s
30bd9d9042
There were three answers to "how do I test against a daemon", and the CLI
— the thinnest client — had none, so its formatting and error handling
were exercised by compiling and forking the real binary plus tmux.

Adds crates/maestro-testing with a MockDaemon that serves the real /api/*
surface from maestro-protocol types, backed by a Vec<Session>. It replaces
two ad-hoc stubs: maestro-web's, which returned [{"id":"session-1"}] —
not a valid Session — and maestro-tui's scripted socket with a hardcoded
timeline.

maestro-cli gets its first tests against a daemon: six cases covering the
catalog, that DaemonInfo carries the version and presets its old private
copy dropped, that a structured failure surfaces the daemon's own message,
and that connection-refused stays distinguishable from an HTTP rejection.

maestro-web's proxy suite gains an end-to-end check that an upstream
rejection reaches the browser as a 4502 close carrying the daemon's
message — upstream_close_reason had only unit tests.

e2e keeps the tmux-shaped tests. cli_list_reads_from_daemon still runs the
shipped binary as a subprocess but now against MockDaemon, and
tui_integration.rs is deleted: the real daemon's /api/events contract is
covered by maestro-daemon/tests/local_api.rs and the client reducer by
maestro-tui/tests/catalog_ws.rs. The e2e suite drops from ~32s to ~20s.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
naps62-yolo merged commit 30bd9d9042 into main 2026-08-22 14:55:43 +01:00
naps62-yolo deleted branch lithuanians 2026-08-22 14:55:43 +01:00
This repo is archived. You cannot comment on pull requests.