11//! Test BuildSchema derive for simple structs
22
33use eure:: { BuildSchema , SchemaDocument } ;
4- use eure_schema:: { SchemaNodeContent , UnknownFieldsPolicy } ;
4+ use eure_schema:: { SchemaNodeContent , SchemaNodeId , UnknownFieldsPolicy } ;
5+
6+ // ============================================================================
7+ // Assertion helpers
8+ // ============================================================================
9+
10+ fn assert_text ( schema : & SchemaDocument , id : SchemaNodeId ) {
11+ assert ! ( matches!( schema. node( id) . content, SchemaNodeContent :: Text ( _) ) ) ;
12+ }
13+
14+ fn assert_integer ( schema : & SchemaDocument , id : SchemaNodeId ) {
15+ assert ! ( matches!( schema. node( id) . content, SchemaNodeContent :: Integer ( _) ) ) ;
16+ }
17+
18+ fn assert_boolean ( schema : & SchemaDocument , id : SchemaNodeId ) {
19+ assert ! ( matches!( schema. node( id) . content, SchemaNodeContent :: Boolean ) ) ;
20+ }
21+
22+ fn assert_null ( schema : & SchemaDocument , id : SchemaNodeId ) {
23+ assert ! ( matches!( schema. node( id) . content, SchemaNodeContent :: Null ) ) ;
24+ }
25+
26+ fn assert_record < F > ( schema : & SchemaDocument , id : SchemaNodeId , check : F )
27+ where
28+ F : Fn ( & SchemaDocument , & eure_schema:: RecordSchema ) ,
29+ {
30+ let SchemaNodeContent :: Record ( record) = & schema. node ( id) . content else {
31+ panic ! ( "Expected Record, got {:?}" , schema. node( id) . content) ;
32+ } ;
33+ check ( schema, record) ;
34+ }
35+
36+ fn assert_union < F > ( schema : & SchemaDocument , id : SchemaNodeId , check : F )
37+ where
38+ F : Fn ( & SchemaDocument , & eure_schema:: UnionSchema ) ,
39+ {
40+ let SchemaNodeContent :: Union ( union) = & schema. node ( id) . content else {
41+ panic ! ( "Expected Union, got {:?}" , schema. node( id) . content) ;
42+ } ;
43+ check ( schema, union) ;
44+ }
45+
46+ fn assert_reference ( schema : & SchemaDocument , id : SchemaNodeId , type_name : & str ) {
47+ let SchemaNodeContent :: Reference ( r) = & schema. node ( id) . content else {
48+ panic ! ( "Expected Reference, got {:?}" , schema. node( id) . content) ;
49+ } ;
50+ assert_eq ! ( r. name. as_ref( ) , type_name) ;
51+ }
52+
53+ // ============================================================================
54+ // Tests
55+ // ============================================================================
556
657#[ derive( BuildSchema ) ]
758struct SimpleStruct {
@@ -13,42 +64,12 @@ struct SimpleStruct {
1364#[ test]
1465fn test_simple_struct_schema ( ) {
1566 let schema = SchemaDocument :: of :: < SimpleStruct > ( ) ;
16-
17- // Check root is a record
18- let root = schema. node ( schema. root ) ;
19- let SchemaNodeContent :: Record ( record) = & root. content else {
20- panic ! ( "Expected Record, got {:?}" , root. content) ;
21- } ;
22-
23- // Check fields exist
24- assert ! ( record. properties. contains_key( "name" ) ) ;
25- assert ! ( record. properties. contains_key( "age" ) ) ;
26- assert ! ( record. properties. contains_key( "active" ) ) ;
27-
28- // Check field types
29- let name_field = & record. properties [ "name" ] ;
30- assert ! ( !name_field. optional) ;
31- assert ! ( matches!(
32- schema. node( name_field. schema) . content,
33- SchemaNodeContent :: Text ( _)
34- ) ) ;
35-
36- let age_field = & record. properties [ "age" ] ;
37- assert ! ( !age_field. optional) ;
38- assert ! ( matches!(
39- schema. node( age_field. schema) . content,
40- SchemaNodeContent :: Integer ( _)
41- ) ) ;
42-
43- let active_field = & record. properties [ "active" ] ;
44- assert ! ( !active_field. optional) ;
45- assert ! ( matches!(
46- schema. node( active_field. schema) . content,
47- SchemaNodeContent :: Boolean
48- ) ) ;
49-
50- // Default unknown fields policy is Deny
51- assert ! ( matches!( record. unknown_fields, UnknownFieldsPolicy :: Deny ) ) ;
67+ assert_record ( & schema, schema. root , |s, rec| {
68+ assert_eq ! ( rec. properties. len( ) , 3 ) ;
69+ assert_text ( s, rec. properties [ "name" ] . schema ) ;
70+ assert_integer ( s, rec. properties [ "age" ] . schema ) ;
71+ assert_boolean ( s, rec. properties [ "active" ] . schema ) ;
72+ } ) ;
5273}
5374
5475#[ derive( BuildSchema ) ]
@@ -61,9 +82,14 @@ struct UserWithTypeName {
6182fn test_type_name_registration ( ) {
6283 let schema = SchemaDocument :: of :: < UserWithTypeName > ( ) ;
6384
64- // Check type is registered
65- let user_type = schema. types . get ( & "user" . parse ( ) . unwrap ( ) ) ;
66- assert ! ( user_type. is_some( ) ) ;
85+ // Root should reference the type
86+ assert_reference ( & schema, schema. root , "user" ) ;
87+
88+ // Type should be registered
89+ let user_id = * schema. types . values ( ) . next ( ) . expect ( "type registered" ) ;
90+ assert_record ( & schema, user_id, |s, rec| {
91+ assert_text ( s, rec. properties [ "name" ] . schema ) ;
92+ } ) ;
6793}
6894
6995#[ derive( BuildSchema ) ]
@@ -75,21 +101,17 @@ struct WithOptionalField {
75101#[ test]
76102fn test_optional_field ( ) {
77103 let schema = SchemaDocument :: of :: < WithOptionalField > ( ) ;
78-
79- let root = schema. node ( schema. root ) ;
80- let SchemaNodeContent :: Record ( record) = & root. content else {
81- panic ! ( "Expected Record" ) ;
82- } ;
83-
84- // Required field should not be optional
85- assert ! ( !record. properties[ "required" ] . optional) ;
86-
87- // Option<T> field should be optional
88- assert ! ( record. properties[ "optional" ] . optional) ;
89-
90- // The schema for Option<i32> should be a union
91- let optional_schema = schema. node ( record. properties [ "optional" ] . schema ) ;
92- assert ! ( matches!( optional_schema. content, SchemaNodeContent :: Union ( _) ) ) ;
104+ assert_record ( & schema, schema. root , |s, rec| {
105+ assert_text ( s, rec. properties [ "required" ] . schema ) ;
106+ // Optional field should have a union schema (some|none)
107+ assert_union ( s, rec. properties [ "optional" ] . schema , |s, union| {
108+ assert_eq ! ( union . variants. len( ) , 2 ) ;
109+ assert_integer ( s, union. variants [ "some" ] ) ;
110+ assert_null ( s, union. variants [ "none" ] ) ;
111+ } ) ;
112+ // Optional field should be marked as optional
113+ assert ! ( rec. properties[ "optional" ] . optional) ;
114+ } ) ;
93115}
94116
95117#[ derive( BuildSchema ) ]
@@ -102,17 +124,12 @@ struct RenamedFields {
102124#[ test]
103125fn test_rename_all ( ) {
104126 let schema = SchemaDocument :: of :: < RenamedFields > ( ) ;
105-
106- let root = schema. node ( schema. root ) ;
107- let SchemaNodeContent :: Record ( record) = & root. content else {
108- panic ! ( "Expected Record" ) ;
109- } ;
110-
111- // Fields should be renamed to kebab-case
112- assert ! ( record. properties. contains_key( "user-name" ) ) ;
113- assert ! ( record. properties. contains_key( "email-address" ) ) ;
114- assert ! ( !record. properties. contains_key( "user_name" ) ) ;
115- assert ! ( !record. properties. contains_key( "email_address" ) ) ;
127+ assert_record ( & schema, schema. root , |s, rec| {
128+ assert ! ( rec. properties. contains_key( "user-name" ) ) ;
129+ assert ! ( rec. properties. contains_key( "email-address" ) ) ;
130+ assert_text ( s, rec. properties [ "user-name" ] . schema ) ;
131+ assert_text ( s, rec. properties [ "email-address" ] . schema ) ;
132+ } ) ;
116133}
117134
118135#[ derive( BuildSchema ) ]
@@ -124,11 +141,8 @@ struct AllowUnknownFields {
124141#[ test]
125142fn test_allow_unknown_fields ( ) {
126143 let schema = SchemaDocument :: of :: < AllowUnknownFields > ( ) ;
127-
128- let root = schema. node ( schema. root ) ;
129- let SchemaNodeContent :: Record ( record) = & root. content else {
130- panic ! ( "Expected Record" ) ;
131- } ;
132-
133- assert ! ( matches!( record. unknown_fields, UnknownFieldsPolicy :: Allow ) ) ;
144+ assert_record ( & schema, schema. root , |s, rec| {
145+ assert_text ( s, rec. properties [ "name" ] . schema ) ;
146+ assert ! ( matches!( rec. unknown_fields, UnknownFieldsPolicy :: Allow ) ) ;
147+ } ) ;
134148}
0 commit comments