chore(checkpoint): save current v0 build state
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
use slhx_core::{event, navigate, redirect, replace, Atom, AtomSnapshot, AtomState, BuildFingerprint, Effect, EffectBatch, Form, IntoEffect, KeyedSlot, NavigateMode, Payload, ResourceKind, SafeHtml, ScopeKey, Slot};
|
||||
|
||||
#[test]
|
||||
fn effect_batch_wire_round_trips() {
|
||||
let count = Slot::<u32>::new(1);
|
||||
let todos = KeyedSlot::<u64, String>::new(2);
|
||||
let user = Atom::<String>::new(3);
|
||||
|
||||
let batch = (
|
||||
count.text(2),
|
||||
todos.append(7, "Buy milk"),
|
||||
todos.replace(7, "Buy oat milk"),
|
||||
user.set("Ada"),
|
||||
navigate("/todos"),
|
||||
event("toast", "Saved"),
|
||||
)
|
||||
.into_batch(BuildFingerprint(42));
|
||||
|
||||
let bytes = batch.to_wire();
|
||||
assert_eq!(&bytes[..4], b"SLHX");
|
||||
let decoded = EffectBatch::from_wire(&bytes).unwrap();
|
||||
|
||||
assert_eq!(decoded, batch);
|
||||
assert!(decoded.is_compatible());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keyed_slot_replace_uses_scoped_resource_ref() {
|
||||
let todos = KeyedSlot::<u64, String>::new(9);
|
||||
let effect = todos.replace(12, "done");
|
||||
|
||||
let Effect::Put { target, payload } = effect else {
|
||||
panic!("expected Put");
|
||||
};
|
||||
|
||||
assert_eq!(target.resource.kind, ResourceKind::Slot);
|
||||
assert_eq!(target.resource.id, 9);
|
||||
assert_eq!(target.scope, Some(ScopeKey::KeyValue(String::from("12"))));
|
||||
assert_eq!(payload, Payload::Text(String::from("done")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_composition_supports_arity_twelve() {
|
||||
let slot = Slot::<u8>::new(1);
|
||||
let batch = (
|
||||
slot.text(1),
|
||||
slot.text(2),
|
||||
slot.text(3),
|
||||
slot.text(4),
|
||||
slot.text(5),
|
||||
slot.text(6),
|
||||
slot.text(7),
|
||||
slot.text(8),
|
||||
slot.text(9),
|
||||
slot.text(10),
|
||||
slot.text(11),
|
||||
slot.text(12),
|
||||
)
|
||||
.into_batch(BuildFingerprint(1));
|
||||
|
||||
assert_eq!(batch.ops.len(), 12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generated_form_helpers_target_form_fields() {
|
||||
let signup = Form::<()>::new(4);
|
||||
|
||||
let Effect::Emit { name, payload } = signup.error("email", "Use your work email") else {
|
||||
panic!("expected Emit");
|
||||
};
|
||||
|
||||
assert_eq!(name, "slhx:form-error");
|
||||
assert_eq!(payload, "4\u{1f}email\u{1f}Use your work email");
|
||||
|
||||
let Effect::Focus { target } = signup.focus("email") else {
|
||||
panic!("expected Focus");
|
||||
};
|
||||
assert_eq!(target.scope, Some(ScopeKey::Field(String::from("email"))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slot_html_requires_explicit_safe_html() {
|
||||
let content = Slot::<String>::new(10);
|
||||
let Effect::Put { payload, .. } = content.html(SafeHtml::trusted("<strong>ok</strong>")) else {
|
||||
panic!("expected Put");
|
||||
};
|
||||
|
||||
assert_eq!(payload, Payload::Html(String::from("<strong>ok</strong>")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn atom_state_bootstrap_is_postcard_round_trippable() {
|
||||
let state = AtomState {
|
||||
atoms: vec![AtomSnapshot {
|
||||
id: 7,
|
||||
bytes: vec![1, 2, 3],
|
||||
}],
|
||||
};
|
||||
|
||||
let bytes = state.to_postcard().unwrap();
|
||||
assert_eq!(AtomState::from_postcard(&bytes).unwrap(), state);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn navigation_helpers_choose_explicit_modes() {
|
||||
let Effect::Navigate { mode, .. } = navigate("/docs") else {
|
||||
panic!("expected Navigate");
|
||||
};
|
||||
assert_eq!(mode, NavigateMode::Push);
|
||||
|
||||
let Effect::Navigate { mode, .. } = replace("/docs") else {
|
||||
panic!("expected Navigate");
|
||||
};
|
||||
assert_eq!(mode, NavigateMode::Replace);
|
||||
|
||||
let Effect::Navigate { mode, .. } = redirect("/login") else {
|
||||
panic!("expected Navigate");
|
||||
};
|
||||
assert_eq!(mode, NavigateMode::Redirect);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_fingerprint_is_deterministic_from_abi_parts() {
|
||||
let a = BuildFingerprint::from_parts(&[1, 2, 3, 4]);
|
||||
let b = BuildFingerprint::from_parts(&[1, 2, 3, 4]);
|
||||
let c = BuildFingerprint::from_parts(&[1, 2, 3, 5]);
|
||||
|
||||
assert_eq!(a, b);
|
||||
assert_ne!(a, c);
|
||||
}
|
||||
Reference in New Issue
Block a user