bevy_yarnspinner 0.1.2

Bevy plugin for Yarn Spinner for Rust, friendly tool for writing game dialogue
Documentation
use bevy::ecs::event::ManualEventReader;
use bevy::prelude::*;
use bevy_yarnspinner::events::*;

#[derive(Debug, Default)]
pub struct EventAsserter {
    pub present_line_reader: ManualEventReader<PresentLineEvent>,
    pub present_options_reader: ManualEventReader<PresentOptionsEvent>,
    pub dialogue_start_reader: ManualEventReader<DialogueStartEvent>,
    pub dialogue_complete_reader: ManualEventReader<DialogueCompleteEvent>,
    pub node_start_reader: ManualEventReader<NodeStartEvent>,
    pub node_complete_reader: ManualEventReader<NodeCompleteEvent>,
    pub line_hints_reader: ManualEventReader<LineHintsEvent>,
    pub execute_command_reader: ManualEventReader<ExecuteCommandEvent>,
}

impl EventAsserter {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn clear_events(&mut self, app: &mut App) {
        self.present_line_reader
            .clear(app.world.resource::<Events<PresentLineEvent>>());
        self.present_options_reader
            .clear(app.world.resource::<Events<PresentOptionsEvent>>());
        self.dialogue_start_reader
            .clear(app.world.resource::<Events<DialogueStartEvent>>());
        self.dialogue_complete_reader
            .clear(app.world.resource::<Events<DialogueCompleteEvent>>());
        self.node_start_reader
            .clear(app.world.resource::<Events<NodeStartEvent>>());
        self.node_complete_reader
            .clear(app.world.resource::<Events<NodeCompleteEvent>>());
        self.line_hints_reader
            .clear(app.world.resource::<Events<LineHintsEvent>>());
        self.execute_command_reader
            .clear(app.world.resource::<Events<ExecuteCommandEvent>>());
    }
}

#[macro_export]
macro_rules! get_reader {
    ($asserter:ident, PresentLineEvent) => {
        &mut $asserter.present_line_reader
    };
    ($asserter:ident, PresentOptionsEvent) => {
        &mut $asserter.present_options_reader
    };
    ($asserter:ident, DialogueStartEvent) => {
        &mut $asserter.dialogue_start_reader
    };
    ($asserter:ident, DialogueCompleteEvent) => {
        &mut $asserter.dialogue_complete_reader
    };
    ($asserter:ident, NodeStartEvent) => {
        &mut $asserter.node_start_reader
    };
    ($asserter:ident, NodeCompleteEvent) => {
        &mut $asserter.node_complete_reader
    };
    ($asserter:ident, LineHintsEvent) => {
        &mut $asserter.line_hints_reader
    };
    ($asserter:ident, ExecuteCommandEvent) => {
        &mut $asserter.execute_command_reader
    };
}

#[macro_export]
macro_rules! assert_events {
    ($asserter:ident, $app:ident contains [$($event:ident $((n = $num:expr))? $(with $pred:expr)?) ,* $(,)?]) => {
        $(
            { assert_events!($asserter, $app contains $event $((n = $num))? $(with $pred)?); }
        )*
    };
    ($asserter:ident, $app:ident contains $event:ident $(with $pred:expr)?) => {
        assert_events!($asserter, $app contains $event (n = 1) $(with $pred)?);
    };
    ($asserter:ident, $app:ident contains $event:ident (n = $num:expr) $(with $pred:expr)?) => {
        let events = $app.world.resource::<bevy::prelude::Events<$event>>();
        let reader = $crate::get_reader!($asserter, $event);
        let events: Vec<&$event> = reader.read(&events).collect();
        assert_eq!($num, events.len(), "Expected {} events of type {}, but found {}: {events:#?}", stringify!($num), stringify!($event), events.len());
        $(
            {
                fn get_pred() -> impl Fn(&$event) -> bool {
                    $pred
                }
                let pred = get_pred();
                let actual = events.into_iter().next().unwrap();
                assert!(pred(actual), "Expected event of type {} to fulfill predicate {}, but found {:#?}", stringify!($event), stringify!($pred), actual);
            }
        )?
    };
}