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
}
pub(crate) const CBOM: &str = include_str!("../../tests/fixtures/cyclonedx/cbom-1.7.cdx.json");
pub(crate) fn cbom_single() -> (NormalizedSbom, BomProfile) {
let sbom = parse_sbom_str(CBOM).expect("cbom fixture must parse");
let profile = BomProfile::detect(&sbom);
(sbom, profile)
}
pub(crate) fn demo_multi_diff() -> crate::diff::MultiDiffResult {
let baseline = parse_sbom_str(DEMO_OLD).expect("baseline fixture must parse");
let webapp = parse_sbom_str(DEMO_NEW).expect("webapp fixture must parse");
let ai = parse_sbom_str(AIBOM_BSI).expect("aibom fixture must parse");
let targets: [(&NormalizedSbom, &str, &str); 2] = [
(&webapp, "webapp", "demo-new.cdx.json"),
(&ai, "ai-service", "aibom.cdx.json"),
];
let mut engine = crate::diff::MultiDiffEngine::new();
engine
.diff_multi(&baseline, "baseline", "demo-old.cdx.json", &targets)
.expect("multi diff must succeed")
}
pub(crate) fn demo_timeline() -> crate::diff::TimelineResult {
let v1 = parse_sbom_str(DEMO_OLD).expect("v1 fixture must parse");
let v2 = parse_sbom_str(DEMO_NEW).expect("v2 fixture must parse");
let v3 = parse_sbom_str(AIBOM_BSI).expect("v3 fixture must parse");
let sboms: [(&NormalizedSbom, &str, &str); 3] = [
(&v1, "v1", "demo-old.cdx.json"),
(&v2, "v2", "demo-new.cdx.json"),
(&v3, "v3", "aibom.cdx.json"),
];
let mut engine = crate::diff::MultiDiffEngine::new();
engine.timeline(&sboms).expect("timeline must succeed")
}
pub(crate) fn demo_matrix_large() -> crate::diff::MatrixResult {
let a = parse_sbom_str(DEMO_OLD).expect("fixture must parse");
let b = parse_sbom_str(DEMO_NEW).expect("fixture must parse");
let names = ["v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"];
let sboms: Vec<(&NormalizedSbom, &str, &str)> = names
.iter()
.enumerate()
.map(|(i, name)| (if i % 2 == 0 { &a } else { &b }, *name, "demo.cdx.json"))
.collect();
let mut engine = crate::diff::MultiDiffEngine::new();
engine
.matrix(&sboms, Some(0.8))
.expect("matrix must succeed")
}
pub(crate) fn demo_matrix() -> crate::diff::MatrixResult {
let a = parse_sbom_str(DEMO_OLD).expect("fixture must parse");
let b = parse_sbom_str(DEMO_NEW).expect("fixture must parse");
let c = parse_sbom_str(AIBOM_BSI).expect("fixture must parse");
let sboms: [(&NormalizedSbom, &str, &str); 3] = [
(&a, "alpha", "demo-old.cdx.json"),
(&b, "beta", "demo-new.cdx.json"),
(&c, "gamma", "aibom.cdx.json"),
];
let mut engine = crate::diff::MultiDiffEngine::new();
engine
.matrix(&sboms, Some(0.5))
.expect("matrix must succeed")
}