From e9bc145b22d08c398cf9af1890ceccbeb045286f Mon Sep 17 00:00:00 2001 From: slhx agent Date: Tue, 2 Jun 2026 00:06:53 +0200 Subject: [PATCH] test(techdemo): build e2e posts from handles Keep valid techdemo E2E interactions on generated Handle values plus the axum handle-field constant, leaving only the unknown-id negative case as raw wire input. req: dx/003 req: examples/003 --- examples/techdemo/tests/e2e.rs | 91 +++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/examples/techdemo/tests/e2e.rs b/examples/techdemo/tests/e2e.rs index 0c66ca6..dcae4f6 100644 --- a/examples/techdemo/tests/e2e.rs +++ b/examples/techdemo/tests/e2e.rs @@ -1,5 +1,6 @@ use scraper::{Html, Selector}; -use slhx::{Effect, EffectBatch, Payload, EFFECT_BATCH_ABI_VERSION}; +use slhx::{Effect, EffectBatch, Handle, Payload, EFFECT_BATCH_ABI_VERSION}; +use slhx_axum::SLHX_HANDLE_FIELD; use slhx_techdemo::ui::BUILD_FINGERPRINT; use slhx_techdemo::ui::control_center::handles; use slhx_techdemo::ui::issue_card::handles as card_handles; @@ -11,6 +12,17 @@ use std::time::{Duration, Instant}; const ADDR: &str = "127.0.0.1:3002"; +fn handle_body(handle: Handle, fields: &[(&str, &str)]) -> String { + let mut body = format!("{SLHX_HANDLE_FIELD}={handle}"); + for (name, value) in fields { + body.push('&'); + body.push_str(name); + body.push('='); + body.push_str(value); + } + body +} + struct Server { child: Child, } @@ -86,9 +98,13 @@ fn product_is_e2e_working_over_http() { let launch = post( "/", - &format!( - "__h={}&title=Design+hero+moment&lane=product&impact=9", - handles::launch_work + &handle_body( + handles::launch_work, + &[ + ("title", "Design+hero+moment"), + ("lane", "product"), + ("impact", "9"), + ], ), ); assert_effect_response(&launch); @@ -105,9 +121,9 @@ fn product_is_e2e_working_over_http() { let default_impact = post( "/", - &format!( - "__h={}&title=Default+impact&lane=compiler", - handles::launch_work + &handle_body( + handles::launch_work, + &[("title", "Default+impact"), ("lane", "compiler")], ), ); assert_effect_response(&default_impact); @@ -117,9 +133,13 @@ fn product_is_e2e_working_over_http() { let low_impact = post( "/", - &format!( - "__h={}&title=Low+impact&lane=runtime&impact=0", - handles::launch_work + &handle_body( + handles::launch_work, + &[ + ("title", "Low+impact"), + ("lane", "runtime"), + ("impact", "0"), + ], ), ); assert_effect_response(&low_impact); @@ -128,9 +148,13 @@ fn product_is_e2e_working_over_http() { let high_impact = post( "/", - &format!( - "__h={}&title=High+impact&lane=runtime&impact=99", - handles::launch_work + &handle_body( + handles::launch_work, + &[ + ("title", "High+impact"), + ("lane", "runtime"), + ("impact", "99"), + ], ), ); assert_effect_response(&high_impact); @@ -139,7 +163,7 @@ fn product_is_e2e_working_over_http() { let missing_title = post( "/", - &format!("__h={}&lane=runtime&impact=8", handles::launch_work), + &handle_body(handles::launch_work, &[("lane", "runtime"), ("impact", "8")]), ); assert_effect_response(&missing_title); let missing_title_batch = missing_title.batch(); @@ -149,37 +173,52 @@ fn product_is_e2e_working_over_http() { let move_to_lane = post( "/", - &format!("__h={}&work_id=4&lane=runtime", lane_handles::move_to_lane), + &handle_body( + lane_handles::move_to_lane, + &[("work_id", "4"), ("lane", "runtime")], + ), ); assert_effect_response(&move_to_lane); let move_to_lane_batch = move_to_lane.batch(); assert_card(&move_to_lane_batch, "Design hero moment", "Runtime", "Active", "width:99%"); assert_payload_contains(&move_to_lane_batch, "Drag-and-drop move persisted"); - let inspect = post("/", &format!("__h={}&work_id=4", card_handles::spotlight_work)); + let inspect = post( + "/", + &handle_body(card_handles::spotlight_work, &[("work_id", "4")]), + ); assert_effect_response(&inspect); let inspect_batch = inspect.batch(); assert_payload_contains(&inspect_batch, "Design hero moment ยท lane=Runtime"); assert_payload_contains(&inspect_batch, "Inspector focused"); - let advance = post("/", &format!("__h={}&work_id=4", card_handles::advance_work)); + let advance = post( + "/", + &handle_body(card_handles::advance_work, &[("work_id", "4")]), + ); assert_effect_response(&advance); let advance_batch = advance.batch(); assert_payload_contains(&advance_batch, "Pipeline advanced"); assert_payload_contains(&advance_batch, "Active"); - let advance_default = post("/", &format!("__h={}&work_id=5", card_handles::advance_work)); + let advance_default = post( + "/", + &handle_body(card_handles::advance_work, &[("work_id", "5")]), + ); assert_effect_response(&advance_default); let advance_default_batch = advance_default.batch(); assert_payload_contains(&advance_default_batch, "Default impact"); assert_card(&advance_default_batch, "Default impact", "Compiler", "Active", "width:55%"); - let ship_default = post("/", &format!("__h={}&work_id=5", card_handles::advance_work)); + let ship_default = post( + "/", + &handle_body(card_handles::advance_work, &[("work_id", "5")]), + ); assert_effect_response(&ship_default); let ship_default_batch = ship_default.batch(); assert_card(&ship_default_batch, "Default impact", "Product", "Shipped", "width:55%"); - let simulated_push = post("/", &format!("__h={}", handles::simulate_push)); + let simulated_push = post("/", &handle_body(handles::simulate_push, &[])); assert_effect_response(&simulated_push); let push_batch = simulated_push.batch(); assert_payload_contains(&push_batch, "SSE tick"); @@ -187,12 +226,18 @@ fn product_is_e2e_working_over_http() { assert_payload_contains(&push_batch, "Simulated push event produced the same EffectBatch shape"); assert_emit(&push_batch, "slhx:island-orbit", "activity rows"); - let delete_missing = post("/", &format!("__h={}&work_id=999", card_handles::delete_work)); + let delete_missing = post( + "/", + &handle_body(card_handles::delete_work, &[("work_id", "999")]), + ); assert_effect_response(&delete_missing); let delete_missing_batch = delete_missing.batch(); assert_payload_not_contains(&delete_missing_batch, "Deleted card #999"); - let delete = post("/", &format!("__h={}&work_id=4", card_handles::delete_work)); + let delete = post( + "/", + &handle_body(card_handles::delete_work, &[("work_id", "4")]), + ); assert_effect_response(&delete); let delete_batch = delete.batch(); assert_payload_contains(&delete_batch, "Card removed"); @@ -200,7 +245,7 @@ fn product_is_e2e_working_over_http() { assert_payload_not_contains(&delete_batch, "data-key=\"4\""); assert_payload_contains(&delete_batch, "Default impact"); - let reset = post("/", &format!("__h={}", handles::reset_demo)); + let reset = post("/", &handle_body(handles::reset_demo, &[])); assert_effect_response(&reset); let reset_batch = reset.batch(); assert_payload_contains(&reset_batch, "Demo reset from Rust state");