fluent_test/
events.rs

1use crate::backend::Assertion;
2use std::cell::RefCell;
3
4/// Event types that can be emitted within the testing system
5#[derive(Debug, Clone)]
6pub enum AssertionEvent {
7    /// A successful assertion
8    Success(Assertion<()>),
9    /// A failed assertion
10    Failure(Assertion<()>),
11    /// Test session completed
12    SessionCompleted,
13}
14
15// Thread-local registry of success handlers
16// Define type aliases to reduce complexity
17type AssertionHandler = Box<dyn Fn(Assertion<()>)>;
18
19thread_local! {
20    static SUCCESS_HANDLERS: RefCell<Vec<AssertionHandler>> = RefCell::new(Vec::new());
21    static FAILURE_HANDLERS: RefCell<Vec<AssertionHandler>> = RefCell::new(Vec::new());
22    static SESSION_COMPLETED_HANDLERS: RefCell<Vec<Box<dyn Fn()>>> = RefCell::new(Vec::new());
23    static INITIALIZED: RefCell<bool> = const { RefCell::new(false) };
24}
25
26/// EventEmitter is responsible for sending events and managing event handlers
27pub struct EventEmitter;
28
29impl EventEmitter {
30    /// Initialize the event system
31    pub fn init() {
32        INITIALIZED.with(|initialized| {
33            let mut initialized = initialized.borrow_mut();
34            if !*initialized {
35                *initialized = true;
36            }
37        });
38    }
39
40    /// Emit an event to all registered handlers
41    pub fn emit(event: AssertionEvent) {
42        match event {
43            AssertionEvent::Success(assertion) => {
44                SUCCESS_HANDLERS.with(|handlers| {
45                    let handlers = handlers.borrow();
46                    for handler in handlers.iter() {
47                        handler(assertion.clone());
48                    }
49                });
50            }
51            AssertionEvent::Failure(assertion) => {
52                FAILURE_HANDLERS.with(|handlers| {
53                    let handlers = handlers.borrow();
54                    for handler in handlers.iter() {
55                        handler(assertion.clone());
56                    }
57                });
58            }
59            AssertionEvent::SessionCompleted => {
60                SESSION_COMPLETED_HANDLERS.with(|handlers| {
61                    let handlers = handlers.borrow();
62                    for handler in handlers.iter() {
63                        handler();
64                    }
65                });
66            }
67        }
68    }
69}
70
71/// Register a handler for success events
72pub fn on_success<F>(handler: F)
73where
74    F: Fn(Assertion<()>) + 'static,
75{
76    SUCCESS_HANDLERS.with(|handlers| {
77        handlers.borrow_mut().push(Box::new(handler));
78    });
79}
80
81/// Register a handler for failure events
82pub fn on_failure<F>(handler: F)
83where
84    F: Fn(Assertion<()>) + 'static,
85{
86    FAILURE_HANDLERS.with(|handlers| {
87        handlers.borrow_mut().push(Box::new(handler));
88    });
89}
90
91/// Register a handler for session completion events
92pub fn on_session_completed<F>(handler: F)
93where
94    F: Fn() + 'static,
95{
96    SESSION_COMPLETED_HANDLERS.with(|handlers| {
97        handlers.borrow_mut().push(Box::new(handler));
98    });
99}
100
101// This is an internal function, deprecated in favor of using Config.apply()
102// but kept for compatibility with example and test code
103#[doc(hidden)]
104pub fn initialize_event_system() {
105    EventEmitter::init();
106
107    // Register default handlers from the Reporter
108    crate::Reporter::init();
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use crate::backend::assertions::AssertionStep;
115    use crate::backend::assertions::sentence::AssertionSentence;
116    use std::cell::RefCell;
117    use std::rc::Rc;
118
119    // Create a test assertion
120    fn create_test_assertion() -> Assertion<()> {
121        let mut assertion = Assertion::new((), "test_value");
122        assertion.steps.push(AssertionStep { sentence: AssertionSentence::new("be", "test assertion"), passed: true, logical_op: None });
123        assertion
124    }
125
126    #[test]
127    fn test_event_emitter_init() {
128        // This will initialize the event system
129        EventEmitter::init();
130
131        // Check that the initialization worked
132        INITIALIZED.with(|initialized| {
133            assert_eq!(*initialized.borrow(), true);
134        });
135    }
136
137    #[test]
138    fn test_on_success_handler() {
139        // Create a flag to check if the handler was called
140        let called = Rc::new(RefCell::new(false));
141        let called_clone = called.clone();
142
143        // Register a success handler
144        on_success(move |_| {
145            *called.borrow_mut() = true;
146        });
147
148        // Emit a success event
149        let assertion = create_test_assertion();
150        EventEmitter::emit(AssertionEvent::Success(assertion));
151
152        // Check that the handler was called
153        assert_eq!(*called_clone.borrow(), true);
154    }
155
156    #[test]
157    fn test_on_failure_handler() {
158        // Create a flag to check if the handler was called
159        let called = Rc::new(RefCell::new(false));
160        let called_clone = called.clone();
161
162        // Register a failure handler
163        on_failure(move |_| {
164            *called.borrow_mut() = true;
165        });
166
167        // Emit a failure event
168        let assertion = create_test_assertion();
169        EventEmitter::emit(AssertionEvent::Failure(assertion));
170
171        // Check that the handler was called
172        assert_eq!(*called_clone.borrow(), true);
173    }
174
175    #[test]
176    fn test_on_session_completed_handler() {
177        // Create a flag to check if the handler was called
178        let called = Rc::new(RefCell::new(false));
179        let called_clone = called.clone();
180
181        // Register a session completed handler
182        on_session_completed(move || {
183            *called.borrow_mut() = true;
184        });
185
186        // Emit a session completed event
187        EventEmitter::emit(AssertionEvent::SessionCompleted);
188
189        // Check that the handler was called
190        assert_eq!(*called_clone.borrow(), true);
191    }
192
193    #[test]
194    fn test_multiple_handlers() {
195        // Create counters for each handler type
196        let success_count = Rc::new(RefCell::new(0));
197        let success_count_clone = success_count.clone();
198
199        let failure_count = Rc::new(RefCell::new(0));
200        let failure_count_clone = failure_count.clone();
201
202        let session_count = Rc::new(RefCell::new(0));
203        let session_count_clone = session_count.clone();
204
205        // Register multiple handlers of each type
206        for _ in 0..3 {
207            let count = success_count.clone();
208            on_success(move |_| {
209                *count.borrow_mut() += 1;
210            });
211
212            let count = failure_count.clone();
213            on_failure(move |_| {
214                *count.borrow_mut() += 1;
215            });
216
217            let count = session_count.clone();
218            on_session_completed(move || {
219                *count.borrow_mut() += 1;
220            });
221        }
222
223        // Emit events
224        let assertion = create_test_assertion();
225        EventEmitter::emit(AssertionEvent::Success(assertion.clone()));
226        EventEmitter::emit(AssertionEvent::Failure(assertion));
227        EventEmitter::emit(AssertionEvent::SessionCompleted);
228
229        // Check that all handlers were called
230        assert_eq!(*success_count_clone.borrow(), 3);
231        assert_eq!(*failure_count_clone.borrow(), 3);
232        assert_eq!(*session_count_clone.borrow(), 3);
233    }
234
235    #[test]
236    fn test_assertion_event_debug() {
237        // Test that the Debug implementation works
238        let assertion = create_test_assertion();
239        let success_event = AssertionEvent::Success(assertion.clone());
240        let failure_event = AssertionEvent::Failure(assertion);
241        let session_event = AssertionEvent::SessionCompleted;
242
243        // Make sure these don't panic and assert that they produce non-empty strings
244        assert!(!format!("{:?}", success_event).is_empty());
245        assert!(!format!("{:?}", failure_event).is_empty());
246        assert!(!format!("{:?}", session_event).is_empty());
247    }
248}