Rust · 4284 bytes Raw Blame History
1 use std::process::Command;
2
3 fn rcal() -> Command {
4 Command::new(env!("CARGO_BIN_EXE_rcal"))
5 }
6
7 fn version_output() -> String {
8 format!("rcal {}\n", env!("CARGO_PKG_VERSION"))
9 }
10
11 #[test]
12 fn deterministic_date_flag_succeeds() {
13 let output = rcal()
14 .args(["--date", "2026-04-23"])
15 .output()
16 .expect("rcal binary runs");
17
18 assert!(output.status.success());
19 assert_eq!(String::from_utf8_lossy(&output.stderr), "");
20
21 let stdout = String::from_utf8_lossy(&output.stdout);
22 assert!(stdout.contains("April 2026"));
23 assert!(stdout.contains("Sun"));
24 assert!(stdout.contains("[23*]"));
25 }
26
27 #[test]
28 fn invalid_date_flag_fails() {
29 let output = rcal()
30 .args(["--date", "2026-02-30"])
31 .output()
32 .expect("rcal binary runs");
33
34 assert_eq!(output.status.code(), Some(2));
35 assert_eq!(String::from_utf8_lossy(&output.stdout), "");
36
37 let stderr = String::from_utf8_lossy(&output.stderr);
38 assert!(stderr.contains("invalid --date value '2026-02-30'"));
39 assert!(stderr.contains("Usage:"));
40 assert!(stderr.contains("rcal [--config PATH|--no-config]"));
41 }
42
43 #[test]
44 fn help_flag_succeeds() {
45 let output = rcal().arg("--help").output().expect("rcal binary runs");
46
47 assert!(output.status.success());
48 assert_eq!(String::from_utf8_lossy(&output.stderr), "");
49 let stdout = String::from_utf8_lossy(&output.stdout);
50 assert!(stdout.contains(version_output().trim_end()));
51 assert!(stdout.contains("Usage:"));
52 assert!(stdout.contains("--holiday-source off|us-federal|nager"));
53 assert!(stdout.contains("Left click selects a visible date"));
54 }
55
56 #[test]
57 fn version_flag_succeeds() {
58 let output = rcal().arg("--version").output().expect("rcal binary runs");
59
60 assert!(output.status.success());
61 assert_eq!(String::from_utf8_lossy(&output.stderr), "");
62 assert_eq!(String::from_utf8_lossy(&output.stdout), version_output());
63 }
64
65 #[test]
66 fn holiday_country_without_nager_fails() {
67 let output = rcal()
68 .args(["--holiday-country", "GB"])
69 .output()
70 .expect("rcal binary runs");
71
72 assert_eq!(output.status.code(), Some(2));
73 assert_eq!(String::from_utf8_lossy(&output.stdout), "");
74
75 let stderr = String::from_utf8_lossy(&output.stderr);
76 assert!(stderr.contains("--holiday-country may only be used with --holiday-source nager"));
77 }
78
79 #[test]
80 fn events_file_renders_local_event() {
81 let path = std::env::temp_dir().join(format!(
82 "rcal-cli-events-{}-{}.json",
83 std::process::id(),
84 "render"
85 ));
86 std::fs::write(
87 &path,
88 r#"{
89 "version": 1,
90 "events": [
91 {
92 "id": "local-test",
93 "title": "Planning",
94 "start_date": "2026-04-23",
95 "start_time": "09:00",
96 "end_date": "2026-04-23",
97 "end_time": "10:00",
98 "location": "War room",
99 "notes": "Bring notes",
100 "reminders_minutes_before": [10, 60]
101 }
102 ]
103 }"#,
104 )
105 .expect("events file can be written");
106
107 let output = rcal()
108 .args([
109 "--date",
110 "2026-04-23",
111 "--events-file",
112 path.to_str().expect("temp path is utf-8"),
113 ])
114 .output()
115 .expect("rcal binary runs");
116
117 let _ = std::fs::remove_file(path);
118
119 assert!(output.status.success());
120 assert_eq!(String::from_utf8_lossy(&output.stderr), "");
121 assert!(String::from_utf8_lossy(&output.stdout).contains("09:00 Plan"));
122 }
123
124 #[test]
125 fn malformed_events_file_fails_cleanly() {
126 let path = std::env::temp_dir().join(format!(
127 "rcal-cli-events-{}-{}.json",
128 std::process::id(),
129 "malformed"
130 ));
131 std::fs::write(&path, "{not json").expect("events file can be written");
132
133 let output = rcal()
134 .args([
135 "--date",
136 "2026-04-23",
137 "--events-file",
138 path.to_str().expect("temp path is utf-8"),
139 ])
140 .output()
141 .expect("rcal binary runs");
142
143 let _ = std::fs::remove_file(path);
144
145 assert_eq!(output.status.code(), Some(2));
146 assert_eq!(String::from_utf8_lossy(&output.stdout), "");
147 let stderr = String::from_utf8_lossy(&output.stderr);
148 assert!(stderr.contains("failed to load local events"));
149 assert!(stderr.contains("failed to parse"));
150 }
151