use std::fs;
use std::path::Path;
use linkmarks_core::canonical_config::CanonicalConfig;
use linkmarks_core::config::load_from;
use tempfile::tempdir;
#[test]
fn load_missing_file_returns_defaults() {
let cfg: CanonicalConfig = load_from(Path::new("/nonexistent/path/config.toml")).unwrap();
assert_eq!(cfg.domains.len(), 0);
}
#[test]
fn load_empty_file_returns_defaults() {
let dir = tempdir().unwrap();
let path = dir.path().join("config.toml");
fs::write(&path, "").unwrap();
let cfg = load_from(&path).unwrap();
assert_eq!(cfg.domains.len(), 0);
}
#[test]
fn load_invalid_toml_returns_storage_error_with_path() {
let dir = tempdir().unwrap();
let path = dir.path().join("broken.toml");
fs::write(&path, "this is = not valid toml [[[").unwrap();
let err = load_from(&path).unwrap_err();
let msg = format!("{err:?}");
assert!(
msg.contains("Storage"),
"expected Storage variant, got: {msg}"
);
assert!(
msg.contains("broken.toml"),
"expected path in error, got: {msg}"
);
}
#[test]
fn per_domain_override_merges_over_defaults() {
let dir = tempdir().unwrap();
let path = dir.path().join("config.toml");
fs::write(
&path,
r#"
[canonical.domains]
"amazon.com" = { preserve_params = ["tag", "ref"] }
"example.org" = { preserve_params = ["query_id"] }
"#,
)
.unwrap();
let cfg = load_from(&path).unwrap();
assert_eq!(cfg.domains.len(), 2);
assert!(cfg.is_preserved("amazon.com", "tag"));
assert!(cfg.is_preserved("amazon.com", "ref"));
assert!(cfg.is_preserved("example.org", "query_id"));
assert!(!cfg.is_preserved("amazon.com", "query_id"));
}
#[test]
fn always_functional_always_wins() {
let dir = tempdir().unwrap();
let path = dir.path().join("config.toml");
fs::write(&path, "").unwrap();
let cfg = load_from(&path).unwrap();
for param in ["id", "page", "q", "query", "search", "lang", "locale"] {
assert!(
cfg.is_preserved("any-host", param),
"{param} must be ALWAYS_FUNCTIONAL"
);
}
assert!(!cfg.is_preserved("any-host", "ref"));
}
#[test]
fn host_case_is_lowercased_in_storage() {
let dir = tempdir().unwrap();
let path = dir.path().join("config.toml");
fs::write(
&path,
r#"
[canonical.domains]
"AMAZON.COM" = { preserve_params = ["tag"] }
"YouTube.com" = { preserve_params = ["t"] }
"#,
)
.unwrap();
let cfg = load_from(&path).unwrap();
assert!(cfg.domains.contains_key("amazon.com"));
assert!(cfg.domains.contains_key("youtube.com"));
assert!(!cfg.domains.contains_key("AMAZON.COM"));
assert!(!cfg.domains.contains_key("YouTube.com"));
}
#[test]
fn config_single_read_per_process() {
let dir = tempdir().unwrap();
let path = dir.path().join("config.toml");
fs::write(
&path,
r#"
[canonical.domains]
"x.com" = { preserve_params = ["a"] }
"#,
)
.unwrap();
let cfg1 = load_from(&path).unwrap();
assert!(cfg1.is_preserved("x.com", "a"));
fs::write(
&path,
r#"
[canonical.domains]
"y.com" = { preserve_params = ["b"] }
"#,
)
.unwrap();
let cfg2 = load_from(&path).unwrap();
assert!(cfg2.is_preserved("y.com", "b"));
assert!(cfg1.is_preserved("x.com", "a"));
}
#[test]
fn always_functional_holds_across_duplicate_overrides() {
let dir = tempdir().unwrap();
let path = dir.path().join("config.toml");
fs::write(
&path,
r#"
[canonical.domains]
"example.com" = { preserve_params = ["id"] }
"example.com" = { preserve_params = ["extra"] }
"#,
)
.unwrap();
let cfg = load_from(&path);
let cfg = match cfg {
Ok(c) => c,
Err(_) => {
fs::write(
&path,
r#"
[canonical.domains]
"example.com" = { preserve_params = ["id", "extra"] }
"#,
)
.unwrap();
load_from(&path).unwrap()
}
};
assert!(cfg.is_preserved("example.com", "id"));
assert!(cfg.is_preserved("example.com", "extra"));
assert!(cfg.is_preserved("other.com", "id"));
}