use ig_client::error::{AppError, AuthError, FetchError};
use reqwest::StatusCode;
use serde_json::Error as JsonError;
use sqlx::Error as SqlxError;
use std::error::Error;
use std::fmt::{self, Display};
use std::io::{Error as IoError, ErrorKind};
#[derive(Debug)]
struct TestError(String);
impl Display for TestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TestError: {}", self.0)
}
}
impl Error for TestError {}
fn assert_display_contains<T: Display>(value: &T, expected: &str) {
let display_string = value.to_string();
assert!(
display_string.contains(expected),
"Expected '{display_string}' to contain '{expected}', but it didn't"
);
}
#[test]
fn test_app_error_from_io_error() {
let io_error = IoError::new(ErrorKind::NotFound, "file not found");
let app_error = AppError::from(io_error);
match app_error {
AppError::Io(_) => {
}
_ => panic!("Expected AppError::Io, got {app_error:?}"),
}
assert_display_contains(&app_error, "io error");
}
#[test]
fn test_app_error_from_serde_json_error() {
let json_str = r#"{"invalid": json"#;
let json_error: JsonError = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
let app_error = AppError::from(json_error);
match app_error {
AppError::Json(_) => {
}
_ => panic!("Expected AppError::Json, got {app_error:?}"),
}
assert_display_contains(&app_error, "json error");
}
#[test]
fn test_app_error_from_sqlx_error() {
let sqlx_error = SqlxError::RowNotFound;
let app_error = AppError::from(sqlx_error);
match app_error {
AppError::Db(_) => {
}
_ => panic!("Expected AppError::Db, got {app_error:?}"),
}
assert_display_contains(&app_error, "db error");
}
#[test]
fn test_app_error_from_auth_error() {
let auth_error = AuthError::BadCredentials;
let app_error = AppError::from(auth_error);
match app_error {
AppError::Unauthorized => {
}
_ => panic!("Expected AppError::Unauthorized, got {app_error:?}"),
}
assert_display_contains(&app_error, "unauthorized");
let auth_error = AuthError::Unexpected(StatusCode::INTERNAL_SERVER_ERROR);
let app_error = AppError::from(auth_error);
match app_error {
AppError::Unexpected(_) => {
}
_ => panic!("Expected AppError::Unexpected, got {app_error:?}"),
}
}
#[test]
fn test_app_error_unauthorized() {
let app_error = AppError::Unauthorized;
assert_display_contains(&app_error, "unauthorized");
}
#[test]
fn test_app_error_not_found() {
let app_error = AppError::NotFound;
assert_display_contains(&app_error, "not found");
}
#[test]
fn test_app_error_rate_limit_exceeded() {
let app_error = AppError::RateLimitExceeded;
assert_display_contains(&app_error, "rate limit exceeded");
}
#[test]
fn test_app_error_serialization_error() {
let app_error = AppError::SerializationError("test error".to_string());
assert_display_contains(&app_error, "serialization error");
assert_display_contains(&app_error, "test error");
}
#[test]
fn test_app_error_websocket_error() {
let app_error = AppError::WebSocketError("connection closed".to_string());
assert_display_contains(&app_error, "websocket error");
assert_display_contains(&app_error, "connection closed");
}
#[test]
fn test_app_error_unexpected() {
let app_error = AppError::Unexpected(StatusCode::BAD_REQUEST);
assert_display_contains(&app_error, "unexpected http status");
assert_display_contains(&app_error, "400");
}
#[test]
fn test_app_error_invalid_input() {
let app_error = AppError::InvalidInput("invalid parameter".to_string());
assert_display_contains(&app_error, "invalid input");
assert_display_contains(&app_error, "invalid parameter");
}
#[test]
fn test_app_error_deserialization() {
let app_error = AppError::Deserialization("failed to deserialize".to_string());
assert_display_contains(&app_error, "deserialization error");
assert_display_contains(&app_error, "failed to deserialize");
}
#[test]
fn test_app_error_from_box_dyn_error() {
let io_error = IoError::new(ErrorKind::NotFound, "file not found");
let boxed_error: Box<dyn Error> = Box::new(io_error);
let app_error = AppError::from(boxed_error);
match app_error {
AppError::Io(_) => {
}
_ => panic!("Expected AppError::Io, got {app_error:?}"),
}
let json_str = r#"{"invalid": json"#;
let json_error: JsonError = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
let boxed_error: Box<dyn Error> = Box::new(json_error);
let app_error = AppError::from(boxed_error);
match app_error {
AppError::Json(_) => {
}
_ => panic!("Expected AppError::Json, got {app_error:?}"),
}
let boxed_error: Box<dyn Error> = Box::new(TestError("test error".to_string()));
let app_error = AppError::from(boxed_error);
match app_error {
AppError::Unexpected(_) => {
}
_ => panic!("Expected AppError::Unexpected, got {app_error:?}"),
}
}
#[test]
fn test_auth_error_display() {
let auth_error = AuthError::BadCredentials;
assert_display_contains(&auth_error, "bad credentials");
let auth_error = AuthError::Other("network error".to_string());
assert_display_contains(&auth_error, "network error");
let auth_error = AuthError::Other("custom error".to_string());
assert_display_contains(&auth_error, "other error");
assert_display_contains(&auth_error, "custom error");
}
#[test]
fn test_auth_error_from_box_dyn_error() {
let io_error = IoError::new(ErrorKind::NotFound, "file not found");
let boxed_error: Box<dyn Error> = Box::new(io_error);
let auth_error = AuthError::from(boxed_error);
match auth_error {
AuthError::Io(_) => {
}
_ => panic!("Expected AuthError::Io, got {auth_error:?}"),
}
let json_str = r#"{"invalid": json"#;
let json_error: JsonError = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
let boxed_error: Box<dyn Error> = Box::new(json_error);
let auth_error = AuthError::from(boxed_error);
match auth_error {
AuthError::Json(_) => {
}
_ => panic!("Expected AuthError::Json, got {auth_error:?}"),
}
let boxed_error: Box<dyn Error> = Box::new(TestError("test error".to_string()));
let auth_error = AuthError::from(boxed_error);
match auth_error {
AuthError::Other(_) => {
}
_ => panic!("Expected AuthError::Other, got {auth_error:?}"),
}
}
#[test]
fn test_auth_error_from_box_dyn_error_send_sync() {
let io_error = IoError::new(ErrorKind::NotFound, "file not found");
let boxed_error: Box<dyn Error + Send + Sync> = Box::new(io_error);
let auth_error = AuthError::from(boxed_error);
match auth_error {
AuthError::Io(_) => {
}
_ => panic!("Expected AuthError::Io, got {auth_error:?}"),
}
let json_str = r#"{"invalid": json"#;
let json_error: JsonError = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
let boxed_error: Box<dyn Error + Send + Sync> = Box::new(json_error);
let auth_error = AuthError::from(boxed_error);
match auth_error {
AuthError::Json(_) => {
}
_ => panic!("Expected AuthError::Json, got {auth_error:?}"),
}
let boxed_error: Box<dyn Error + Send + Sync> = Box::new(TestError("test error".to_string()));
let auth_error = AuthError::from(boxed_error);
match auth_error {
AuthError::Other(_) => {
}
_ => panic!("Expected AuthError::Other, got {auth_error:?}"),
}
}
#[test]
fn test_fetch_error_display() {
let fetch_error = FetchError::Parser("parsing failed".to_string());
assert_display_contains(&fetch_error, "parser error");
assert_display_contains(&fetch_error, "parsing failed");
let fetch_error = FetchError::Sqlx(SqlxError::RowNotFound);
assert_display_contains(&fetch_error, "db error");
}
#[test]
fn test_auth_error_rate_limit_exceeded() {
let auth_error = AuthError::RateLimitExceeded;
assert_display_contains(&auth_error, "rate limit exceeded");
}
#[test]
fn test_auth_error_unexpected() {
let auth_error = AuthError::Unexpected(StatusCode::BAD_REQUEST);
assert_display_contains(&auth_error, "unexpected http status");
assert_display_contains(&auth_error, "400");
}
#[test]
fn test_app_error_historical_data_allowance_exceeded() {
let error = AppError::HistoricalDataAllowanceExceeded {
allowance_expiry: 604800,
};
assert_display_contains(&error, "historical data allowance exceeded");
assert_display_contains(&error, "604800");
}
#[test]
fn test_app_error_historical_data_allowance_exceeded_zero_expiry() {
let error = AppError::HistoricalDataAllowanceExceeded {
allowance_expiry: 0,
};
assert_display_contains(&error, "historical data allowance exceeded");
assert_display_contains(&error, "0 seconds");
}
#[test]
fn test_app_error_historical_data_allowance_is_not_rate_limit() {
let historical = AppError::HistoricalDataAllowanceExceeded {
allowance_expiry: 3600,
};
let rate_limit = AppError::RateLimitExceeded;
let historical_msg = historical.to_string();
let rate_limit_msg = rate_limit.to_string();
assert_ne!(historical_msg, rate_limit_msg);
assert!(historical_msg.contains("historical data allowance"));
assert!(!historical_msg.contains("rate limit exceeded"));
}