use thiserror::Error;
pub type Result<T> = std::result::Result<T, SearchError>;
#[derive(Error, Debug)]
pub enum SearchError {
#[error("HTTP request failed: {0}")]
Http(#[from] reqwest::Error),
#[error("Failed to parse response: {0}")]
Parse(String),
#[error("Engine '{0}' is suspended until {1}")]
EngineSuspended(String, String),
#[error("Search timeout exceeded")]
Timeout,
#[error("No search engines configured")]
NoEngines,
#[error("Invalid query: {0}")]
InvalidQuery(String),
#[error("URL parsing error: {0}")]
UrlParse(#[from] url::ParseError),
#[error("Browser error: {0}")]
Browser(String),
#[error("{0}")]
Other(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display_parse() {
let err = SearchError::Parse("invalid JSON".to_string());
assert_eq!(err.to_string(), "Failed to parse response: invalid JSON");
}
#[test]
fn test_error_display_engine_suspended() {
let err = SearchError::EngineSuspended("Google".to_string(), "2024-01-01".to_string());
assert_eq!(
err.to_string(),
"Engine 'Google' is suspended until 2024-01-01"
);
}
#[test]
fn test_error_display_timeout() {
let err = SearchError::Timeout;
assert_eq!(err.to_string(), "Search timeout exceeded");
}
#[test]
fn test_error_display_no_engines() {
let err = SearchError::NoEngines;
assert_eq!(err.to_string(), "No search engines configured");
}
#[test]
fn test_error_display_invalid_query() {
let err = SearchError::InvalidQuery("empty query".to_string());
assert_eq!(err.to_string(), "Invalid query: empty query");
}
#[test]
fn test_error_display_browser() {
let err = SearchError::Browser("chrome crashed".to_string());
assert_eq!(err.to_string(), "Browser error: chrome crashed");
}
#[test]
fn test_error_display_other() {
let err = SearchError::Other("something went wrong".to_string());
assert_eq!(err.to_string(), "something went wrong");
}
#[test]
fn test_error_debug() {
let err = SearchError::Timeout;
let debug_str = format!("{:?}", err);
assert!(debug_str.contains("Timeout"));
}
#[test]
fn test_error_url_parse() {
let url_err = url::Url::parse("not a url").unwrap_err();
let err: SearchError = url_err.into();
let msg = err.to_string();
assert!(msg.contains("URL parsing error"));
}
#[test]
fn test_error_display_all_variants() {
let errors: Vec<SearchError> = vec![
SearchError::Parse("parse error".to_string()),
SearchError::EngineSuspended("engine".to_string(), "date".to_string()),
SearchError::Timeout,
SearchError::NoEngines,
SearchError::InvalidQuery("bad query".to_string()),
SearchError::Browser("browser error".to_string()),
SearchError::Other("other error".to_string()),
];
for err in errors {
assert!(!err.to_string().is_empty());
}
}
}