elif_orm/
event_error.rs

1use std::fmt;
2
3#[derive(Debug, Clone)]
4pub enum EventError {
5    Validation {
6        message: String,
7        hint: Option<String>,
8    },
9    Database {
10        message: String,
11    },
12    Observer {
13        message: String,
14    },
15    PropagationStopped {
16        reason: String,
17    },
18}
19
20impl EventError {
21    pub fn validation(message: &str) -> Self {
22        Self::Validation {
23            message: message.to_string(),
24            hint: None,
25        }
26    }
27
28    pub fn validation_with_hint(message: &str, hint: &str) -> Self {
29        Self::Validation {
30            message: message.to_string(),
31            hint: Some(hint.to_string()),
32        }
33    }
34
35    pub fn database(message: &str) -> Self {
36        Self::Database {
37            message: message.to_string(),
38        }
39    }
40
41    pub fn observer(message: &str) -> Self {
42        Self::Observer {
43            message: message.to_string(),
44        }
45    }
46
47    pub fn propagation_stopped(reason: &str) -> Self {
48        Self::PropagationStopped {
49            reason: reason.to_string(),
50        }
51    }
52}
53
54impl fmt::Display for EventError {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match self {
57            EventError::Validation { message, hint } => {
58                write!(f, "Validation error: {}", message)?;
59                if let Some(hint) = hint {
60                    write!(f, " (hint: {})", hint)?;
61                }
62                Ok(())
63            }
64            EventError::Database { message } => write!(f, "Database error: {}", message),
65            EventError::Observer { message } => write!(f, "Observer error: {}", message),
66            EventError::PropagationStopped { reason } => {
67                write!(f, "Event propagation stopped: {}", reason)
68            }
69        }
70    }
71}
72
73impl std::error::Error for EventError {}
74
75impl From<std::io::Error> for EventError {
76    fn from(err: std::io::Error) -> Self {
77        Self::database(&err.to_string())
78    }
79}
80
81impl From<sqlx::Error> for EventError {
82    fn from(err: sqlx::Error) -> Self {
83        Self::database(&err.to_string())
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[tokio::test]
92    async fn test_event_error_validation() {
93        let error = EventError::validation("Invalid email format");
94
95        match error {
96            EventError::Validation { message, hint } => {
97                assert_eq!(message, "Invalid email format");
98                assert!(hint.is_none());
99            }
100            _ => panic!("Expected validation error"),
101        }
102    }
103
104    #[tokio::test]
105    async fn test_event_error_validation_with_hint() {
106        let error =
107            EventError::validation_with_hint("Invalid email format", "Use format user@domain.com");
108
109        match error {
110            EventError::Validation { message, hint } => {
111                assert_eq!(message, "Invalid email format");
112                assert_eq!(hint.unwrap(), "Use format user@domain.com");
113            }
114            _ => panic!("Expected validation error"),
115        }
116    }
117
118    #[tokio::test]
119    async fn test_event_error_database() {
120        let error = EventError::database("Connection timeout");
121
122        match error {
123            EventError::Database { message, .. } => {
124                assert_eq!(message, "Connection timeout");
125            }
126            _ => panic!("Expected database error"),
127        }
128    }
129
130    #[tokio::test]
131    async fn test_event_error_observer() {
132        let error = EventError::observer("Observer failed to execute");
133
134        match error {
135            EventError::Observer { message, .. } => {
136                assert_eq!(message, "Observer failed to execute");
137            }
138            _ => panic!("Expected observer error"),
139        }
140    }
141
142    #[tokio::test]
143    async fn test_event_error_propagation_stopped() {
144        let error = EventError::propagation_stopped("User cancelled operation");
145
146        match error {
147            EventError::PropagationStopped { reason, .. } => {
148                assert_eq!(reason, "User cancelled operation");
149            }
150            _ => panic!("Expected propagation stopped error"),
151        }
152    }
153
154    #[tokio::test]
155    async fn test_event_error_display() {
156        let error = EventError::validation("Test error");
157        let display_message = format!("{}", error);
158        assert!(display_message.contains("Test error"));
159    }
160
161    #[tokio::test]
162    async fn test_event_error_debug() {
163        let error = EventError::validation("Test error");
164        let debug_message = format!("{:?}", error);
165        assert!(debug_message.contains("Validation"));
166        assert!(debug_message.contains("Test error"));
167    }
168
169    #[tokio::test]
170    async fn test_event_error_conversion_from_std_error() {
171        let std_error = std::io::Error::new(std::io::ErrorKind::Other, "IO error");
172        let event_error: EventError = std_error.into();
173
174        match event_error {
175            EventError::Database { message, .. } => {
176                assert!(message.contains("IO error"));
177            }
178            _ => panic!("Expected database error from std error conversion"),
179        }
180    }
181}