From 85754582c0c4ae3dd4482d588fd411cdef542ed5 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Sun, 27 Sep 2026 20:33:45 +0200 Subject: [PATCH] fix(ci): the svg text tests assumed the host has fonts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #394 turned main red. Two tests written against a Mac asserted that Helvetica resolves; CI's Ubuntu runner installs `libfontconfig1-dev` and `libfreetype6-dev` — the font *libraries* — and no font *files* at all, so nothing resolved and usvg dropped the `` node exactly as it does for any host with an empty fontdb. That is the residual gap #374's own rule file documents, arriving as a red build rather than as a render. Both sides fixed, because each was wrong on its own: The tests no longer name a family. They ask the shared fontdb for a family the host actually has and skip when there is none, so they mean the same thing on a laptop and in a container. A new test covers the other side directly: with an empty fontdb the `` count resolves to 0, which is the condition the warning exists for. CI gains `fonts-dejavu-core`. A renderer that draws text needs font files on the host, and a runner that has none is not a realistic environment to prove anything about text in. I merged #394 while its `test` job was still pending. That is what let this reach main. --- .github/workflows/ci.yaml | 8 ++++-- crates/rustmotion-components/src/svg.rs | 34 ++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 153b0f0..7cc4785 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,7 +27,9 @@ jobs: # xkbcommon-x11/wayland/xcb-cursor: required to LINK the studio (gpui). # clippy passes without them — it never links — so the failure only shows in tests. # asound: required by cpal, which rodio pulls in for preview audio - run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev libfreetype6-dev libxkbcommon-x11-dev libwayland-dev libxcb-cursor-dev libasound2-dev + # fonts-dejavu-core: font *files*, not just the libraries. A bare runner has none, + # and usvg silently drops an 's when no face resolves. + run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev libfreetype6-dev libxkbcommon-x11-dev libwayland-dev libxcb-cursor-dev libasound2-dev fonts-dejavu-core - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable channel, 2026-09-22 with: components: clippy @@ -48,7 +50,9 @@ jobs: # xkbcommon-x11/wayland/xcb-cursor: required to LINK the studio (gpui). # clippy passes without them — it never links — so the failure only shows in tests. # asound: required by cpal, which rodio pulls in for preview audio - run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev libfreetype6-dev libxkbcommon-x11-dev libwayland-dev libxcb-cursor-dev libasound2-dev + # fonts-dejavu-core: font *files*, not just the libraries. A bare runner has none, + # and usvg silently drops an 's when no face resolves. + run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev libfreetype6-dev libxkbcommon-x11-dev libwayland-dev libxcb-cursor-dev libasound2-dev fonts-dejavu-core - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable channel, 2026-09-22 - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: Run tests diff --git a/crates/rustmotion-components/src/svg.rs b/crates/rustmotion-components/src/svg.rs index c77fb6a..cbaac0d 100644 --- a/crates/rustmotion-components/src/svg.rs +++ b/crates/rustmotion-components/src/svg.rs @@ -911,6 +911,13 @@ mod tests { ); } + fn a_family_this_host_actually_has() -> Option { + shared_svg_fontdb() + .faces() + .next() + .and_then(|face| face.families.first().map(|(name, _)| name.clone())) + } + fn text_svg(font_family: &str) -> Svg { Svg { src: None, @@ -930,7 +937,10 @@ mod tests { #[test] fn svg_text_with_a_system_font_is_rasterized() { - let svg = text_svg("Helvetica"); + let Some(family) = a_family_this_host_actually_has() else { + return; + }; + let svg = text_svg(&family); let layout = BoxLayout { x: 0.0, y: 0.0, @@ -982,9 +992,27 @@ mod tests { ); } + #[test] + fn a_host_with_no_font_at_all_says_so_instead_of_dropping_the_text() { + let svg_data = text_svg("Helvetica").data.unwrap().into_bytes(); + let empty_db = usvg::Options::default(); + let tree = usvg::Tree::from_data(&svg_data, &empty_db).expect("valid svg"); + + assert_eq!(count_svg_text_elements(&svg_data), 1); + assert_eq!( + count_resolved_text_nodes(tree.root()), + 0, + "with an empty fontdb usvg drops the node from the tree entirely — this \ + is the condition the warning exists for, and the one a bare CI container is in" + ); + } + #[test] fn a_resolvable_font_family_matches_declared_and_resolved_text_counts() { - let svg = text_svg("Helvetica"); + let Some(family) = a_family_this_host_actually_has() else { + return; + }; + let svg = text_svg(&family); let svg_data = svg.data.as_ref().unwrap().as_bytes().to_vec(); let opt = svg_parse_options(); let tree = usvg::Tree::from_data(&svg_data, &opt).expect("valid svg"); @@ -993,7 +1021,7 @@ mod tests { assert_eq!( count_resolved_text_nodes(tree.root()), 1, - "Helvetica is a system font and must resolve once system fonts are loaded" + "a family this host actually has must resolve once system fonts are loaded" ); }