#![cfg(feature = "validator")]
use anycms_core::{ApiResult, FieldError, validation_errors_to_field_errors};
use validator::Validate;
#[derive(Debug, Validate)]
struct SimpleForm {
#[validate(email(message = "邮箱格式不正确"))]
email: String,
#[validate(length(min = 1, message = "名称不能为空"))]
name: String,
}
#[derive(Debug, Validate)]
struct NestedChild {
#[validate(length(min = 1))]
city: String,
}
#[derive(Debug, Validate)]
struct NestedParent {
#[validate(length(min = 1))]
title: String,
#[validate(nested)]
address: NestedChild,
}
#[derive(Debug, Validate)]
struct ListParent {
#[validate(length(min = 1))]
id: String,
#[validate(nested)]
items: Vec<NestedChild>,
}
#[test]
fn test_valid_data_passes() {
let form = SimpleForm {
email: "test@example.com".into(),
name: "Alice".into(),
};
assert!(form.validate().is_ok());
}
#[test]
fn test_invalid_data_to_field_errors() {
let form = SimpleForm {
email: "not-email".into(),
name: "".into(),
};
let errors = form.validate().unwrap_err();
let field_errors = validation_errors_to_field_errors(&errors);
assert_eq!(field_errors.len(), 2);
let fields: Vec<&str> = field_errors.iter().map(|e| e.field.as_str()).collect();
assert!(fields.contains(&"email"));
assert!(fields.contains(&"name"));
let email_error = field_errors.iter().find(|e| e.field == "email").unwrap();
assert_eq!(email_error.message, "邮箱格式不正确");
}
#[test]
fn test_from_validation_errors_to_api_result() {
let form = SimpleForm {
email: "bad".into(),
name: "".into(),
};
let errors = form.validate().unwrap_err();
let result: ApiResult<String> = errors.into();
assert!(!result.success);
assert!(result.data.is_none());
assert_eq!(result.code, Some(422));
assert!(result.message.is_some());
assert!(result.errors.is_some());
let errors = result.errors.unwrap();
assert_eq!(errors.len(), 2);
}
#[test]
fn test_api_result_json_format() {
let form = SimpleForm {
email: "not-email".into(),
name: "".into(),
};
let errors = form.validate().unwrap_err();
let result: ApiResult<String> = errors.into();
let json = serde_json::to_value(&result).unwrap();
assert_eq!(json["success"], false);
assert_eq!(json["code"], 422);
assert_eq!(json["message"], "Validation failed");
assert!(json["errors"].is_array());
assert!(json["data"].is_null());
}
#[test]
fn test_nested_struct_field_prefixing() {
let parent = NestedParent {
title: "valid title".into(),
address: NestedChild { city: "".into() },
};
let errors = parent.validate().unwrap_err();
let field_errors = validation_errors_to_field_errors(&errors);
assert_eq!(field_errors.len(), 1);
assert_eq!(field_errors[0].field, "address.city");
}
#[test]
fn test_nested_struct_multiple_errors() {
let parent = NestedParent {
title: "".into(),
address: NestedChild { city: "".into() },
};
let errors = parent.validate().unwrap_err();
let field_errors = validation_errors_to_field_errors(&errors);
assert_eq!(field_errors.len(), 2);
let fields: Vec<&str> = field_errors.iter().map(|e| e.field.as_str()).collect();
assert!(fields.contains(&"title"));
assert!(fields.contains(&"address.city"));
}
#[test]
fn test_list_validation_with_index_prefixing() {
let parent = ListParent {
id: "".into(),
items: vec![
NestedChild {
city: "valid".into(),
},
NestedChild { city: "".into() },
],
};
let errors = parent.validate().unwrap_err();
let field_errors = validation_errors_to_field_errors(&errors);
let fields: Vec<&str> = field_errors.iter().map(|e| e.field.as_str()).collect();
assert!(fields.contains(&"id"));
assert!(fields.contains(&"items.1.city"));
}
#[test]
fn test_empty_validation_errors() {
let form = SimpleForm {
email: "ok@test.com".into(),
name: "valid".into(),
};
let result = form.validate();
assert!(result.is_ok());
}
#[test]
fn test_single_field_error() {
let form = SimpleForm {
email: "good@example.com".into(),
name: "".into(),
};
let errors = form.validate().unwrap_err();
let field_errors = validation_errors_to_field_errors(&errors);
assert_eq!(field_errors.len(), 1);
assert_eq!(field_errors[0].field, "name");
assert_eq!(field_errors[0].message, "名称不能为空");
}
#[test]
fn test_merge_validator_errors_with_custom() {
let form = SimpleForm {
email: "ok@test.com".into(),
name: "admin".into(),
};
let mut errors: Vec<FieldError> = Vec::new();
if let Err(ve) = form.validate() {
errors.extend(validation_errors_to_field_errors(&ve));
}
errors.push(FieldError::new("name", "用户名 'admin' 已被保留"));
let result = ApiResult::<String>::validation_errors(errors);
assert!(!result.success);
assert_eq!(result.code, Some(422));
let errors = result.errors.unwrap();
assert_eq!(errors.len(), 1);
assert_eq!(errors[0].message, "用户名 'admin' 已被保留");
}