use super::*;
#[test]
fn test_init_creates_agents_md_in_empty_dir() {
let dir = TempDir::new().unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let agents = dir.path().join("AGENTS.md");
assert!(agents.exists(), "AGENTS.md should be created");
let content = fs::read_to_string(&agents).unwrap();
assert!(content.contains("patchloom"));
assert!(content.contains("# Patchloom"));
}
#[test]
fn test_init_appends_to_existing_agents_md() {
let dir = TempDir::new().unwrap();
fs::write(dir.path().join("AGENTS.md"), "# My Rules\n").unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let content = fs::read_to_string(dir.path().join("AGENTS.md")).unwrap();
assert!(
content.starts_with("# My Rules\n"),
"original content should be preserved"
);
assert!(
content.contains("# Patchloom"),
"patchloom rules should be appended"
);
}
#[test]
fn test_init_appends_when_existing_agents_mentions_patchloom_without_generated_header() {
let dir = TempDir::new().unwrap();
fs::write(
dir.path().join("AGENTS.md"),
"# Rules\nUse patchloom for edits.\n",
)
.unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.env("SHELL", "unknown")
.output()
.unwrap();
assert!(output.status.success());
let content = fs::read_to_string(dir.path().join("AGENTS.md")).unwrap();
assert!(content.starts_with("# Rules\nUse patchloom for edits.\n"));
assert!(content.contains("# Patchloom"));
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("appended patchloom rules"));
}
#[test]
fn test_init_skips_if_patchloom_already_present() {
let dir = TempDir::new().unwrap();
fs::write(
dir.path().join("AGENTS.md"),
"# Rules\n<!-- Generated by patchloom v0.1.0 -->\n",
)
.unwrap();
let before = fs::read_to_string(dir.path().join("AGENTS.md")).unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let after = fs::read_to_string(dir.path().join("AGENTS.md")).unwrap();
assert_eq!(before, after, "file should not be modified");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("already contains patchloom rules"));
}
#[test]
fn test_init_errors_on_non_utf8_existing_agents_md() {
let dir = TempDir::new().unwrap();
let agents = dir.path().join("AGENTS.md");
fs::write(&agents, [0xff, 0xfe, 0x00]).unwrap();
let before = fs::read(&agents).unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.env("SHELL", "unknown")
.output()
.unwrap();
assert!(!output.status.success());
assert_eq!(
fs::read(&agents).unwrap(),
before,
"file should not be modified"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("reading existing"));
}
#[test]
fn test_init_appends_to_existing_claude_md() {
let dir = TempDir::new().unwrap();
let claude = dir.path().join("Claude.md");
fs::write(&claude, "# Claude Rules\n").unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.env("SHELL", "unknown")
.output()
.unwrap();
assert!(output.status.success());
assert!(!dir.path().join("AGENTS.md").exists());
let content = fs::read_to_string(&claude).unwrap();
assert!(content.starts_with("# Claude Rules\n"));
assert!(content.contains("# Patchloom"));
}
#[test]
fn test_init_quiet_suppresses_output() {
let dir = TempDir::new().unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--quiet", "--cwd"])
.arg(dir.path())
.output()
.unwrap();
assert!(output.status.success());
assert!(dir.path().join("AGENTS.md").exists());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.is_empty(), "stderr should be empty with --quiet");
}
#[test]
fn test_init_falls_back_to_completion_command_when_completion_dir_creation_fails() {
let dir = TempDir::new().unwrap();
let fake_home = dir.path().join("fake-home");
let blocking_file = fake_home.join(".config");
fs::create_dir_all(&fake_home).unwrap();
fs::write(&blocking_file, "not a directory\n").unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.env("HOME", &fake_home)
.env("SHELL", "fish")
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("failed to prepare completion directory:"));
assert!(
stderr.contains("patchloom completions fish > ~/.config/fish/completions/patchloom.fish")
);
}
#[cfg(unix)]
#[test]
fn test_init_confirm_eof_skips_agents_creation() {
let dir = TempDir::new().unwrap();
let output = run_patchloom_confirm_in_pty_with_env(
&["init", "--cwd", dir.path().to_str().unwrap()],
"\u{4}",
&[("SHELL", "unknown")],
);
assert!(output.status.success());
assert!(!dir.path().join("AGENTS.md").exists());
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("Create AGENTS.md? [Y/n]"));
assert!(stdout.contains("skipped AGENTS.md"));
}
#[cfg(feature = "mcp")]
#[test]
fn test_init_shows_vscode_mcp_json_hint() {
if !has_mcp_support() {
return;
}
let dir = TempDir::new().unwrap();
fs::create_dir(dir.path().join(".vscode")).unwrap();
let home = TempDir::new().unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.env("HOME", home.path())
.env("SHELL", "unknown")
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("VS Code: create .vscode/mcp.json:"));
assert!(stderr.contains(
"\"servers\": { \"patchloom\": { \"command\": \"patchloom\", \"args\": [\"mcp-server\"] } }"
));
assert!(!stderr.contains(".vscode/settings.json"));
}
#[cfg(feature = "mcp")]
#[test]
fn test_init_shows_cursor_mcp_json_hint() {
if !has_mcp_support() {
return;
}
let dir = TempDir::new().unwrap();
fs::create_dir(dir.path().join(".cursor")).unwrap();
let home = TempDir::new().unwrap();
let output = Command::cargo_bin("patchloom")
.unwrap()
.args(["init", "--yes", "--cwd"])
.arg(dir.path())
.env("HOME", home.path())
.env("SHELL", "unknown")
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("Cursor: create .cursor/mcp.json:"));
assert!(stderr.contains(
"\"servers\": { \"patchloom\": { \"command\": \"patchloom\", \"args\": [\"mcp-server\"] } }"
));
}