use super::*;
use pretty_assertions::assert_eq;
use std::fs;
#[test]
fn parses_hex_colors() {
assert_eq!(Rgb::from_hex("#112233"), Some(Rgb::new(0x11, 0x22, 0x33)));
assert_eq!(Rgb::from_hex("aabbcc"), Some(Rgb::new(0xaa, 0xbb, 0xcc)));
assert_eq!(Rgb::from_hex("#abc"), Some(Rgb::new(0xaa, 0xbb, 0xcc)));
assert_eq!(Rgb::from_hex("zz"), None);
assert_eq!(Rgb::from_hex("+112233"), None);
assert_eq!(Rgb::from_hex("-abc"), None);
assert_eq!(Rgb::from_hex("12 34 56"), None);
}
#[test]
fn parses_windows_terminal_scheme_json() {
let json = r##"{
"name": "Example",
"background": "#000000",
"foreground": "#ffffff",
"cursorColor": "#eeeeee",
"selectionBackground": "#333333",
"black": "#010101",
"red": "#ff0000",
"green": "#00ff00",
"yellow": "#ffff00",
"blue": "#0000ff",
"purple": "#ff00ff",
"cyan": "#00ffff",
"white": "#f0f0f0",
"brightBlack": "#808080",
"brightRed": "#ff8080",
"brightGreen": "#80ff80",
"brightYellow": "#ffff80",
"brightBlue": "#8080ff",
"brightPurple": "#ff80ff",
"brightCyan": "#80ffff",
"brightWhite": "#ffffff"
}"##;
let file: WindowsTerminalScheme = serde_json::from_str(json).unwrap();
let scheme = file
.into_scheme("example", ThemeSourceKind::Custom)
.unwrap();
assert_eq!(scheme.name, "Example");
assert_eq!(scheme.background, Rgb::new(0, 0, 0));
assert_eq!(scheme.ansi[1], Rgb::new(255, 0, 0));
assert_eq!(scheme.ansi[8], Rgb::new(128, 128, 128));
}
#[test]
fn ignores_invalid_optional_cursor_and_selection() {
let json = r##"{
"name": "Tolerant",
"background": "#000000",
"foreground": "#ffffff",
"cursorColor": "not-a-color",
"selectionBackground": "also-bad",
"black": "#000000",
"red": "#ff0000",
"green": "#00ff00",
"yellow": "#ffff00",
"blue": "#0000ff",
"purple": "#ff00ff",
"cyan": "#00ffff",
"white": "#ffffff",
"brightBlack": "#808080",
"brightRed": "#ff0000",
"brightGreen": "#00ff00",
"brightYellow": "#ffff00",
"brightBlue": "#0000ff",
"brightPurple": "#ff00ff",
"brightCyan": "#00ffff",
"brightWhite": "#ffffff"
}"##;
let file: WindowsTerminalScheme = serde_json::from_str(json).unwrap();
let scheme = file
.into_scheme("tolerant", ThemeSourceKind::Custom)
.expect("optional fields must not fail the scheme");
assert_eq!(scheme.name, "Tolerant");
}
#[test]
fn resolves_builtin_and_terminal_ids() {
assert!(resolve_fixed_scheme(TERMINAL_THEME_ID).is_none());
assert!(resolve_fixed_scheme("").is_none());
let classic = resolve_fixed_scheme("one-half-dark").expect("one-half-dark");
assert_eq!(classic.id, "one-half-dark");
assert_eq!(classic.source, ThemeSourceKind::Builtin);
assert!(resolve_fixed_scheme("missing-theme-xyz").is_none());
assert_eq!(theme_display_name("one-half-dark"), "One Half Dark");
assert_eq!(theme_display_name("terminal"), "Terminal");
assert_eq!(theme_display_name(""), "Terminal");
}
#[test]
fn builtin_catalog_ids_are_unique_and_reserved() {
let mut ids: Vec<_> = BUILTIN_SCHEMES.iter().map(|spec| spec.id).collect();
ids.sort_unstable();
let mut unique = ids.clone();
unique.dedup();
assert_eq!(ids, unique);
for spec in BUILTIN_SCHEMES {
assert!(!is_terminal_theme_id(spec.id));
assert!(is_builtin_theme_id(spec.id));
let resolved = resolve_fixed_scheme(spec.id).expect("builtin resolves");
assert_eq!(resolved.source, ThemeSourceKind::Builtin);
assert_eq!(resolved.id, spec.id);
}
}
#[test]
fn lists_custom_themes_from_injected_dir() {
let root = tempfile::tempdir().unwrap();
let themes = root.path().join("themes");
fs::create_dir_all(&themes).unwrap();
fs::write(
themes.join("forest.json"),
r##"{
"name": "Forest",
"background": "#0b1a0b",
"foreground": "#e8f5e8",
"black": "#0b1a0b",
"red": "#cc6666",
"green": "#66cc66",
"yellow": "#cccc66",
"blue": "#6666cc",
"purple": "#cc66cc",
"cyan": "#66cccc",
"white": "#e8f5e8",
"brightBlack": "#3a4a3a",
"brightRed": "#ff8888",
"brightGreen": "#88ff88",
"brightYellow": "#ffff88",
"brightBlue": "#8888ff",
"brightPurple": "#ff88ff",
"brightCyan": "#88ffff",
"brightWhite": "#ffffff"
}"##,
)
.unwrap();
fs::write(themes.join("one-half-dark.json"), "{}").unwrap();
fs::write(themes.join("broken.json"), "{not json").unwrap();
let items = list_themes_in(Some(&themes));
let forest = items
.iter()
.find(|item| item.id() == "forest")
.expect("custom forest theme");
assert_eq!(forest.name(), "Forest");
assert!(forest.is_custom());
assert!(items.iter().any(|item| item.id() == "one-half-dark"));
assert!(items.iter().any(|item| item.id() == TERMINAL_THEME_ID));
assert!(!items.iter().any(|item| item.id() == "broken"));
let names: Vec<_> = items.iter().map(|item| item.name()).collect();
let mut sorted = names.clone();
sorted.sort_by_key(|a| a.to_ascii_lowercase());
assert_eq!(names, sorted);
let loaded = resolve_fixed_scheme_in("forest", Some(&themes)).expect("load forest");
assert_eq!(loaded.name, "Forest");
assert_eq!(loaded.source, ThemeSourceKind::Custom);
match forest {
ThemeEntry::Fixed(scheme) => assert_eq!(scheme.name, "Forest"),
ThemeEntry::Terminal => panic!("forest should be fixed"),
}
}