use crate::common::harness::{layout, EditorTestHarness, HarnessOptions};
use crossterm::event::{KeyCode, KeyModifiers};
use fresh::config::Config;
use fresh::config_io::DirectoryContext;
use tempfile::TempDir;
#[test]
fn test_tab_bar_visible_by_default() {
let mut harness = EditorTestHarness::new(80, 24).unwrap();
harness.render().unwrap();
let tab_bar_row = harness.get_tab_bar();
assert!(
tab_bar_row.contains("[No Name]") || tab_bar_row.contains("untitled"),
"Tab bar should show buffer name at row {}. Got: {}",
layout::TAB_BAR_ROW,
tab_bar_row
);
}
#[test]
fn test_menu_bar_visible_by_default() {
let mut harness = EditorTestHarness::new(80, 24).unwrap();
harness.render().unwrap();
let menu_bar_row = harness.get_menu_bar();
assert!(
menu_bar_row.contains("File") && menu_bar_row.contains("Edit"),
"Menu bar should show File and Edit menus at row {}. Got: {}",
layout::MENU_BAR_ROW,
menu_bar_row
);
}
#[test]
fn test_toggle_tab_bar_via_command_palette() {
let mut harness = EditorTestHarness::new(120, 24).unwrap();
harness.render().unwrap();
harness.assert_screen_contains("[No Name]");
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains(">command");
harness.type_text("Toggle Tab Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Tab bar hidden");
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Tab Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Tab bar shown");
}
#[test]
fn test_toggle_menu_bar_via_command_palette() {
let mut harness = EditorTestHarness::new(120, 24).unwrap();
harness.render().unwrap();
let menu_bar = harness.get_menu_bar();
assert!(
menu_bar.contains("File"),
"Menu bar should be visible initially"
);
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Menu Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Menu bar hidden");
let menu_bar = harness.get_screen_row(layout::MENU_BAR_ROW);
assert!(
!menu_bar.contains("File"),
"Menu bar should be hidden after toggle"
);
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Menu Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Menu bar shown");
}
#[test]
fn test_config_show_tab_bar_false() {
let mut config = Config::default();
config.editor.show_tab_bar = false;
let mut harness = EditorTestHarness::with_config(80, 24, config).unwrap();
harness.render().unwrap();
let menu_bar = harness.get_menu_bar();
assert!(
menu_bar.contains("File"),
"Menu bar should still be visible"
);
assert!(!harness.editor().active_window().tab_bar_visible);
}
#[test]
fn test_config_show_menu_bar_false() {
let mut config = Config::default();
config.editor.show_menu_bar = false;
let mut harness = EditorTestHarness::with_config(80, 24, config).unwrap();
harness.render().unwrap();
let row0 = harness.get_screen_row(0);
assert!(
!row0.contains("File"),
"Menu bar should be hidden when show_menu_bar is false. Got: {}",
row0
);
}
#[test]
fn test_both_bars_hidden() {
let mut config = Config::default();
config.editor.show_menu_bar = false;
config.editor.show_tab_bar = false;
let mut harness = EditorTestHarness::with_config(80, 24, config).unwrap();
harness.render().unwrap();
let row0 = harness.get_screen_row(0);
assert!(!row0.contains("File"), "Menu bar should be hidden");
assert!(!harness.editor().active_window().tab_bar_visible);
}
#[test]
fn test_tab_bar_toggle_with_multiple_buffers() {
let mut harness = EditorTestHarness::with_temp_project(120, 24).unwrap();
let project_dir = harness.project_dir().unwrap().to_path_buf();
std::fs::write(project_dir.join("file1.txt"), "content 1").unwrap();
std::fs::write(project_dir.join("file2.txt"), "content 2").unwrap();
harness
.send_key(KeyCode::Char('o'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("file1.txt").unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Char('o'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("file2.txt").unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("file1.txt");
harness.assert_screen_contains("file2.txt");
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Tab Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Tab bar hidden");
assert!(!harness.editor().active_window().tab_bar_visible);
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Tab Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Tab bar shown");
assert!(harness.editor().active_window().tab_bar_visible);
}
#[test]
fn test_status_bar_visible_by_default() {
let mut harness = EditorTestHarness::new(80, 24).unwrap();
harness.render().unwrap();
let status_bar = harness.get_status_bar();
assert!(
status_bar.contains("Ln") && status_bar.contains("Col"),
"Status bar should show cursor position. Got: {}",
status_bar
);
}
#[test]
fn test_toggle_status_bar_via_command_palette() {
let mut harness = EditorTestHarness::new(120, 24).unwrap();
harness.render().unwrap();
let status_bar = harness.get_status_bar();
assert!(
status_bar.contains("Ln"),
"Status bar should be visible initially. Got: {}",
status_bar
);
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Status Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
let status_bar = harness.get_status_bar();
assert!(
!status_bar.contains("Ln"),
"Status bar should be hidden after toggle. Got: {}",
status_bar
);
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Status Bar").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Status bar shown");
}
#[test]
fn test_config_show_status_bar_false() {
let mut config = Config::default();
config.editor.show_status_bar = false;
let mut harness = EditorTestHarness::with_config(80, 24, config).unwrap();
harness.render().unwrap();
let status_bar_row = harness.get_screen_row(layout::status_bar_row(24));
assert!(
!status_bar_row.contains("Ln"),
"Status bar should be hidden when show_status_bar is false. Got: {}",
status_bar_row
);
}
#[test]
fn test_all_bars_hidden() {
let mut config = Config::default();
config.editor.show_menu_bar = false;
config.editor.show_tab_bar = false;
config.editor.show_status_bar = false;
let mut harness = EditorTestHarness::with_config(80, 24, config).unwrap();
harness.render().unwrap();
let row0 = harness.get_screen_row(0);
assert!(!row0.contains("File"), "Menu bar should be hidden");
let status_bar_row = harness.get_screen_row(layout::status_bar_row(24));
assert!(
!status_bar_row.contains("Ln"),
"Status bar should be hidden. Got: {}",
status_bar_row
);
}
#[test]
fn test_prompt_line_visible_by_default() {
let harness = EditorTestHarness::new(80, 24).unwrap();
assert!(
harness.editor().active_window().prompt_line_visible,
"Prompt line should be visible by default"
);
}
#[test]
fn test_toggle_prompt_line_off_hides_it() {
let mut harness = EditorTestHarness::new(80, 24).unwrap();
assert!(harness.editor().active_window().prompt_line_visible);
harness
.editor_mut()
.active_window_mut()
.toggle_prompt_line();
assert!(
!harness.editor().active_window().prompt_line_visible,
"Prompt line should be hidden after toggling it off"
);
}
#[test]
fn test_settings_show_prompt_line_applies_immediately() {
let mut harness = EditorTestHarness::new(100, 40).unwrap();
harness.render().unwrap();
assert!(harness.editor().active_window().prompt_line_visible);
harness.open_settings().unwrap();
harness
.send_key(KeyCode::Char('/'), KeyModifiers::NONE)
.unwrap();
harness.type_text("show_prompt").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Char('s'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
assert!(
!harness.editor().is_settings_open(),
"Settings should be closed after Ctrl+S"
);
assert!(
!harness.editor().active_window().prompt_line_visible,
"Prompt line should be hidden after toggling show_prompt_line off via Settings UI"
);
}
#[test]
fn test_toggle_prompt_line_via_command_palette() {
let mut harness = EditorTestHarness::new(120, 24).unwrap();
harness.render().unwrap();
assert!(harness.editor().active_window().prompt_line_visible);
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Prompt Line").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Prompt line hidden");
assert!(!harness.editor().active_window().prompt_line_visible);
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.render().unwrap();
harness.type_text("Toggle Prompt Line").unwrap();
harness.render().unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Prompt line shown");
assert!(harness.editor().active_window().prompt_line_visible);
}
#[test]
fn test_toggle_menu_bar_persists_to_global_config() {
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("project");
std::fs::create_dir(&project_dir).unwrap();
let dir_context = DirectoryContext::for_testing(temp_dir.path());
{
let mut harness = EditorTestHarness::create(
80,
24,
HarnessOptions::new()
.with_config(Config::default())
.with_working_dir(project_dir.clone())
.with_shared_dir_context(dir_context.clone())
.without_empty_plugins_dir(),
)
.unwrap();
harness.render().unwrap();
assert!(harness.editor().config().editor.show_menu_bar);
harness.editor_mut().toggle_menu_bar();
assert!(
!harness.editor().config().editor.show_menu_bar,
"toggle_menu_bar should update show_menu_bar in the global config"
);
}
let other_project = temp_dir.path().join("other_project");
std::fs::create_dir(&other_project).unwrap();
let loaded = Config::load_with_layers(&dir_context, &other_project);
assert!(
!loaded.editor.show_menu_bar,
"Toggle should persist to user config so unrelated workspaces inherit it"
);
}
#[test]
fn test_workspace_override_does_not_shadow_global_show_menu_bar() {
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("project");
std::fs::create_dir(&project_dir).unwrap();
let dir_context = DirectoryContext::for_testing(temp_dir.path());
{
let mut harness = EditorTestHarness::create(
80,
24,
HarnessOptions::new()
.with_config(Config::default())
.with_working_dir(project_dir.clone())
.with_shared_dir_context(dir_context.clone())
.without_empty_plugins_dir(),
)
.unwrap();
harness.render().unwrap();
harness.editor_mut().toggle_menu_bar();
harness.shutdown(true).unwrap();
}
let mut harness = EditorTestHarness::create(
80,
24,
HarnessOptions::new()
.with_config({
let mut c = Config::default();
c.editor.show_menu_bar = true;
c
})
.with_working_dir(project_dir.clone())
.with_shared_dir_context(dir_context.clone())
.without_empty_plugins_dir(),
)
.unwrap();
harness.editor_mut().try_restore_workspace().unwrap();
harness.render().unwrap();
let menu_bar_row = harness.get_screen_row(0);
assert!(
menu_bar_row.contains("File"),
"Global show_menu_bar=true must take precedence over a stale \
workspace override. Got row 0: {:?}",
menu_bar_row
);
}