rmv_bevy_testing_tools/
app.rs

1use bevy_app::{App, AppExit};
2use bevy_derive::{Deref, DerefMut};
3use bevy_ecs::{
4    event::{Event, SendBatchIds},
5    query::{QueryData, QueryFilter, QuerySingleError, ReadOnlyQueryData, WorldQuery},
6};
7use bevy_state::state::{FreelyMutableState, NextState, State, States};
8
9use crate::{
10    events::{CollectedEvents, EventCollectorPlugin, EventFilterPlugin},
11    traits::{BasicQuery, CollectEvents, ImmediateQuery, ManageState, SendEvents},
12};
13
14#[derive(Debug, Deref, DerefMut)]
15pub struct TestApp(pub App);
16
17impl TestApp {
18    pub fn get_state<S: States>(&self) -> Option<&S> {
19        self.world().get_resource::<State<S>>().map(|s| s.get())
20    }
21    pub fn get_next_state<S: FreelyMutableState>(&self) -> Option<&NextState<S>> {
22        self.world().get_resource::<NextState<S>>()
23    }
24    pub fn set_next_state<S: FreelyMutableState>(&mut self, next: S) -> Option<()> {
25        self.world_mut()
26            .get_resource_mut::<NextState<S>>()
27            .map(|mut s| s.set(next))
28    }
29}
30
31impl Drop for TestApp {
32    fn drop(&mut self) {
33        self.world_mut().send_event(AppExit::Success);
34    }
35}
36
37impl ManageState for TestApp {
38    fn get_state<S: States>(&self) -> Option<&S> {
39        self.world().get_resource::<State<S>>().map(|s| s.get())
40    }
41    fn get_next_state<S: FreelyMutableState>(&self) -> Option<&NextState<S>> {
42        self.world().get_resource::<NextState<S>>()
43    }
44    fn set_next_state<S: FreelyMutableState>(&mut self, next: S) -> Option<()> {
45        self.world_mut()
46            .get_resource_mut::<NextState<S>>()
47            .map(|mut s| s.set(next))
48    }
49}
50
51impl BasicQuery for TestApp {
52    fn query_any<'a, Q, C>(&mut self) -> bool
53    where
54        Q: QueryData<Item<'a> = C>,
55    {
56        let mut q = self.world_mut().query::<Q>();
57        q.iter(self.world()).next().is_some()
58    }
59}
60
61impl CollectEvents for TestApp {
62    fn collect_events<E: Event + Clone>(&mut self) -> &mut TestApp {
63        self.add_plugins(EventCollectorPlugin::<E>::default());
64        self
65    }
66
67    fn collect_events_only<E: Event + Clone + PartialEq>(&mut self, event: E) -> &mut TestApp {
68        self.add_plugins(EventFilterPlugin::<E>::Only(event.clone()));
69        self
70    }
71
72    fn collect_events_any_of<E: Event + Clone + PartialEq>(&mut self, events: &[E]) -> &mut Self {
73        self.add_plugins(EventFilterPlugin::<E>::AnyOf(events.into()));
74        self
75    }
76
77    fn get_collected_events<E: Event + Clone>(&self) -> Option<Vec<E>> {
78        self.world()
79            .get_resource::<CollectedEvents<E>>()
80            .map(|e| e.get().clone())
81    }
82}
83
84impl SendEvents for TestApp {
85    fn send_event_default<E: Event + Default>(&mut self) {
86        self.world_mut().send_event_default::<E>();
87    }
88    fn send_event<E: Event>(&mut self, event: E) {
89        self.world_mut().send_event::<E>(event);
90    }
91    fn send_event_batch<E: Event>(
92        &mut self,
93        events: impl IntoIterator<Item = E>,
94    ) -> Option<SendBatchIds<E>> {
95        self.world_mut().send_event_batch(events)
96    }
97}
98
99impl ImmediateQuery for TestApp {
100    fn query_single<D>(&mut self) -> Result<<D as WorldQuery>::Item<'_>, QuerySingleError>
101    where
102        D: ReadOnlyQueryData,
103    {
104        let mut query = self.world_mut().query::<D>();
105        query.get_single(self.world_mut())
106    }
107    fn query_single_filtered<D, F>(
108        &mut self,
109    ) -> Result<<D as WorldQuery>::Item<'_>, QuerySingleError>
110    where
111        D: ReadOnlyQueryData,
112        F: QueryFilter,
113    {
114        let mut query = self.world_mut().query_filtered::<D, F>();
115        query.get_single(self.world_mut())
116    }
117    #[cfg(feature = "iter_tools")]
118    fn query_vec<D>(&mut self) -> Vec<<D as WorldQuery>::Item<'_>>
119    where
120        D: ReadOnlyQueryData,
121    {
122        use iter_tools::Itertools;
123
124        let mut query = self.world_mut().query::<D>();
125        query.iter(self.world_mut()).collect_vec()
126    }
127
128    fn query_collect<D, C>(&mut self) -> C
129    where
130        D: ReadOnlyQueryData,
131        for<'a> C: std::iter::FromIterator<<D as bevy_ecs::query::WorldQuery>::Item<'a>>,
132    {
133        let mut query = self.world_mut().query::<D>();
134        let result = query.iter(self.world_mut()).collect::<C>();
135        result
136    }
137}