use crate::assert_diag_snapshot;
use facet::Facet;
use figue::{self as args, Driver, DriverError, MockEnv, builder};
#[derive(Facet, Debug)]
struct SimpleConfig {
port: u16,
host: String,
}
#[derive(Facet, Debug)]
struct ArgsWithSimpleConfig {
#[facet(args::config, args::env_prefix = "APP")]
config: SimpleConfig,
}
#[derive(Facet, Debug)]
struct NestedConfig {
database: DatabaseConfig,
}
#[derive(Facet, Debug)]
struct DatabaseConfig {
url: String,
max_connections: u32,
}
#[derive(Facet, Debug)]
struct ArgsWithNestedConfig {
#[facet(args::config, args::env_prefix = "APP")]
config: NestedConfig,
}
#[test]
fn test_deser_error_env_wrong_type_for_port() {
let env = MockEnv::from_pairs([("APP__PORT", "not_a_number"), ("APP__HOST", "localhost")]);
let config = builder::<ArgsWithSimpleConfig>()
.unwrap()
.env(|e| e.source(env))
.build();
let result = Driver::new(config).run().into_result();
match result {
Err(DriverError::Failed { report }) => {
assert_diag_snapshot!(report);
}
other => panic!("expected DriverError::Failed, got {:?}", other),
}
}
#[test]
fn test_deser_error_env_negative_for_unsigned() {
let env = MockEnv::from_pairs([("APP__PORT", "-1"), ("APP__HOST", "localhost")]);
let config = builder::<ArgsWithSimpleConfig>()
.unwrap()
.env(|e| e.source(env))
.build();
let result = Driver::new(config).run().into_result();
match result {
Err(DriverError::Failed { report }) => {
assert_diag_snapshot!(report);
}
other => panic!("expected DriverError::Failed, got {:?}", other),
}
}
#[test]
fn test_deser_error_env_number_out_of_range() {
let env = MockEnv::from_pairs([("APP__PORT", "99999"), ("APP__HOST", "localhost")]);
let config = builder::<ArgsWithSimpleConfig>()
.unwrap()
.env(|e| e.source(env))
.build();
let result = Driver::new(config).run().into_result();
match result {
Err(DriverError::Failed { report }) => {
assert_diag_snapshot!(report);
}
other => panic!("expected DriverError::Failed, got {:?}", other),
}
}
#[test]
fn test_deser_error_file_wrong_type_for_port() {
let config_json = r#"{
"port": "not_a_number",
"host": "localhost"
}"#;
let config = builder::<ArgsWithSimpleConfig>()
.unwrap()
.file(|f| f.content(config_json, "config.json"))
.build();
let result = Driver::new(config).run().into_result();
match result {
Err(DriverError::Failed { report }) => {
assert_diag_snapshot!(report);
}
other => panic!("expected DriverError::Failed, got {:?}", other),
}
}
#[test]
fn test_deser_error_file_nested_wrong_type() {
let config_json = r#"{
"database": {
"url": "postgres://localhost/db",
"max_connections": "lots"
}
}"#;
let config = builder::<ArgsWithNestedConfig>()
.unwrap()
.file(|f| f.content(config_json, "config.json"))
.build();
let result = Driver::new(config).run().into_result();
match result {
Err(DriverError::Failed { report }) => {
assert_diag_snapshot!(report);
}
other => panic!("expected DriverError::Failed, got {:?}", other),
}
}
#[test]
fn test_deser_error_cli_override_wrong_type() {
let config = builder::<ArgsWithSimpleConfig>()
.unwrap()
.cli(|cli| cli.args(["--config.port", "oops", "--config.host", "localhost"]))
.build();
let result = Driver::new(config).run().into_result();
match result {
Err(DriverError::Failed { report }) => {
assert_diag_snapshot!(report);
}
other => panic!("expected DriverError::Failed, got {:?}", other),
}
}
#[test]
fn test_deser_error_env_overrides_valid_file() {
let config_json = r#"{
"port": 8080,
"host": "localhost"
}"#;
let env = MockEnv::from_pairs([("APP__PORT", "invalid")]);
let config = builder::<ArgsWithSimpleConfig>()
.unwrap()
.file(|f| f.content(config_json, "config.json"))
.env(|e| e.source(env))
.build();
let result = Driver::new(config).run().into_result();
match result {
Err(DriverError::Failed { report }) => {
assert_diag_snapshot!(report);
}
other => panic!("expected DriverError::Failed, got {:?}", other),
}
}