use std::io::Write;
use std::process::{Command, Stdio};
use tempfile::TempDir;
fn initialized_project() -> TempDir {
let dir = TempDir::new().unwrap();
std::fs::create_dir(dir.path().join("src")).unwrap();
std::fs::write(dir.path().join("src/lib.rs"), "pub fn hello() {}\n").unwrap();
let status = Command::new(env!("CARGO_BIN_EXE_tokensave"))
.arg("init")
.arg(dir.path())
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.expect("failed to spawn tokensave init");
assert!(status.success(), "init must succeed to set up the fixture");
dir
}
fn run_bare(dir: &std::path::Path, stdin_data: &str) -> (String, String) {
let mut child = Command::new(env!("CARGO_BIN_EXE_tokensave"))
.current_dir(dir)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("failed to spawn tokensave");
child
.stdin
.take()
.expect("stdin piped")
.write_all(stdin_data.as_bytes())
.expect("failed to write stdin");
let output = child
.wait_with_output()
.expect("failed to wait for tokensave");
(
String::from_utf8_lossy(&output.stdout).into_owned(),
String::from_utf8_lossy(&output.stderr).into_owned(),
)
}
#[test]
fn bare_invocation_in_initialized_project_keeps_stdout_empty() {
let dir = initialized_project();
let (stdout, stderr) = run_bare(dir.path(), "{\"tool\":\"Bash\"}\n");
assert!(
stdout.is_empty(),
"bare invocation must write nothing to stdout so hooks can parse it as JSON, got: {stdout:?}"
);
assert!(
stderr.contains("Usage"),
"help should be rendered to stderr instead: {stderr:?}"
);
}
#[test]
fn bare_invocation_uninitialized_with_piped_stdin_does_not_prompt_or_init() {
let dir = TempDir::new().unwrap();
std::fs::create_dir(dir.path().join("src")).unwrap();
std::fs::write(dir.path().join("src/lib.rs"), "pub fn hello() {}\n").unwrap();
let (stdout, stderr) = run_bare(dir.path(), "y\n");
assert!(
stdout.is_empty(),
"bare invocation must write nothing to stdout, got: {stdout:?}"
);
assert!(
!stderr.contains("Create one now?"),
"a non-interactive bare invocation must not prompt: {stderr:?}"
);
assert!(
!dir.path().join(".tokensave").exists(),
"the piped 'y' must not be taken as consent to initialize"
);
}