feat(axum): add concise interaction request dispatch

Wrap extracted interaction forms in an InteractionRequest with a concise dispatch path, add a handlers() helper, and move canonical examples off direct HandlerRegistry/InteractionForm plumbing.

req: axum_integration/003

req: ceremony/001

req: dx/003

req: examples/003
This commit is contained in:
slhx agent
2026-06-02 00:19:38 +02:00
parent 7b7cb7da15
commit 42ede63361
6 changed files with 96 additions and 19 deletions
+21 -3
View File
@@ -2,9 +2,10 @@ use axum::http::{header, HeaderMap};
use axum::response::IntoResponse;
use scraper::{Html, Selector};
use slhx_axum::{
runtime_js, DispatchRejection, EffectResponse, HandlerRegistry, InteractionForm,
InteractionFormRejection, PageMode, PageRequest, PageResponse, SLHX_CONTENT_TYPE,
SLHX_FINGERPRINT_HEADER, SLHX_PARTIAL_HEADER, SLHX_RUNTIME_CONTENT_TYPE, SLHX_TITLE_HEADER,
handlers, runtime_js, DispatchRejection, EffectResponse, HandlerRegistry, InteractionForm,
InteractionFormRejection, InteractionRequest, PageMode, PageRequest, PageResponse,
SLHX_CONTENT_TYPE, SLHX_FINGERPRINT_HEADER, SLHX_PARTIAL_HEADER, SLHX_RUNTIME_CONTENT_TYPE,
SLHX_TITLE_HEADER,
};
use slhx_core::{push, BuildFingerprint, Handle, SafeHtml, Slot};
@@ -139,6 +140,23 @@ fn interaction_form_preserves_hidden_csrf_fields_for_extractors() {
assert!(form.fields().iter().any(|(name, _)| name == "csrf_token"));
}
#[test]
fn interaction_request_dispatches_with_concise_handlers_helper() {
// req: axum_integration/003 req: ceremony/001 req: dx/003
let request = InteractionRequest::from(InteractionForm::for_handle(
Handle::<()>::new(7),
Vec::new(),
));
let response = request
.dispatch(handlers(BuildFingerprint(4)).register_handle(Handle::<()>::new(7), |_| {
Slot::<String>::new(3).text("ok")
}))
.unwrap();
assert_eq!(response.batch.fingerprint, BuildFingerprint(4));
assert_eq!(response.batch.ops, vec![Slot::<String>::new(3).text("ok")]);
}
#[test]
fn handler_registry_dispatches_by_checked_handle() {
// req: ceremony/004 req: public_api/001