use super::*;
fn expansion(source: &str) -> String {
let input: DeriveInput = syn::parse_str(source).expect("the derive input parses");
expand_tokens(input).to_string()
}
fn first_field(source: &str) -> (DeriveInput, syn::Field) {
let input: DeriveInput = syn::parse_str(source).expect("the derive input parses");
let field = match &input.data {
Data::Struct(data) => data
.fields
.iter()
.next()
.expect("the struct declares a field")
.clone(),
_ => panic!("the source declares a struct"),
};
(input, field)
}
#[test]
fn a_raw_identifier_keeps_its_spelling_without_the_raw_prefix() {
let ident: syn::Ident = syn::parse_str("r#type").expect("a raw identifier");
assert_eq!(label(&ident), "Type");
let ident: syn::Ident = syn::parse_str("canonical_url").expect("an identifier");
assert_eq!(label(&ident), "Canonical Url");
}
#[test]
fn a_raw_identifier_field_is_labelled_without_the_raw_prefix() {
let krate = quote! { ::tablo_core };
let owner: syn::Ident = syn::parse_str("Seo").unwrap();
let (_, field) = first_field("struct Seo { r#type: String }");
let member = &members([&field]).unwrap()[0];
let add = build_member(&krate, &owner, member, 0, None).to_string();
assert!(add.contains(r#"label ("Type")"#), "{add}");
let (_, field) = first_field(r#"struct Seo { #[form(label = "Kind")] r#type: String }"#);
let member = &members([&field]).unwrap()[0];
let add = build_member(&krate, &owner, member, 0, None).to_string();
assert!(add.contains(r#"label ("Kind")"#), "{add}");
}
#[test]
fn a_scalar_carries_a_form_scalar_assertion_first() {
let member = Member {
ident: syn::parse_str("tags").unwrap(),
ty: syn::parse_str("Vec<String>").unwrap(),
attrs: FormAttrs::default(),
shared: false,
};
let krate = quote! { ::tablo_core };
let owner: syn::Ident = syn::parse_str("Seo").unwrap();
let add = build_member(&krate, &owner, &member, 0, None).to_string();
let assert = add
.find("assert_form_scalar :: < Vec < String > >")
.unwrap_or_else(|| panic!("the schema asserts the bound, got {add}"));
let leaf = add.find("embedded_leaf").expect("the leaf's field");
assert!(assert < leaf, "the assertion comes first, got {add}");
}
#[test]
fn an_embedded_member_delegates_to_its_own_impl() {
let member = Member {
ident: syn::parse_str("seo").unwrap(),
ty: syn::parse_str("Seo").unwrap(),
attrs: FormAttrs {
embed: true,
..FormAttrs::default()
},
shared: false,
};
let krate = quote! { ::tablo_core };
let read = read_member(&krate, &member, 0, "e! { None }).to_string();
assert!(read.contains("read_node"), "{read}");
let owner: syn::Ident = syn::parse_str("Holder").unwrap();
let add = build_member(&krate, &owner, &member, 0, None).to_string();
assert!(!add.contains("assert_form_scalar"), "{add}");
}
#[test]
fn an_unknown_form_key_is_refused() {
let error = expansion("struct Seo { #[form(textarea)] body: String }");
assert!(error.contains("unknown `#[form(..)]` key"), "got {error}");
let error = expansion("enum Kind { Draft { #[form(rows = 3)] body: String } }");
assert!(
error.contains("unknown `#[form(..)]` key"),
"an enum payload is checked too, got {error}"
);
}