use serde_json::{Value, json};
use crate::font::Fonts;
use crate::host::Engine;
fn send(e: &mut Engine, msg: Value) -> Value {
let r: Value = serde_json::from_str(&e.send_json(&msg.to_string())).expect("a reply");
assert!(r.get("error").is_none() && r["answer"].get("error").is_none(), "{msg} -> {r}");
r
}
fn part(bytes: &[u8], name: &str) -> Vec<u8> {
let mut z = zip::ZipArchive::new(std::io::Cursor::new(bytes)).unwrap();
let mut out = Vec::new();
std::io::Read::read_to_end(&mut z.by_name(name).unwrap(), &mut out).unwrap();
out
}
fn layout_text(e: &mut Engine) -> String {
let fonts = Fonts::system();
let ed = e.editor().unwrap();
ed.complete(&fonts);
crate::layout::dump::page_text(&ed.snapshot(), ed.document())
}
#[test]
fn data_parts_survive_edits_and_saves() {
let bytes = std::fs::read(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/editor/FX-MERGE-DATA.docx")).unwrap();
let mut e = Engine::with_fonts(Fonts::system());
e.open(&bytes);
let xml = r#"<calc xmlns="urn:store:calc"><field name="Total">Cost + Fee</field></calc>"#;
send(&mut e, json!({ "type": "command", "id": "data.write", "arg": { "namespace": "urn:store:calc", "xml": xml } }));
send(&mut e, json!({ "type": "text", "text": "Edited. " }));
let saved = e.save().unwrap();
if let Some(d) = std::env::var_os("WORD_CHECK_DIR") {
std::fs::write(std::path::Path::new(&d).join("US5-DATA.docx"), &saved).unwrap();
}
let mut again = Engine::with_fonts(Fonts::system());
again.open(&saved);
let parts = send(&mut again, json!({ "type": "query", "q": "data" }))["answer"].clone();
assert!(parts.as_array().unwrap().iter().any(|p| p["namespace"] == "urn:store:calc" && p["xml"] == xml), "{parts}");
let src = crate::docx::read_editable(&bytes).unwrap();
for p in &src.data_parts {
let name = p.src.clone().expect("read from the package");
assert_eq!(part(&saved, &name), part(&bytes, &name), "{name} unchanged");
}
let els = send(&mut again, json!({ "type": "query", "q": "elements" }))["answer"].clone();
assert!(els.as_array().unwrap().iter().any(|x| x["binding"] == true), "{els}");
}
#[test]
fn data_parts_dont_change_the_layout() {
let bytes = std::fs::read(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/editor/FX-MERGE-DATA.docx")).unwrap();
let mut e = Engine::with_fonts(Fonts::system());
e.open(&bytes);
let with = layout_text(&mut e);
for ns in ["urn:store:form-definition", "urn:store:form-data"] {
send(&mut e, json!({ "type": "command", "id": "data.remove", "arg": { "namespace": ns } }));
}
let saved = e.save().unwrap();
let mut without = Engine::with_fonts(Fonts::system());
without.open(&saved);
assert!(send(&mut without, json!({ "type": "query", "q": "data" }))["answer"].as_array().unwrap().is_empty());
assert_eq!(layout_text(&mut without), with, "data parts don't change the layout");
}