use crate::derive_configuration_enum;
use crate::tests::pretty_print;
#[test]
fn simple_enum() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum LogLevel {
Debug,
Info,
Warn,
Error,
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn public_enum() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
pub enum Visibility {
Public,
Private,
Internal,
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_tuple_variants() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Value {
Int(i64),
Float(f64),
Text(String),
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_struct_variants() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Endpoint {
Http { url: String, timeout: u64 },
Grpc { host: String, port: u16 },
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_doc_comments() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Mode {
Development,
Production,
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_preserves_existing_attributes() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
#[derive(PartialEq, Eq)]
#[allow(dead_code)]
enum Status {
#[serde(rename = "ACTIVE")]
Active,
#[serde(rename = "INACTIVE")]
Inactive,
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_generics() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Container<T> {
Empty,
Single(T),
Multiple(Vec<T>),
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_default_unit_variant() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum LogLevel {
Debug,
#[config(default)]
Info,
Warn,
Error,
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_default_tuple_variant() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Value {
#[config(default)]
Int(i64),
Float(f64),
Text(String),
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_default_struct_variant() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Endpoint {
#[config(default)]
Http { url: String, timeout: u64 },
Grpc { host: String, port: u16 },
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_multiple_defaults_error() {
let result = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Invalid {
#[config(default)]
First,
#[config(default)]
Second,
}
},
);
let Err(err) = result else {
panic!("multiple defaults should return error");
};
assert_eq!(
err.to_string(),
"only one variant can be marked as #[config(default)]"
);
}
#[test]
fn enum_struct_variant_with_field_defaults() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Endpoint {
#[config(default)]
Http {
#[config(default = "http://localhost".to_string())]
url: String,
#[config(default = 30)]
timeout: u64,
},
Grpc {
#[config(required)]
host: String,
#[config(default = 9090)]
port: u16,
},
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_struct_variant_with_required_fields() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Auth {
ApiKey {
#[config(required)]
key: String,
},
Basic {
#[config(required)]
username: String,
#[config(required)]
password: String,
},
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_default_variant_with_required_field_error() {
let result = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Invalid {
#[config(default)]
Variant {
#[config(required)]
field: String,
},
}
},
);
let Err(err) = result else {
panic!("default variant with required field should return error");
};
assert_eq!(
err.to_string(),
"cannot mark field as required in a #[config(default)] variant"
);
}
#[test]
fn enum_struct_variant_with_validation() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Auth {
ApiKey {
#[config(pattern("^[A-Za-z0-9_-]+$"))]
key: String,
},
Timeout {
#[config(range(min = 1, max = 3600))]
seconds: u64,
},
Name {
#[config(length(min = 1, max = 100))]
value: String,
},
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_struct_variant_with_custom_validation() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum EnumConfig {
#[config(default)]
Valid { valid_field: usize },
Invalid {
#[config(validate = always_errors)]
erroring_field: usize,
},
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_struct_variant_with_cfg_attributes() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum FeatureGatedEnum {
#[config(default)]
Http {
url: String,
#[cfg(feature = "timeout")]
timeout: u64,
},
Grpc {
host: String,
#[cfg(feature = "compression")]
compression: String,
},
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}
#[test]
fn enum_with_cfg_gated_variants() {
let output = derive_configuration_enum(
Default::default(),
syn::parse_quote! {
enum Exporter {
#[config(default)]
Stdout,
#[cfg(feature = "otlp")]
Otlp { endpoint: String },
#[cfg(feature = "datadog")]
Datadog { api_key: String },
}
},
)
.unwrap();
insta::assert_snapshot!(pretty_print(output));
}