use crate::tui::render::presets::{built_ins, by_name};
use crate::tui::render::user_themes::{build_theme, parse_hex};
use crate::tui::theme_catalog::theme_pack::sources;
#[test]
fn every_embedded_pack_theme_passes_the_validator_unchanged() {
assert!(!sources().is_empty(), "pack is empty");
for (name, toml) in sources() {
let shadow = format!("packcheck-{name}");
build_theme(&shadow, toml)
.unwrap_or_else(|e| panic!("pack theme {name} rejected by validator: {e}"));
}
}
#[test]
fn pack_is_curated_unique_and_provenance_stamped() {
let names: Vec<&str> = sources().iter().map(|(n, _)| *n).collect();
assert!(
names.len() >= 30,
"expected ~30 curated themes, got {}",
names.len()
);
let mut sorted = names.clone();
sorted.sort_unstable();
sorted.dedup();
assert_eq!(sorted.len(), names.len(), "duplicate pack names");
for (name, toml) in sources() {
assert!(
toml.starts_with("# source:"),
"{name}: missing '# source:' provenance header"
);
assert!(
toml.contains("generated by tui::theme_catalog::converter"),
"{name}: missing generator stamp"
);
}
}
#[test]
fn pack_serves_through_built_ins_and_by_name() {
let all = built_ins();
assert_eq!(all[0].name, "crab-dark", "default theme stays first");
assert!(
all.len() >= 8 + sources().len(),
"built_ins should hold 8 hand-built + {} pack themes, got {}",
sources().len(),
all.len()
);
let mut names: Vec<&str> = all.iter().map(|t| t.name).collect();
let total = names.len();
names.sort_unstable();
names.dedup();
assert_eq!(
names.len(),
total,
"name collision between hand-built presets and pack"
);
let tokyonight = by_name("tokyonight").expect("pack theme via by_name");
assert_eq!(
tokyonight.colors.ink,
parse_hex("#1a1b26").unwrap(),
"tokyonight ink = darkStep1"
);
assert!(
by_name("TokyoNight").is_some(),
"lookup is case-insensitive"
);
assert!(
by_name("gruvbox-light").is_some(),
"alacritty complement shipped"
);
}