yesser_todo_errors/
api_error.rs1use std::fmt::Display;
2
3use thiserror::Error;
4
5use crate::server_error::ServerError;
6
7#[derive(Debug, Error)]
8pub enum ApiError {
9 ServerError(ServerError),
10 HTTPError(u16),
11 #[cfg(feature = "client")]
12 RequestError(ureq::Error),
13}
14
15#[cfg(feature = "client")]
16impl From<ureq::Error> for ApiError {
17 fn from(value: ureq::Error) -> Self {
18 ApiError::RequestError(value)
19 }
20}
21
22impl Display for ApiError {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 match self {
38 Self::ServerError(err) => err.fmt(f),
39 Self::HTTPError(status_code) => write!(f, "Server returned HTTP error code {status_code}"),
40 #[cfg(feature = "client")]
41 Self::RequestError(_) => write!(f, "Failed to connect to server"),
42 }
43 }
44}
45
46#[cfg(feature = "client")]
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn test_api_error_is_error_trait() {
53 fn assert_error<T: std::error::Error>() {}
54 assert_error::<ApiError>();
55 }
56
57 #[test]
58 fn test_api_error_debug() {
59 let err = ApiError::HTTPError(400);
60 let debug_str = format!("{:?}", err);
61 assert!(debug_str.contains("HTTPError"));
62 assert!(debug_str.contains("400"));
63 }
64
65 #[test]
66 fn test_http_error_various_status_codes() {
67 let test_cases = vec![
68 (200, "Server returned HTTP error code 200"),
69 (201, "Server returned HTTP error code 201"),
70 (403, "Server returned HTTP error code 403"),
71 (503, "Server returned HTTP error code 503"),
72 ];
73
74 for (status, expected) in test_cases {
75 let err = ApiError::HTTPError(status);
76 assert_eq!(format!("{}", err), expected);
77 }
78 }
79
80 #[test]
81 fn test_server_error_display_not_found() {
82 use crate::server_error::TaskSelector;
83 let err = ApiError::ServerError(ServerError::NotFound(TaskSelector::Name("test task".into())));
84 assert_eq!(format!("{}", err), "Task test task not found!");
85 }
86
87 #[test]
88 fn test_server_error_display_conflict() {
89 use crate::server_error::TaskSelector;
90 let err = ApiError::ServerError(ServerError::Conflict(TaskSelector::Index(1)));
91 assert_eq!(format!("{}", err), "Task of index 1 already exists!");
92 }
93
94 #[test]
95 fn test_server_error_display_io_error() {
96 let err = ApiError::ServerError(ServerError::IOError("database connection failed".into()));
97 assert_eq!(format!("{}", err), "IO error: database connection failed");
98 }
99}