use robin::config::RobinConfig;
use std::fs;
use tempfile::tempdir;
#[test]
fn load_missing_file_gives_helpful_error() {
let dir = tempdir().unwrap();
let path = dir.path().join(".robin.json");
let err = RobinConfig::load(&path).unwrap_err();
assert!(
err.to_string().contains("No .robin.json found"),
"unexpected error: {err}"
);
}
#[test]
fn load_malformed_json_gives_helpful_error() {
let dir = tempdir().unwrap();
let path = dir.path().join(".robin.json");
fs::write(&path, "{ this is not valid json ").unwrap();
let err = RobinConfig::load(&path).unwrap_err();
assert!(
err.to_string().contains("malformed JSON"),
"unexpected error: {err}"
);
}
#[test]
fn load_defaults_include_to_empty() {
let dir = tempdir().unwrap();
let path = dir.path().join(".robin.json");
fs::write(&path, r#"{"scripts":{"build":"cargo build"}}"#).unwrap();
let config = RobinConfig::load(&path).unwrap();
assert!(config.include.is_empty());
assert_eq!(config.scripts.len(), 1);
}
#[test]
fn includes_are_merged_with_base_taking_precedence() {
let dir = tempdir().unwrap();
let base = dir.path().join(".robin.json");
let child = dir.path().join("child.json");
fs::write(
&base,
r#"{"include":["child.json"],"scripts":{"shared":"base wins","only_base":"b"}}"#,
)
.unwrap();
fs::write(
&child,
r#"{"scripts":{"shared":"child loses","only_child":"c"}}"#,
)
.unwrap();
let config = RobinConfig::load(&base).unwrap();
assert_eq!(
config.scripts.get("shared").unwrap().as_str().unwrap(),
"base wins"
);
assert_eq!(
config.scripts.get("only_base").unwrap().as_str().unwrap(),
"b"
);
assert_eq!(
config.scripts.get("only_child").unwrap().as_str().unwrap(),
"c"
);
assert_eq!(config.scripts.len(), 3);
}
#[test]
fn includes_resolve_relative_to_config_dir() {
let dir = tempdir().unwrap();
let sub = dir.path().join("sub");
fs::create_dir(&sub).unwrap();
let base = sub.join(".robin.json");
fs::write(&base, r#"{"include":["extra.json"],"scripts":{"a":"1"}}"#).unwrap();
fs::write(sub.join("extra.json"), r#"{"scripts":{"b":"2"}}"#).unwrap();
let config = RobinConfig::load(&base).unwrap();
assert!(config.scripts.contains_key("a"));
assert!(config.scripts.contains_key("b"));
}
#[test]
fn missing_include_reports_which_file_failed() {
let dir = tempdir().unwrap();
let base = dir.path().join(".robin.json");
fs::write(&base, r#"{"include":["does_not_exist.json"],"scripts":{}}"#).unwrap();
let err = RobinConfig::load(&base).unwrap_err();
assert!(
err.to_string().contains("does_not_exist.json"),
"error should name the missing include: {err}"
);
}
#[test]
fn save_then_load_roundtrips() {
let dir = tempdir().unwrap();
let path = dir.path().join(".robin.json");
let config = RobinConfig::create_template();
config.save(&path).unwrap();
assert!(path.exists());
let loaded = RobinConfig::load(&path).unwrap();
assert_eq!(loaded.scripts.len(), config.scripts.len());
}