1use pretty_assertions::assert_eq;
4
5use crate::{
6 decider::{Decider, EventComputation, StateComputation},
7 view::{View, ViewStateComputation},
8};
9
10pub struct DeciderTestSpecification<'a, Command, State, Event, Error>
17where
18 Event: PartialEq + std::fmt::Debug,
19 Error: PartialEq + std::fmt::Debug,
20{
21 events: Vec<Event>,
22 state: Option<State>,
23 command: Option<Command>,
24 decider: Option<Decider<'a, Command, State, Event, Error>>,
25}
26
27impl<Command, State, Event, Error> Default
28 for DeciderTestSpecification<'_, Command, State, Event, Error>
29where
30 Event: PartialEq + std::fmt::Debug,
31 Error: PartialEq + std::fmt::Debug,
32{
33 fn default() -> Self {
34 Self {
35 events: Vec::new(),
36 state: None,
37 command: None,
38 decider: None,
39 }
40 }
41}
42
43impl<'a, Command, State, Event, Error> DeciderTestSpecification<'a, Command, State, Event, Error>
44where
45 Command: std::fmt::Debug,
46 Event: PartialEq + std::fmt::Debug,
47 State: PartialEq + std::fmt::Debug,
48 Error: PartialEq + std::fmt::Debug,
49{
50 #[allow(dead_code)]
51 pub fn for_decider(mut self, decider: Decider<'a, Command, State, Event, Error>) -> Self {
53 self.decider = Some(decider);
54 self
55 }
56
57 #[allow(dead_code)]
58 pub fn given(mut self, events: Vec<Event>) -> Self {
60 self.events = events;
61 self
62 }
63
64 #[allow(dead_code)]
65 pub fn given_state(mut self, state: Option<State>) -> Self {
67 self.state = state;
68 self
69 }
70
71 #[allow(dead_code)]
72 pub fn when(mut self, command: Command) -> Self {
74 self.command = Some(command);
75 self
76 }
77
78 #[allow(dead_code)]
79 #[track_caller]
80 pub fn then(self, expected_events: Vec<Event>) {
82 let decider = self
83 .decider
84 .expect("Decider must be initialized. Did you forget to call `for_decider`?");
85 let command = self
86 .command
87 .expect("Command must be initialized. Did you forget to call `when`?");
88 let events = self.events;
89
90 let new_events_result = decider.compute_new_events(&events, &command);
91 let new_events = match new_events_result {
92 Ok(events) => events,
93 Err(error) => {
94 panic!("Events were expected but the decider returned an error instead: {error:?}")
95 }
96 };
97 assert_eq!(
98 new_events, expected_events,
99 "Actual and Expected events do not match!\nCommand: {command:?}\n",
100 );
101 }
102
103 #[allow(dead_code)]
104 #[track_caller]
105 pub fn then_state(self, expected_state: State) {
107 let decider = self
108 .decider
109 .expect("Decider must be initialized. Did you forget to call `for_decider`?");
110 let command = self
111 .command
112 .expect("Command must be initialized. Did you forget to call `when`?");
113 let state = self.state;
114
115 let new_state_result = decider.compute_new_state(state, &command);
116 let new_state = match new_state_result {
117 Ok(state) => state,
118 Err(error) => {
119 panic!("State was expected but the decider returned an error instead: {error:?}")
120 }
121 };
122 assert_eq!(
123 new_state, expected_state,
124 "Actual and Expected states do not match.\nCommand: {command:?}\n"
125 );
126 }
127
128 #[allow(dead_code)]
129 #[track_caller]
130 pub fn then_error(self, expected_error: Error) {
132 let decider = self
133 .decider
134 .expect("Decider must be initialized. Did you forget to call `for_decider`?");
135 let command = self
136 .command
137 .expect("Command must be initialized. Did you forget to call `when`?");
138 let events = self.events;
139
140 let error_result = decider.compute_new_events(&events, &command);
141 let error = match error_result {
142 Ok(events) => {
143 panic!("An error was expected but the decider returned events instead: {events:?}")
144 }
145 Err(error) => error,
146 };
147 assert_eq!(
148 error, expected_error,
149 "Actual and Expected errors do not match.\nCommand: {command:?}\n"
150 );
151 }
152}
153
154pub struct ViewTestSpecification<'a, State, Event>
161where
162 State: PartialEq + std::fmt::Debug,
163{
164 events: Vec<Event>,
165 view: Option<View<'a, State, Event>>,
166}
167
168impl<State, Event> Default for ViewTestSpecification<'_, State, Event>
169where
170 State: PartialEq + std::fmt::Debug,
171{
172 fn default() -> Self {
173 Self {
174 events: Vec::new(),
175 view: None,
176 }
177 }
178}
179
180impl<'a, State, Event> ViewTestSpecification<'a, State, Event>
181where
182 State: PartialEq + std::fmt::Debug,
183 Event: std::fmt::Debug,
184{
185 #[allow(dead_code)]
186 pub fn for_view(mut self, view: View<'a, State, Event>) -> Self {
188 self.view = Some(view);
189 self
190 }
191
192 #[allow(dead_code)]
193 pub fn given(mut self, events: Vec<Event>) -> Self {
195 self.events = events;
196 self
197 }
198
199 #[allow(dead_code)]
200 #[track_caller]
201 pub fn then(self, expected_state: State) {
203 let view = self
204 .view
205 .expect("View must be initialized. Did you forget to call `for_view`?");
206
207 let events = self.events;
208
209 let initial_state = (view.initial_state)();
210 let event_refs: Vec<&Event> = events.iter().collect();
211 let new_state_result = view.compute_new_state(Some(initial_state), &event_refs);
212
213 assert_eq!(
214 new_state_result, expected_state,
215 "Actual and Expected states do not match.\nEvents: {events:?}\n"
216 );
217 }
218}