From 5e555f4d938dd78ce41553b6fe9af8abcf627e3d Mon Sep 17 00:00:00 2001 From: slhx agent Date: Thu, 16 Jul 2026 22:34:41 +0200 Subject: [PATCH] test(build): close generated contract mutants Exercise invalid client contracts through AppBuilder and simplify invariant-only generation paths so the focused build contract mutation set has no unexplained survivors. req: build/004 req: build/007 req: client_local/011 --- hemx-build/src/lib.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/hemx-build/src/lib.rs b/hemx-build/src/lib.rs index d5b60e8..73e8658 100644 --- a/hemx-build/src/lib.rs +++ b/hemx-build/src/lib.rs @@ -573,11 +573,12 @@ impl Resources { // req: build/001 req: component/003 let component_names: BTreeSet = self.component_names().into_iter().collect(); + let root_indent = usize::default(); if global_exports { - self.push_component_refs(&mut out, 0); - self.push_resource_modules(&mut out, &component_names, None, 0); + self.push_component_refs(&mut out, root_indent); + self.push_resource_modules(&mut out, &component_names, None, root_indent); } - self.push_lowering_api(&mut out, None, 0); + self.push_lowering_api(&mut out, None, root_indent); for component in self.component_names() { out.push_str("\n#[allow(non_upper_case_globals)]\n"); @@ -1196,7 +1197,7 @@ fn __hemx_attr(tag: &str, attr: &str) -> Option<::std::string::String> { return Ok(String::new()); } let module = match self.client_modules.len() { - 1 => self.client_modules.iter().next().expect("one module"), + 1 => self.client_modules.iter().next().unwrap(), 0 => { return Err(io::Error::new( io::ErrorKind::InvalidInput, @@ -2449,6 +2450,22 @@ mod tests { let result = std::panic::catch_unwind(|| app().out_dir(&out).run()); assert!(result.is_ok(), "client output errors must not panic"); assert!(result.unwrap().is_err()); + + let templates = root.join("templates"); + let invalid_out = root.join("invalid-out"); + std::fs::create_dir_all(&templates).unwrap(); + std::fs::write( + templates.join("client.heml"), + "", + ) + .unwrap(); + let result = + std::panic::catch_unwind(|| app().template_dir(&templates).out_dir(&invalid_out).run()); + assert!(result.is_ok(), "invalid client contracts must not panic"); + assert_eq!( + result.unwrap().unwrap_err().to_string(), + "client-local handlers require one data-hemx-client-module on a hemx root" + ); let _ = std::fs::remove_dir_all(root); // test req: build/004 }