use serde::Deserialize;
#[derive(Debug, PartialEq, Deserialize)]
struct AppConfig {
name: String,
debug: bool,
tags: Vec<String>,
server: Server,
}
#[derive(Debug, PartialEq, Deserialize)]
struct Server {
host: String,
port: u16,
}
fn expected() -> AppConfig {
AppConfig {
name: "confy-demo".into(),
debug: false,
tags: vec!["alpha".into(), "beta".into()],
server: Server {
host: "127.0.0.1".into(),
port: 8080,
},
}
}
#[cfg(feature = "toml")]
#[test]
fn load_toml_file() {
let config: AppConfig = confy_rs::load("fixtures/config.toml").unwrap();
assert_eq!(config, expected());
}
#[cfg(feature = "yaml")]
#[test]
fn load_yaml_file() {
let config: AppConfig = confy_rs::load("fixtures/config.yaml").unwrap();
assert_eq!(config, expected());
}
#[test]
fn load_json_file() {
let config: AppConfig = confy_rs::load("fixtures/config.json").unwrap();
assert_eq!(config, expected());
}
#[cfg(feature = "toml")]
#[test]
fn layered_merge_across_formats() {
let config: AppConfig = confy_rs::builder()
.file("fixtures/default.toml")
.file("fixtures/override.json")
.file_optional("fixtures/nonexistent.json")
.build()
.unwrap();
assert_eq!(
config,
AppConfig {
name: "layered-demo".into(),
tags: vec!["default".into()],
server: Server {
host: "0.0.0.0".into(),
port: 9090
},
debug: true,
}
);
}
#[cfg(feature = "toml")]
#[test]
fn defaults_layer_has_lowest_priority() {
let config: AppConfig = confy_rs::builder()
.defaults(serde_json::json!({
"name": "from-defaults",
"debug": true,
"tags": ["x"],
"server": { "host": "localhost", "port": 1 },
}))
.unwrap()
.file("fixtures/override.json")
.build()
.unwrap();
assert_eq!(config.name, "from-defaults");
assert_eq!(config.server.port, 9090);
assert_eq!(config.server.host, "localhost");
}
#[cfg(feature = "toml")]
#[test]
fn parse_error_mentions_path() {
let err = confy_rs::load::<AppConfig>("fixtures/invalid.toml").unwrap_err();
assert!(matches!(err, confy_rs::Error::Parse { .. }), "{err}");
let message = err.to_string();
assert!(message.contains("invalid.toml"), "{message}");
assert!(message.contains("TOML"), "{message}");
}
#[test]
fn missing_required_file() {
let err = confy_rs::load::<AppConfig>("fixtures/nope.json").unwrap_err();
assert!(matches!(err, confy_rs::Error::NotFound { .. }), "{err}");
assert!(err.to_string().contains("nope.json"), "{err}");
}