1use std::path::PathBuf;
2
3use clap::Parser;
4
5#[derive(Parser, Debug, Clone)]
6#[command(name = "domi-server", version, about = "DOMicile live feedback server")]
7pub struct Args {
8 #[arg(long, default_value = "4173", value_parser = clap::value_parser!(u16).range(0..=65535))]
9 pub port: u16,
10 #[arg(long, default_value = "127.0.0.1")]
11 pub host: String,
12 #[arg(long, default_value = ".domi/output")]
13 pub root: PathBuf,
14 #[arg(long, default_value = ".domi/state")]
15 pub state: PathBuf,
16 #[arg(long)]
17 pub library_root: Option<PathBuf>,
18 #[arg(long, default_value = "info")]
19 pub log_level: String,
20}
21
22#[cfg(test)]
23mod tests {
24 use super::*;
25
26 #[test]
27 fn defaults_apply_when_no_flags() {
28 let a = Args::try_parse_from(["domi-server"]).unwrap();
29 assert_eq!(a.port, 4173);
30 assert_eq!(a.host, "127.0.0.1");
31 assert_eq!(a.root, PathBuf::from(".domi/output"));
32 assert_eq!(a.state, PathBuf::from(".domi/state"));
33 assert_eq!(a.log_level, "info");
34 }
35
36 #[test]
37 fn overrides_parse() {
38 let a = Args::try_parse_from([
39 "domi-server",
40 "--port",
41 "9000",
42 "--host",
43 "0.0.0.0",
44 "--root",
45 "/tmp/root",
46 "--state",
47 "/tmp/state",
48 "--log-level",
49 "debug",
50 ])
51 .unwrap();
52 assert_eq!(a.port, 9000);
53 assert_eq!(a.host, "0.0.0.0");
54 assert_eq!(a.root, PathBuf::from("/tmp/root"));
55 assert_eq!(a.state, PathBuf::from("/tmp/state"));
56 assert_eq!(a.log_level, "debug");
57 }
58
59 #[test]
60 fn invalid_port_rejected() {
61 let r = Args::try_parse_from(["domi-server", "--port", "not-a-number"]);
62 assert!(r.is_err(), "expected parse error for non-numeric port");
63 }
64 #[test]
68 fn port_zero_accepted() {
69 let a = Args::try_parse_from(["domi-server", "--port", "0"]).expect("--port 0 must parse");
70 assert_eq!(a.port, 0);
71 }
72
73 #[test]
74 fn library_root_defaults_to_none() {
75 let a = Args::try_parse_from(["domi-server"]).unwrap();
76 assert!(a.library_root.is_none(), "library_root must default to None");
77 }
78
79 #[test]
80 fn library_root_accepts_path() {
81 let a = Args::try_parse_from(["domi-server", "--library-root", "/tmp/lib"]).unwrap();
82 assert_eq!(a.library_root, Some(PathBuf::from("/tmp/lib")));
83 }
84
85 #[test]
86 fn library_root_can_be_omitted_alongside_other_flags() {
87 let a = Args::try_parse_from([
88 "domi-server",
89 "--port", "9000",
90 "--root", "/tmp/r",
91 "--state", "/tmp/s",
92 ])
93 .unwrap();
94 assert!(a.library_root.is_none());
95 assert_eq!(a.port, 9000);
96 }
97}