use anyhow::{anyhow, Result};
use debtmap::core::monadic::ResultExt;
#[test]
fn test_map_err_context_adds_context_on_error() {
let result: Result<i32> = Err(anyhow!("original error"));
let with_context = result.map_err_context("additional context");
assert!(with_context.is_err());
let error_string = format!("{:?}", with_context.unwrap_err());
assert!(error_string.contains("additional context"));
assert!(error_string.contains("original error"));
}
#[test]
fn test_map_err_context_preserves_ok_value() {
let result: Result<i32> = Ok(42);
let with_context = result.map_err_context("this context won't be used");
assert!(with_context.is_ok());
assert_eq!(with_context.unwrap(), 42);
}
#[test]
fn test_map_err_context_with_formatted_message() {
let value = 10;
let result: Result<i32> = Err(anyhow!("failed"));
let with_context = result.map_err_context(format!("Processing value {value}"));
assert!(with_context.is_err());
let error_string = format!("{:?}", with_context.unwrap_err());
assert!(error_string.contains("Processing value 10"));
}
#[test]
fn test_and_then_async_chains_operations() {
let result: Result<i32> = Ok(5);
let chained = result
.and_then_async(|x| Ok(x * 2))
.and_then_async(|x| Ok(x + 3));
assert!(chained.is_ok());
assert_eq!(chained.unwrap(), 13); }
#[test]
fn test_and_then_async_stops_on_first_error() {
let result: Result<i32> = Ok(5);
let chained = result
.and_then_async(|_| Err(anyhow!("first error")))
.and_then_async(|x: i32| Ok(x + 3));
assert!(chained.is_err());
let error_string = format!("{:?}", chained.unwrap_err());
assert!(error_string.contains("first error"));
}
#[test]
fn test_or_else_with_provides_alternative() {
let result: Result<i32> = Err(anyhow!("original error"));
let with_alternative = result.or_else_with(|| Ok(100));
assert!(with_alternative.is_ok());
assert_eq!(with_alternative.unwrap(), 100);
}
#[test]
fn test_or_else_with_preserves_ok() {
let result: Result<i32> = Ok(42);
let with_alternative = result.or_else_with(|| Ok(100));
assert!(with_alternative.is_ok());
assert_eq!(with_alternative.unwrap(), 42); }
#[test]
fn test_or_else_with_can_also_fail() {
let result: Result<i32> = Err(anyhow!("original error"));
let with_alternative = result.or_else_with(|| Err(anyhow!("alternative error")));
assert!(with_alternative.is_err());
let error_string = format!("{:?}", with_alternative.unwrap_err());
assert!(error_string.contains("alternative error"));
}
#[test]
fn test_map_ok_transforms_value() {
let result: Result<i32> = Ok(10);
let mapped = result.map_ok(|x| x.to_string());
assert!(mapped.is_ok());
assert_eq!(mapped.unwrap(), "10");
}
#[test]
fn test_map_ok_preserves_error() {
let result: Result<i32> = Err(anyhow!("error"));
let mapped = result.map_ok(|x| x.to_string());
assert!(mapped.is_err());
let error_string = format!("{:?}", mapped.unwrap_err());
assert!(error_string.contains("error"));
}
#[test]
fn test_tap_inspects_ok_value() {
let mut side_effect = 0;
let result: Result<i32> = Ok(42);
let tapped = result.tap(|&x| {
side_effect = x * 2;
});
assert!(tapped.is_ok());
assert_eq!(tapped.unwrap(), 42); assert_eq!(side_effect, 84); }
#[test]
fn test_tap_skips_on_error() {
let mut side_effect = 0;
let result: Result<i32> = Err(anyhow!("error"));
let tapped = result.tap(|&x| {
side_effect = x * 2;
});
assert!(tapped.is_err());
assert_eq!(side_effect, 0); }
#[test]
fn test_tap_err_inspects_error() {
let mut error_message = String::new();
let result: Result<i32> = Err(anyhow!("test error"));
let tapped = result.tap_err(|e| {
error_message = format!("{e}");
});
assert!(tapped.is_err());
assert!(error_message.contains("test error")); }
#[test]
fn test_tap_err_skips_on_ok() {
let mut error_message = String::new();
let result: Result<i32> = Ok(42);
let tapped = result.tap_err(|e| {
error_message = format!("{e}");
});
assert!(tapped.is_ok());
assert_eq!(tapped.unwrap(), 42);
assert_eq!(error_message, ""); }
#[test]
fn test_chaining_multiple_extensions() {
let result: Result<i32> = Ok(5);
let final_result = result
.map_ok(|x| x * 2)
.and_then_async(|x| Ok(x + 1))
.tap(|&x| assert_eq!(x, 11))
.map_err_context("Failed to process number");
assert!(final_result.is_ok());
assert_eq!(final_result.unwrap(), 11);
}
#[test]
fn test_error_handling_chain() {
let result: Result<i32> = Err(anyhow!("initial error"));
let final_result = result
.map_err_context("step 1 failed")
.or_else_with(|| Ok(10))
.and_then_async(|x| Ok(x * 2))
.tap(|&x| assert_eq!(x, 20));
assert!(final_result.is_ok());
assert_eq!(final_result.unwrap(), 20);
}