Skip to content

Commit 2683fd6

Browse files
committed
Refactor BuildSchema tests and fix type_name handling
- Update BuildSchema tests to use helper assertion functions instead of many individual assertions (addressing visual clutter feedback) - Fix SchemaBuilder::build() to return a Reference node for types with type_name, matching expected behavior where root references the registered type in $types - Add PartialEq derives to all schema types for equality comparison - Add custom PartialEq for TextSchema to compare Regex by pattern string
1 parent 7e28105 commit 2683fd6

File tree

4 files changed

+273
-219
lines changed

4 files changed

+273
-219
lines changed
Lines changed: 87 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,58 @@
11
//! Test BuildSchema derive for simple structs
22
33
use 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)]
758
struct SimpleStruct {
@@ -13,42 +64,12 @@ struct SimpleStruct {
1364
#[test]
1465
fn 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 {
6182
fn 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]
76102
fn 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]
103125
fn 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]
125142
fn 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

Comments
 (0)