use super::*;
use crate::core::ir::{EnumVariant, FieldDef, TypeRef};
fn named_field(name: &str, serde_rename: Option<&str>) -> FieldDef {
FieldDef {
name: name.to_string(),
ty: TypeRef::String,
serde_rename: serde_rename.map(str::to_string),
..FieldDef::default()
}
}
fn struct_variant(name: &str, fields: Vec<FieldDef>) -> EnumVariant {
EnumVariant {
name: name.to_string(),
fields,
..EnumVariant::default()
}
}
fn tagged_union_enum(variants: Vec<EnumVariant>, rename_all_fields: Option<&str>) -> EnumDef {
EnumDef {
name: "SampleUnion".to_string(),
serde_tag: Some("type".to_string()),
variants,
rename_all_fields: rename_all_fields.map(str::to_string),
..EnumDef::default()
}
}
#[test]
fn struct_variant_field_with_serde_rename_uses_the_renamed_wire_name() {
let enum_def = tagged_union_enum(
vec![struct_variant(
"Explicit",
vec![named_field("resource_url", Some("resourceUrl"))],
)],
None,
);
let emitted = gen_tagged_union(&enum_def, "Sample.Namespace");
assert!(
emitted.contains(r#"JsonPropertyName("resourceUrl")"#),
"an explicit serde_rename on the field must drive the wire name:\n{emitted}"
);
assert!(
!emitted.contains(r#"JsonPropertyName("resource_url")"#),
"the raw Rust field name must not leak onto the wire once serde_rename overrides it:\n{emitted}"
);
}
#[test]
fn struct_variant_field_with_container_rename_all_fields_uses_the_cased_wire_name() {
let enum_def = tagged_union_enum(
vec![struct_variant("Explicit", vec![named_field("display_name", None)])],
Some("camelCase"),
);
let emitted = gen_tagged_union(&enum_def, "Sample.Namespace");
assert!(
emitted.contains(r#"JsonPropertyName("displayName")"#),
"the enum's rename_all_fields container rule must case a field with no explicit rename:\n{emitted}"
);
assert!(
!emitted.contains(r#"JsonPropertyName("display_name")"#),
"the raw Rust field name must not leak onto the wire once rename_all_fields applies:\n{emitted}"
);
}
#[test]
fn struct_variant_field_explicit_rename_wins_over_container_rename_all_fields() {
let enum_def = tagged_union_enum(
vec![struct_variant(
"Explicit",
vec![named_field("display_name", Some("explicitName"))],
)],
Some("camelCase"),
);
let emitted = gen_tagged_union(&enum_def, "Sample.Namespace");
assert!(
emitted.contains(r#"JsonPropertyName("explicitName")"#),
"an explicit serde_rename must win over the enum's rename_all_fields container rule:\n{emitted}"
);
assert!(
!emitted.contains(r#"JsonPropertyName("displayName")"#),
"the container-cased name must not be used when the field carries its own serde_rename:\n{emitted}"
);
assert!(
!emitted.contains(r#"JsonPropertyName("display_name")"#),
"the raw Rust field name must not leak onto the wire when either rule applies:\n{emitted}"
);
assert!(
emitted.contains(r#")] string DisplayName"#),
"the public C# property identifier must stay derived from the raw field name, unaffected \
by either wire-naming rule:\n{emitted}"
);
}
#[test]
fn struct_variant_field_without_any_rename_keeps_its_raw_name() {
let enum_def = tagged_union_enum(
vec![struct_variant("Explicit", vec![named_field("resource_url", None)])],
None,
);
let emitted = gen_tagged_union(&enum_def, "Sample.Namespace");
assert!(
emitted.contains(r#"JsonPropertyName("resource_url")"#),
"a field with neither serde_rename nor an enum rename_all_fields must keep its raw name:\n{emitted}"
);
}