rmv_bevy_testing_tools/
app.rs1use 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}