feat(api): streamline generated app authoring
Move the canonical examples toward generated component-root helpers, typed form decoding, async/state handler registration, and derive-driven app/component registry wiring. Tighten requirements and diagnostics for the server-first, selectorless authoring path. Verified with cargo run -p slhx-xtask -- test, cargo check --workspace, redgate list, redgate refs, redgate health --strict, and git diff --check. req: canonical/001 req: canonical/003 req: canonical/004 req: dx/002 req: derive_app/001 req: component/003 req: form/004 req: axum_integration/003
This commit is contained in:
@@ -3,11 +3,11 @@ pub mod ui {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ui::control_center::{forms, handles, slots, targets};
|
||||
use super::ui::issue_card::handles as card_handles;
|
||||
use super::ui::control_center::{hero_metrics, launch_work, launch_work_form, notice};
|
||||
use super::ui::issue_card::advance_work;
|
||||
use super::ui::issue_lane::events as lane_events;
|
||||
use hemplate::Hemplate;
|
||||
use slhx::{Effect, IntoEffect, Payload};
|
||||
use slhx::IntoEffect;
|
||||
use slhx_test::inspect;
|
||||
|
||||
#[derive(Hemplate)]
|
||||
@@ -30,14 +30,14 @@ mod tests {
|
||||
fn techdemo_uses_generated_slots_for_multi_target_updates() {
|
||||
fn update() -> impl IntoEffect {
|
||||
(
|
||||
targets::hero_metrics.put(&FastMetric { label: "fast" }),
|
||||
slots::notice.text("typed"),
|
||||
hero_metrics.put(&FastMetric { label: "fast" }),
|
||||
notice.text("typed"),
|
||||
)
|
||||
}
|
||||
|
||||
let batch = inspect(update());
|
||||
assert!(batch.has_slot(slots::hero_metrics));
|
||||
assert!(batch.has_slot(slots::notice));
|
||||
assert!(batch.has_target(hero_metrics));
|
||||
assert!(batch.has_target(notice));
|
||||
}
|
||||
|
||||
// req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003
|
||||
@@ -45,22 +45,21 @@ mod tests {
|
||||
fn techdemo_form_handler_is_checked_against_hemplate_form() {
|
||||
#[slhx::handler]
|
||||
fn launch_work(_form: slhx::Form<LaunchWork>) -> impl IntoEffect {
|
||||
slots::notice.text("queued")
|
||||
notice.text("queued")
|
||||
}
|
||||
|
||||
let batch = inspect(launch_work(LaunchWork::FORM));
|
||||
|
||||
assert!(batch.has_slot(slots::notice));
|
||||
assert!(matches!(batch.ops(), [Effect::Put { payload: Payload::Text(_), .. }]));
|
||||
assert!(batch.updates_text(notice));
|
||||
}
|
||||
|
||||
// req: examples/001 req: form/002 req: codegen/003
|
||||
#[test]
|
||||
fn techdemo_exports_form_and_interaction_handles() {
|
||||
assert_ne!(handles::launch_work.id(), card_handles::advance_work.id());
|
||||
assert_ne!(launch_work.id(), advance_work.id());
|
||||
assert_eq!(
|
||||
forms::launch_work.field("title").resource,
|
||||
forms::launch_work.id()
|
||||
launch_work_form.field("title").resource,
|
||||
launch_work_form.id()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,9 +67,7 @@ mod tests {
|
||||
#[test]
|
||||
fn techdemo_exports_generated_event_constants() {
|
||||
assert_eq!(lane_events::drop.as_str(), "drop");
|
||||
assert!(matches!(
|
||||
slhx::event(lane_events::drop, "card-1"),
|
||||
Effect::Emit { name, payload } if name == "drop" && payload == "card-1"
|
||||
));
|
||||
let event = inspect(lane_events::drop.emit("card-1"));
|
||||
assert!(event.emits("drop", "card-1"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user