tokenburn_core/features/theme/
mod.rs1pub mod presets;
4pub mod types;
5
6pub use presets::*;
7pub use types::*;
8
9#[cfg(test)]
10mod tests {
11 use super::*;
12
13 #[test]
14 fn every_name_has_a_theme_and_the_counts_agree() {
15 assert_eq!(THEME_NAMES.len(), THEME_COUNT);
16 for i in 0..THEME_COUNT {
17 let t = theme_by_index(i);
18 assert_ne!(t.background, t.text_primary, "theme {i} is unreadable");
19 assert_ne!(
20 t.border, t.accent,
21 "theme {i}: border and accent are identical"
22 );
23 }
24 }
25
26 #[test]
27 fn names_are_unique_and_found_case_insensitively() {
28 for (i, n) in THEME_NAMES.iter().enumerate() {
29 assert_eq!(
30 THEME_NAMES.iter().filter(|m| m == &n).count(),
31 1,
32 "duplicate {n}"
33 );
34 assert_eq!(find_theme(&n.to_ascii_uppercase()), Some(i));
35 }
36 assert_eq!(find_theme(" nord "), find_theme("Nord"));
37 assert_eq!(find_theme("no such theme"), None);
38 assert_eq!(theme_index_by_name("no such theme"), 0);
39 }
40
41 #[test]
42 fn dark_and_light_themes_have_matching_luminance() {
43 let lum = |c: Rgb| 0.299 * f32::from(c.r) + 0.587 * f32::from(c.g) + 0.114 * f32::from(c.b);
46 for (i, name) in THEME_NAMES.iter().enumerate() {
47 let t = theme_by_index(i);
48 assert_eq!(
49 t.is_dark,
50 lum(t.background) < 128.0,
51 "{name} says is_dark={}",
52 t.is_dark
53 );
54 }
55 }
56
57 #[test]
58 fn there_are_light_and_dark_themes() {
59 let dark = (0..THEME_COUNT)
60 .filter(|i| theme_by_index(*i).is_dark)
61 .count();
62 assert!(dark > 10 && dark < THEME_COUNT - 5);
63 }
64
65 #[test]
66 fn text_contrasts_with_the_background_in_every_theme() {
67 let lum = |c: Rgb| 0.299 * f32::from(c.r) + 0.587 * f32::from(c.g) + 0.114 * f32::from(c.b);
69 for (i, name) in THEME_NAMES.iter().enumerate() {
70 let t = theme_by_index(i);
71 let d = (lum(t.text_primary) - lum(t.background)).abs();
72 assert!(
73 d > 90.0,
74 "{name}: text/background luminance gap only {d:.0}"
75 );
76 }
77 }
78
79 #[test]
80 fn hex_and_unit_conversions() {
81 assert_eq!(Rgb::new(255, 0, 16).hex(), "#ff0010");
82 assert_eq!(Rgb::new(255, 0, 0).unit(), (1.0, 0.0, 0.0));
83 }
84
85 #[test]
86 fn every_tool_gets_a_series_colour() {
87 let t = theme_by_index(0);
88 for tool in crate::Tool::ALL {
89 let _ = t.tool_color(tool);
90 }
91 let idx: std::collections::HashSet<_> = crate::Tool::ALL
93 .iter()
94 .map(|t| t.series_index() % 8)
95 .collect();
96 assert_eq!(idx.len(), crate::Tool::ALL.len());
97 }
98}