use night_fury_core::NightFuryError;
use tail_fin_core::SiteError;
#[derive(Debug, thiserror::Error)]
pub enum TailFinError {
#[error("not logged in: auth cookie not found")]
AuthRequired,
#[error("browser error: {0}")]
Browser(#[from] NightFuryError),
#[error("API error: {0}")]
Api(String),
#[error("HTTP {status} {status_text} — body: {body}")]
Http {
status: u16,
status_text: String,
body: String,
},
#[error("IO error: {0}")]
Io(String),
#[error("parse error: {0}")]
Parse(String),
#[error("site error: {0}")]
Site(#[from] SiteError),
}
impl From<serde_json::Error> for TailFinError {
fn from(e: serde_json::Error) -> Self {
TailFinError::Parse(e.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serde_json_error_converts_to_parse_variant() {
let bad_json = "not json at all";
let serde_err: serde_json::Error =
serde_json::from_str::<serde_json::Value>(bad_json).unwrap_err();
let tail_err: TailFinError = serde_err.into();
match &tail_err {
TailFinError::Parse(msg) => assert!(!msg.is_empty()),
other => panic!("expected Parse variant, got {:?}", other),
}
}
#[test]
fn display_auth_required() {
let err = TailFinError::AuthRequired;
assert_eq!(err.to_string(), "not logged in: auth cookie not found");
}
#[test]
fn display_api_error() {
let err = TailFinError::Api("rate limited".into());
assert_eq!(err.to_string(), "API error: rate limited");
}
#[test]
fn display_http_error_includes_status_and_body() {
let err = TailFinError::Http {
status: 403,
status_text: "Forbidden".into(),
body: "invalid token".into(),
};
let s = err.to_string();
assert!(s.contains("403"), "expected status in: {s}");
assert!(s.contains("Forbidden"), "expected status text in: {s}");
assert!(s.contains("invalid token"), "expected body in: {s}");
}
#[test]
fn display_io_error() {
let err = TailFinError::Io("file not found".into());
assert_eq!(err.to_string(), "IO error: file not found");
}
#[test]
fn display_parse_error() {
let err = TailFinError::Parse("unexpected token".into());
assert_eq!(err.to_string(), "parse error: unexpected token");
}
#[test]
fn debug_output_is_not_empty() {
let err = TailFinError::AuthRequired;
let debug = format!("{:?}", err);
assert!(!debug.is_empty());
}
#[test]
fn tail_fin_error_from_site_error() {
let site_err = SiteError::ManualLoginRequired { site: "shopee" };
let tail_err: TailFinError = site_err.into();
match tail_err {
TailFinError::Site(_) => {}
other => panic!("expected Site variant, got {other:?}"),
}
}
}