diff --git a/crates/jacquard-lexicon/src/codegen/builder_gen/state_mod.rs b/crates/jacquard-lexicon/src/codegen/builder_gen/state_mod.rs index 41d290f86..136cea29c 100644 --- a/crates/jacquard-lexicon/src/codegen/builder_gen/state_mod.rs +++ b/crates/jacquard-lexicon/src/codegen/builder_gen/state_mod.rs @@ -13,7 +13,7 @@ use quote::{format_ident, quote}; use crate::codegen::utils::make_ident; /// Information about a required field for builder state generation -#[derive(Debug, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct RequiredField { /// Field name (snake_case) pub name_snake: SmolStr, @@ -47,7 +47,9 @@ pub fn collect_required_fields(schema: &super::BuilderSchema<'_>) -> Vec = set.into_iter().collect(); + fields.sort(); + fields } /// Generate the complete state module for a builder diff --git a/crates/jacquard-lexicon/src/codegen/builder_gen/tests.rs b/crates/jacquard-lexicon/src/codegen/builder_gen/tests.rs index 1f408cf0f..fae929ac9 100644 --- a/crates/jacquard-lexicon/src/codegen/builder_gen/tests.rs +++ b/crates/jacquard-lexicon/src/codegen/builder_gen/tests.rs @@ -46,49 +46,50 @@ fn test_common_types_generation() { let _parsed: syn::File = syn::parse2(tokens).expect("Generated code should parse"); } -// TODO: re-enable these tests once i have time to get them to properly check and not be order-dependent -// #[test] -// fn test_collect_required_fields_object() { -// let obj = LexObject { -// description: None, -// required: Some(vec![ -// SmolStr::new_static("foo"), -// SmolStr::new_static("barBaz"), -// ]), -// nullable: None, -// properties: Default::default(), -// }; - -// let schema = BuilderSchema::Object(&obj); -// let fields = collect_required_fields(&schema); - -// assert_eq!(fields.len(), 2); -// assert_eq!(fields[0].name_snake, "foo"); -// assert_eq!(fields[0].name_pascal, "Foo"); -// assert_eq!(fields[1].name_snake, "bar_baz"); -// assert_eq!(fields[1].name_pascal, "BarBaz"); -// } - -// #[test] -// fn test_collect_required_fields_parameters() { -// let params = LexXrpcParameters { -// description: None, -// required: Some(vec![ -// SmolStr::new_static("limit"), -// SmolStr::new_static("cursor"), -// ]), -// properties: Default::default(), -// }; - -// let schema = BuilderSchema::Parameters(¶ms); -// let fields = collect_required_fields(&schema); - -// assert_eq!(fields.len(), 2); -// assert_eq!(fields[1].name_snake, "limit"); -// assert_eq!(fields[1].name_pascal, "Limit"); -// assert_eq!(fields[0].name_snake, "cursor"); -// assert_eq!(fields[0].name_pascal, "Cursor"); -// } +#[test] +fn test_collect_required_fields_object() { + let obj = LexObject { + description: None, + required: Some(vec![ + SmolStr::new_static("foo"), + SmolStr::new_static("barBaz"), + ]), + nullable: None, + properties: Default::default(), + }; + + let schema = BuilderSchema::Object(&obj); + let fields = collect_required_fields(&schema); + + assert_eq!(fields.len(), 2); + // bar_baz comes before foo alphabetically + assert_eq!(fields[0].name_snake, "bar_baz"); + assert_eq!(fields[0].name_pascal, "BarBaz"); + assert_eq!(fields[1].name_snake, "foo"); + assert_eq!(fields[1].name_pascal, "Foo"); +} + +#[test] +fn test_collect_required_fields_parameters() { + let params = LexXrpcParameters { + description: None, + required: Some(vec![ + SmolStr::new_static("limit"), + SmolStr::new_static("cursor"), + ]), + properties: Default::default(), + }; + + let schema = BuilderSchema::Parameters(¶ms); + let fields = collect_required_fields(&schema); + + assert_eq!(fields.len(), 2); + // cursor comes before limit alphabetically + assert_eq!(fields[0].name_snake, "cursor"); + assert_eq!(fields[0].name_pascal, "Cursor"); + assert_eq!(fields[1].name_snake, "limit"); + assert_eq!(fields[1].name_pascal, "Limit"); +} #[test] fn test_state_module_generation() {