test(examples): avoid literal handle ids
Remove the last handwritten __h input from techdemo markup, switch E2E posts to generated handles, and extend example contracts to catch literal handle fields in templates. req: dx/003 req: ceremony/002 req: examples/003
This commit is contained in:
@@ -17,7 +17,6 @@
|
|||||||
<aside class="command-card">
|
<aside class="command-card">
|
||||||
<h2>Create an issue</h2>
|
<h2>Create an issue</h2>
|
||||||
<form id="launch-work" method="post" data-slhx-handle="launch_work" data-slhx-form="launch_work" data-slhx-disable-while-pending>
|
<form id="launch-work" method="post" data-slhx-handle="launch_work" data-slhx-form="launch_work" data-slhx-disable-while-pending>
|
||||||
<input type="hidden" name="__h" value="539242093">
|
|
||||||
<label>Title <input name="title" required="required" value="Ship typed effects"></label>
|
<label>Title <input name="title" required="required" value="Ship typed effects"></label>
|
||||||
<label>Lane
|
<label>Lane
|
||||||
<select name="lane" required="required">
|
<select name="lane" required="required">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use scraper::{Html, Selector};
|
use scraper::{Html, Selector};
|
||||||
use slhx::{Effect, EffectBatch, Payload, EFFECT_BATCH_ABI_VERSION};
|
use slhx::{Effect, EffectBatch, Payload, EFFECT_BATCH_ABI_VERSION};
|
||||||
use slhx_techdemo::ui::BUILD_FINGERPRINT;
|
use slhx_techdemo::ui::BUILD_FINGERPRINT;
|
||||||
|
use slhx_techdemo::ui::control_center::handles;
|
||||||
use slhx_techdemo::ui::issue_card::handles as card_handles;
|
use slhx_techdemo::ui::issue_card::handles as card_handles;
|
||||||
use slhx_techdemo::ui::issue_lane::handles as lane_handles;
|
use slhx_techdemo::ui::issue_lane::handles as lane_handles;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
@@ -83,7 +84,13 @@ fn product_is_e2e_working_over_http() {
|
|||||||
assert_text(&architecture_doc, "Page swap");
|
assert_text(&architecture_doc, "Page swap");
|
||||||
assert_text(&architecture_doc, "slhx-build");
|
assert_text(&architecture_doc, "slhx-build");
|
||||||
|
|
||||||
let launch = post("/", "__h=539242093&title=Design+hero+moment&lane=product&impact=9");
|
let launch = post(
|
||||||
|
"/",
|
||||||
|
&format!(
|
||||||
|
"__h={}&title=Design+hero+moment&lane=product&impact=9",
|
||||||
|
handles::launch_work
|
||||||
|
),
|
||||||
|
);
|
||||||
assert_effect_response(&launch);
|
assert_effect_response(&launch);
|
||||||
let launch_batch = launch.batch();
|
let launch_batch = launch.batch();
|
||||||
assert_payload_contains(&launch_batch, "Design hero moment");
|
assert_payload_contains(&launch_batch, "Design hero moment");
|
||||||
@@ -91,25 +98,49 @@ fn product_is_e2e_working_over_http() {
|
|||||||
assert_payload_contains(&launch_batch, "Launch accepted");
|
assert_payload_contains(&launch_batch, "Launch accepted");
|
||||||
assert_payload_contains(&launch_batch, "Launched card #4");
|
assert_payload_contains(&launch_batch, "Launched card #4");
|
||||||
assert_emit(&launch_batch, "slhx:island-orbit", "activity rows");
|
assert_emit(&launch_batch, "slhx:island-orbit", "activity rows");
|
||||||
assert!(launch_batch.ops.len() >= 6, "launch should update generated targets and notify the island");
|
assert!(
|
||||||
|
launch_batch.ops.len() >= 6,
|
||||||
|
"launch should update generated targets and notify the island"
|
||||||
|
);
|
||||||
|
|
||||||
let default_impact = post("/", "__h=539242093&title=Default+impact&lane=compiler");
|
let default_impact = post(
|
||||||
|
"/",
|
||||||
|
&format!(
|
||||||
|
"__h={}&title=Default+impact&lane=compiler",
|
||||||
|
handles::launch_work
|
||||||
|
),
|
||||||
|
);
|
||||||
assert_effect_response(&default_impact);
|
assert_effect_response(&default_impact);
|
||||||
let default_impact_batch = default_impact.batch();
|
let default_impact_batch = default_impact.batch();
|
||||||
assert_payload_contains(&default_impact_batch, "Default impact");
|
assert_payload_contains(&default_impact_batch, "Default impact");
|
||||||
assert_card(&default_impact_batch, "Default impact", "Compiler", "Draft", "width:55%");
|
assert_card(&default_impact_batch, "Default impact", "Compiler", "Draft", "width:55%");
|
||||||
|
|
||||||
let low_impact = post("/", "__h=539242093&title=Low+impact&lane=runtime&impact=0");
|
let low_impact = post(
|
||||||
|
"/",
|
||||||
|
&format!(
|
||||||
|
"__h={}&title=Low+impact&lane=runtime&impact=0",
|
||||||
|
handles::launch_work
|
||||||
|
),
|
||||||
|
);
|
||||||
assert_effect_response(&low_impact);
|
assert_effect_response(&low_impact);
|
||||||
let low_impact_batch = low_impact.batch();
|
let low_impact_batch = low_impact.batch();
|
||||||
assert_card(&low_impact_batch, "Low impact", "Runtime", "Draft", "width:11%");
|
assert_card(&low_impact_batch, "Low impact", "Runtime", "Draft", "width:11%");
|
||||||
|
|
||||||
let high_impact = post("/", "__h=539242093&title=High+impact&lane=runtime&impact=99");
|
let high_impact = post(
|
||||||
|
"/",
|
||||||
|
&format!(
|
||||||
|
"__h={}&title=High+impact&lane=runtime&impact=99",
|
||||||
|
handles::launch_work
|
||||||
|
),
|
||||||
|
);
|
||||||
assert_effect_response(&high_impact);
|
assert_effect_response(&high_impact);
|
||||||
let high_impact_batch = high_impact.batch();
|
let high_impact_batch = high_impact.batch();
|
||||||
assert_card(&high_impact_batch, "High impact", "Runtime", "Draft", "width:99%");
|
assert_card(&high_impact_batch, "High impact", "Runtime", "Draft", "width:99%");
|
||||||
|
|
||||||
let missing_title = post("/", "__h=539242093&lane=runtime&impact=8");
|
let missing_title = post(
|
||||||
|
"/",
|
||||||
|
&format!("__h={}&lane=runtime&impact=8", handles::launch_work),
|
||||||
|
);
|
||||||
assert_effect_response(&missing_title);
|
assert_effect_response(&missing_title);
|
||||||
let missing_title_batch = missing_title.batch();
|
let missing_title_batch = missing_title.batch();
|
||||||
assert_payload_contains(&missing_title_batch, "Launch accepted");
|
assert_payload_contains(&missing_title_batch, "Launch accepted");
|
||||||
@@ -148,7 +179,7 @@ fn product_is_e2e_working_over_http() {
|
|||||||
let ship_default_batch = ship_default.batch();
|
let ship_default_batch = ship_default.batch();
|
||||||
assert_card(&ship_default_batch, "Default impact", "Product", "Shipped", "width:55%");
|
assert_card(&ship_default_batch, "Default impact", "Product", "Shipped", "width:55%");
|
||||||
|
|
||||||
let simulated_push = post("/", "__h=2942980687");
|
let simulated_push = post("/", &format!("__h={}", handles::simulate_push));
|
||||||
assert_effect_response(&simulated_push);
|
assert_effect_response(&simulated_push);
|
||||||
let push_batch = simulated_push.batch();
|
let push_batch = simulated_push.batch();
|
||||||
assert_payload_contains(&push_batch, "SSE tick");
|
assert_payload_contains(&push_batch, "SSE tick");
|
||||||
@@ -169,7 +200,7 @@ fn product_is_e2e_working_over_http() {
|
|||||||
assert_payload_not_contains(&delete_batch, "data-key=\"4\"");
|
assert_payload_not_contains(&delete_batch, "data-key=\"4\"");
|
||||||
assert_payload_contains(&delete_batch, "Default impact");
|
assert_payload_contains(&delete_batch, "Default impact");
|
||||||
|
|
||||||
let reset = post("/", "__h=4166593243");
|
let reset = post("/", &format!("__h={}", handles::reset_demo));
|
||||||
assert_effect_response(&reset);
|
assert_effect_response(&reset);
|
||||||
let reset_batch = reset.batch();
|
let reset_batch = reset.batch();
|
||||||
assert_payload_contains(&reset_batch, "Demo reset from Rust state");
|
assert_payload_contains(&reset_batch, "Demo reset from Rust state");
|
||||||
|
|||||||
@@ -63,16 +63,25 @@ fn canonical_examples_do_not_author_low_level_resource_plumbing() {
|
|||||||
"::lower(include_str!",
|
"::lower(include_str!",
|
||||||
"lower_html(",
|
"lower_html(",
|
||||||
"render_html(",
|
"render_html(",
|
||||||
|
"name=\"__h\"",
|
||||||
|
"name='__h'",
|
||||||
];
|
];
|
||||||
let mut failures = Vec::new();
|
let mut failures = Vec::new();
|
||||||
scan_examples(&examples, &mut |path, text| {
|
scan_examples(&examples, &mut |path, text| {
|
||||||
if path.components().any(|part| part.as_os_str() == "tests") {
|
if path.components().any(|part| part.as_os_str() == "tests") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if path.extension().and_then(|ext| ext.to_str()) != Some("rs") {
|
let Some(ext) = path.extension().and_then(|ext| ext.to_str()) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !matches!(ext, "rs" | "heml" | "html") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let runtime_source = text.split("#[cfg(test)]").next().unwrap_or(text);
|
let runtime_source = if ext == "rs" {
|
||||||
|
text.split("#[cfg(test)]").next().unwrap_or(text)
|
||||||
|
} else {
|
||||||
|
text
|
||||||
|
};
|
||||||
for (line_no, line) in runtime_source.lines().enumerate() {
|
for (line_no, line) in runtime_source.lines().enumerate() {
|
||||||
if let Some(token) = forbidden.iter().find(|token| line.contains(*token)) {
|
if let Some(token) = forbidden.iter().find(|token| line.contains(*token)) {
|
||||||
failures.push(format!(
|
failures.push(format!(
|
||||||
|
|||||||
Reference in New Issue
Block a user