1
use supp_macro::command;
2

            
3
// Test the new pure typed system with no HashMap usage
4

            
5
#[derive(Debug)]
6
pub enum CmdError {
7
    Args(String),
8
}
9

            
10
impl std::fmt::Display for CmdError {
11
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12
        write!(f, "{:?}", self)
13
    }
14
}
15

            
16
impl std::error::Error for CmdError {}
17

            
18
#[derive(Debug)]
19
pub enum CmdResult {
20
    Success(String),
21
}
22

            
23
// Progressive types approach - no unified CommandArgs struct needed!
24

            
25
// Test command with mixed required and optional arguments - pure typed
26
command! {
27
    CreateUser {
28
        #[required]
29
        name: String,
30
        #[required]
31
        age: i64,
32
        #[optional]
33
        email: String,
34
        #[optional]
35
        is_admin: bool,
36
    } => {
37
        let email_str = email.map_or("no email".to_string(), |e| e);
38
2
        let admin_str = is_admin.map_or("false".to_string(), |a| a.to_string());
39

            
40
        Ok(Some(CmdResult::Success(format!(
41
            "User: {} (age: {}), email: {}, admin: {}",
42
            name, age, email_str, admin_str
43
        ))))
44
    }
45
28
}
46

            
47
// Test command with no arguments
48
command! {
49
    GetVersion {
50
    } => {
51
        Ok(Some(CmdResult::Success("Version 1.0.0".to_string())))
52
    }
53
4
}
54

            
55
#[cfg(test)]
56
mod tests {
57
    use super::*;
58

            
59
    #[tokio::test]
60
3
    async fn test_pure_typed_system() {
61
        // ✅ Progressive types - pure value-based argument passing
62
2
        let result = CreateUser::new()
63
2
            .name("Alice".to_string())
64
2
            .age(30)
65
2
            .email("alice@example.com".to_string())
66
2
            .is_admin(true)
67
2
            .run()
68
2
            .await
69
2
            .unwrap();
70

            
71
3
        if let Some(CmdResult::Success(msg)) = result {
72
3
            assert!(msg.contains("Alice"));
73
3
            assert!(msg.contains("30"));
74
3
            assert!(msg.contains("alice@example.com"));
75
3
            assert!(msg.contains("true"));
76
2
        } else {
77
2
            panic!("Expected success result");
78
2
        }
79
2
    }
80

            
81
    #[tokio::test]
82
3
    async fn test_no_args_command() {
83
2
        let result = GetVersion::new().run().await.unwrap();
84

            
85
3
        if let Some(CmdResult::Success(msg)) = result {
86
3
            assert_eq!(msg, "Version 1.0.0");
87
2
        } else {
88
2
            panic!("Expected success result");
89
2
        }
90
2
    }
91

            
92
    #[tokio::test]
93
3
    async fn test_optional_args_none() {
94
2
        let result = CreateUser::new()
95
2
            .name("Bob".to_string())
96
2
            .age(25)
97
2
            .run()
98
2
            .await
99
2
            .unwrap();
100

            
101
3
        if let Some(CmdResult::Success(msg)) = result {
102
3
            assert!(msg.contains("Bob"));
103
3
            assert!(msg.contains("25"));
104
3
            assert!(msg.contains("no email"));
105
3
            assert!(msg.contains("false"));
106
2
        } else {
107
2
            panic!("Expected success result");
108
2
        }
109
2
    }
110

            
111
    #[test]
112
2
    fn test_compile_time_validation() {
113
        // ✅ Progressive types - all validation happens at compile time
114
2
        let _runner = CreateUser::new()
115
2
            .name("Charlie".to_string())
116
2
            .age(35)
117
2
            .email("charlie@example.com".to_string());
118

            
119
        // The following would be compile errors with progressive types:
120
        // let _invalid = CreateUser::new()
121
        //     .name("Dave".to_string())
122
        //     .run();  // Missing required field 'age' - compile error!
123

            
124
        // let _invalid2 = CreateUser::new()
125
        //     .name(123)  // Wrong type - compile error!
126
        //     .age(40);
127
2
    }
128
}