use std::collections::BTreeMap;
use lorum::config::{HookHandler, HooksConfig, LorumConfig, McpConfig, McpServer, OutputFormat};
use serial_test::serial;
fn make_server(cmd: &str, args: &[&str], env: &[(&str, &str)]) -> McpServer {
McpServer {
command: cmd.into(),
args: args.iter().map(|a| a.to_string()).collect(),
env: env
.iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
}
}
fn temp_config_with_hooks() -> (tempfile::TempDir, std::path::PathBuf, LorumConfig) {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("config.yaml");
let config = LorumConfig {
mcp: McpConfig {
servers: {
let mut m = BTreeMap::new();
m.insert("test".into(), make_server("cmd", &["arg"], &[]));
m
},
},
hooks: HooksConfig {
events: {
let mut m = BTreeMap::new();
m.insert(
"pre-tool-use".into(),
vec![HookHandler {
matcher: "Bash".into(),
command: "echo ${TEST_VAR}".into(),
timeout: Some(30),
handler_type: Some("command".into()),
}],
);
m
},
},
};
lorum::config::save_config(&path, &config).unwrap();
(dir, path, config)
}
#[test]
fn config_yaml_output_with_source() {
let (_dir, path, _config) = temp_config_with_hooks();
let path_s = path.to_str().unwrap();
let output = std::panic::catch_unwind(|| {
lorum::commands::run_config(false, false, false, OutputFormat::Yaml, Some(path_s))
});
assert!(output.is_ok());
}
#[test]
fn config_json_output_with_source() {
let (_dir, path, _config) = temp_config_with_hooks();
let path_s = path.to_str().unwrap();
let output = std::panic::catch_unwind(|| {
lorum::commands::run_config(false, false, false, OutputFormat::Json, Some(path_s))
});
assert!(output.is_ok());
}
#[test]
fn config_resolve_env_interpolates_hooks() {
let (_dir, path, _config) = temp_config_with_hooks();
let path_s = path.to_str().unwrap();
unsafe { std::env::set_var("TEST_VAR", "hello") };
let output = std::panic::catch_unwind(|| {
lorum::commands::run_config(true, false, false, OutputFormat::Yaml, Some(path_s)).unwrap();
});
unsafe { std::env::remove_var("TEST_VAR") };
assert!(output.is_ok());
}
#[test]
#[serial]
fn config_local_source_annotation() {
let dir = tempfile::tempdir().unwrap();
let lorum_dir = dir.path().join(".lorum");
std::fs::create_dir_all(&lorum_dir).unwrap();
let project_config = LorumConfig {
mcp: McpConfig {
servers: {
let mut m = BTreeMap::new();
m.insert("local-srv".into(), make_server("local-cmd", &[], &[]));
m
},
},
..Default::default()
};
lorum::config::save_config(&lorum_dir.join("config.yaml"), &project_config).unwrap();
let orig = std::env::current_dir().unwrap();
std::env::set_current_dir(dir.path()).unwrap();
let result = std::panic::catch_unwind(|| {
lorum::commands::run_config(false, true, false, OutputFormat::Yaml, None).unwrap();
});
std::env::set_current_dir(&orig).unwrap();
assert!(result.is_ok());
}
#[test]
fn config_global_source_annotation() {
let output = std::panic::catch_unwind(|| {
lorum::commands::run_config(false, false, true, OutputFormat::Yaml, None).unwrap();
});
assert!(output.is_ok());
}
#[test]
fn config_no_resolve_env_preserves_placeholders() {
let (_dir, path, _config) = temp_config_with_hooks();
let path_s = path.to_str().unwrap();
let output = std::panic::catch_unwind(|| {
lorum::commands::run_config(false, false, false, OutputFormat::Yaml, Some(path_s))
});
assert!(output.is_ok());
}
#[test]
fn config_local_missing_returns_error() {
let dir = tempfile::tempdir().unwrap();
let orig = std::env::current_dir().unwrap();
std::env::set_current_dir(dir.path()).unwrap();
let result = lorum::commands::run_config(false, true, false, OutputFormat::Yaml, None);
std::env::set_current_dir(&orig).unwrap();
assert!(result.is_err());
}