fluent_test/backend/matchers/
option.rs

1use crate::backend::Assertion;
2use crate::backend::assertions::sentence::AssertionSentence;
3use std::fmt::Debug;
4
5/// Trait for Option<T> assertions
6pub trait OptionMatchers<T: Debug> {
7    fn to_be_some(self) -> Self;
8    fn to_be_none(self) -> Self;
9    fn to_contain(self, expected: &T) -> Self
10    where
11        T: PartialEq;
12}
13
14/// Helper trait for Optiony types
15trait AsOption {
16    type Item: Debug;
17
18    fn is_some_option(&self) -> bool;
19    fn is_none_option(&self) -> bool;
20    fn contains_item<U>(&self, expected: &U) -> bool
21    where
22        U: PartialEq<Self::Item>;
23}
24
25// Implementation for Option<T>
26impl<T: Debug + PartialEq> AsOption for Option<T> {
27    type Item = T;
28
29    fn is_some_option(&self) -> bool {
30        self.is_some()
31    }
32
33    fn is_none_option(&self) -> bool {
34        self.is_none()
35    }
36
37    fn contains_item<U>(&self, expected: &U) -> bool
38    where
39        U: PartialEq<Self::Item>,
40    {
41        match self {
42            Some(actual) => expected == actual,
43            None => false,
44        }
45    }
46}
47
48// Implementation for &Option<T>
49impl<T: Debug + PartialEq> AsOption for &Option<T> {
50    type Item = T;
51
52    fn is_some_option(&self) -> bool {
53        self.is_some()
54    }
55
56    fn is_none_option(&self) -> bool {
57        self.is_none()
58    }
59
60    fn contains_item<U>(&self, expected: &U) -> bool
61    where
62        U: PartialEq<Self::Item>,
63    {
64        match self {
65            Some(actual) => expected == actual,
66            None => false,
67        }
68    }
69}
70
71// Single implementation of OptionMatchers for any type that implements AsOption
72impl<T, V> OptionMatchers<T> for Assertion<V>
73where
74    T: Debug + Clone + PartialEq,
75    V: AsOption<Item = T> + Debug + Clone,
76{
77    fn to_be_some(self) -> Self {
78        let result = self.value.is_some_option();
79        let sentence = AssertionSentence::new("be", "some");
80
81        return self.add_step(sentence, result);
82    }
83
84    fn to_be_none(self) -> Self {
85        let result = self.value.is_none_option();
86        let sentence = AssertionSentence::new("be", "none");
87
88        return self.add_step(sentence, result);
89    }
90
91    fn to_contain(self, expected: &T) -> Self
92    where
93        T: PartialEq,
94    {
95        let result = self.value.contains_item(expected);
96        let sentence = AssertionSentence::new("contain", format!("{:?}", expected));
97
98        return self.add_step(sentence, result);
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use crate::prelude::*;
105
106    #[test]
107    fn test_option_to_be_some() {
108        // Disable deduplication for tests
109        crate::Reporter::disable_deduplication();
110
111        let some_value: Option<i32> = Some(42);
112        let none_value: Option<i32> = None;
113
114        // These should pass
115        expect!(some_value).to_be_some();
116        expect!(none_value).to_be_none();
117        expect!(none_value).not().to_be_some();
118        expect!(some_value).not().to_be_none();
119    }
120
121    #[test]
122    #[should_panic(expected = "be some")]
123    fn test_none_to_be_some_fails() {
124        let value: Option<i32> = None;
125        let _assertion = expect!(value).to_be_some();
126        std::hint::black_box(_assertion);
127    }
128
129    #[test]
130    #[should_panic(expected = "be none")]
131    fn test_some_to_be_none_fails() {
132        let value: Option<i32> = Some(42);
133        let _assertion = expect!(value).to_be_none();
134        std::hint::black_box(_assertion);
135    }
136
137    #[test]
138    fn test_option_to_contain() {
139        // Disable deduplication for tests
140        crate::Reporter::disable_deduplication();
141
142        let value: Option<i32> = Some(42);
143
144        // These should pass
145        expect!(value).to_contain(&42);
146        expect!(value).not().to_contain(&43);
147
148        let none_value: Option<i32> = None;
149        expect!(none_value).not().to_contain(&42);
150    }
151
152    #[test]
153    #[should_panic(expected = "contain")]
154    fn test_wrong_value_not_fails() {
155        let value: Option<i32> = Some(42);
156        let _assertion = expect!(value).not().to_contain(&42);
157        std::hint::black_box(_assertion);
158    }
159
160    #[test]
161    #[should_panic(expected = "contain 43")]
162    fn test_missing_value_fails() {
163        let value: Option<i32> = Some(42);
164        let _assertion = expect!(value).to_contain(&43);
165        std::hint::black_box(_assertion);
166    }
167
168    #[test]
169    #[should_panic(expected = "contain 42")]
170    fn test_none_value_fails() {
171        let value: Option<i32> = None;
172        let _assertion = expect!(value).to_contain(&42);
173        std::hint::black_box(_assertion);
174    }
175}