Skip to content

Commit b424a1d

Browse files
authored
tests: Add tests for internal functions (#47)
Add some tests
2 parents 5797470 + f7cfc84 commit b424a1d

2 files changed

Lines changed: 232 additions & 2 deletions

File tree

src/attributes.rs

Lines changed: 204 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ where
6565
}
6666

6767
/// Represents a rename attribute for an enum variant.
68-
#[derive(Clone)]
68+
#[derive(Clone, Debug, PartialEq)]
6969
struct VariantRename(String);
7070

7171
impl TryFrom<(String, String)> for VariantRename {
@@ -98,7 +98,7 @@ impl VariantRename {
9898
}
9999

100100
/// Represents attribute configurations for renaming enum variants.
101-
#[derive(Default)]
101+
#[derive(Default, Debug, PartialEq)]
102102
pub(crate) struct Attributes {
103103
case: Option<Case>,
104104
prefix: Option<String>,
@@ -211,3 +211,205 @@ impl Variants {
211211
.collect()
212212
}
213213
}
214+
215+
#[cfg(test)]
216+
mod tests {
217+
use quote::quote;
218+
219+
use super::*;
220+
221+
#[test]
222+
fn test_parse_string() {
223+
assert_eq!(parse_string("\"hello\""), Ok("hello".to_string()));
224+
assert_eq!(
225+
parse_string("hello"),
226+
Err("String must be enclosed in double quotes")
227+
);
228+
229+
assert_eq!(
230+
parse_string("\"hello"),
231+
Err("String must be enclosed in double quotes")
232+
);
233+
assert_eq!(
234+
parse_string("hello\""),
235+
Err("String must be enclosed in double quotes")
236+
);
237+
assert_eq!(parse_string("\"he\"llo\""), Ok("he\"llo".to_string()));
238+
239+
assert_eq!(parse_string("\"\""), Ok("".to_string()));
240+
assert_eq!(parse_string("\"\"\""), Ok("\"".to_string()));
241+
}
242+
243+
fn assert_parse_token_list<T>(tokens: TokenStream, expected: Vec<T>)
244+
where
245+
T: TryFrom<(String, String)> + PartialEq + std::fmt::Debug,
246+
{
247+
let result = parse_token_list::<T>(&tokens).unwrap();
248+
assert_eq!(result, expected);
249+
}
250+
251+
#[test]
252+
fn test_parse_token_list_string_string() {
253+
assert_parse_token_list::<(String, String)>(quote! {}, vec![]);
254+
255+
assert_parse_token_list::<(String, String)>(
256+
quote! { rename = "hello" },
257+
vec![("rename".to_string(), "\"hello\"".to_string())],
258+
);
259+
260+
assert_parse_token_list(
261+
quote! { rename = "hello", rename = "world" },
262+
vec![
263+
("rename".to_string(), "\"hello\"".to_string()),
264+
("rename".to_string(), "\"world\"".to_string()),
265+
],
266+
);
267+
}
268+
269+
#[derive(Debug, PartialEq)]
270+
struct TestStruct(String);
271+
272+
impl TryFrom<(String, String)> for TestStruct {
273+
type Error = &'static str;
274+
275+
fn try_from(value: (String, String)) -> Result<Self, Self::Error> {
276+
Ok(Self(parse_string(value.1.as_str())?))
277+
}
278+
}
279+
280+
#[test]
281+
fn test_parse_token_list_struct() {
282+
assert_parse_token_list::<TestStruct>(
283+
quote! { rename = "hello" },
284+
vec![TestStruct("hello".to_string())],
285+
);
286+
287+
assert_parse_token_list::<TestStruct>(
288+
quote! { rename = "hello", rename = "world" },
289+
vec![
290+
TestStruct("hello".to_string()),
291+
TestStruct("world".to_string()),
292+
],
293+
);
294+
}
295+
296+
#[test]
297+
fn test_variant_rename_try_from() {
298+
assert_eq!(
299+
VariantRename::try_from(("rename".to_string(), "\"hello\"".to_string())),
300+
Ok(VariantRename("hello".to_string()))
301+
);
302+
303+
assert_eq!(
304+
VariantRename::try_from(("rename".to_string(), "hello".to_string())),
305+
Err("String must be enclosed in double quotes")
306+
);
307+
308+
assert_eq!(
309+
VariantRename::try_from(("not_rename".to_string(), "\"hello\"".to_string())),
310+
Err("Not a rename string")
311+
);
312+
}
313+
314+
#[test]
315+
fn test_parse_token_list_variant_rename() {
316+
assert_parse_token_list::<VariantRename>(
317+
quote! { rename = "hello" },
318+
vec![VariantRename("hello".to_string())],
319+
);
320+
321+
assert_parse_token_list::<VariantRename>(
322+
quote! { rename = "hello", rename = "world" },
323+
vec![
324+
VariantRename("hello".to_string()),
325+
VariantRename("world".to_string()),
326+
],
327+
);
328+
}
329+
330+
#[test]
331+
fn test_attributes_parse_args() {
332+
let attribute =
333+
syn::parse_quote! { #[enum_stringify(prefix = "pre", suffix = "suf", case = "snake")] };
334+
let attributes = Attributes::parse_args(&attribute).unwrap();
335+
assert_eq!(attributes.prefix, Some("pre".to_string()));
336+
assert_eq!(attributes.suffix, Some("suf".to_string()));
337+
assert_eq!(
338+
attributes.case.map(|a| a.to_string()),
339+
Some("snake".to_string())
340+
);
341+
342+
let attribute = syn::parse_quote! { #[enum_stringify(prefix = "pre", suffix = "suf")] };
343+
let attributes = Attributes::parse_args(&attribute).unwrap();
344+
assert_eq!(attributes.prefix, Some("pre".to_string()));
345+
assert_eq!(attributes.suffix, Some("suf".to_string()));
346+
assert_eq!(attributes.case, None);
347+
348+
let attribute = syn::parse_quote! { #[enum_stringify(case = "snake")] };
349+
let attributes = Attributes::parse_args(&attribute).unwrap();
350+
assert_eq!(attributes.prefix, None);
351+
assert_eq!(attributes.suffix, None);
352+
assert_eq!(
353+
attributes.case.map(|a| a.to_string()),
354+
Some("snake".to_string())
355+
);
356+
357+
let attribute = syn::parse_quote! { #[enum_stringify] };
358+
assert_eq!(Attributes::parse_args(&attribute), None);
359+
}
360+
361+
#[test]
362+
fn test_attributes_update_attribute() {
363+
let mut attributes = Attributes::default();
364+
attributes.update_attribute(("prefix".to_string(), "\"pre\"".to_string()));
365+
assert_eq!(attributes.prefix, Some("pre".to_string()));
366+
367+
attributes.update_attribute(("suffix".to_string(), "\"suf\"".to_string()));
368+
assert_eq!(attributes.suffix, Some("suf".to_string()));
369+
370+
attributes.update_attribute(("case".to_string(), "\"snake\"".to_string()));
371+
assert_eq!(
372+
attributes.case.clone().map(|a| a.to_string()),
373+
Some("snake".to_string())
374+
);
375+
376+
attributes.update_attribute(("invalid".to_string(), "\"value\"".to_string()));
377+
assert_eq!(attributes.prefix, Some("pre".to_string()));
378+
assert_eq!(attributes.suffix, Some("suf".to_string()));
379+
assert_eq!(
380+
attributes.case.clone().map(|a| a.to_string()),
381+
Some("snake".to_string())
382+
);
383+
384+
attributes.update_attribute(("prefix".to_string(), "\"new1\"".to_string()));
385+
assert_eq!(attributes.prefix, Some("new1".to_string()));
386+
387+
attributes.update_attribute(("suffix".to_string(), "\"new2\"".to_string()));
388+
assert_eq!(attributes.suffix, Some("new2".to_string()));
389+
390+
attributes.update_attribute(("case".to_string(), "\"upper\"".to_string()));
391+
assert_eq!(
392+
attributes.case.clone().map(|a| a.to_string()),
393+
Some("upper".to_string())
394+
);
395+
}
396+
397+
#[test]
398+
fn test_attributes_rename() {
399+
let mut attributes = Attributes {
400+
prefix: Some("pre".to_string()),
401+
suffix: Some("suf".to_string()),
402+
case: None,
403+
};
404+
405+
assert_eq!(attributes.rename("name"), "prenamesuf");
406+
assert_eq!(attributes.rename("Name"), "preNamesuf");
407+
assert_eq!(attributes.rename("NAME"), "preNAMEsuf");
408+
409+
attributes.update_attribute(("case".to_string(), "\"upper_flat\"".to_string()));
410+
411+
assert_eq!(attributes.rename("name"), "PRENAMESUF");
412+
assert_eq!(attributes.rename("Name"), "PRENAMESUF");
413+
assert_eq!(attributes.rename("NAME"), "PRENAMESUF");
414+
}
415+
}

src/case.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
use std::fmt::Display;
2+
13
use convert_case::Casing;
24

35
/// Wrapper struct around `convert_case::Case` to represent different casing styles.
6+
#[derive(Debug, PartialEq, Clone)]
47
pub(crate) struct Case(convert_case::Case);
58

69
// This is used to check if the first string is "case" and then attempt conversion of the second string.
@@ -44,6 +47,31 @@ impl TryFrom<String> for Case {
4447
}
4548
}
4649

50+
impl Display for Case {
51+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
52+
let v = match self.0 {
53+
convert_case::Case::Upper => "upper".to_string(),
54+
convert_case::Case::Lower => "lower".to_string(),
55+
convert_case::Case::Title => "title".to_string(),
56+
convert_case::Case::Toggle => "toggle".to_string(),
57+
convert_case::Case::Camel => "camel".to_string(),
58+
convert_case::Case::Pascal => "pascal".to_string(),
59+
convert_case::Case::UpperCamel => "upper_camel".to_string(),
60+
convert_case::Case::Snake => "snake".to_string(),
61+
convert_case::Case::UpperSnake => "upper_snake".to_string(),
62+
convert_case::Case::ScreamingSnake => "screaming_snake".to_string(),
63+
convert_case::Case::Kebab => "kebab".to_string(),
64+
convert_case::Case::Cobol => "cobol".to_string(),
65+
convert_case::Case::UpperKebab => "upper_kebab".to_string(),
66+
convert_case::Case::Train => "train".to_string(),
67+
convert_case::Case::Flat => "flat".to_string(),
68+
convert_case::Case::UpperFlat => "upper_flat".to_string(),
69+
convert_case::Case::Alternating => "alternating".to_string(),
70+
};
71+
write!(f, "{v}")
72+
}
73+
}
74+
4775
impl Case {
4876
/// Applies the stored casing style to the given string `s` and returns the formatted result.
4977
pub(crate) fn to_case(&self, s: &str) -> String {

0 commit comments

Comments
 (0)