use domainstack_derive::ToSchema;
use domainstack_schema::{OpenApiBuilder, ToSchema as ToSchemaTrait};
#[derive(ToSchema)]
#[allow(dead_code)]
struct SimpleUser {
#[validate(email)]
#[validate(max_len = 255)]
#[schema(description = "User's email address", example = "user@example.com")]
email: String,
#[validate(range(min = 18, max = 120))]
#[schema(description = "User's age")]
age: u8,
}
#[test]
fn test_simple_schema_derivation() {
let schema = SimpleUser::schema();
let json = serde_json::to_value(&schema).unwrap();
eprintln!(
"SimpleUser schema: {}",
serde_json::to_string_pretty(&json).unwrap()
);
assert_eq!(json["type"], "object");
assert!(json["properties"]["email"].is_object());
assert!(json["properties"]["age"].is_object());
assert_eq!(json["properties"]["email"]["type"], "string");
assert_eq!(json["properties"]["email"]["format"], "email");
assert_eq!(
json["properties"]["email"]["maxLength"].as_f64(),
Some(255.0)
);
assert_eq!(json["properties"]["age"]["type"], "integer");
assert_eq!(json["properties"]["age"]["minimum"].as_f64(), Some(18.0));
assert_eq!(json["properties"]["age"]["maximum"].as_f64(), Some(120.0));
assert_eq!(json["required"], serde_json::json!(["email", "age"]));
}
#[derive(ToSchema)]
#[allow(dead_code)]
struct UserWithOptional {
#[validate(email)]
email: String,
#[validate(min_len = 1)]
#[validate(max_len = 100)]
nickname: Option<String>,
}
#[test]
fn test_optional_fields() {
let schema = UserWithOptional::schema();
let json = serde_json::to_value(&schema).unwrap();
assert_eq!(json["required"], serde_json::json!(["email"]));
assert!(json["properties"]["nickname"].is_object());
assert_eq!(
json["properties"]["nickname"]["minLength"].as_f64(),
Some(1.0)
);
assert_eq!(
json["properties"]["nickname"]["maxLength"].as_f64(),
Some(100.0)
);
}
#[derive(ToSchema)]
#[allow(dead_code)]
struct Address {
#[validate(min_len = 1)]
#[validate(max_len = 100)]
street: String,
#[validate(min_len = 1)]
#[validate(max_len = 50)]
city: String,
}
#[derive(ToSchema)]
#[allow(dead_code)]
struct UserWithAddress {
#[validate(email)]
email: String,
#[validate(nested)]
address: Address,
}
#[test]
fn test_nested_types() {
let schema = UserWithAddress::schema();
let json = serde_json::to_value(&schema).unwrap();
assert!(json["properties"]["address"].is_object());
}
#[derive(ToSchema)]
#[allow(dead_code)]
struct Team {
#[validate(min_len = 1)]
#[validate(max_len = 50)]
name: String,
#[validate(each_nested)]
#[validate(min_items = 1)]
#[validate(max_items = 10)]
members: Vec<SimpleUser>,
}
#[test]
fn test_collections() {
let schema = Team::schema();
let json = serde_json::to_value(&schema).unwrap();
assert_eq!(json["properties"]["members"]["type"], "array");
assert_eq!(
json["properties"]["members"]["minItems"].as_f64(),
Some(1.0)
);
assert_eq!(
json["properties"]["members"]["maxItems"].as_f64(),
Some(10.0)
);
}
#[derive(ToSchema)]
#[allow(dead_code)]
#[schema(description = "Product in the catalog")]
struct Product {
#[validate(min_len = 1)]
#[validate(max_len = 100)]
#[schema(description = "Product name", example = "Acme Widget")]
name: String,
#[validate(range(min = 0, max = 1000000))]
#[schema(description = "Price in cents", example = 1999)]
price: i32,
}
#[test]
fn test_schema_hints() {
let schema = Product::schema();
let json = serde_json::to_value(&schema).unwrap();
assert_eq!(json["properties"]["name"]["description"], "Product name");
assert_eq!(json["properties"]["name"]["example"], "Acme Widget");
assert_eq!(json["properties"]["price"]["description"], "Price in cents");
assert_eq!(json["properties"]["price"]["example"].as_i64(), Some(1999));
}
#[test]
fn test_openapi_builder_integration() {
let spec = OpenApiBuilder::new("Test API", "1.0.0")
.description("API with auto-derived schemas")
.register::<SimpleUser>()
.register::<Product>()
.build();
let json_string = spec.to_json().unwrap();
let json: serde_json::Value = serde_json::from_str(&json_string).unwrap();
assert!(json["components"]["schemas"]["SimpleUser"].is_object());
assert!(json["components"]["schemas"]["Product"].is_object());
}
#[derive(ToSchema)]
#[allow(dead_code)]
struct PatternTest {
#[validate(alphanumeric)]
#[schema(description = "Alphanumeric only")]
code: String,
#[validate(ascii)]
#[schema(description = "ASCII characters only")]
text: String,
}
#[test]
fn test_pattern_rules() {
let schema = PatternTest::schema();
let json = serde_json::to_value(&schema).unwrap();
eprintln!(
"PatternTest schema: {}",
serde_json::to_string_pretty(&json).unwrap()
);
assert_eq!(json["properties"]["code"]["pattern"], "^[a-zA-Z0-9]*$");
assert_eq!(json["properties"]["text"]["pattern"], "^[\\x00-\\x7F]*$");
}