use thiserror::Error;
pub type Result<T> = std::result::Result<T, TailwindError>;
#[derive(Error, Debug)]
pub enum TailwindError {
#[error("Configuration error: {message}")]
Config { message: String },
#[error("Theme error: {message}")]
Theme { message: String },
#[error("Class generation error: {message}")]
ClassGeneration { message: String },
#[error("Build error: {message}")]
Build { message: String },
#[error("Validation error: {message}")]
Validation { message: String },
#[error("File I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("Generic error: {0}")]
Generic(#[from] anyhow::Error),
#[error("Regex error: {0}")]
Regex(#[from] regex::Error),
}
impl TailwindError {
pub fn config(message: impl Into<String>) -> Self {
Self::Config {
message: message.into(),
}
}
pub fn theme(message: impl Into<String>) -> Self {
Self::Theme {
message: message.into(),
}
}
pub fn class_generation(message: impl Into<String>) -> Self {
Self::ClassGeneration {
message: message.into(),
}
}
pub fn build(message: impl Into<String>) -> Self {
Self::Build {
message: message.into(),
}
}
pub fn validation(message: impl Into<String>) -> Self {
Self::Validation {
message: message.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_error() {
let error = TailwindError::config("Invalid configuration");
assert!(matches!(error, TailwindError::Config { .. }));
assert!(error.to_string().contains("Invalid configuration"));
}
#[test]
fn test_theme_error() {
let error = TailwindError::theme("Theme not found");
assert!(matches!(error, TailwindError::Theme { .. }));
assert!(error.to_string().contains("Theme not found"));
}
#[test]
fn test_class_generation_error() {
let error = TailwindError::class_generation("Invalid class name");
assert!(matches!(error, TailwindError::ClassGeneration { .. }));
assert!(error.to_string().contains("Invalid class name"));
}
#[test]
fn test_build_error() {
let error = TailwindError::build("Build failed");
assert!(matches!(error, TailwindError::Build { .. }));
assert!(error.to_string().contains("Build failed"));
}
#[test]
fn test_io_error_conversion() {
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
let tailwind_error: TailwindError = io_error.into();
assert!(matches!(tailwind_error, TailwindError::Io(_)));
}
#[test]
fn test_json_error_conversion() {
let json_error = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
let tailwind_error: TailwindError = json_error.into();
assert!(matches!(tailwind_error, TailwindError::Json(_)));
}
#[test]
fn test_generic_error_conversion() {
let anyhow_error = anyhow::anyhow!("Generic error");
let tailwind_error: TailwindError = anyhow_error.into();
assert!(matches!(tailwind_error, TailwindError::Generic(_)));
}
#[test]
fn test_week17_error_handling() {
let config_error = TailwindError::config("Invalid configuration");
assert!(matches!(config_error, TailwindError::Config { .. }));
assert!(config_error.to_string().contains("Configuration error"));
let theme_error = TailwindError::theme("Theme not found");
assert!(matches!(theme_error, TailwindError::Theme { .. }));
assert!(theme_error.to_string().contains("Theme error"));
let class_error = TailwindError::class_generation("Invalid class name");
assert!(matches!(class_error, TailwindError::ClassGeneration { .. }));
assert!(class_error.to_string().contains("Class generation error"));
let build_error = TailwindError::build("Build failed");
assert!(matches!(build_error, TailwindError::Build { .. }));
assert!(build_error.to_string().contains("Build error"));
let validation_error = TailwindError::validation("Invalid input");
assert!(matches!(validation_error, TailwindError::Validation { .. }));
assert!(validation_error.to_string().contains("Validation error"));
let result: Result<()> = Err(config_error);
assert!(result.is_err());
let error = TailwindError::config("Test error");
let error_string = format!("{}", error);
let debug_string = format!("{:?}", error);
assert!(!error_string.is_empty());
assert!(!debug_string.is_empty());
assert!(error_string.contains("Configuration error"));
assert!(error_string.contains("Test error"));
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
let converted_error: TailwindError = io_error.into();
assert!(matches!(converted_error, TailwindError::Io(_)));
let json_error = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
let json_tailwind_error: TailwindError = json_error.into();
assert!(matches!(json_tailwind_error, TailwindError::Json(_)));
let anyhow_error = anyhow::anyhow!("Generic error");
let anyhow_tailwind_error: TailwindError = anyhow_error.into();
assert!(matches!(anyhow_tailwind_error, TailwindError::Generic(_)));
}
}
#[cfg(feature = "postcss")]
impl From<tailwind_rs_postcss::PostCSSError> for TailwindError {
fn from(err: tailwind_rs_postcss::PostCSSError) -> Self {
TailwindError::Generic(anyhow::anyhow!(err))
}
}