use crate::backend::Assertion;
use std::cell::RefCell;
#[derive(Debug, Clone)]
pub enum AssertionEvent {
Success(Assertion<()>),
Failure(Assertion<()>),
SessionCompleted,
}
type AssertionHandler = Box<dyn Fn(Assertion<()>)>;
thread_local! {
static SUCCESS_HANDLERS: RefCell<Vec<AssertionHandler>> = RefCell::new(Vec::new());
static FAILURE_HANDLERS: RefCell<Vec<AssertionHandler>> = RefCell::new(Vec::new());
static SESSION_COMPLETED_HANDLERS: RefCell<Vec<Box<dyn Fn()>>> = RefCell::new(Vec::new());
static INITIALIZED: RefCell<bool> = const { RefCell::new(false) };
}
pub struct EventEmitter;
impl EventEmitter {
pub fn init() {
INITIALIZED.with(|initialized| {
let mut initialized = initialized.borrow_mut();
if !*initialized {
*initialized = true;
}
});
}
pub fn emit(event: AssertionEvent) {
match event {
AssertionEvent::Success(assertion) => {
SUCCESS_HANDLERS.with(|handlers| {
let handlers = handlers.borrow();
for handler in handlers.iter() {
handler(assertion.clone());
}
});
}
AssertionEvent::Failure(assertion) => {
FAILURE_HANDLERS.with(|handlers| {
let handlers = handlers.borrow();
for handler in handlers.iter() {
handler(assertion.clone());
}
});
}
AssertionEvent::SessionCompleted => {
SESSION_COMPLETED_HANDLERS.with(|handlers| {
let handlers = handlers.borrow();
for handler in handlers.iter() {
handler();
}
});
}
}
}
}
pub fn on_success<F>(handler: F)
where
F: Fn(Assertion<()>) + 'static,
{
SUCCESS_HANDLERS.with(|handlers| {
handlers.borrow_mut().push(Box::new(handler));
});
}
pub fn on_failure<F>(handler: F)
where
F: Fn(Assertion<()>) + 'static,
{
FAILURE_HANDLERS.with(|handlers| {
handlers.borrow_mut().push(Box::new(handler));
});
}
pub fn on_session_completed<F>(handler: F)
where
F: Fn() + 'static,
{
SESSION_COMPLETED_HANDLERS.with(|handlers| {
handlers.borrow_mut().push(Box::new(handler));
});
}
#[doc(hidden)]
pub fn initialize_event_system() {
EventEmitter::init();
crate::Reporter::init();
}
#[cfg(test)]
mod tests {
use super::*;
use crate::backend::assertions::AssertionStep;
use crate::backend::assertions::sentence::AssertionSentence;
use std::cell::RefCell;
use std::rc::Rc;
fn create_test_assertion() -> Assertion<()> {
let mut assertion = Assertion::new((), "test_value");
assertion.steps.push(AssertionStep { sentence: AssertionSentence::new("be", "test assertion"), passed: true, logical_op: None });
assertion
}
#[test]
fn test_event_emitter_init() {
EventEmitter::init();
INITIALIZED.with(|initialized| {
assert_eq!(*initialized.borrow(), true);
});
}
#[test]
fn test_on_success_handler() {
let called = Rc::new(RefCell::new(false));
let called_clone = called.clone();
on_success(move |_| {
*called.borrow_mut() = true;
});
let assertion = create_test_assertion();
EventEmitter::emit(AssertionEvent::Success(assertion));
assert_eq!(*called_clone.borrow(), true);
}
#[test]
fn test_on_failure_handler() {
let called = Rc::new(RefCell::new(false));
let called_clone = called.clone();
on_failure(move |_| {
*called.borrow_mut() = true;
});
let assertion = create_test_assertion();
EventEmitter::emit(AssertionEvent::Failure(assertion));
assert_eq!(*called_clone.borrow(), true);
}
#[test]
fn test_on_session_completed_handler() {
let called = Rc::new(RefCell::new(false));
let called_clone = called.clone();
on_session_completed(move || {
*called.borrow_mut() = true;
});
EventEmitter::emit(AssertionEvent::SessionCompleted);
assert_eq!(*called_clone.borrow(), true);
}
#[test]
fn test_multiple_handlers() {
let success_count = Rc::new(RefCell::new(0));
let success_count_clone = success_count.clone();
let failure_count = Rc::new(RefCell::new(0));
let failure_count_clone = failure_count.clone();
let session_count = Rc::new(RefCell::new(0));
let session_count_clone = session_count.clone();
for _ in 0..3 {
let count = success_count.clone();
on_success(move |_| {
*count.borrow_mut() += 1;
});
let count = failure_count.clone();
on_failure(move |_| {
*count.borrow_mut() += 1;
});
let count = session_count.clone();
on_session_completed(move || {
*count.borrow_mut() += 1;
});
}
let assertion = create_test_assertion();
EventEmitter::emit(AssertionEvent::Success(assertion.clone()));
EventEmitter::emit(AssertionEvent::Failure(assertion));
EventEmitter::emit(AssertionEvent::SessionCompleted);
assert_eq!(*success_count_clone.borrow(), 3);
assert_eq!(*failure_count_clone.borrow(), 3);
assert_eq!(*session_count_clone.borrow(), 3);
}
#[test]
fn test_assertion_event_debug() {
let assertion = create_test_assertion();
let success_event = AssertionEvent::Success(assertion.clone());
let failure_event = AssertionEvent::Failure(assertion);
let session_event = AssertionEvent::SessionCompleted;
assert!(!format!("{:?}", success_event).is_empty());
assert!(!format!("{:?}", failure_event).is_empty());
assert!(!format!("{:?}", session_event).is_empty());
}
}