use crate::common::harness::EditorTestHarness;
use crossterm::event::{KeyCode, KeyModifiers};
use std::fs;
use std::path::MAIN_SEPARATOR;
fn run_command_palette(harness: &mut EditorTestHarness, query: &str) {
harness
.send_key(KeyCode::Char('p'), KeyModifiers::CONTROL)
.unwrap();
harness.type_text(query).unwrap();
harness.send_key(KeyCode::Tab, KeyModifiers::NONE).unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness.render().unwrap();
}
fn wide_temp_project_harness() -> EditorTestHarness {
EditorTestHarness::with_temp_project_and_config(220, 30, Default::default()).unwrap()
}
#[test]
fn copy_relative_file_path_via_command_palette() {
let mut harness = wide_temp_project_harness();
let project_root = harness.project_dir().unwrap();
let file_path = project_root.join("hello.txt");
fs::write(&file_path, "hi\n").unwrap();
harness.open_file(&file_path).unwrap();
harness.render().unwrap();
run_command_palette(&mut harness, "Copy Relative File Path");
harness.assert_screen_contains("Copied path: hello.txt");
}
#[test]
fn copy_file_path_via_command_palette_uses_absolute_path() {
let mut harness = wide_temp_project_harness();
let project_root = harness.project_dir().unwrap();
let file_path = project_root.join("absolute.txt");
fs::write(&file_path, "x\n").unwrap();
harness.open_file(&file_path).unwrap();
harness.render().unwrap();
run_command_palette(&mut harness, "Copy File Path");
let screen = harness.screen_to_string();
let expected_segment = format!("project_root{}absolute.txt", MAIN_SEPARATOR);
assert!(
screen.contains("Copied path:") && screen.contains(&expected_segment),
"expected status bar to render the absolute path containing {expected_segment:?}, \
got screen:\n{screen}"
);
}
#[test]
fn copy_relative_file_path_falls_back_to_absolute_outside_workspace() {
let outside = tempfile::tempdir().unwrap();
let outside_dir = outside.path().join("outside_marker");
fs::create_dir(&outside_dir).unwrap();
let outside_file = outside_dir.join("outside.txt");
fs::write(&outside_file, "out\n").unwrap();
let mut harness = wide_temp_project_harness();
harness.open_file(&outside_file).unwrap();
harness.render().unwrap();
run_command_palette(&mut harness, "Copy Relative File Path");
let screen = harness.screen_to_string();
let expected_segment = format!("outside_marker{}outside.txt", MAIN_SEPARATOR);
assert!(
screen.contains("Copied path:") && screen.contains(&expected_segment),
"expected status bar to render the absolute fallback path containing \
{expected_segment:?}, got screen:\n{screen}"
);
}
#[test]
fn copy_file_path_on_unsaved_buffer_reports_no_path() {
let mut harness = EditorTestHarness::new(120, 24).unwrap();
harness.render().unwrap();
run_command_palette(&mut harness, "Copy File Path");
harness.assert_screen_contains("Buffer has no file path");
}
fn active_tab_position(harness: &EditorTestHarness) -> (u16, u16) {
let active = harness.editor().active_buffer();
for (_split_id, tab_layout) in harness.editor().get_tab_layouts() {
for tab in &tab_layout.tabs {
if tab.buffer_id() == Some(active) {
let center_col = tab.tab_area.x + tab.tab_area.width / 2;
return (center_col, tab.tab_area.y);
}
}
}
panic!("active tab not found in tab layouts");
}
#[test]
fn tab_right_click_menu_lists_copy_path_entries() {
let mut harness = wide_temp_project_harness();
let project_root = harness.project_dir().unwrap();
let file_path = project_root.join("ctx.txt");
fs::write(&file_path, "x\n").unwrap();
harness.open_file(&file_path).unwrap();
harness.render().unwrap();
let (col, row) = active_tab_position(&harness);
harness.mouse_right_click(col, row).unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Copy Relative Path");
harness.assert_screen_contains("Copy Full Path");
harness.assert_screen_contains("Close");
}
#[test]
fn tab_right_click_copy_relative_path_copies_to_clipboard() {
let mut harness = wide_temp_project_harness();
let project_root = harness.project_dir().unwrap();
let file_path = project_root.join("rel.txt");
fs::write(&file_path, "x\n").unwrap();
harness.open_file(&file_path).unwrap();
harness.render().unwrap();
let (col, row) = active_tab_position(&harness);
harness.mouse_right_click(col, row).unwrap();
harness.render().unwrap();
let (item_col, item_row) = harness
.find_text_on_screen("Copy Relative Path")
.expect("'Copy Relative Path' should be visible after tab right-click");
harness.mouse_click(item_col, item_row).unwrap();
harness.render().unwrap();
harness.assert_screen_contains("Copied path: rel.txt");
}
#[test]
fn tab_right_click_copy_full_path_copies_absolute() {
let mut harness = wide_temp_project_harness();
let project_root = harness.project_dir().unwrap();
let file_path = project_root.join("full.txt");
fs::write(&file_path, "x\n").unwrap();
harness.open_file(&file_path).unwrap();
harness.render().unwrap();
let (col, row) = active_tab_position(&harness);
harness.mouse_right_click(col, row).unwrap();
harness.render().unwrap();
let (item_col, item_row) = harness
.find_text_on_screen("Copy Full Path")
.expect("'Copy Full Path' should be visible after tab right-click");
harness.mouse_click(item_col, item_row).unwrap();
harness.render().unwrap();
let screen = harness.screen_to_string();
let expected_segment = format!("project_root{}full.txt", MAIN_SEPARATOR);
assert!(
screen.contains("Copied path:") && screen.contains(&expected_segment),
"expected status bar to render the absolute path containing {expected_segment:?}, \
got screen:\n{screen}"
);
}