Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-docview/tests/robot.rs

//! **Robot manual-viewer scenario for `DocView`** (`egui_kittest`).
//!
//! Renders the REAL [`facett_docview::DocView`] body over a synthetic 3-page SVG
//! book (each page a real `<text>` word, so the pages carry a genuine searchable
//! text layer) and asserts — off the live AccessKit tree + the viewer's
//! `state_json` — that every premium-reader capability reaches the surface a robot
//! (or a screen reader) sees, matching the markdown Manual pane's capability set:
//!
//! 1. **Sidebar navigation** — the table-of-contents entries paint as clickable
//!    labels, and clicking one sets the target page (the same `JumpTo` a TOC click
//!    emits) — proven by an AccessKit click driving `current_page`.
//! 2. **Continuous scroll** — with the whole short book in a tall viewport, the
//!    continuous mode reports ≥2 pages' regions rasterized in one scroll view.
//! 3. **Paged mode** — toggling to paged reports exactly the current page visible
//!    (one page at a time), and the mode is reflected in `state_json`.
//! 4. **Search** — a query over the real text layer finds the known word on the
//!    pages that carry it, and next-hit navigation lands on a hit page. A book
//!    with no text layer would honestly report `search_available:false` (covered
//!    by the crate's unit tests).
//! 5. No crash: the whole viewer body runs through the harness without panicking.
//!
//! RED-when-broken: neutralizing the sidebar, the continuous band, the paged
//! single-page path, or the search index turns an assertion red.

use std::sync::{Arc, Mutex};

use egui_kittest::kittest::Queryable;
use egui_kittest::Harness;
use facett_docview::{DocPage, DocView, Facet};

/// A 1-page SVG carrying a single real `<text>` word — a searchable text layer.
fn word_page(word: &str) -> String {
    format!(
        r#"<svg xmlns="http://www.w3.org/2000/svg" width="200" height="80" viewBox="0 0 200 80">
  <rect x="0" y="0" width="200" height="80" fill="white"/>
  <text x="10" y="55" font-size="32" fill="black">{word}</text>
</svg>"#
    )
}

/// A 3-page book with real text (alpha / beta / gamma-beta) + a TOC per page.
fn book() -> DocView {
    let pages = vec![
        DocPage::from_svg_bytes(word_page("alpha").as_bytes()).unwrap(),
        DocPage::from_svg_bytes(word_page("beta").as_bytes()).unwrap(),
        DocPage::from_svg_bytes(word_page("gamma beta").as_bytes()).unwrap(),
    ];
    let toc = vec![
        ("Alpha".to_string(), 0usize),
        ("Beta".to_string(), 1usize),
        ("Gamma".to_string(), 2usize),
    ];
    DocView::new("robot manual", pages, toc)
}

#[test]
fn docview_renders_sidebar_continuous_paged_and_search() {
    let view = Arc::new(Mutex::new(book()));

    let mut harness = Harness::builder().with_size(egui::vec2(760.0, 900.0)).build_ui({
        let view = Arc::clone(&view);
        move |ui| {
            Facet::ui(&mut *view.lock().unwrap(), ui);
        }
    });

    // A frame — proves the whole viewer body paints without panicking (no crash).
    harness.run();

    let seen = |h: &Harness, label: &str| h.query_all_by_label(label).count() >= 1;

    // (1) Sidebar navigation: every TOC entry paints as a label …
    let toc_all_shown = seen(&harness, "Alpha") && seen(&harness, "Beta") && seen(&harness, "Gamma");
    assert!(toc_all_shown, "the TOC sidebar lists every page's entry");

    // (2) Continuous scroll: the short book fits a tall viewport → ≥2 pages'
    //     regions rasterize in one scroll view.
    let visible_continuous = view.lock().unwrap().state_json()["visible_pages"]
        .as_array()
        .unwrap()
        .len();
    assert!(
        visible_continuous >= 2,
        "continuous mode rasterizes ≥2 pages in one view, got {visible_continuous}"
    );

    // (1b) A TOC CLICK sets the target page (the JumpTo a click emits).
    harness.get_by_label("Gamma").click();
    harness.run();
    let after_click = view.lock().unwrap().state_json()["current_page"].as_u64().unwrap();
    assert_eq!(after_click, 2, "clicking the 'Gamma' TOC entry jumped to page 3 (index 2)");

    // (4) Search over the real text layer: "beta" is on pages 1 and 2 (0-based).
    {
        let mut g = view.lock().unwrap();
        assert!(g.search_available(), "the book carries a searchable text layer");
        g.set_query("beta");
    }
    harness.run();
    let hits: Vec<u64> = view.lock().unwrap().state_json()["search_hits"]
        .as_array()
        .unwrap()
        .iter()
        .map(|v| v.as_u64().unwrap())
        .collect();
    assert_eq!(hits, vec![1, 2], "search found the 'beta' pages");
    // Next-hit navigation targets the first hit page. Asserted on the model right
    // after the message (continuous mode then RE-derives current_page as the
    // centremost visible page on the next render — expected for a short book in a
    // tall viewport — so we assert the navigation before that re-derivation).
    {
        let mut g = view.lock().unwrap();
        g.next_hit();
        assert_eq!(g.current_page(), 1, "next-hit navigated to the first 'beta' page");
        assert_eq!(g.search_hits(), &[1, 2]);
    }

    // (3) Paged mode: toggle, then exactly the current page is visible.
    view.lock().unwrap().clear_search();
    view.lock().unwrap().toggle_mode();
    harness.run();
    let s = view.lock().unwrap().state_json();
    assert_eq!(s["mode"], "paged", "mode toggled to paged");
    let visible_paged = s["visible_pages"].as_array().unwrap();
    assert_eq!(visible_paged.len(), 1, "paged mode shows exactly one page");

    // testmatrix cell — facett_docview has SVG-book parity with the Markdown viewer
    // (sidebar TOC, paged/continuous, text search); surfaces in the dwarves testmatrix.
    facett_core::testmatrix::emit(
        "facett-docview",
        "docview_renders_sidebar_continuous_paged_and_search",
        toc_all_shown && visible_continuous >= 2 && hits == vec![1, 2] && visible_paged.len() == 1,
        &format!(
            "SVG docview: TOC listed, {visible_continuous} pages in continuous, search 'beta' hit {hits:?}, paged shows 1"
        ),
    );
}