#[cfg(feature = "derive")]
mod tests {
use web_core_validator::{ValidateArgs, ValidationError};
#[derive(Clone, Copy)]
struct TestContext {
min_length: usize,
}
async fn validate_name_with_context(
name: &str,
context: &TestContext,
) -> Result<(), ValidationError> {
if name.len() < context.min_length {
return Err(ValidationError::new("too_short_name"));
}
Ok(())
}
#[derive(web_core_validator_derive::Validate)]
#[validate(context = "TestContext")]
struct ChildWithContext {
#[validate(custom(function = "validate_name_with_context", use_context))]
name: String,
}
#[derive(web_core_validator_derive::Validate)]
#[validate(context = "TestContext")]
struct ParentWithNestedContext {
#[validate(nested(use_context))]
child: ChildWithContext,
}
#[derive(web_core_validator_derive::Validate)]
#[validate(context = "TestContext")]
struct ParentWithOptionalNestedContext {
#[validate(nested(use_context))]
child: Option<ChildWithContext>,
}
#[derive(web_core_validator_derive::Validate)]
#[validate(context = "TestContext")]
struct ParentWithVecNestedContext {
#[validate(nested(use_context))]
children: Vec<ChildWithContext>,
}
#[derive(web_core_validator_derive::Validate)]
#[validate(context = "TestContext")]
struct DeepParent {
#[validate(nested(use_context))]
middle: MiddleParent,
}
#[derive(web_core_validator_derive::Validate)]
#[validate(context = "TestContext")]
struct MiddleParent {
#[validate(nested(use_context))]
child: ChildWithContext,
}
#[tokio::test]
async fn test_nested_use_context_basic() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithNestedContext {
child: ChildWithContext {
name: "ab".to_string(), },
};
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_err());
let err = result.unwrap_err();
let err_str = format!("{}", err);
assert!(err_str.contains("child"));
}
#[tokio::test]
async fn test_nested_use_context_valid() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithNestedContext {
child: ChildWithContext {
name: "abcd".to_string(), },
};
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_nested_use_context_with_option_some() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithOptionalNestedContext {
child: Some(ChildWithContext {
name: "ab".to_string(), }),
};
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_nested_use_context_with_option_none() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithOptionalNestedContext { child: None };
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_ok()); }
#[tokio::test]
async fn test_nested_use_context_with_option_valid() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithOptionalNestedContext {
child: Some(ChildWithContext {
name: "abcd".to_string(), }),
};
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_nested_use_context_with_vec_valid() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithVecNestedContext {
children: vec![
ChildWithContext {
name: "abcd".to_string(), },
ChildWithContext {
name: "efgh".to_string(), },
],
};
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_nested_use_context_with_vec_invalid() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithVecNestedContext {
children: vec![ChildWithContext {
name: "ab".to_string(), }],
};
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_nested_use_context_with_multiple_vec_errors() {
let mut context = TestContext { min_length: 3 };
let parent = ParentWithVecNestedContext {
children: vec![
ChildWithContext {
name: "ab".to_string(), },
ChildWithContext {
name: "a".to_string(), },
],
};
let result = parent.validate_with_args(&mut context).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_deep_nesting_use_context() {
let mut context = TestContext { min_length: 3 };
let deep = DeepParent {
middle: MiddleParent {
child: ChildWithContext {
name: "ab".to_string(), },
},
};
let result = deep.validate_with_args(&mut context).await;
assert!(result.is_err());
let err = result.unwrap_err();
let err_str = format!("{}", err);
assert!(err_str.contains("middle"));
assert!(err_str.contains("child"));
}
#[tokio::test]
async fn test_deep_nesting_use_context_valid() {
let mut context = TestContext { min_length: 3 };
let deep = DeepParent {
middle: MiddleParent {
child: ChildWithContext {
name: "valid".to_string(),
},
},
};
let result = deep.validate_with_args(&mut context).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_context_propagation_changes_validation() {
let mut strict_context = TestContext { min_length: 5 };
let parent = ParentWithNestedContext {
child: ChildWithContext {
name: "abcd".to_string(), },
};
assert!(
parent
.validate_with_args(&mut strict_context)
.await
.is_err()
);
let mut lenient_context = TestContext { min_length: 3 };
assert!(
parent
.validate_with_args(&mut lenient_context)
.await
.is_ok()
);
}
}