use ratatui::Terminal;
use ratatui::backend::TestBackend;
use crate::diff::{DiffEngine, DiffResult};
use crate::model::{BomProfile, NormalizedSbom};
use crate::parsers::parse_sbom_str;
pub(crate) const DEMO_OLD: &str = include_str!("../../tests/fixtures/demo-old.cdx.json");
pub(crate) const DEMO_NEW: &str = include_str!("../../tests/fixtures/demo-new.cdx.json");
pub(crate) const AIBOM_BSI: &str =
include_str!("../../tests/fixtures/cyclonedx/bsi-aibom-complete.cdx.json");
pub(crate) const SIZES: [(u16, u16); 2] = [(80, 24), (120, 40)];
pub(crate) fn pin_theme() {
crate::tui::theme::set_theme(crate::tui::theme::Theme::dark());
}
pub(crate) fn demo_diff() -> (DiffResult, NormalizedSbom, NormalizedSbom) {
let old = parse_sbom_str(DEMO_OLD).expect("demo-old fixture must parse");
let new = parse_sbom_str(DEMO_NEW).expect("demo-new fixture must parse");
let result = DiffEngine::new()
.diff(&old, &new)
.expect("demo diff must succeed");
(result, old, new)
}
pub(crate) fn demo_single() -> (NormalizedSbom, BomProfile) {
let sbom = parse_sbom_str(DEMO_NEW).expect("demo-new fixture must parse");
let profile = BomProfile::detect(&sbom);
(sbom, profile)
}
pub(crate) fn aibom_single() -> (NormalizedSbom, BomProfile) {
let sbom = parse_sbom_str(AIBOM_BSI).expect("bsi-aibom fixture must parse");
let profile = BomProfile::detect(&sbom);
(sbom, profile)
}
pub(crate) fn render_to_text<F>(width: u16, height: u16, draw: F) -> String
where
F: FnOnce(&mut ratatui::Frame),
{
let backend = TestBackend::new(width, height);
let mut terminal = Terminal::new(backend).expect("TestBackend terminal");
terminal.draw(draw).expect("draw must succeed");
buffer_to_text(terminal.backend().buffer())
}
fn buffer_to_text(buffer: &ratatui::buffer::Buffer) -> String {
let width = buffer.area.width as usize;
let mut out = String::new();
for row in buffer.content.chunks(width) {
let mut line = String::new();
for cell in row {
line.push_str(cell.symbol());
}
out.push_str(line.trim_end());
out.push('\n');
}
out
}