use errcraft::{ErrFrame, ErrResult};
#[test]
fn test_basic_error_creation() {
let err = ErrFrame::new("Test error");
assert_eq!(err.message(), "Test error");
}
#[test]
fn test_error_with_context() {
let err = ErrFrame::new("Database error")
.context("table", "users")
.context("id", 42);
assert_eq!(err.message(), "Database error");
let context_vec: Vec<_> = err.context_layers().collect();
assert_eq!(context_vec.len(), 2);
}
#[test]
fn test_error_with_text_context() {
let err = ErrFrame::new("Upload failed").context_text("File too large");
let context_vec: Vec<_> = err.context_layers().collect();
assert_eq!(context_vec.len(), 1);
assert!(context_vec[0].key().is_none());
}
#[test]
fn test_error_with_source() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let err = ErrFrame::new("Failed to read file").with_source(io_err);
assert_eq!(err.message(), "Failed to read file");
assert!(std::error::Error::source(&err).is_some());
}
#[test]
fn test_error_chaining() {
let inner = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
let middle = ErrFrame::new("Could not write file").with_source(inner);
let outer = ErrFrame::new("Configuration update failed").with_source(middle);
assert_eq!(outer.message(), "Configuration update failed");
}
#[test]
fn test_display_impl() {
let err = ErrFrame::new("Test error").context("key", "value");
let display = format!("{}", err);
assert!(display.contains("Test error"));
assert!(display.contains("key=value"));
}
#[test]
fn test_craft_macro() {
let err = errcraft::craft!("Error: {}", 404);
assert_eq!(err.message(), "Error: 404");
}
#[test]
fn test_bail_macro() {
fn failing_function() -> ErrResult<()> {
errcraft::bail!("Something went wrong");
}
let result = failing_function();
assert!(result.is_err());
assert_eq!(result.unwrap_err().message(), "Something went wrong");
}
#[test]
fn test_ensure_macro() {
fn check_value(x: i32) -> ErrResult<()> {
errcraft::ensure!(x > 0, "Value must be positive");
Ok(())
}
assert!(check_value(5).is_ok());
assert!(check_value(-1).is_err());
}
#[test]
fn test_from_std_error() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "not found");
let err = ErrFrame::new("IO error occurred").with_source(io_err);
assert!(err.message().contains("IO error"));
}
#[test]
fn test_display_options() {
use errcraft::{ColorMode, DisplayOptions};
let opts = DisplayOptions::new()
.with_emoji(true)
.with_color(ColorMode::Never)
.with_max_depth(Some(3));
assert!(opts.emoji);
assert_eq!(opts.color, ColorMode::Never);
assert_eq!(opts.max_depth, Some(3));
}
#[test]
fn test_styled_output() {
use errcraft::DisplayOptions;
let err = ErrFrame::new("Test error").context("key", "value");
let opts = DisplayOptions::new();
let output = err.to_string_styled(&opts);
assert!(output.contains("Error:"));
assert!(output.contains("Test error"));
}
#[test]
fn test_backtrace_capture() {
let err = ErrFrame::new("Test with backtrace").capture_backtrace();
assert_eq!(err.message(), "Test with backtrace");
}
#[cfg(feature = "serde")]
#[test]
fn test_json_serialization() {
let err = ErrFrame::new("JSON test").context("key", "value");
let json = err.to_json();
assert!(json["message"].as_str().unwrap().contains("JSON test"));
let json_str = err.to_json_string();
assert!(json_str.contains("JSON test"));
}
#[cfg(feature = "markdown")]
#[test]
fn test_markdown_output() {
let err = ErrFrame::new("Markdown test").context("key", "value");
let md = err.to_markdown();
assert!(md.contains("# Error"));
assert!(md.contains("Markdown test"));
}
#[cfg(feature = "anyhow")]
#[test]
fn test_anyhow_conversion() {
let anyhow_err = anyhow::anyhow!("anyhow error");
let err: ErrFrame = anyhow_err.into();
assert!(err.message().contains("anyhow error"));
}
#[test]
fn test_multiple_context_layers() {
let err = ErrFrame::new("Multi-context error")
.context("layer1", "value1")
.context("layer2", "value2")
.context("layer3", "value3")
.context_text("Additional info");
let layers: Vec<_> = err.context_layers().collect();
assert_eq!(layers.len(), 4);
}
#[test]
fn test_nested_error_source_chain() {
let e1 = std::io::Error::new(std::io::ErrorKind::NotFound, "base error");
let e2 = ErrFrame::new("level 2").with_source(e1);
let e3 = ErrFrame::new("level 3").with_source(e2);
assert_eq!(e3.message(), "level 3");
let source = std::error::Error::source(&e3);
assert!(source.is_some());
}