tailwind_rs_core/
error.rs1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, TailwindError>;
7
8#[derive(Error, Debug)]
10pub enum TailwindError {
11 #[error("Configuration error: {message}")]
13 Config { message: String },
14
15 #[error("Theme error: {message}")]
17 Theme { message: String },
18
19 #[error("Class generation error: {message}")]
21 ClassGeneration { message: String },
22
23 #[error("Build error: {message}")]
25 Build { message: String },
26
27 #[error("Validation error: {message}")]
29 Validation { message: String },
30
31 #[error("File I/O error: {0}")]
33 Io(#[from] std::io::Error),
34
35 #[error("JSON error: {0}")]
37 Json(#[from] serde_json::Error),
38
39 #[error("Generic error: {0}")]
41 Generic(#[from] anyhow::Error),
42
43 #[error("Regex error: {0}")]
45 Regex(#[from] regex::Error),
46}
47
48impl TailwindError {
49 pub fn config(message: impl Into<String>) -> Self {
51 Self::Config {
52 message: message.into(),
53 }
54 }
55
56 pub fn theme(message: impl Into<String>) -> Self {
58 Self::Theme {
59 message: message.into(),
60 }
61 }
62
63 pub fn class_generation(message: impl Into<String>) -> Self {
65 Self::ClassGeneration {
66 message: message.into(),
67 }
68 }
69
70 pub fn build(message: impl Into<String>) -> Self {
72 Self::Build {
73 message: message.into(),
74 }
75 }
76
77 pub fn validation(message: impl Into<String>) -> Self {
79 Self::Validation {
80 message: message.into(),
81 }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_config_error() {
91 let error = TailwindError::config("Invalid configuration");
92 assert!(matches!(error, TailwindError::Config { .. }));
93 assert!(error.to_string().contains("Invalid configuration"));
94 }
95
96 #[test]
97 fn test_theme_error() {
98 let error = TailwindError::theme("Theme not found");
99 assert!(matches!(error, TailwindError::Theme { .. }));
100 assert!(error.to_string().contains("Theme not found"));
101 }
102
103 #[test]
104 fn test_class_generation_error() {
105 let error = TailwindError::class_generation("Invalid class name");
106 assert!(matches!(error, TailwindError::ClassGeneration { .. }));
107 assert!(error.to_string().contains("Invalid class name"));
108 }
109
110 #[test]
111 fn test_build_error() {
112 let error = TailwindError::build("Build failed");
113 assert!(matches!(error, TailwindError::Build { .. }));
114 assert!(error.to_string().contains("Build failed"));
115 }
116
117 #[test]
118 fn test_io_error_conversion() {
119 let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
120 let tailwind_error: TailwindError = io_error.into();
121 assert!(matches!(tailwind_error, TailwindError::Io(_)));
122 }
123
124 #[test]
125 fn test_json_error_conversion() {
126 let json_error = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
127 let tailwind_error: TailwindError = json_error.into();
128 assert!(matches!(tailwind_error, TailwindError::Json(_)));
129 }
130
131 #[test]
132 fn test_generic_error_conversion() {
133 let anyhow_error = anyhow::anyhow!("Generic error");
134 let tailwind_error: TailwindError = anyhow_error.into();
135 assert!(matches!(tailwind_error, TailwindError::Generic(_)));
136 }
137
138 #[test]
140 fn test_week17_error_handling() {
141 let config_error = TailwindError::config("Invalid configuration");
143 assert!(matches!(config_error, TailwindError::Config { .. }));
144 assert!(config_error.to_string().contains("Configuration error"));
145
146 let theme_error = TailwindError::theme("Theme not found");
147 assert!(matches!(theme_error, TailwindError::Theme { .. }));
148 assert!(theme_error.to_string().contains("Theme error"));
149
150 let class_error = TailwindError::class_generation("Invalid class name");
151 assert!(matches!(class_error, TailwindError::ClassGeneration { .. }));
152 assert!(class_error.to_string().contains("Class generation error"));
153
154 let build_error = TailwindError::build("Build failed");
155 assert!(matches!(build_error, TailwindError::Build { .. }));
156 assert!(build_error.to_string().contains("Build error"));
157
158 let validation_error = TailwindError::validation("Invalid input");
159 assert!(matches!(validation_error, TailwindError::Validation { .. }));
160 assert!(validation_error.to_string().contains("Validation error"));
161
162 let result: Result<()> = Err(config_error);
164 assert!(result.is_err());
165
166 let error = TailwindError::config("Test error");
168 let error_string = format!("{}", error);
169 let debug_string = format!("{:?}", error);
170 assert!(!error_string.is_empty());
171 assert!(!debug_string.is_empty());
172
173 assert!(error_string.contains("Configuration error"));
175 assert!(error_string.contains("Test error"));
176
177 let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
179 let converted_error: TailwindError = io_error.into();
180 assert!(matches!(converted_error, TailwindError::Io(_)));
181
182 let json_error = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
184 let json_tailwind_error: TailwindError = json_error.into();
185 assert!(matches!(json_tailwind_error, TailwindError::Json(_)));
186
187 let anyhow_error = anyhow::anyhow!("Generic error");
189 let anyhow_tailwind_error: TailwindError = anyhow_error.into();
190 assert!(matches!(anyhow_tailwind_error, TailwindError::Generic(_)));
191 }
192}
193
194#[cfg(feature = "postcss")]
195impl From<tailwind_rs_postcss::PostCSSError> for TailwindError {
196 fn from(err: tailwind_rs_postcss::PostCSSError) -> Self {
197 TailwindError::Generic(anyhow::anyhow!(err))
198 }
199}