test(derive): close third mutation shard
Prove missing generated-symbol fallback and exact accumulated form diagnostics for unknown forms, unnamed structs, missing fields, singular/multiple mismatches, and required Option fields. req: form/004 req: diagnostics/003 req: derive_handler/005 req: test/022 req: test/023
This commit is contained in:
+60
-3
@@ -1023,8 +1023,8 @@ fn compile_error(message: &str) -> TokenStream {
|
||||
mod tests {
|
||||
use super::{
|
||||
add_app_registry_helper, add_component_register_helper, client_handler_has_inputs,
|
||||
component_handler_names, expand_handler_function, form_fields, form_impl_generics,
|
||||
form_model_type, form_resource_id, handle_params, handle_requires_form,
|
||||
component_handler_names, expand_handler_function, form_contract_errors, form_fields,
|
||||
form_impl_generics, form_model_type, form_resource_id, handle_params, handle_requires_form,
|
||||
handler_form_model_type, handler_placement, handler_syms_path, has_form_param,
|
||||
has_non_unit_return, is_type_named, join_contract_errors, missing_component_handlers,
|
||||
missing_form_generated_files_message, missing_handle_params,
|
||||
@@ -1249,6 +1249,58 @@ mod tests {
|
||||
// test req: derive_handler/001 req: derive_handler/005
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn form_contract_diagnostics_accumulate_all_mismatches() {
|
||||
let path = std::env::temp_dir().join(format!(
|
||||
"hemx-derive-form-contract-errors-{}",
|
||||
std::process::id()
|
||||
));
|
||||
let missing: syn::ItemStruct = parse_quote!(
|
||||
struct Profile {
|
||||
first: String,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
form_contract_errors(&path, "profile", &missing),
|
||||
vec!["#[hemx::form] could not find generated hemx symbols; add hemx_build::app().run()? to build.rs or check template generation"]
|
||||
);
|
||||
|
||||
std::fs::write(
|
||||
&path,
|
||||
"hemx-syms-v1\nform\tprofile.heml::profile\tprofile\t42\nform_field\tprofile\tfirst\tfalse\tfalse\nform_field\tprofile\tsecond\ttrue\tfalse\nform_field\tprofile\ttags\tfalse\ttrue\nform_field\tprofile\trequired_name\ttrue\tfalse\n",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
form_contract_errors(&path, "unknown", &missing),
|
||||
vec!["unknown hemx form `unknown`; add data-hemx-form=\"unknown\" to a template or rename this form binding"]
|
||||
);
|
||||
let tuple: syn::ItemStruct = parse_quote!(
|
||||
struct Profile(String);
|
||||
);
|
||||
assert_eq!(
|
||||
form_contract_errors(&path, "profile", &tuple),
|
||||
vec!["hemx form `profile` must be a struct with named fields"]
|
||||
);
|
||||
let mismatched: syn::ItemStruct = parse_quote!(
|
||||
struct Profile {
|
||||
first: Vec<String>,
|
||||
tags: String,
|
||||
required_name: Option<String>,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
form_contract_errors(&path, "profile", &mismatched),
|
||||
vec![
|
||||
"hemx form `profile` field `first` accepts one value and must not be Vec<_>",
|
||||
"hemx form `profile` is missing field `second` for form control `second`",
|
||||
"hemx form `profile` field `tags` accepts multiple values and must be Vec<_>",
|
||||
"hemx form `profile` field `required_name` is required in HTML and must not be Option<_>",
|
||||
]
|
||||
);
|
||||
std::fs::remove_file(path).unwrap();
|
||||
// test req: form/004 req: diagnostics/003
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn syms_lookup_matches_handle_ident() {
|
||||
let path = std::env::temp_dir().join("hemx-derive-syms-test.syms");
|
||||
@@ -1265,7 +1317,12 @@ mod tests {
|
||||
assert_eq!(handle_params(&path, "create"), vec!["todo_id"]);
|
||||
assert!(handle_params(&path, "missing").is_empty());
|
||||
|
||||
let _ = std::fs::remove_file(path);
|
||||
let _ = std::fs::remove_file(&path);
|
||||
assert!(
|
||||
syms_contains_handle(&path, "create"),
|
||||
"missing generated symbols defer to the dedicated generated-file diagnostic"
|
||||
);
|
||||
assert!(!handle_requires_form(&path, "create"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user