cron_when/cli/dispatch/
mod.rs

1use crate::cli::actions::Action;
2use anyhow::Result;
3use clap::ArgMatches;
4use std::path::PathBuf;
5
6/// Convert ArgMatches into an Action
7pub fn handler(matches: &ArgMatches) -> Result<Action> {
8    // Determine verbosity level
9    let verbose = matches.get_count("verbose") > 0;
10
11    // Extract next count if provided
12    let next = matches.get_one::<u32>("next").copied();
13
14    // Check which mode was requested
15    if matches.get_flag("crontab") {
16        Ok(Action::Crontab { verbose })
17    } else if let Some(file_path) = matches.get_one::<String>("file") {
18        Ok(Action::File {
19            path: PathBuf::from(file_path),
20            verbose,
21        })
22    } else if let Some(expression) = matches.get_one::<String>("cron") {
23        Ok(Action::Single {
24            expression: expression.clone(),
25            verbose,
26            next,
27        })
28    } else {
29        anyhow::bail!(
30            "Please provide a cron expression, use --file, or use --crontab\n\
31             Run with --help for usage information"
32        )
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use crate::cli::commands;
40
41    #[test]
42    fn test_handler_single() {
43        let matches = commands::new().get_matches_from(vec!["cron-when", "*/5 * * * *"]);
44        let action = handler(&matches).unwrap();
45        assert!(matches!(action, Action::Single { .. }));
46    }
47
48    #[test]
49    fn test_handler_file() {
50        let matches = commands::new().get_matches_from(vec!["cron-when", "-f", "test.crontab"]);
51        let action = handler(&matches).unwrap();
52        assert!(matches!(action, Action::File { .. }));
53    }
54
55    #[test]
56    fn test_handler_crontab() {
57        let matches = commands::new().get_matches_from(vec!["cron-when", "--crontab"]);
58        let action = handler(&matches).unwrap();
59        assert!(matches!(action, Action::Crontab { verbose: false }));
60    }
61
62    #[test]
63    fn test_handler_verbose() {
64        let matches = commands::new().get_matches_from(vec!["cron-when", "-v", "*/5 * * * *"]);
65        let action = handler(&matches).unwrap();
66        if let Action::Single { verbose, .. } = action {
67            assert!(verbose);
68        } else {
69            panic!("Expected Single action");
70        }
71    }
72
73    #[test]
74    fn test_handler_no_args() {
75        let matches = commands::new().get_matches_from(vec!["cron-when"]);
76        let result = handler(&matches);
77        assert!(result.is_err());
78    }
79
80    #[test]
81    fn test_handler_next() {
82        let matches =
83            commands::new().get_matches_from(vec!["cron-when", "--next", "5", "*/5 * * * *"]);
84        let action = handler(&matches).unwrap();
85        if let Action::Single { next, .. } = action {
86            assert_eq!(next, Some(5));
87        } else {
88            panic!("Expected Single action");
89        }
90    }
91}