diff --git a/stdlib/src/xml.rs b/stdlib/src/xml.rs
index d4f04739..0bbaaa21 100644
--- a/stdlib/src/xml.rs
+++ b/stdlib/src/xml.rs
@@ -66,3 +66,82 @@ impl StdlibRegistry {
);
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use techscript_runtime::context::{RuntimeConfig, RuntimeContext};
+
+ #[test]
+ fn test_register_xml() {
+ let mut registry = StdlibRegistry::default();
+ registry.register_xml();
+
+ let module = registry
+ .modules
+ .get("std.xml")
+ .expect("Module std.xml should be registered");
+ assert_eq!(module.name, "std.xml");
+ assert_eq!(module.version, "1.0.0");
+ assert!(module.required_capabilities.is_empty());
+ assert!(module.exports.contains_key("parse"));
+ assert!(module.exports.contains_key("stringify"));
+ }
+
+ #[test]
+ fn test_xml_parse() {
+ let mut registry = StdlibRegistry::default();
+ registry.register_xml();
+
+ let module = registry.modules.get("std.xml").unwrap();
+ let parse_fn = module.exports.get("parse").unwrap();
+
+ let mut ctx = RuntimeContext::new(RuntimeConfig::default());
+
+ // Valid XML
+ let args = vec![RuntimeValue::Str("- hello
".to_string())];
+ let result = parse_fn.call(&mut ctx, args).unwrap();
+
+ if let RuntimeValue::Map { entries, .. } = result {
+ let map = entries.borrow();
+ assert_eq!(map.get("item").and_then(|v| v.as_string()), Some("hello"));
+ } else {
+ panic!("parse should return a Map");
+ }
+
+ // Non-matching XML input (returns empty map)
+ let plain_str = vec![RuntimeValue::Str("not xml".to_string())];
+ let result = parse_fn.call(&mut ctx, plain_str).unwrap();
+ if let RuntimeValue::Map { entries, .. } = result {
+ assert!(entries.borrow().is_empty());
+ } else {
+ panic!("parse should return a Map even for non-matching strings");
+ }
+ }
+
+ #[test]
+ fn test_xml_stringify() {
+ let mut registry = StdlibRegistry::default();
+ registry.register_xml();
+
+ let module = registry.modules.get("std.xml").unwrap();
+ let stringify_fn = module.exports.get("stringify").unwrap();
+
+ let mut ctx = RuntimeContext::new(RuntimeConfig::default());
+
+ let mut map = IndexMap::new();
+ map.insert("name".to_string(), RuntimeValue::Str("Alice".to_string()));
+ let map_val = RuntimeValue::Map {
+ entries: Rc::new(RefCell::new(map)),
+ is_const: false,
+ };
+
+ let result = stringify_fn.call(&mut ctx, vec![map_val]).unwrap();
+ assert_eq!(result.as_string(), Some("Alice"));
+
+ // Non-map argument returns empty string
+ let non_map = vec![RuntimeValue::Int(42)];
+ let result = stringify_fn.call(&mut ctx, non_map).unwrap();
+ assert_eq!(result.as_string(), Some(""));
+ }
+}