rmv_bevy_testing_tools/
traits.rs

1use std::time::Duration;
2
3use bevy_ecs::{
4    event::{Event, SendBatchIds},
5    query::{QueryData, QueryFilter, QuerySingleError, ReadOnlyQueryData, WorldQuery},
6};
7use bevy_state::state::{FreelyMutableState, NextState, States};
8
9pub trait CollectEvents {
10    fn collect_events<E: Event + Clone>(&mut self) -> &mut Self;
11
12    fn collect_events_only<E: Event + Clone + PartialEq>(&mut self, event: E) -> &mut Self;
13
14    fn collect_events_any_of<E: Event + Clone + PartialEq>(&mut self, events: &[E]) -> &mut Self;
15
16    fn get_collected_events<E: Event + Clone>(&self) -> Option<Vec<E>>;
17}
18
19pub trait SendEvents {
20    fn send_event_default<E: Event + Default>(&mut self);
21    fn send_event<E: Event>(&mut self, event: E);
22    fn send_event_batch<E: Event>(
23        &mut self,
24        events: impl IntoIterator<Item = E>,
25    ) -> Option<SendBatchIds<E>>;
26}
27
28pub trait ManageState {
29    fn get_state<S: States>(&self) -> Option<&S>;
30    fn get_next_state<S: FreelyMutableState>(&self) -> Option<&NextState<S>>;
31    fn set_next_state<S: FreelyMutableState>(&mut self, next: S) -> Option<()>;
32}
33
34pub trait BasicQuery {
35    fn query_any<'a, Q, C>(&mut self) -> bool
36    where
37        Q: QueryData<Item<'a> = C>;
38}
39
40pub trait ImmediateQuery {
41    fn query_single<D>(&mut self) -> Result<<D as WorldQuery>::Item<'_>, QuerySingleError>
42    where
43        D: ReadOnlyQueryData;
44    fn query_single_filtered<D, F>(
45        &mut self,
46    ) -> Result<<D as WorldQuery>::Item<'_>, QuerySingleError>
47    where
48        D: ReadOnlyQueryData,
49        F: QueryFilter;
50    fn query_collect<D, C>(&mut self) -> C
51    where
52        D: ReadOnlyQueryData,
53        for<'a> C: std::iter::FromIterator<<D as bevy_ecs::query::WorldQuery>::Item<'a>>;
54    #[cfg(feature = "iter_tools")]
55    fn query_vec<D>(&mut self) -> Vec<<D as WorldQuery>::Item<'_>>
56    where
57        D: ReadOnlyQueryData;
58}
59
60pub trait AdvanceTime {
61    fn advance_time_to(app: &mut Self, duration: Duration);
62    fn advance_time_by(app: &mut Self, duration: Duration);
63}
64
65#[cfg(test)]
66mod tests {
67    use rstest::rstest;
68    use speculoos::{assert_that, option::OptionAssertions};
69
70    use super::*;
71    use crate::{app::TestApp, events::CollectedEvents, fixtures::minimal_test_app};
72    #[derive(Event, Clone, Debug, PartialEq)]
73    struct MyEvent;
74
75    #[rstest]
76    fn event_collector_trait_get_collected_events(#[from(minimal_test_app)] mut app: TestApp) {
77        assert_that!(app.get_collected_events::<MyEvent>())
78            .named("no resource")
79            .is_none();
80
81        app.insert_resource(CollectedEvents::<MyEvent>::default());
82
83        assert_that!(app.get_collected_events::<MyEvent>())
84            .named("after resource inserted")
85            .is_some();
86    }
87
88    #[rstest]
89    fn event_collector_trait_collect_events(#[from(minimal_test_app)] mut app: TestApp) {
90        assert_that!(app.get_collected_events::<MyEvent>())
91            .named("no plugin before collect_events")
92            .is_none();
93
94        app.collect_events::<MyEvent>();
95
96        assert_that!(app.get_collected_events::<MyEvent>())
97            .named("plugin inserted after collect_events")
98            .is_some();
99    }
100
101    #[rstest]
102    fn event_collector_trait_collect_events_only(#[from(minimal_test_app)] mut app: TestApp) {
103        assert_that!(app.get_collected_events::<MyEvent>())
104            .named("no plugin before collect_events_only")
105            .is_none();
106
107        app.collect_events_only(MyEvent);
108
109        assert_that!(app.get_collected_events::<MyEvent>())
110            .named("plugin inserted after collect_events_only")
111            .is_some();
112    }
113
114    #[rstest]
115    fn event_collector_trait_collect_events_any_of(#[from(minimal_test_app)] mut app: TestApp) {
116        assert_that!(app.get_collected_events::<MyEvent>())
117            .named("no plugin before collect_events_any_of")
118            .is_none();
119
120        app.collect_events_any_of(&[MyEvent]);
121
122        assert_that!(app.get_collected_events::<MyEvent>())
123            .named("plugin inserted after collect_events_any_of")
124            .is_some();
125    }
126}