Skip to main content

rxpect/
root.rs

1use crate::borrow::BorrowedOrOwned;
2use crate::expectation_list::ExpectationList;
3use crate::{CheckResult, Expectation, ExpectationBuilder};
4use std::fmt::Debug;
5
6/// Container for expectations on a value.
7///
8/// Returned by [expect](crate::expect)
9///
10/// Contains the value under test and all expectations.
11/// Expectations are automatically run when `RootExpectations` is dropped.
12///
13/// Expectation failures result in a panic
14pub struct RootExpectations<'e, T: Debug> {
15    value: BorrowedOrOwned<'e, T>,
16    expectations: ExpectationList<'e, T>,
17}
18
19impl<'e, T: Debug> RootExpectations<'e, T> {
20    /// Create new `RootExpectations` on an owned value
21    pub fn new(value: T) -> Self {
22        RootExpectations {
23            expectations: ExpectationList::new(),
24            value: BorrowedOrOwned::Owned(value),
25        }
26    }
27
28    /// Create new `RootExpectations` on a borrowed value
29    pub fn new_ref(value: &'e T) -> Self {
30        RootExpectations {
31            expectations: ExpectationList::new(),
32            value: BorrowedOrOwned::Borrowed(value),
33        }
34    }
35
36    /// Manually run all the expectations
37    pub fn check(self) {
38        drop(self)
39    }
40}
41
42impl<'e, T: Debug + 'e> ExpectationBuilder<'e> for RootExpectations<'e, T> {
43    /// Target value type for this builder
44    type Value = T;
45
46    /// Add an expectation to the list of expectations
47    fn to_pass(mut self, expectation: impl Expectation<T> + 'e) -> Self {
48        self.expectations.push(expectation);
49        self
50    }
51}
52
53impl<'e, T: Debug> Drop for RootExpectations<'e, T> {
54    fn drop(&mut self) {
55        let value = self.value.borrow_self();
56        if let CheckResult::Fail(message) = self.expectations.check(value) {
57            panic!("{}", message);
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use crate::tests::TestExpectation;
65    use crate::{CheckResult, ExpectationBuilder, expect, expect_ref};
66
67    #[test]
68    pub fn that_assert_runs_an_expectation() {
69        // Given an expectation
70        let (expectation, expected) = TestExpectation::new(CheckResult::Pass);
71
72        // And expectations containing it
73        let expectations = expect(true).to_pass(expectation);
74
75        // When the expectations are checked
76        expectations.check();
77
78        // Then the expectation was run
79        assert!(*expected.lock().unwrap());
80    }
81
82    #[test]
83    pub fn that_assert_works_on_references() {
84        // Given an expectation
85        let (expectation, _) = TestExpectation::new(CheckResult::Pass);
86
87        // Expect a reference to work
88        let value = true;
89        expect_ref(&value).to_pass(expectation);
90    }
91
92    #[test]
93    pub fn that_check_runs_all_expectations() {
94        // Given two expectations that both pass
95        let (expectation1, expected1) = TestExpectation::new(CheckResult::Pass);
96        let (expectation2, expected2) = TestExpectation::new(CheckResult::Pass);
97
98        // And expectations containing those
99        let expectations = expect(true).to_pass(expectation1).to_pass(expectation2);
100
101        // When the expectations are checked
102        expectations.check();
103
104        // Then both expectations were run
105        assert!(*expected1.lock().unwrap());
106        assert!(*expected2.lock().unwrap());
107    }
108
109    #[test]
110    #[should_panic]
111    pub fn that_failure_panics() {
112        // Given an expectation that fails
113        let (expectation, _) = TestExpectation::new(CheckResult::Fail("message".to_owned()));
114
115        // And expectations containing it
116        let expectations = expect(true).to_pass(expectation);
117
118        // Expect a panic when checked
119        expectations.check();
120    }
121}