gitignore_template_generator/parser/
api.rs1use std::ffi::OsString;
2
3pub use crate::parser::impls::DefaultArgsParser;
4use crate::{ProgramError, config::Args};
5
6pub trait ArgsParser {
7 fn parse(args: impl IntoIterator<Item = OsString>) -> Args;
8 fn try_parse(
9 args: impl IntoIterator<Item = OsString>,
10 ) -> Result<Args, ProgramError>;
11}
12
13#[cfg(test)]
14mod tests {
15 use rstest::*;
16
17 use super::*;
18 use crate::helper::*;
19
20 mod default_args_parser {
21 use super::*;
22
23 mod try_parse {
24 use super::*;
25
26 mod success {
27 use crate::{ErrorKind, constant};
28
29 use super::*;
30
31 #[rstest]
32 #[case("-V")]
33 #[case("--version")]
34 #[case("-V rust")]
35 #[case("rust -V")]
36 #[case("rust -s foo -V")]
37 #[case("-aV")]
38 fn it_parses_version_cli_option(#[case] cli_args: &str) {
39 let cli_args = parse_cli_args(cli_args);
40 let parsed_args = DefaultArgsParser::try_parse(cli_args);
41
42 let actual_error = parsed_args.as_ref().err();
43 let expected_error = ProgramError {
44 message: format!(
45 "{} {}",
46 env!("CARGO_PKG_NAME"),
47 env!("CARGO_PKG_VERSION")
48 ),
49 exit_status: 0,
50 styled_message: None,
51 error_kind: ErrorKind::VersionInfos,
52 };
53 let expected_error = Some(&expected_error);
54
55 assert!(actual_error.is_some());
56 assert_eq!(actual_error, expected_error);
57 }
58
59 #[rstest]
60 #[case("-h")]
61 #[case("--help")]
62 #[case("-h rust")]
63 #[case("rust -h")]
64 #[case("rust -s foo -h")]
65 #[case("-aVh")]
66 fn it_parses_help_cli_option(#[case] cli_args: &str) {
67 let cli_args = parse_cli_args(cli_args);
68 let parsed_args = DefaultArgsParser::try_parse(cli_args);
69
70 let actual_error = parsed_args.as_ref().err();
71 let expected_error = ProgramError {
72 message: get_help_message(),
73 exit_status: 0,
74 styled_message: Some(get_ansi_help_message()),
75 error_kind: ErrorKind::HelpInfos,
76 };
77 let expected_error = Some(&expected_error);
78
79 assert!(actual_error.is_some());
80 assert_eq!(actual_error, expected_error);
81 }
82
83 #[rstest]
84 #[case("-a")]
85 #[case("--author")]
86 #[case("-a rust")]
87 #[case("rust -a")]
88 #[case("rust -s foo -a")]
89 fn it_parses_author_cli_option_preemptively(
90 #[case] cli_args: &str,
91 ) {
92 let cli_args = parse_cli_args(cli_args);
93 let parsed_args = DefaultArgsParser::try_parse(cli_args);
94
95 let actual_error = parsed_args.as_ref().err();
96 let expected_error = ProgramError {
97 message: env!("CARGO_PKG_AUTHORS").to_string(),
98 exit_status: 0,
99 styled_message: None,
100 error_kind: ErrorKind::AuthorInfos,
101 };
102 let expected_error = Some(&expected_error);
103
104 assert!(actual_error.is_some());
105 assert_eq!(actual_error, expected_error);
106 }
107
108 #[rstest]
109 #[case("rust")]
110 #[case("rust python node")]
111 fn it_parses_pos_args_without_server_url_cli_option(
112 #[case] cli_options: &str,
113 ) {
114 let cli_args = parse_cli_args(cli_options);
115 let parsed_args = DefaultArgsParser::try_parse(cli_args);
116
117 let actual_result = parsed_args.as_ref().ok();
118 let expected_result = Args::default()
119 .with_template_names(make_string_vec(cli_options))
120 .with_server_url(
121 constant::template_generator::BASE_URL,
122 );
123 let expected_result = Some(&expected_result);
124
125 assert!(actual_result.is_some());
126 assert_eq!(actual_result, expected_result);
127 }
128
129 #[rstest]
130 #[case("rust -s https://test.com")]
131 #[case("rust --server-url https://test.com")]
132 fn it_parses_pos_args_with_server_url_cli_option(
133 #[case] cli_args: &str,
134 ) {
135 let cli_args = parse_cli_args(cli_args);
136 let parsed_args = DefaultArgsParser::try_parse(cli_args);
137
138 let actual_result = parsed_args.as_ref().ok();
139 let expected_result = Args::default()
140 .with_template_names(make_string_vec("rust"))
141 .with_server_url("https://test.com");
142 let expected_result = Some(&expected_result);
143
144 assert!(actual_result.is_some());
145 assert_eq!(actual_result, expected_result);
146 }
147 }
148
149 mod failure {
150 use crate::{ErrorKind, constant};
151
152 use super::*;
153
154 #[test]
155 fn it_fails_parsing_when_no_pos_args_given() {
156 let cli_args = parse_cli_args("");
157 let parsed_args = DefaultArgsParser::try_parse(cli_args);
158
159 let actual_error = parsed_args.as_ref().err();
160 let expected_error = ProgramError {
161 message: load_expectation_file_as_string(
162 "no_pos_args_error",
163 ),
164 exit_status: constant::exit_status::GENERIC,
165
166 styled_message: Some(load_expectation_file_as_string(
167 "ansi_no_pos_args_error",
168 )),
169 error_kind: ErrorKind::Other,
170 };
171 let expected_error = Some(&expected_error);
172
173 assert!(actual_error.is_some());
174 assert_eq!(actual_error, expected_error);
175 }
176
177 #[test]
178 fn it_fails_parsing_when_commas_in_pos_args() {
179 let cli_args = parse_cli_args("python,java");
180 let parsed_args = DefaultArgsParser::try_parse(cli_args);
181
182 let actual_error = parsed_args.as_ref().err();
183 let expected_error = ProgramError {
184 message: load_expectation_file_as_string(
185 "comma_pos_args_error",
186 ),
187 exit_status: constant::exit_status::GENERIC,
188
189 styled_message: Some(load_expectation_file_as_string(
190 "ansi_comma_pos_args_error",
191 )),
192 error_kind: ErrorKind::Other,
193 };
194 let expected_error = Some(&expected_error);
195
196 assert!(actual_error.is_some());
197 assert_eq!(actual_error, expected_error);
198 }
199
200 #[test]
201 fn it_fails_parsing_when_server_url_but_no_pos_args() {
202 let cli_args = parse_cli_args("-s https://test.com");
203 let parsed_args = DefaultArgsParser::try_parse(cli_args);
204
205 let actual_error = parsed_args.as_ref().err();
206 let expected_error = ProgramError {
207 message: load_expectation_file_as_string(
208 "server_url_no_pos_args_error",
209 ),
210 exit_status: constant::exit_status::GENERIC,
211
212 styled_message: Some(load_expectation_file_as_string(
213 "ansi_server_url_no_pos_args_error",
214 )),
215 error_kind: ErrorKind::Other,
216 };
217 let expected_error = Some(&expected_error);
218
219 assert!(actual_error.is_some());
220 assert_eq!(actual_error, expected_error);
221 }
222
223 #[test]
224 fn it_fails_parsing_when_inexistent_cli_option() {
225 let cli_args = parse_cli_args("-x");
226 let parsed_args = DefaultArgsParser::try_parse(cli_args);
227
228 let actual_error = parsed_args.as_ref().err();
229 let expected_error = ProgramError {
230 message: load_expectation_file_as_string(
231 "unexpected_argument_error",
232 ),
233 exit_status: constant::exit_status::GENERIC,
234 styled_message: Some(load_expectation_file_as_string(
235 "ansi_unexpected_argument_error",
236 )),
237 error_kind: ErrorKind::Other,
238 };
239 let expected_error = Some(&expected_error);
240
241 assert!(actual_error.is_some());
242 assert_eq!(actual_error, expected_error);
243 }
244 }
245 }
246 }
247}