#[slhx::surface] pub mod ui {} #[cfg(test)] mod tests { use super::ui::{auth, counter, notifications, page_swap, todos, wizard}; use hemplate::Hemplate; use slhx::{push, IntoEffect}; use slhx_test::inspect; #[derive(Clone, Debug)] struct Todo { id: u64, title: String, } #[derive(Clone, Debug)] #[slhx::form("new_todo")] struct TodoInput { title: String, } #[derive(Clone, Debug)] #[slhx::form("wizard_input")] struct WizardInput { step: u8, } #[derive(Clone, Debug)] #[slhx::form("credentials")] struct Credentials { email: String, password: String, } #[derive(Hemplate)] #[hemplate = "partials"] struct TodoRow { id: u64, title: String, } impl slhx::KeyedPartial for TodoRow { fn slhx_key(&self) -> String { self.id.to_string() } } #[derive(Hemplate)] #[hemplate = "partials"] struct DocsContent { message: &'static str, } // req: examples/001 req: ceremony/001 req: build/001 req: build/005 req: codegen/002 #[test] fn counter_updates_a_generated_slot() { fn increment(count: u64) -> impl IntoEffect { counter::counter_value.set(count + 1) } let effect = inspect(increment(1)); assert!(effect.updates_text(counter::counter_value)); } // 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 { todos::todo_list.set("queued") } let effect = inspect(add_todo(TodoInput::FORM)); assert!(effect.updates_text(todos::todo_list)); } // 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() { fn add_todo(input: TodoInput) -> impl IntoEffect { let todo = Todo { id: 7, title: input.title, }; todos::todo_row.append(TodoRow { id: todo.id, title: todo.title, }) } let effect = inspect(add_todo(TodoInput { title: "Ship v0".into(), })); assert!(effect.inserts_html_containing(todos::todo_row, 7, "Ship v0")); } // req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003 #[test] fn wizard_form_handler_is_checked_against_hemplate_form() { #[slhx::handler] fn next_step(_form: slhx::Form) -> impl IntoEffect { wizard::wizard_step.set("queued") } let effect = inspect(next_step(WizardInput::FORM)); assert!(effect.updates_text(wizard::wizard_step)); } // req: examples/001 req: progressive_disclosure/001 req: build/001 req: build/005 req: codegen/004 #[test] fn wizard_form_swaps_the_current_step() { fn next_step(input: WizardInput) -> impl IntoEffect { wizard::wizard_step.set(format!("Step {}", input.step + 1)) } let effect = inspect(next_step(WizardInput { step: 1 })); assert!(effect.updates_text(wizard::wizard_step)); } // req: examples/001 req: page_swap/002 req: page_swap/003 req: build/001 req: build/005 req: view/001 #[test] fn page_swap_updates_content_and_history() { fn load_docs() -> impl IntoEffect { ( page_swap::content.put(&DocsContent { message: "This page was swapped.", }), page_swap::title.set("Docs"), push("/docs"), ) } let effect = inspect(load_docs()); assert!(effect.updates_html_containing(page_swap::content, "This page was swapped.")); assert!(effect.updates_text(page_swap::title)); assert!(effect.pushes_to("/docs")); } // req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003 #[test] fn auth_form_handler_is_checked_against_hemplate_form() { #[slhx::handler] fn login(_form: slhx::Form) -> impl IntoEffect { auth::login_status.set("queued") } let effect = inspect(login(Credentials::FORM)); assert!(effect.updates_text(auth::login_status)); } // req: examples/001 req: progressive_disclosure/001 req: build/001 req: build/005 req: codegen/004 #[test] fn auth_flow_reads_typed_input_and_updates_status() { fn login(input: Credentials) -> impl IntoEffect { let status = if input.email == "demo@example.com" && !input.password.is_empty() { "Signed in" } else { "Try again" }; auth::login_status.set(status) } let effect = inspect(login(Credentials { email: "demo@example.com".into(), password: "secret".into(), })); assert!(effect.updates_text(auth::login_status)); } // req: examples/001 req: push/001 req: push/003 req: build/001 req: build/005 #[test] fn sse_notifications_update_a_generated_slot() { fn notification(message: &str) -> impl IntoEffect { notifications::notifications.set(message) } let effect = inspect(notification("Build finished")); assert!(effect.updates_text(notifications::notifications)); } }