#[derive(Debug, Clone)]
pub struct ValidationError {
pub message: String,
}
impl std::fmt::Display for ValidationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.message)
}
}
impl std::error::Error for ValidationError {}
impl From<String> for ValidationError {
fn from(message: String) -> Self {
Self { message }
}
}
impl From<&str> for ValidationError {
fn from(message: &str) -> Self {
Self {
message: message.to_string(),
}
}
}
pub trait Validate {
fn validate(&self) -> Result<(), ValidationError>;
}
#[cfg(test)]
mod tests {
use super::*;
struct ValidUser;
impl Validate for ValidUser {
fn validate(&self) -> Result<(), ValidationError> {
Ok(())
}
}
struct InvalidUser;
impl Validate for InvalidUser {
fn validate(&self) -> Result<(), ValidationError> {
Err("always fails".into())
}
}
#[test]
fn valid_passes() {
assert!(ValidUser.validate().is_ok());
}
#[test]
fn invalid_fails() {
let err = InvalidUser.validate().unwrap_err();
assert_eq!(err.message, "always fails");
assert_eq!(err.to_string(), "always fails");
}
#[test]
fn error_from_string() {
let err = ValidationError::from("test".to_string());
assert_eq!(err.message, "test");
}
#[test]
fn error_from_str() {
let err = ValidationError::from("test");
assert_eq!(err.message, "test");
}
#[test]
fn error_display() {
let err = ValidationError::from("display test");
assert_eq!(format!("{err}"), "display test");
}
#[test]
fn error_debug() {
let err = ValidationError::from("debug test");
let debug = format!("{err:?}");
assert!(debug.contains("debug test"));
}
}