use assert_cmd::Command;
use std::fs;
use std::path::Path;
type TestResult = Result<(), Box<dyn std::error::Error>>;
const MANIFEST: &str = r#"
version = 1
canonical = "json-schema-2020-12"
authoring = "zod"
[[contracts]]
name = "user"
source = "contracts/user.zod.ts"
emit = ["zod"]
[[mappings]]
glob = "app/api/**/*.ts"
contracts = ["user"]
require = "boundary-validation"
[gates]
protected_paths = ["pushkin.toml"]
"#;
const FOREIGN_LEFTHOOK: &str = "pre-commit:\n \
parallel: true\n \
commands:\n \
ruff:\n \
glob: \"*.py\"\n \
run: uv run ruff check {staged_files}\n";
const FLOOR: &str = "lefthook.yml";
fn repo() -> Result<tempfile::TempDir, Box<dyn std::error::Error>> {
let dir = tempfile::tempdir()?;
fs::write(dir.path().join("pushkin.toml"), MANIFEST)?;
Ok(dir)
}
fn run(dir: &Path, args: &[&str]) -> Result<(Option<i32>, String), Box<dyn std::error::Error>> {
let output = Command::cargo_bin("pushkin")?
.current_dir(dir)
.args(args)
.output()?;
Ok((
output.status.code(),
format!(
"{}{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
),
))
}
fn read_floor(dir: &Path) -> Result<String, Box<dyn std::error::Error>> {
Ok(fs::read_to_string(dir.join(FLOOR))?)
}
const STALE_V1_FLOOR: &str = "# GENERATED by pushkin init — do not hand-edit. marker: pushkin-v1\n\
pre-commit:\n commands:\n pushkin:\n \
run: echo '{\"stop_hook_active\":false}' | /Users/someone/target/release/pushkin check\n";
#[test]
fn fresh_repo_gets_the_spec_command_with_no_absolute_path() -> TestResult {
let dir = repo()?;
let (code, _) = run(dir.path(), &["init", "--agent", "lefthook"])?;
assert_eq!(code, Some(0));
let content = read_floor(dir.path())?;
assert!(
content.contains("pushkin check --staged --json"),
"spec §17 command emitted verbatim: {content}"
);
assert!(
!content.contains('/'),
"no absolute path may be baked into the generated floor: {content}"
);
assert!(
!content.contains("stop_hook_active"),
"the echo'd Stop payload pattern is retired: {content}"
);
Ok(())
}
#[test]
fn generated_floor_carries_the_v3_marker() -> TestResult {
let dir = repo()?;
run(dir.path(), &["init", "--agent", "lefthook"])?;
let content = read_floor(dir.path())?;
assert!(
content.contains("pushkin-v3"),
"marker bumped so the v2 (pre-guard) format is detectable: {content}"
);
Ok(())
}
#[test]
fn existing_foreign_config_is_preserved_and_pushkin_block_added() -> TestResult {
let dir = repo()?;
fs::write(dir.path().join(FLOOR), FOREIGN_LEFTHOOK)?;
let (code, _) = run(dir.path(), &["init", "--agent", "lefthook"])?;
assert_eq!(code, Some(0));
let content = read_floor(dir.path())?;
assert!(
content.contains("ruff:") && content.contains("uv run ruff check"),
"the foreign ruff command must survive install: {content}"
);
assert!(
content.contains("parallel: true"),
"foreign keys are untouched: {content}"
);
assert!(
content.contains("pushkin check --staged --json"),
"the pushkin block is added alongside: {content}"
);
Ok(())
}
#[test]
fn reinstall_is_idempotent_and_replaces_only_our_block() -> TestResult {
let dir = repo()?;
fs::write(dir.path().join(FLOOR), FOREIGN_LEFTHOOK)?;
run(dir.path(), &["init", "--agent", "lefthook"])?;
let first = read_floor(dir.path())?;
run(dir.path(), &["init", "--agent", "lefthook"])?;
let second = read_floor(dir.path())?;
assert_eq!(
first, second,
"re-running init must be a no-op on an already-current floor"
);
assert_eq!(
second.matches("pushkin check --staged --json").count(),
1,
"our command appears exactly once — no stacking: {second}"
);
assert!(
second.contains("uv run ruff check"),
"the foreign command survives re-run too: {second}"
);
Ok(())
}
#[test]
fn a_stale_v1_block_is_replaced_not_duplicated() -> TestResult {
let dir = repo()?;
fs::write(dir.path().join(FLOOR), STALE_V1_FLOOR)?;
run(dir.path(), &["init", "--agent", "lefthook"])?;
let content = read_floor(dir.path())?;
assert!(
!content.contains("/Users/someone"),
"the stale absolute path must be gone: {content}"
);
assert!(
!content.contains("stop_hook_active"),
"the stale Stop payload must be gone: {content}"
);
assert!(
content.contains("pushkin check --staged --json"),
"replaced by the spec command: {content}"
);
Ok(())
}
#[test]
fn remove_agent_strips_our_block_and_keeps_foreign_commands() -> TestResult {
let dir = repo()?;
fs::write(dir.path().join(FLOOR), FOREIGN_LEFTHOOK)?;
run(dir.path(), &["init", "--agent", "lefthook"])?;
let (code, _) = run(dir.path(), &["init", "--remove-agent", "lefthook"])?;
assert_eq!(code, Some(0));
let content = read_floor(dir.path())?;
assert!(
content.contains("uv run ruff check"),
"uninstall must not take the team's hooks with it: {content}"
);
assert!(
!content.contains("pushkin check --staged --json"),
"our command is gone: {content}"
);
Ok(())
}
#[test]
fn remove_agent_deletes_a_file_that_is_only_ours() -> TestResult {
let dir = repo()?;
run(dir.path(), &["init", "--agent", "lefthook"])?;
run(dir.path(), &["init", "--remove-agent", "lefthook"])?;
assert!(
!dir.path().join(FLOOR).exists(),
"a purely generated floor is removed entirely"
);
Ok(())
}
#[test]
fn doctor_flags_a_stale_v1_floor() -> TestResult {
let dir = repo()?;
fs::write(dir.path().join(FLOOR), STALE_V1_FLOOR)?;
let (code, output) = run(dir.path(), &["doctor"])?;
assert_eq!(code, Some(1), "a stale floor is a red finding: {output}");
assert!(
output.contains("lefthook"),
"the finding names the floor: {output}"
);
assert!(
output.contains("stale"),
"the finding says what is wrong: {output}"
);
Ok(())
}
#[test]
fn doctor_repair_regenerates_a_stale_floor() -> TestResult {
let dir = repo()?;
fs::write(dir.path().join(FLOOR), STALE_V1_FLOOR)?;
run(dir.path(), &["doctor", "--repair"])?;
let content = read_floor(dir.path())?;
assert!(
content.contains("exec pushkin check --staged --json") && content.contains("pushkin-v3"),
"repair regenerates through the merge path: {content}"
);
Ok(())
}
#[test]
fn doctor_is_quiet_when_no_floor_is_installed() -> TestResult {
let dir = repo()?;
let (_, output) = run(dir.path(), &["doctor"])?;
assert!(
!output.contains("lefthook.yml is stale"),
"no floor installed → no stale finding: {output}"
);
Ok(())
}
#[test]
fn doctor_names_an_unresolvable_pushkin_binary() -> TestResult {
let dir = repo()?;
run(dir.path(), &["init", "--agent", "lefthook"])?;
let output = Command::cargo_bin("pushkin")?
.current_dir(dir.path())
.arg("doctor")
.env("PATH", "")
.output()?;
let text = format!(
"{}{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
assert!(
text.contains("PATH"),
"the finding names the PATH problem: {text}"
);
assert!(
text.contains("install") || text.contains("cargo install"),
"the finding carries an actionable hint: {text}"
);
Ok(())
}