Skip to main content

clearcheck/matchers/
mod.rs

1//! Matchers provide the granular tools for carrying out the assertions.
2//! They examine the data and verify that the data conforms to specific criteria.
3//!
4//! Let's take an example of a collection matcher.
5//!
6//! ```
7//! use clearcheck::matchers::collection::membership::contain_all;
8//! use clearcheck::matchers::Matcher;
9//!
10//! let collection = vec!["clearcheck", "testify", "assert4j", "xunit"];
11//! let all_to_be_contained = vec!["testify", "assert4j", "xunit"];
12//!
13//! let matcher = contain_all(all_to_be_contained);
14//! assert!(matcher.test(&collection).passed());
15//! ```
16
17pub mod bool;
18pub mod char;
19pub mod collection;
20pub mod compose;
21#[cfg(feature = "date")]
22pub mod date;
23pub mod equal;
24#[cfg(feature = "file")]
25pub mod file;
26#[cfg(feature = "num")]
27pub mod float;
28#[cfg(feature = "num")]
29pub mod int;
30pub mod map;
31pub mod option;
32pub mod ordered;
33pub mod range;
34pub mod result;
35pub mod string;
36
37/// Should provides a convenient way to express positive assertions within tests, indicating that a value should meet a certain condition.
38pub trait Should<T> {
39    /// - Takes a matcher as input and performs an assertion against the value itself.
40    /// - Panics if the assertion fails, indicating that the value did not match the matcher's expectations.
41    fn should(&self, matcher: &dyn Matcher<T>);
42}
43
44/// ShouldNot provides a convenient way to express negative assertions within tests, indicating that a value should not meet a certain condition.
45pub trait ShouldNot<T> {
46    /// - Takes a matcher as input and performs an inverted assertion against the value itself.
47    /// - Inverts the result of the matcher's test method, ensuring the value does not match.
48    /// - Panics if the inverted assertion fails, indicating that the value unexpectedly matched the matcher.
49    fn should_not(&self, matcher: &dyn Matcher<T>);
50}
51
52impl<T> Should<T> for T {
53    fn should(&self, matcher: &dyn Matcher<T>) {
54        let matcher_result = matcher.test(self);
55        if !matcher_result.passed {
56            panic!("assertion failed: {}", matcher_result.failure_message);
57        }
58    }
59}
60
61impl<T> ShouldNot<T> for T {
62    fn should_not(&self, matcher: &dyn Matcher<T>) {
63        let matcher_result = matcher.test(self);
64        let passed = !matcher_result.passed;
65        if !passed {
66            panic!(
67                "assertion failed: {}",
68                matcher_result.inverted_failure_message
69            );
70        }
71    }
72}
73
74/// Matcher defines the core functionality of matchers. All the matchers implement `Matcher<T>` trait.
75pub trait Matcher<T> {
76    fn test(&self, value: &T) -> MatcherResult;
77}
78
79/// BoxWrap provides a `boxed` method to wrap a Matcher into Box object.
80///
81/// It is used to compose matchers in [`crate::matchers::compose::Matchers`].
82///
83/// BoxWrap is implemented for any `T: Matcher<M>`.
84pub trait BoxWrap<W> {
85    fn boxed(self) -> Box<dyn Matcher<W>>;
86}
87
88impl<M, T: Matcher<M> + 'static> BoxWrap<M> for T {
89    fn boxed(self) -> Box<dyn Matcher<M>> {
90        Box::new(self)
91    }
92}
93
94/// MatcherResult defines the result of a matcher execution.
95pub struct MatcherResult {
96    passed: bool,
97    failure_message: String,
98    inverted_failure_message: String,
99}
100
101impl MatcherResult {
102    /// Creates a new instance of MatcherResult using failure_message and inverted_failure_message of type &'static str.
103    pub fn new(
104        passed: bool,
105        failure_message: &'static str,
106        inverted_failure_message: &'static str,
107    ) -> Self {
108        MatcherResult::formatted(
109            passed,
110            failure_message.to_string(),
111            inverted_failure_message.to_string(),
112        )
113    }
114
115    /// Creates a new instance of MatcherResult using failure_message and inverted_failure_message of type String.
116    pub fn formatted(
117        passed: bool,
118        failure_message: String,
119        inverted_failure_message: String,
120    ) -> Self {
121        MatcherResult {
122            passed,
123            failure_message,
124            inverted_failure_message,
125        }
126    }
127
128    /// Returns true if the result of a matcher execution was successful, false otherwise.
129    pub fn passed(&self) -> bool {
130        self.passed
131    }
132}