From 11f710d276a61af0aef1d54e639892562785a198 Mon Sep 17 00:00:00 2001 From: slhx agent Date: Mon, 25 May 2026 23:52:10 +0200 Subject: [PATCH] test(v0): exercise checked form handler path Use #[slhx::form] in the v0 example tests and add a checked form-handler smoke test, with a typed() helper for generated form ids so examples do not rebuild ids by hand. req: form/001 req: form/004 req: form/006 req: derive_handler/003 --- examples/v0/src/lib.rs | 15 +++++++++++++++ slhx-core/src/lib.rs | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/examples/v0/src/lib.rs b/examples/v0/src/lib.rs index 51cb967..a049eaa 100644 --- a/examples/v0/src/lib.rs +++ b/examples/v0/src/lib.rs @@ -15,6 +15,7 @@ mod tests { } #[derive(Clone, Debug)] + #[slhx::form("new_todo")] struct TodoInput { title: String, } @@ -55,6 +56,20 @@ mod tests { assert!(matches!(effect.ops(), [Effect::Put { .. }])); } + // req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003 + #[test] + fn form_handler_is_checked_against_hemplate_form() { + #[slhx::handler] + fn add_todo(_form: slhx::Form) -> impl IntoEffect { + ui::slots::todo_list.text("queued") + } + + let effect = inspect(add_todo(ui::forms::new_todo.typed::())); + + assert!(effect.has_slot(ui::slots::todo_list)); + assert!(matches!(effect.ops(), [Effect::Put { payload: Payload::Text(_), .. }])); + } + // req: examples/001 req: progressive_disclosure/001 req: build/001 req: build/005 req: codegen/002 #[test] fn todos_append_keyed_rows_from_form_input() { diff --git a/slhx-core/src/lib.rs b/slhx-core/src/lib.rs index 7fac023..e37f983 100644 --- a/slhx-core/src/lib.rs +++ b/slhx-core/src/lib.rs @@ -881,6 +881,13 @@ impl Form { self.id } + pub const fn typed(self) -> Form { + Form { + id: self.id, + _marker: PhantomData, + } + } + pub fn field(self, name: impl Into) -> ResourceRef { ResourceRef::scoped(self.id, ScopeKey::Field(name.into())) }