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).
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>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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-testingholds aMockDaemonthat serves the real/api/*surface frommaestro-protocoltypes, backed by aVec<Session>. It replaces two ad-hoc stubs:maestro-web/tests/proxy.rsreturned[{"id": "session-1"}]— not even a validSession, so the test could not have caught a wire-shape changemaestro-tui/tests/catalog_ws.rswas a scripted socket with a hardcoded timeline and asleep(2s)to stop the client reconnectingmaestro-cligets its first tests against a daemon — six cases, 10ms: reading the catalog, thatDaemonInfocarries theversionandpresetsits 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 toupstream_close_reason(unit-tested only until now).maestro-e2ekeeps the tmux-shaped tests and loses the rest:cli_list_reads_from_daemonstill runs the shipped binary as a subprocess — that's the point of it — but againstMockDaemonrather than a real daemon and tmuxtui_integration.rsis deleted. Its three cases asserted thatCatalogStoreworks against a real daemon; the real daemon's/api/eventscontract is now covered bymaestro-daemon/tests/local_api.rs(added in #43) and the client reducer bycatalog_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.rsstill has its own stub. It needs a server that produces PTY bytes unprompted, andMockDaemon's attach endpoint echoes. Making it scriptable is a reasonable follow-up, not something to bolt on here.Verification
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).
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>