use std::time::Instant;
use super::{render_mermaid, MermaidRender, PHASE_CHAIN_FLOWCHART};
const MAX_PROBE_WIDTH: usize = 300;
const TIMING_WIDTH: usize = 120;
const TIMING_ITERS: u32 = 40;
struct Fixture {
name: &'static str,
source: &'static str,
}
const FIXTURES: &[Fixture] = &[
Fixture {
name: "branchy_td_labeled",
source: "flowchart TD\n\
D[delta arrives] --> N{new complete line in open mermaid fence?}\n\
N -- no --> S[skip - no diagram work]\n\
N -- yes --> R[render_open_prefix]\n\
R -- art --> P[paint live panel]\n\
R -- malformed prefix --> L[walk back to last-good]\n\
R -- sticky fallback --> Src[ordinary source fence]\n\
F[fence closes] --> E[render_closed_fence]",
},
Fixture {
name: "phase_chain_lr",
source: PHASE_CHAIN_FLOWCHART,
},
Fixture {
name: "state_fallback_modes",
source: "stateDiagram-v2\n\
[*] --> Open\n\
Open --> Art: prefix renders\n\
Open --> Art: walk back last-good\n\
Open --> Source: sticky fallback\n\
Art --> Closed: fence closes\n\
Source --> Closed: fence closes",
},
Fixture {
name: "long_edge_label",
source: "flowchart TD\n\
A[start] -->|when the renderer reports a terminal width failure| B[fallback]\n\
A -->|otherwise| C[art]",
},
Fixture {
name: "sequence_typical",
source: "sequenceDiagram\n\
participant TUI\n\
participant Markdown\n\
participant Renderer\n\
TUI->>Markdown: open mermaid fence\n\
Markdown->>Renderer: complete prefix\n\
Renderer-->>Markdown: art or none\n\
Markdown-->>TUI: panel or source",
},
Fixture {
name: "class_small",
source: "classDiagram\n\
Animal <|-- Duck\n\
class Animal {\n+name: String\n+speak()\n}\n\
class Duck {\n+quack()\n}",
},
Fixture {
name: "er_small",
source: "erDiagram\n\
CUSTOMER ||--o{ ORDER : places\n\
ORDER ||--|{ LINE_ITEM : contains",
},
Fixture {
name: "gitgraph_small",
source: "gitGraph\n\
commit id: \"init\" msg: \"init\"\n\
branch develop\n\
commit id: \"parser\" msg: \"parser\"\n\
checkout main\n\
merge develop",
},
Fixture {
name: "gantt_small",
source: "gantt\n\
title Plan\n\
section Build\n\
Parser :p1, 3d\n\
Painter :after p1, 2d",
},
Fixture {
name: "mindmap_small",
source: "mindmap\n Root\n Child\n Other",
},
];
fn renders(source: &str, width: usize) -> bool {
matches!(
render_mermaid(source, width),
MermaidRender::Rendered(_) | MermaidRender::Clipped { .. }
)
}
#[test]
#[ignore = "instrumentation: prints mermaid width/cost receipts"]
fn run_mermaid_width_receipts() {
println!(
"{:<24} {:>9} {:>6} {:>14}",
"fixture", "min_width", "holes", "mean_render_us"
);
for fixture in FIXTURES {
let min_width = (1..=MAX_PROBE_WIDTH).find(|&width| renders(fixture.source, width));
let holes = min_width.map_or(0, |min| {
(min..=MAX_PROBE_WIDTH)
.filter(|&width| !renders(fixture.source, width))
.count()
});
let start = Instant::now();
for _ in 0..TIMING_ITERS {
std::hint::black_box(render_mermaid(
std::hint::black_box(fixture.source),
TIMING_WIDTH,
));
}
let mean_us = start.elapsed().as_micros() / u128::from(TIMING_ITERS);
let min_display = min_width.map_or_else(|| "never".to_owned(), |width| width.to_string());
println!(
"{:<24} {:>9} {:>6} {:>14}",
fixture.name, min_display, holes, mean_us
);
}
}