This repository has been archived on 2026-10-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
maestro/crates/maestro/tests/cli.rs
T

120 lines
3.7 KiB
Rust

//! Smoke tests for the umbrella `maestro` binary's dispatch surface (NAP-271).
//!
//! These run against the real built binary via Cargo's `CARGO_BIN_EXE_maestro`
//! env var. Integration tests are compiled with the package's active feature
//! set, so the per-subcommand checks are `#[cfg]`-gated and the suite is
//! meaningful under every feature subset (`cli` / `daemon` / `tui`)
//! as well as the default all-features build. The asserts only inspect
//! `--help`/`--version` output and exit codes, so nothing is actually started.
use std::process::Command;
fn maestro() -> Command {
Command::new(env!("CARGO_BIN_EXE_maestro"))
}
fn run(args: &[&str]) -> (bool, String) {
let out = maestro().args(args).output().expect("run maestro");
let combined = format!(
"{}{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
(out.status.success(), combined)
}
/// Subcommands expected in `--help`, derived from the active feature set.
fn expected_subcommands() -> Vec<&'static str> {
let mut subs: Vec<&'static str> = Vec::new();
#[cfg(feature = "cli")]
subs.extend(["list", "spawn", "attach", "kill"]);
#[cfg(feature = "daemon")]
subs.extend(["daemon"]);
#[cfg(feature = "tui")]
subs.extend(["tui"]);
subs
}
#[test]
fn top_level_help_lists_subcommands() {
let (ok, text) = run(&["--help"]);
assert!(ok, "--help should exit 0:\n{text}");
for sub in expected_subcommands() {
assert!(
text.contains(sub),
"--help missing subcommand `{sub}`:\n{text}"
);
}
}
#[test]
fn version_flag_succeeds() {
let (ok, text) = run(&["--version"]);
assert!(ok, "--version should exit 0:\n{text}");
assert!(text.contains("maestro"), "--version output: {text}");
}
/// A bare `maestro` must never fall back to help on a build that has a TUI:
/// the missing subcommand defaults to `tui` (#119). Point at a port with
/// nothing listening so the TUI's health probe fails fast instead of blocking
/// on a terminal.
#[cfg(feature = "tui")]
#[test]
fn bare_invocation_dispatches_to_the_tui() {
let (ok, text) = run(&["--daemon-url", "http://127.0.0.1:9"]);
assert!(
!ok,
"TUI against a dead daemon should exit non-zero:\n{text}"
);
assert!(
text.contains("daemon unreachable"),
"bare invocation should have run the TUI's daemon probe:\n{text}"
);
assert!(
!text.contains("Usage"),
"bare invocation must not print help when a TUI exists:\n{text}"
);
}
/// Builds without the `tui` feature keep the historical behaviour: no args =>
/// help, exit 0 (#119).
#[cfg(not(feature = "tui"))]
#[test]
fn bare_invocation_prints_help_and_exits_zero() {
let (ok, text) = run(&[]);
assert!(ok, "bare invocation should exit 0:\n{text}");
assert!(text.contains("Usage"), "expected usage text:\n{text}");
}
#[test]
fn unknown_subcommand_fails() {
let (ok, text) = run(&["definitely-not-a-subcommand"]);
assert!(!ok, "unknown subcommand should fail:\n{text}");
}
#[cfg(feature = "cli")]
#[test]
fn cli_subcommand_help_works() {
// A representative CLI subcommand resolves and renders help.
let (ok, text) = run(&["spawn", "--help"]);
assert!(ok, "spawn --help should exit 0:\n{text}");
assert!(
text.contains("--daemon-url"),
"spawn help missing flags:\n{text}"
);
}
#[cfg(feature = "daemon")]
#[test]
fn daemon_subcommand_help_works() {
let (ok, text) = run(&["daemon", "--help"]);
assert!(ok, "daemon --help should exit 0:\n{text}");
}
#[cfg(feature = "tui")]
#[test]
fn tui_subcommand_help_works() {
let (ok, text) = run(&["tui", "--help"]);
assert!(ok, "tui --help should exit 0:\n{text}");
}