use std::{env, process::Command};
#[test]
fn test_sync_config_env_vars() {
let guardy_binary = find_guardy_binary();
let output = Command::new(&guardy_binary)
.args(["sync", "status"])
.env("GUARDY_SYNC_FORCE", "1")
.env("GUARDY_SYNC_SHOW_DIFF", "0")
.env("RUST_LOG", "debug")
.output()
.expect("Failed to execute guardy");
let logs = get_command_logs(&output);
assert!(
logs.contains("Found env var GUARDY_SYNC_FORCE (type: bool): 1"),
"GUARDY_SYNC_FORCE should be parsed. Output: {logs}"
);
assert!(
logs.contains("Found env var GUARDY_SYNC_SHOW_DIFF (type: bool): 0"),
"GUARDY_SYNC_SHOW_DIFF should be parsed. Output: {logs}"
);
}
#[test]
fn test_sync_config_numeric_env_vars() {
let guardy_binary = find_guardy_binary();
let output = Command::new(&guardy_binary)
.args(["sync", "status"])
.env("GUARDY_SYNC_GIT_TIMEOUT", "60")
.env("GUARDY_SYNC_DIFF_CONTEXT", "5")
.env("RUST_LOG", "debug")
.output()
.expect("Failed to execute guardy");
let logs = get_command_logs(&output);
assert!(
logs.contains("Found env var GUARDY_SYNC_GIT_TIMEOUT"),
"GUARDY_SYNC_GIT_TIMEOUT should be parsed. Output: {logs}"
);
assert!(
logs.contains("Found env var GUARDY_SYNC_DIFF_CONTEXT"),
"GUARDY_SYNC_DIFF_CONTEXT should be parsed. Output: {logs}"
);
}
#[test]
fn test_sync_config_string_env_vars() {
let guardy_binary = find_guardy_binary();
let output = Command::new(&guardy_binary)
.args(["sync", "status"])
.env("GUARDY_SYNC_CACHE_DIR", "/tmp/custom_cache")
.env("RUST_LOG", "debug")
.output()
.expect("Failed to execute guardy");
let logs = get_command_logs(&output);
assert!(
logs.contains("Found env var GUARDY_SYNC_CACHE_DIR"),
"GUARDY_SYNC_CACHE_DIR should be parsed. Output: {logs}"
);
}
#[test]
fn test_sync_cli_overrides_env() {
let guardy_binary = find_guardy_binary();
let output = Command::new(&guardy_binary)
.args(["sync", "update", "--force"])
.env("GUARDY_SYNC_FORCE", "0")
.env("RUST_LOG", "debug")
.output()
.expect("Failed to execute guardy");
let logs = get_command_logs(&output);
assert!(
output.status.success() || logs.contains("No sync configuration"),
"Command should handle CLI override of env vars. Output: {logs}"
);
}
#[test]
fn test_sync_boolean_env_formats() {
let guardy_binary = find_guardy_binary();
for truthy_val in ["1", "true", "TRUE", "yes", "YES", "on", "ON"] {
let output = Command::new(&guardy_binary)
.args(["sync", "status"])
.env("GUARDY_SYNC_FORCE", truthy_val)
.env("RUST_LOG", "debug")
.output()
.expect("Failed to execute guardy");
let logs = get_command_logs(&output);
assert!(
logs.contains("Parsed GUARDY_SYNC_FORCE as boolean: true"),
"Value '{truthy_val}' should be parsed as true. Output: {logs}"
);
}
for falsy_val in ["0", "false", "FALSE", "no", "NO", "off", "OFF"] {
let output = Command::new(&guardy_binary)
.args(["sync", "status"])
.env("GUARDY_SYNC_FORCE", falsy_val)
.env("RUST_LOG", "debug")
.output()
.expect("Failed to execute guardy");
let logs = get_command_logs(&output);
assert!(
logs.contains("Parsed GUARDY_SYNC_FORCE as boolean: false"),
"Value '{falsy_val}' should be parsed as false. Output: {logs}"
);
}
}
#[test]
fn test_sync_config_file_override() {
use std::fs;
use tempfile::tempdir;
let guardy_binary = find_guardy_binary();
let temp_dir = tempdir().expect("Failed to create temp dir");
let config_file = temp_dir.path().join("guardy.yaml");
let config_content = r#"
sync:
force: true
show-diff: false # Test dash format
git_timeout_seconds: 120 # Test underscore format
cache_dir: "/tmp/test_cache"
repolist: []
"#;
fs::write(&config_file, config_content).expect("Failed to write config file");
let output = Command::new(&guardy_binary)
.args(["sync", "status", "--config", config_file.to_str().unwrap()])
.env("RUST_LOG", "debug")
.current_dir(temp_dir.path())
.output()
.expect("Failed to execute guardy");
let logs = get_command_logs(&output);
assert!(
output.status.success() || logs.contains("No sync configuration"),
"Config file should be loaded successfully. Output: {logs}"
);
}
fn find_guardy_binary() -> String {
env::var("CARGO_BIN_EXE_guardy")
.or_else(|_| {
let paths = [
"target/release/guardy",
"target/debug/guardy",
"../../target/release/guardy",
"../../target/debug/guardy",
"../../../target/release/guardy",
"../../../target/debug/guardy",
"../../../../target/release/guardy",
"../../../../target/debug/guardy",
"../../../guardy/target/release/guardy",
"../../../guardy/target/debug/guardy",
];
for path in &paths {
let path_buf = std::path::Path::new(path);
if path_buf.exists() {
match path_buf.canonicalize() {
Ok(abs_path) => return Ok(abs_path.to_string_lossy().to_string()),
Err(_) => continue,
}
}
}
Err("Could not find guardy binary")
})
.expect("Failed to locate guardy binary for testing")
}
fn get_command_logs(output: &std::process::Output) -> String {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
format!("{stdout}{stderr}")
}