1use std::fmt::{Debug, Display};
7
8pub struct TestResult<T, E> {
10 inner: Result<T, E>,
11 context: Option<String>,
12}
13
14impl<T: Debug, E: Display + Debug> TestResult<T, E> {
15 pub fn new(result: Result<T, E>) -> Self {
16 Self {
17 inner: result,
18 context: None,
19 }
20 }
21
22 pub fn with_context(mut self, context: &str) -> Self {
23 self.context = Some(context.to_string());
24 self
25 }
26
27 fn format_context(&self) -> String {
28 self.context
29 .as_ref()
30 .map(|c| format!("\nContext: {}", c))
31 .unwrap_or_default()
32 }
33
34 pub fn assert_success(self) -> T {
36 let ctx = self.format_context();
37 match self.inner {
38 Ok(val) => val,
39 Err(e) => {
40 panic!(
41 "\n🔴 TEST FAILED (Expected Success, but got Error):{}\nMessage: {}\nError Debug: {:?}\n",
42 ctx, e, e
43 );
44 }
45 }
46 }
47
48 pub fn assert_success_is<Exp>(self, expected: Exp) -> T
51 where
52 T: PartialEq<Exp>,
53 Exp: Debug,
54 {
55 let ctx = self.format_context();
56 let val = self.assert_success();
57 if val != expected {
58 panic!(
59 "\n🔴 TEST FAILED (Value Mismatch):{}\nExpected: {:?}\nGot: {:?}\n",
60 ctx, expected, val
61 );
62 }
63 val
64 }
65
66 pub fn assert_success_with<F>(self, f: F) -> T
69 where
70 F: FnOnce(&T),
71 {
72 let val = self.assert_success();
73 f(&val);
74 val
75 }
76
77 pub fn assert_success_debug(self, expected_debug: &str) -> T {
80 let ctx = self.format_context();
81 let val = self.assert_success();
82 let actual_debug = format!("{:?}", val);
83 if actual_debug != expected_debug {
84 panic!(
85 "\n🔴 TEST FAILED (Debug Mismatch):{}\nExpected: {:?}\nGot: {:?}\n",
86 ctx, expected_debug, actual_debug
87 );
88 }
89 val
90 }
91
92 pub fn assert_failure(self) -> E {
94 let ctx = self.format_context();
95 match self.inner {
96 Ok(val) => {
97 panic!(
98 "\n🔴 TEST FAILED (Expected Failure, but got Success):{}\nParsed Value: {:?}\n",
99 ctx, val
100 );
101 }
102 Err(e) => e,
103 }
104 }
105
106 pub fn assert_failure_contains(self, expected_msg_part: &str) {
108 let ctx = self.format_context();
109 let err = self.assert_failure();
110 let actual_msg = err.to_string();
111 if !actual_msg.contains(expected_msg_part) {
112 panic!(
113 "\n🔴 TEST FAILED (Error Message Mismatch):{}\nExpected part: {:?}\nActual msg: {:?}\nError Debug: {:?}\n",
114 ctx, expected_msg_part, actual_msg, err
115 );
116 }
117 }
118
119 pub fn assert_success_contains(self, expected_part: &str) -> T
121 where
122 T: Display,
123 {
124 let ctx = self.format_context();
125 let val = self.assert_success();
126 let val_str = val.to_string();
127 if !val_str.contains(expected_part) {
128 panic!(
129 "\n🔴 TEST FAILED (Content Mismatch):{}\nExpected to contain: {:?}\nGot: {:?}\n",
130 ctx, expected_part, val_str
131 );
132 }
133 val
134 }
135}
136
137pub trait Testable<T, E> {
138 fn test(self) -> TestResult<T, E>;
139}
140
141#[cfg(feature = "syn")]
142impl<T: Debug> Testable<T, syn::Error> for syn::Result<T> {
143 fn test(self) -> TestResult<T, syn::Error> {
144 TestResult::new(self)
145 }
146}