//! Loader tests — split from `mod.rs` (file-size budget); same `super::*` view. mod loader_tests { use crate::framexml; use crate::loader::*; use crate::order::ZTarget; use crate::script::{QuadContent, UiScript}; /// No-provider `files` closure (for docs with no ``/`\n\ ", ); let report = load_in(&s, &doc, "Bagnon/src/main.xml", &no_files); let err = report.errors.join("\n"); // The file, in the shape an addon's own `debugstack()` matches (backslashes, no `@`). assert!( err.contains("Bagnon\\src\\main.xml:"), "the raise must name the document, got: {err}" ); // Line 5 of the literal above is `error("boom")` — the body starts on line 4 and the // padding carries it there. Without the pad this reads `:2:`. assert!( err.contains("main.xml:5:"), "the line must be the FILE's line, not the block's, got: {err}" ); } /// The same, one level down: an ``d document's inline script names **its own** file, /// not the includer's. The path is saved and restored around the recursion exactly as the /// directory used to be, so depth-1 and depth-5 each report themselves. #[test] fn an_included_documents_script_names_the_included_file() { let s = UiScript::new().unwrap(); let inner = "\n\n"; let files = |req: &str| -> Option> { (req == "Addon/sub/inner.xml").then(|| inner.as_bytes().to_vec()) }; let doc = parse("\n\n"); let report = load_in(&s, &doc, "Addon/outer.xml", &files); let err = report.errors.join("\n"); assert!( err.contains("Addon\\sub\\inner.xml:3:"), "the INCLUDED file and its line, not the includer's: {err}" ); assert!( !err.contains("outer.xml"), "the includer must not be blamed: {err}" ); } /// **The CDATA shape, which is the only shape our own FrameXML uses.** `\n\ \n\ \n\ \n\ ", ); let report = load_in(&s, &doc, "Ours/Bag.xml", &no_files); let err = report.errors.join("\n"); assert!( err.contains("Ours\\Bag.xml:6:"), "line 6 is `error(\"cdata boom\")` in the literal above, got: {err}" ); } /// A `