test(build): cover form contract metadata

Assert that slhx-build lowers Surface form controls into generated FormContract field metadata, including names, control kinds, required flags, and handle-to-form syms.

req: codegen/004

req: form/001
This commit is contained in:
slhx agent
2026-05-25 23:27:16 +02:00
parent 4d4f5cd2bc
commit c1fb5e986a
+43
View File
@@ -1036,6 +1036,49 @@ mod tests {
let _ = std::fs::remove_dir_all(&base);
}
#[test]
fn emits_form_contract_metadata_from_surface_controls() {
// req: codegen/004 req: form/001
let base = test_dir("slhx-build-form-contract-test");
let templates = base.join("templates");
let out = base.join("out");
let _ = std::fs::remove_dir_all(&base);
std::fs::create_dir_all(&templates).unwrap();
std::fs::write(
templates.join("profile.heml"),
r#"<form data-slhx-handle="save" data-slhx-form="profile">
<input name="title" required>
<input name="count" type="number" min="1" max="10" step="1">
<select name="labels" multiple></select>
<input name="avatar" type="file">
</form>"#,
)
.unwrap();
app().template_dir(&templates).out_dir(&out).run().unwrap();
let generated = std::fs::read_to_string(out.join("slhx.generated.rs")).unwrap();
assert!(generated.contains("pub const PROFILE_CONTRACT: ::slhx::FormContract"));
assert!(generated.contains("pub const PROFILE_FIELDS: &[::slhx::FormField]"));
assert!(generated.contains(
"::slhx::FormField { name: \"title\", kind: ::slhx::FormControlKind::Text, required: true }"
));
assert!(generated.contains(
"::slhx::FormField { name: \"count\", kind: ::slhx::FormControlKind::Number { min: Some(\"1\"), max: Some(\"10\"), step: Some(\"1\") }, required: false }"
));
assert!(generated.contains(
"::slhx::FormField { name: \"labels\", kind: ::slhx::FormControlKind::Select { multiple: true }, required: false }"
));
assert!(generated.contains(
"::slhx::FormField { name: \"avatar\", kind: ::slhx::FormControlKind::File, required: false }"
));
let syms = std::fs::read_to_string(out.join("slhx.syms")).unwrap();
assert!(syms.contains("handle_form\tsave\tprofile\n"));
let _ = std::fs::remove_dir_all(&base);
}
#[test]
fn emits_checked_css_class_tokens_from_templates_and_stylesheets() {
// req: style/001, req: codegen/001