aboutsummaryrefslogtreecommitdiff
path: root/examples/example-unit-test/src/main.rs
blob: b89c6296655cd29fd35333b6b87245bc5ef8a5ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! Example Unit Test
//!
//! > This example shows how to write unit tests for Chain and Renderer in Mingling
//!
//! ```bash
//! cargo test --manifest-path examples/example-unit-test/Cargo.toml
//! ```

use mingling::prelude::*;

#[cfg(test)]
mod tests {
    use super::*;
    use mingling::macros::entry;
    use mingling::{assert_member_id, assert_render_result, unpack_chain_process};

    // --------- IMPORTANT ---------
    #[test]
    fn test_handle_hello() {
        let hello_without_args = handle_hello(entry!()).into();
        assert_render_result!(hello_without_args);
        assert_member_id!(hello_without_args, ThisProgram::ErrorNoNameProvided);

        let hello_with_registered_name = handle_hello(entry!("Alice")).into();
        assert_render_result!(hello_with_registered_name);
        assert_member_id!(
            hello_with_registered_name,
            ThisProgram::ErrorNameNotAvailable
        );

        let hello_with_long_name = handle_hello(entry!("It's a VeryLongName")).into();
        assert_render_result!(hello_with_long_name);
        assert_member_id!(hello_with_long_name, ThisProgram::ErrorNameTooLong);

        let hello_with_valid_name = handle_hello(entry!("Peter")).into();
        assert_render_result!(hello_with_valid_name);
        let result_name = unpack_chain_process!(hello_with_valid_name, ResultName);
        assert_eq!(result_name.inner, "Peter");
    }

    #[test]
    fn test_render_result_name() {
        let r = render_result_name(ResultName::new("Peter".into()));
        assert_eq!(r, "Hello, Peter!\n")
    }

    #[test]
    fn test_render_error_no_name_provided() {
        let r = render_error_no_name_provided(ErrorNoNameProvided::default());
        assert_eq!(r, "No name provided\n")
    }

    #[test]
    fn test_render_error_name_not_available() {
        let r = render_error_name_not_available(ErrorNameNotAvailable::default());
        assert_eq!(r, "Name not available\n")
    }

    #[test]
    fn test_render_error_name_too_long() {
        let r = render_error_name_too_long(ErrorNameTooLong::new(17));
        assert_eq!(r, "Name too long: 17 > 10\n")
    }
    // --------- IMPORTANT ---------
}

dispatcher!("hello", CMDHello => EntryHello);

pack!(ErrorNoNameProvided = ());
pack!(ErrorNameTooLong = u16);
pack!(ErrorNameNotAvailable = ());

pack!(ResultName = String);

static VEC_REGISTERED_NAMES: &[&str] = &["Alice", "Bob", "Charlie", "David", "Eve"];

#[chain]
fn handle_hello(args: EntryHello) -> Next {
    let Some(name) = args.inner.first().cloned() else {
        return ErrorNoNameProvided::default().to_render();
    };

    if name.len() > 10 {
        return ErrorNameTooLong::new(name.len() as u16).to_render();
    }

    if VEC_REGISTERED_NAMES.contains(&name.as_str()) {
        return ErrorNameNotAvailable::default().to_render();
    }

    ResultName::new(name).to_render()
}

/// Renders a successful greeting with the given name.
#[renderer]
fn render_result_name(name: ResultName) -> String {
    r_println!("Hello, {}!", *name);
}

/// Renders the error when no name is provided.
#[renderer]
fn render_error_no_name_provided(_: ErrorNoNameProvided) -> String {
    r_println!("No name provided");
}

/// Renders the error when the name is already taken.
#[renderer]
fn render_error_name_not_available(_: ErrorNameNotAvailable) -> String {
    r_println!("Name not available");
}

/// Renders the error when the name exceeds the maximum length.
#[renderer]
fn render_error_name_too_long(len: ErrorNameTooLong) -> String {
    r_println!("Name too long: {} > 10", *len);
}

/// Renders the error when the dispatcher (subcommand) is not found.
#[renderer]
fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
    r_println!("Command not found: \"{}\"", err.inner.join(" "));
}

gen_program!();

fn main() {
    let mut program = ThisProgram::new();
    program.with_dispatcher(CMDHello);
    program.exec_and_exit();
}