use thiserror::Error;
#[derive(Debug, Error)]
pub enum CliError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("File already exists: {0}")]
FileExists(String),
#[error("Clap error: {0}")]
Clap(String),
#[error("Generation error: {0}")]
Generation(String),
#[error("Migration error: {0}")]
Migration(String),
#[error("Cache error: {0}")]
Cache(String),
#[error("Scheduler error: {0}")]
Scheduler(String),
#[error("{0}")]
Generic(String),
}
impl From<clap::Error> for CliError {
fn from(e: clap::Error) -> Self {
CliError::Clap(e.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_io_error_display() {
let err = CliError::Io(std::io::Error::new(
std::io::ErrorKind::NotFound,
"file not found",
));
assert!(err.to_string().contains("IO error"));
assert!(err.to_string().contains("file not found"));
}
#[test]
fn test_file_exists_error_display() {
let err = CliError::FileExists("/path/to/file".to_string());
assert!(err.to_string().contains("File already exists"));
assert!(err.to_string().contains("/path/to/file"));
}
#[test]
fn test_clap_error_conversion() {
let clap_err = clap::Error::new(clap::error::ErrorKind::InvalidValue);
let cli_err: CliError = clap_err.into();
assert!(matches!(cli_err, CliError::Clap(_)));
}
#[test]
fn test_generation_error_display() {
let err = CliError::Generation("template substitution failed".to_string());
assert!(err.to_string().contains("Generation error"));
}
#[test]
fn test_migration_error_display() {
let err = CliError::Migration("database connection failed".to_string());
assert!(err.to_string().contains("Migration error"));
}
#[test]
fn test_cache_error_display() {
let err = CliError::Cache("redis connection failed".to_string());
assert!(err.to_string().contains("Cache error"));
}
#[test]
fn test_scheduler_error_display() {
let err = CliError::Scheduler("cron parse failed".to_string());
assert!(err.to_string().contains("Scheduler error"));
}
}