Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions crates/conch_core/src/color_scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
}
}
58 changes: 58 additions & 0 deletions crates/conch_core/src/config/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
99 changes: 99 additions & 0 deletions crates/conch_core/src/config/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
Loading