From 11a7a1f8fc0e8dd376b87611646c113c3ef6d8c7 Mon Sep 17 00:00:00 2001 From: Cody Date: Sun, 12 Apr 2026 23:22:46 -0400 Subject: [PATCH] test(core): add integration tests for public API surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Existing coverage is per-module unit tests. This adds a tests/integration.rs exercising draw-core as an external consumer would — only `pub use` re-exports from the crate root. New coverage: - Full pipeline across all 7 element types: new -> populate -> JSON round-trip -> save/load -> SVG export (per-type tag checks) -> PNG export (magic bytes) - Arrow start_binding/end_binding round-trip (Binding added in #35, had no test coverage) - Legacy doc parsing when binding fields are absent (serde default=None) - Element dispatch helpers (id/position/set_position/opacity/is_locked/group_id) across every variant - Empty-document SVG/PNG exports don't panic Co-Authored-By: Claude Opus 4.6 --- crates/draw-core/tests/integration.rs | 196 ++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 crates/draw-core/tests/integration.rs diff --git a/crates/draw-core/tests/integration.rs b/crates/draw-core/tests/integration.rs new file mode 100644 index 0000000..364db67 --- /dev/null +++ b/crates/draw-core/tests/integration.rs @@ -0,0 +1,196 @@ +//! Integration tests exercising draw_core as an external consumer would — +//! only `pub use` re-exports from the crate root, cross-module flows, +//! and gaps in inline unit-test coverage (Binding round-trip, full pipeline). + +use draw_core::{ + Binding, Document, Element, FreeDrawElement, LineElement, Point, ShapeElement, TextElement, + export_png, export_svg, +}; + +/// Build a document containing one of every Element variant. +fn populated_doc(name: &str) -> Document { + let mut doc = Document::new(name.to_string()); + doc.add_element(Element::Rectangle(ShapeElement::new( + "rect-1".into(), + 10.0, + 10.0, + 80.0, + 40.0, + ))); + doc.add_element(Element::Ellipse(ShapeElement::new( + "ell-1".into(), + 120.0, + 10.0, + 60.0, + 60.0, + ))); + doc.add_element(Element::Diamond(ShapeElement::new( + "dia-1".into(), + 10.0, + 80.0, + 60.0, + 60.0, + ))); + doc.add_element(Element::Line(LineElement::new( + "line-1".into(), + 120.0, + 80.0, + vec![Point::new(0.0, 0.0), Point::new(40.0, 40.0)], + ))); + doc.add_element(Element::Arrow(LineElement::new( + "arr-1".into(), + 10.0, + 160.0, + vec![Point::new(0.0, 0.0), Point::new(60.0, 0.0)], + ))); + doc.add_element(Element::FreeDraw(FreeDrawElement::new( + "fd-1".into(), + 120.0, + 160.0, + vec![ + Point::new(0.0, 0.0), + Point::new(10.0, 15.0), + Point::new(25.0, 5.0), + ], + ))); + doc.add_element(Element::Text(TextElement::new( + "txt-1".into(), + 10.0, + 240.0, + "hello draw".into(), + ))); + doc +} + +#[test] +fn full_pipeline_all_element_types() { + let doc = populated_doc("full pipeline"); + assert_eq!(doc.elements.len(), 7); + + // JSON round-trip preserves structure + let json = serde_json::to_string(&doc).expect("serialize"); + let loaded: Document = serde_json::from_str(&json).expect("deserialize"); + assert_eq!(doc, loaded); + + // SVG export is well-formed and mentions every element we put in + let svg = export_svg(&doc); + assert!(svg.starts_with("")); + // Each element type produces at least one of its SVG primitive + assert!(svg.contains("")); + let png = export_png(&doc).expect("png of empty doc"); + assert!(png.starts_with(&[0x89, b'P', b'N', b'G'])); +}