From 81dfb0fadb01a281b863f0f4bccdcee6a633a6fe Mon Sep 17 00:00:00 2001 From: an0nn30 Date: Fri, 27 Mar 2026 12:16:03 -0500 Subject: [PATCH] Add unit tests for conch_core color_scheme, font, and persistent modules Test defaults, serde round-trips, TOML deserialization with complete, partial, and empty inputs, and optional field handling across all three config modules. Adds 18 new tests. --- crates/conch_core/src/color_scheme.rs | 195 +++++++++++++++++++++ crates/conch_core/src/config/font.rs | 58 ++++++ crates/conch_core/src/config/persistent.rs | 99 +++++++++++ 3 files changed, 352 insertions(+) diff --git a/crates/conch_core/src/color_scheme.rs b/crates/conch_core/src/color_scheme.rs index be3283c..c623ca7 100644 --- a/crates/conch_core/src/color_scheme.rs +++ b/crates/conch_core/src/color_scheme.rs @@ -206,3 +206,198 @@ pub fn resolve_theme(value: &str) -> ColorScheme { } ColorScheme::default() } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn default_color_scheme_primary_colors() { + let cs = ColorScheme::default(); + assert_eq!(cs.primary.background, "#282a36", "Dracula background"); + assert_eq!(cs.primary.foreground, "#f8f8f2", "Dracula foreground"); + assert_eq!( + cs.primary.dim_foreground.as_deref(), + Some("#6272a4"), + "Dracula dim foreground" + ); + assert_eq!( + cs.primary.bright_foreground.as_deref(), + Some("#ffffff"), + "Dracula bright foreground" + ); + } + + #[test] + fn default_color_scheme_optional_fields() { + let cs = ColorScheme::default(); + assert!(cs.dim.is_none(), "dim should be None by default"); + assert!(cs.cursor.is_some(), "cursor should be Some by default"); + assert!( + cs.selection.is_some(), + "selection should be Some by default" + ); + + let cursor = cs.cursor.unwrap(); + assert_eq!(cursor.text, "#282a36"); + assert_eq!(cursor.cursor, "#f8f8f2"); + + let selection = cs.selection.unwrap(); + assert_eq!(selection.text, "#f8f8f2"); + assert_eq!(selection.background, "#44475a"); + } + + #[test] + fn ansi_colors_as_array() { + let cs = ColorScheme::default(); + let normal = cs.normal.as_array(); + assert_eq!(normal.len(), 8); + assert_eq!(normal[0], "#21222c", "black"); + assert_eq!(normal[1], "#ff5555", "red"); + assert_eq!(normal[2], "#50fa7b", "green"); + assert_eq!(normal[3], "#f1fa8c", "yellow"); + assert_eq!(normal[4], "#bd93f9", "blue"); + assert_eq!(normal[5], "#ff79c6", "magenta"); + assert_eq!(normal[6], "#8be9fd", "cyan"); + assert_eq!(normal[7], "#f8f8f2", "white"); + } + + #[test] + fn deserialize_complete_alacritty_theme() { + let toml_str = r##" +[colors.primary] +background = "#1e1e2e" +foreground = "#cdd6f4" + +[colors.normal] +black = "#45475a" +red = "#f38ba8" +green = "#a6e3a1" +yellow = "#f9e2af" +blue = "#89b4fa" +magenta = "#f5c2e7" +cyan = "#94e2d5" +white = "#bac2de" + +[colors.bright] +black = "#585b70" +red = "#f38ba8" +green = "#a6e3a1" +yellow = "#f9e2af" +blue = "#89b4fa" +magenta = "#f5c2e7" +cyan = "#94e2d5" +white = "#a6adc8" + +[colors.cursor] +text = "#1e1e2e" +cursor = "#f5e0dc" + +[colors.selection] +text = "#1e1e2e" +background = "#f5e0dc" +"##; + let theme: AlacrittyThemeFile = toml::from_str(toml_str).expect("valid TOML"); + assert_eq!(theme.colors.primary.background, "#1e1e2e"); + assert_eq!(theme.colors.primary.foreground, "#cdd6f4"); + assert_eq!(theme.colors.normal.black, "#45475a"); + assert_eq!(theme.colors.bright.white, "#a6adc8"); + assert!(theme.colors.cursor.is_some()); + assert!(theme.colors.selection.is_some()); + } + + #[test] + fn deserialize_missing_optional_fields() { + let toml_str = r##" +[colors.primary] +background = "#000000" +foreground = "#ffffff" + +[colors.normal] +black = "#000000" +red = "#ff0000" +green = "#00ff00" +yellow = "#ffff00" +blue = "#0000ff" +magenta = "#ff00ff" +cyan = "#00ffff" +white = "#ffffff" + +[colors.bright] +black = "#808080" +red = "#ff0000" +green = "#00ff00" +yellow = "#ffff00" +blue = "#0000ff" +magenta = "#ff00ff" +cyan = "#00ffff" +white = "#ffffff" +"##; + let theme: AlacrittyThemeFile = toml::from_str(toml_str).expect("valid TOML"); + let cs = theme.colors; + assert!(cs.dim.is_none(), "dim should be None when absent from TOML"); + assert!( + cs.cursor.is_none(), + "cursor should be None when absent from TOML" + ); + assert!( + cs.selection.is_none(), + "selection should be None when absent from TOML" + ); + assert!( + cs.primary.dim_foreground.is_none(), + "dim_foreground should be None when absent" + ); + assert!( + cs.primary.bright_foreground.is_none(), + "bright_foreground should be None when absent" + ); + } + + #[test] + fn deserialize_with_dim_colors() { + let toml_str = r##" +[colors.primary] +background = "#000000" +foreground = "#ffffff" +dim_foreground = "#aaaaaa" + +[colors.normal] +black = "#000" +red = "#f00" +green = "#0f0" +yellow = "#ff0" +blue = "#00f" +magenta = "#f0f" +cyan = "#0ff" +white = "#fff" + +[colors.bright] +black = "#888" +red = "#f00" +green = "#0f0" +yellow = "#ff0" +blue = "#00f" +magenta = "#f0f" +cyan = "#0ff" +white = "#fff" + +[colors.dim] +black = "#111" +red = "#a00" +green = "#0a0" +yellow = "#aa0" +blue = "#00a" +magenta = "#a0a" +cyan = "#0aa" +white = "#aaa" +"##; + let theme: AlacrittyThemeFile = toml::from_str(toml_str).expect("valid TOML"); + let cs = theme.colors; + assert!(cs.dim.is_some(), "dim should be present"); + let dim = cs.dim.unwrap(); + assert_eq!(dim.black, "#111"); + assert_eq!(dim.white, "#aaa"); + assert_eq!(cs.primary.dim_foreground.as_deref(), Some("#aaaaaa")); + } +} diff --git a/crates/conch_core/src/config/font.rs b/crates/conch_core/src/config/font.rs index 7f91633..7f08842 100644 --- a/crates/conch_core/src/config/font.rs +++ b/crates/conch_core/src/config/font.rs @@ -46,3 +46,61 @@ impl Default for FontConfig { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn font_family_default() { + let ff = FontFamily::default(); + assert_eq!(ff.family, "JetBrains Mono"); + } + + #[test] + fn font_offset_default() { + let fo = FontOffset::default(); + assert_eq!(fo.x, 0.0); + assert_eq!(fo.y, 0.0); + } + + #[test] + fn font_config_default() { + let fc = FontConfig::default(); + assert_eq!(fc.normal.family, "JetBrains Mono"); + assert_eq!(fc.size, 14.0); + assert_eq!(fc.offset.x, 0.0); + assert_eq!(fc.offset.y, 0.0); + } + + #[test] + fn font_config_serde_round_trip() { + let original = FontConfig { + normal: FontFamily { + family: "Fira Code".into(), + }, + size: 16.5, + offset: FontOffset { x: 1.0, y: -0.5 }, + }; + let toml_str = toml::to_string(&original).expect("serialize"); + let restored: FontConfig = toml::from_str(&toml_str).expect("deserialize"); + assert_eq!(original, restored); + } + + #[test] + fn font_config_deserialize_partial_toml() { + // Only set size; normal and offset should use defaults + let toml_str = "size = 18.0\n"; + let fc: FontConfig = toml::from_str(toml_str).expect("deserialize partial"); + assert_eq!(fc.size, 18.0); + assert_eq!(fc.normal.family, "JetBrains Mono", "default family"); + assert_eq!(fc.offset.x, 0.0, "default offset x"); + assert_eq!(fc.offset.y, 0.0, "default offset y"); + } + + #[test] + fn font_config_deserialize_empty_toml() { + let fc: FontConfig = toml::from_str("").expect("deserialize empty"); + assert_eq!(fc, FontConfig::default()); + } +} diff --git a/crates/conch_core/src/config/persistent.rs b/crates/conch_core/src/config/persistent.rs index b6d2e66..d0209a8 100644 --- a/crates/conch_core/src/config/persistent.rs +++ b/crates/conch_core/src/config/persistent.rs @@ -60,3 +60,102 @@ impl Default for LayoutConfig { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn persistent_state_default() { + let ps = PersistentState::default(); + assert!( + ps.loaded_plugins.is_empty(), + "loaded_plugins should be empty by default" + ); + assert_eq!(ps.layout.zoom_factor, 1.0); + } + + #[test] + fn layout_config_default_panels_visible() { + let lc = LayoutConfig::default(); + assert!(lc.left_panel_visible); + assert!(lc.right_panel_visible); + assert!(lc.bottom_panel_visible); + assert!(lc.status_bar_visible); + } + + #[test] + fn layout_config_default_dimensions() { + let lc = LayoutConfig::default(); + assert_eq!(lc.window_width, 0.0); + assert_eq!(lc.window_height, 0.0); + assert_eq!(lc.left_panel_width, 0.0); + assert_eq!(lc.right_panel_width, 0.0); + assert_eq!(lc.bottom_panel_height, 0.0); + } + + #[test] + fn persistent_state_serde_round_trip() { + let original = PersistentState { + layout: LayoutConfig { + window_width: 1280.0, + window_height: 720.0, + zoom_factor: 1.25, + left_panel_width: 250.0, + right_panel_width: 300.0, + bottom_panel_height: 200.0, + left_panel_visible: true, + right_panel_visible: false, + bottom_panel_visible: true, + status_bar_visible: false, + }, + loaded_plugins: vec!["ssh-manager".into(), "git-status".into()], + }; + let toml_str = toml::to_string(&original).expect("serialize"); + let restored: PersistentState = toml::from_str(&toml_str).expect("deserialize"); + + assert_eq!(restored.layout.window_width, 1280.0); + assert_eq!(restored.layout.window_height, 720.0); + assert_eq!(restored.layout.zoom_factor, 1.25); + assert_eq!(restored.layout.left_panel_width, 250.0); + assert!(!restored.layout.right_panel_visible); + assert!(!restored.layout.status_bar_visible); + assert_eq!(restored.loaded_plugins.len(), 2); + assert_eq!(restored.loaded_plugins[0], "ssh-manager"); + assert_eq!(restored.loaded_plugins[1], "git-status"); + } + + #[test] + fn persistent_state_deserialize_empty_toml() { + let ps: PersistentState = toml::from_str("").expect("deserialize empty"); + assert!(ps.loaded_plugins.is_empty()); + assert_eq!(ps.layout.zoom_factor, 1.0); + assert!(ps.layout.left_panel_visible); + assert!(ps.layout.status_bar_visible); + } + + #[test] + fn persistent_state_deserialize_partial_toml() { + let toml_str = r#" +loaded_plugins = ["my-plugin"] + +[layout] +zoom_factor = 1.5 +left_panel_visible = false +"#; + let ps: PersistentState = toml::from_str(toml_str).expect("deserialize partial"); + assert_eq!(ps.loaded_plugins.len(), 1); + assert_eq!(ps.loaded_plugins[0], "my-plugin"); + assert_eq!(ps.layout.zoom_factor, 1.5); + assert!(!ps.layout.left_panel_visible); + // Unset fields should get defaults + assert_eq!(ps.layout.window_width, 0.0, "default window_width"); + assert_eq!(ps.layout.window_height, 0.0, "default window_height"); + assert!(ps.layout.right_panel_visible, "default right_panel_visible"); + assert!( + ps.layout.bottom_panel_visible, + "default bottom_panel_visible" + ); + assert!(ps.layout.status_bar_visible, "default status_bar_visible"); + } +}