1use super::fake_data::*;
4use super::traits::FactoryState;
5use crate::error::OrmResult;
6use chrono::{DateTime, Utc};
7use serde_json::{json, Value};
8use std::collections::HashMap;
9
10#[derive(Debug, Clone)]
12pub struct ActiveState;
13
14#[async_trait::async_trait]
15impl<T> FactoryState<T> for ActiveState {
16 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
17 attributes.insert("status".to_string(), json!("active"));
18 attributes.insert("is_active".to_string(), json!(true));
19 Ok(())
20 }
21
22 fn state_name(&self) -> &'static str {
23 "Active"
24 }
25}
26
27#[derive(Debug, Clone)]
28pub struct InactiveState;
29
30#[async_trait::async_trait]
31impl<T> FactoryState<T> for InactiveState {
32 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
33 attributes.insert("status".to_string(), json!("inactive"));
34 attributes.insert("is_active".to_string(), json!(false));
35 Ok(())
36 }
37
38 fn state_name(&self) -> &'static str {
39 "Inactive"
40 }
41}
42
43#[derive(Debug, Clone)]
44pub struct PendingState;
45
46#[async_trait::async_trait]
47impl<T> FactoryState<T> for PendingState {
48 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
49 attributes.insert("status".to_string(), json!("pending"));
50 attributes.insert("is_verified".to_string(), json!(false));
51 attributes.insert("verified_at".to_string(), Value::Null);
52 Ok(())
53 }
54
55 fn state_name(&self) -> &'static str {
56 "Pending"
57 }
58}
59
60#[derive(Debug, Clone)]
61pub struct VerifiedState;
62
63#[async_trait::async_trait]
64impl<T> FactoryState<T> for VerifiedState {
65 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
66 attributes.insert("status".to_string(), json!("verified"));
67 attributes.insert("is_verified".to_string(), json!(true));
68 attributes.insert(
69 "verified_at".to_string(),
70 json!(fake_datetime().to_rfc3339()),
71 );
72 Ok(())
73 }
74
75 fn state_name(&self) -> &'static str {
76 "Verified"
77 }
78}
79
80#[derive(Debug, Clone)]
82pub struct AdminState;
83
84#[async_trait::async_trait]
85impl<T> FactoryState<T> for AdminState {
86 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
87 attributes.insert("role".to_string(), json!("admin"));
88 attributes.insert("is_admin".to_string(), json!(true));
89 attributes.insert(
90 "permissions".to_string(),
91 json!(["read", "write", "delete", "admin"]),
92 );
93 Ok(())
94 }
95
96 fn state_name(&self) -> &'static str {
97 "Admin"
98 }
99}
100
101#[derive(Debug, Clone)]
103pub struct ModeratorState;
104
105#[async_trait::async_trait]
106impl<T> FactoryState<T> for ModeratorState {
107 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
108 attributes.insert("role".to_string(), json!("moderator"));
109 attributes.insert("is_admin".to_string(), json!(false));
110 attributes.insert(
111 "permissions".to_string(),
112 json!(["read", "write", "moderate"]),
113 );
114 Ok(())
115 }
116
117 fn state_name(&self) -> &'static str {
118 "Moderator"
119 }
120}
121
122#[derive(Debug, Clone)]
124pub struct SuspendedState;
125
126#[async_trait::async_trait]
127impl<T> FactoryState<T> for SuspendedState {
128 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
129 attributes.insert("status".to_string(), json!("suspended"));
130 attributes.insert("is_active".to_string(), json!(false));
131 attributes.insert(
132 "suspended_at".to_string(),
133 json!(fake_datetime().to_rfc3339()),
134 );
135 attributes.insert("suspension_reason".to_string(), json!("Policy violation"));
136 Ok(())
137 }
138
139 fn state_name(&self) -> &'static str {
140 "Suspended"
141 }
142}
143
144#[derive(Debug, Clone)]
146pub struct PublishedState;
147
148#[async_trait::async_trait]
149impl<T> FactoryState<T> for PublishedState {
150 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
151 attributes.insert("status".to_string(), json!("published"));
152 attributes.insert("is_published".to_string(), json!(true));
153 attributes.insert(
154 "published_at".to_string(),
155 json!(fake_datetime().to_rfc3339()),
156 );
157 Ok(())
158 }
159
160 fn state_name(&self) -> &'static str {
161 "Published"
162 }
163}
164
165#[derive(Debug, Clone)]
167pub struct DraftState;
168
169#[async_trait::async_trait]
170impl<T> FactoryState<T> for DraftState {
171 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
172 attributes.insert("status".to_string(), json!("draft"));
173 attributes.insert("is_published".to_string(), json!(false));
174 attributes.insert("published_at".to_string(), Value::Null);
175 Ok(())
176 }
177
178 fn state_name(&self) -> &'static str {
179 "Draft"
180 }
181}
182
183#[derive(Debug, Clone)]
185pub struct ArchivedState;
186
187#[async_trait::async_trait]
188impl<T> FactoryState<T> for ArchivedState {
189 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
190 attributes.insert("status".to_string(), json!("archived"));
191 attributes.insert("is_archived".to_string(), json!(true));
192 attributes.insert(
193 "archived_at".to_string(),
194 json!(fake_datetime().to_rfc3339()),
195 );
196 Ok(())
197 }
198
199 fn state_name(&self) -> &'static str {
200 "Archived"
201 }
202}
203
204#[derive(Debug, Clone)]
206pub struct PremiumState;
207
208#[async_trait::async_trait]
209impl<T> FactoryState<T> for PremiumState {
210 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
211 attributes.insert("account_type".to_string(), json!("premium"));
212 attributes.insert("is_premium".to_string(), json!(true));
213 attributes.insert(
214 "premium_expires_at".to_string(),
215 json!(fake_future_datetime().to_rfc3339()),
216 );
217 Ok(())
218 }
219
220 fn state_name(&self) -> &'static str {
221 "Premium"
222 }
223}
224
225#[derive(Debug, Clone)]
227pub struct FreeState;
228
229#[async_trait::async_trait]
230impl<T> FactoryState<T> for FreeState {
231 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
232 attributes.insert("account_type".to_string(), json!("free"));
233 attributes.insert("is_premium".to_string(), json!(false));
234 attributes.insert("premium_expires_at".to_string(), Value::Null);
235 Ok(())
236 }
237
238 fn state_name(&self) -> &'static str {
239 "Free"
240 }
241}
242
243#[derive(Debug, Clone)]
245pub struct CompletedState;
246
247#[async_trait::async_trait]
248impl<T> FactoryState<T> for CompletedState {
249 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
250 attributes.insert("status".to_string(), json!("completed"));
251 attributes.insert("is_completed".to_string(), json!(true));
252 attributes.insert(
253 "completed_at".to_string(),
254 json!(fake_datetime().to_rfc3339()),
255 );
256 attributes.insert("progress".to_string(), json!(100));
257 Ok(())
258 }
259
260 fn state_name(&self) -> &'static str {
261 "Completed"
262 }
263}
264
265#[derive(Debug, Clone)]
267pub struct InProgressState;
268
269#[async_trait::async_trait]
270impl<T> FactoryState<T> for InProgressState {
271 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
272 attributes.insert("status".to_string(), json!("in_progress"));
273 attributes.insert("is_completed".to_string(), json!(false));
274 attributes.insert(
275 "started_at".to_string(),
276 json!(fake_datetime().to_rfc3339()),
277 );
278 attributes.insert("progress".to_string(), json!(random_range(1, 99)));
279 Ok(())
280 }
281
282 fn state_name(&self) -> &'static str {
283 "InProgress"
284 }
285}
286
287#[derive(Debug, Clone)]
289pub struct CustomState {
290 modifications: HashMap<String, Value>,
291 name: String,
292}
293
294impl CustomState {
295 pub fn new(name: impl Into<String>) -> Self {
296 Self {
297 modifications: HashMap::new(),
298 name: name.into(),
299 }
300 }
301
302 pub fn name(&self) -> &str {
303 &self.name
304 }
305
306 pub fn with(mut self, key: impl Into<String>, value: Value) -> Self {
307 self.modifications.insert(key.into(), value);
308 self
309 }
310
311 pub fn with_status(self, status: impl Into<String>) -> Self {
312 self.with("status", json!(status.into()))
313 }
314
315 pub fn with_bool_flag(self, flag: impl Into<String>, value: bool) -> Self {
316 self.with(flag.into(), json!(value))
317 }
318
319 pub fn with_timestamp(self, field: impl Into<String>, datetime: DateTime<Utc>) -> Self {
320 self.with(field.into(), json!(datetime.to_rfc3339()))
321 }
322
323 pub fn with_null(self, field: impl Into<String>) -> Self {
324 self.with(field.into(), Value::Null)
325 }
326}
327
328#[async_trait::async_trait]
329impl<T> FactoryState<T> for CustomState {
330 async fn apply(&self, attributes: &mut HashMap<String, Value>) -> OrmResult<()> {
331 for (key, value) in &self.modifications {
332 attributes.insert(key.clone(), value.clone());
333 }
334 Ok(())
335 }
336
337 fn state_name(&self) -> &'static str {
338 "Custom"
341 }
342}
343
344#[macro_export]
346macro_rules! factory_state {
347 ($name:ident { $($field:ident: $value:expr),* $(,)? }) => {
348 #[derive(Debug, Clone)]
349 pub struct $name;
350
351 #[async_trait::async_trait]
352 impl<T> $crate::factory::FactoryState<T> for $name {
353 async fn apply(&self, attributes: &mut std::collections::HashMap<String, serde_json::Value>) -> $crate::error::OrmResult<()> {
354 $(
355 attributes.insert(stringify!($field).to_string(), serde_json::json!($value));
356 )*
357 Ok(())
358 }
359
360 fn state_name(&self) -> &'static str {
361 stringify!($name)
362 }
363 }
364 };
365}
366
367#[cfg(test)]
368mod tests {
369 use super::*;
370 use serde_json::json;
371
372 #[tokio::test]
373 async fn test_active_state() {
374 let state = ActiveState;
375 let mut attributes = HashMap::new();
376
377 FactoryState::<()>::apply(&state, &mut attributes)
378 .await
379 .unwrap();
380
381 assert_eq!(attributes.get("status").unwrap(), &json!("active"));
382 assert_eq!(attributes.get("is_active").unwrap(), &json!(true));
383 assert_eq!(FactoryState::<()>::state_name(&state), "Active");
384 }
385
386 #[tokio::test]
387 async fn test_admin_state() {
388 let state = AdminState;
389 let mut attributes = HashMap::new();
390
391 FactoryState::<()>::apply(&state, &mut attributes)
392 .await
393 .unwrap();
394
395 assert_eq!(attributes.get("role").unwrap(), &json!("admin"));
396 assert_eq!(attributes.get("is_admin").unwrap(), &json!(true));
397 assert!(attributes.get("permissions").unwrap().is_array());
398 }
399
400 #[tokio::test]
401 async fn test_verified_state() {
402 let state = VerifiedState;
403 let mut attributes = HashMap::new();
404
405 FactoryState::<()>::apply(&state, &mut attributes)
406 .await
407 .unwrap();
408
409 assert_eq!(attributes.get("status").unwrap(), &json!("verified"));
410 assert_eq!(attributes.get("is_verified").unwrap(), &json!(true));
411 assert!(attributes.get("verified_at").unwrap().is_string());
412 }
413
414 #[tokio::test]
415 async fn test_draft_state() {
416 let state = DraftState;
417 let mut attributes = HashMap::new();
418
419 FactoryState::<()>::apply(&state, &mut attributes)
420 .await
421 .unwrap();
422
423 assert_eq!(attributes.get("status").unwrap(), &json!("draft"));
424 assert_eq!(attributes.get("is_published").unwrap(), &json!(false));
425 assert!(attributes.get("published_at").unwrap().is_null());
426 }
427
428 #[tokio::test]
429 async fn test_custom_state() {
430 let state = CustomState::new("test")
431 .with("custom_field", json!("custom_value"))
432 .with_status("custom_status")
433 .with_bool_flag("custom_flag", true)
434 .with_null("null_field");
435
436 let mut attributes = HashMap::new();
437
438 FactoryState::<()>::apply(&state, &mut attributes)
439 .await
440 .unwrap();
441
442 assert_eq!(
443 attributes.get("custom_field").unwrap(),
444 &json!("custom_value")
445 );
446 assert_eq!(attributes.get("status").unwrap(), &json!("custom_status"));
447 assert_eq!(attributes.get("custom_flag").unwrap(), &json!(true));
448 assert!(attributes.get("null_field").unwrap().is_null());
449 }
450
451 #[tokio::test]
452 async fn test_in_progress_state() {
453 let state = InProgressState;
454 let mut attributes = HashMap::new();
455
456 FactoryState::<()>::apply(&state, &mut attributes)
457 .await
458 .unwrap();
459
460 assert_eq!(attributes.get("status").unwrap(), &json!("in_progress"));
461 assert_eq!(attributes.get("is_completed").unwrap(), &json!(false));
462 assert!(attributes.get("started_at").unwrap().is_string());
463
464 let progress = attributes.get("progress").unwrap().as_i64().unwrap();
465 assert!(progress >= 1 && progress <= 99);
466 }
467
468 factory_state!(TestMacroState {
470 test_field: "test_value",
471 test_bool: true,
472 test_number: 42,
473 });
474
475 #[tokio::test]
476 async fn test_macro_generated_state() {
477 let state = TestMacroState;
478 let mut attributes = HashMap::new();
479
480 FactoryState::<()>::apply(&state, &mut attributes)
481 .await
482 .unwrap();
483
484 assert_eq!(attributes.get("test_field").unwrap(), &json!("test_value"));
485 assert_eq!(attributes.get("test_bool").unwrap(), &json!(true));
486 assert_eq!(attributes.get("test_number").unwrap(), &json!(42));
487 assert_eq!(FactoryState::<()>::state_name(&state), "TestMacroState");
488 }
489}