test(build): prove public inspection contracts

Exercise file and source diagnostics, generated targets, Hemlate-derived context facts, missing-file propagation, and invalid Rust context through hemx-build's public inspection API; classify only the currently infallible hemplate parser seam.

req: diagnostics/004

req: diagnostics/006

req: surface/008

req: test/021
This commit is contained in:
slhx agent
2026-07-17 03:14:24 +02:00
parent 1a9c090028
commit 8a21cad98e
3 changed files with 93 additions and 1 deletions
+87
View File
@@ -2326,6 +2326,93 @@ fn parse_error(path: &Path, err: impl std::fmt::Display) -> io::Error {
mod tests {
use super::*;
#[test]
fn public_heml_inspection_entry_points_preserve_paths_and_io_diagnostics() {
let root = std::env::temp_dir().join(format!(
"hemx-build-inspection-{}-{}",
std::process::id(),
std::thread::current().name().unwrap_or("test")
));
std::fs::create_dir_all(&root).unwrap();
let template = root.join("card.heml");
let source = r#"<template h-for="todo in &self.todos"><button data-hemx-handle="save">Save</button></template>"#;
std::fs::write(&template, source).unwrap();
let from_source = diagnostics_for_heml_source(&template, source.to_owned()).unwrap();
let from_file = diagnostics_for_heml_file(&template).unwrap();
assert_eq!(from_file, from_source);
assert_eq!(from_source.len(), 1);
assert_eq!(from_source[0].file, template);
assert_eq!(from_source[0].directive, "data-hemx-handle");
let targets = generated_targets_for_heml_source(
&template,
r#"<main data-hemx-root="app"><section h-slot="notice"></section><button data-hemx-handle="save">Save</button></main>"#,
)
.unwrap();
assert_eq!(targets.len(), 1);
assert_eq!(targets[0].name, "save");
assert_eq!(
template_context_facts_for_heml_source(
&template,
"<main>{{ self.title }}</main>".to_owned(),
)
.unwrap(),
None
);
let crate_root = root.join("crate");
let templates = crate_root.join("templates");
std::fs::create_dir_all(crate_root.join("src")).unwrap();
std::fs::create_dir_all(&templates).unwrap();
std::fs::write(
crate_root.join("Cargo.toml"),
"[package]\nname='facts'\nversion='0.0.0'\n",
)
.unwrap();
std::fs::write(
crate_root.join("src/lib.rs"),
"#[derive(Hemplate)] struct Profile { title: String }\nstruct Plain { title: String }",
)
.unwrap();
let profile = templates.join("profile.heml");
let facts = template_context_facts_for_heml_source(
&profile,
"<main>{{ self.title }}</main>".to_owned(),
)
.unwrap()
.expect("Hemlate-derived context facts");
assert_eq!(facts.context_type, "Profile");
assert_eq!(facts.self_fields[0].name, "title");
std::fs::write(crate_root.join("src/broken.rs"), [0xff]).unwrap();
assert_eq!(
template_context_facts_for_heml_source(
&profile,
"<main>{{ self.title }}</main>".to_owned(),
)
.unwrap_err()
.kind(),
io::ErrorKind::InvalidData
);
std::fs::remove_file(crate_root.join("src/broken.rs")).unwrap();
assert_eq!(
template_context_facts_for_heml_source(
templates.join("plain.heml"),
"<main>{{ self.title }}</main>".to_owned(),
)
.unwrap(),
None
);
let missing = root.join("missing.heml");
for error in [
diagnostics_for_heml_file(&missing).unwrap_err(),
template_context_facts_for_heml_file(&missing).unwrap_err(),
] {
assert_eq!(error.kind(), io::ErrorKind::NotFound);
}
let _ = std::fs::remove_dir_all(root);
// test req: diagnostics/004 req: diagnostics/006 req: surface/008
}
#[test]
fn generated_contract_fingerprint_and_client_bootstrap_are_deterministic() {
let resource = |symbol: &str, component: &str, id| Resource {