use fresh::config::Config;
use fresh::config_io::DirectoryContext;
use fresh::server::editor_server::{EditorServer, EditorServerConfig};
use tempfile::TempDir;
fn unique_session_name(prefix: &str) -> String {
format!(
"{}-{}-{}",
prefix,
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
)
}
fn make_server_config(
session_name: &str,
working_dir: std::path::PathBuf,
dir_context: DirectoryContext,
) -> EditorServerConfig {
let mut config = Config::default();
config.editor.hot_exit = true;
EditorServerConfig {
working_dir,
session_name: Some(session_name.to_string()),
idle_timeout: None,
editor_config: config,
dir_context,
plugins_enabled: false,
init_enabled: false,
startup_authority: None,
session_keepalive: None,
}
}
#[test]
fn test_editor_server_initialize_restores_workspace() {
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("project");
std::fs::create_dir(&project_dir).unwrap();
let file1 = project_dir.join("hello.txt");
std::fs::write(&file1, "original content").unwrap();
let dir_context = DirectoryContext::for_testing(temp_dir.path());
let session_name = unique_session_name("restore-ws");
{
let config = make_server_config(&session_name, project_dir.clone(), dir_context.clone());
let mut server = EditorServer::new(config).unwrap();
server.initialize_editor().unwrap();
let editor = server.editor_mut().unwrap();
editor.queue_file_open(file1.clone(), None, None, None, None, None, None);
editor.process_pending_file_opens();
let content = editor.active_state().buffer.to_string().unwrap_or_default();
assert!(
content.contains("original content"),
"Session 1 failed to open file"
);
editor.end_recovery_session().unwrap();
editor.save_workspace().unwrap();
}
{
let config = make_server_config(&session_name, project_dir.clone(), dir_context.clone());
let mut server = EditorServer::new(config).unwrap();
server.initialize_editor().unwrap();
let editor = server.editor().unwrap();
let content = editor.active_state().buffer.to_string().unwrap_or_default();
assert!(
content.contains("original content"),
"Session 2: initialize_editor should have restored hello.txt, got: {:?}",
content
);
}
}
#[test]
fn test_editor_server_initialize_restores_unnamed_buffers() {
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 session_name = unique_session_name("restore-unnamed");
{
let config = make_server_config(&session_name, project_dir.clone(), dir_context.clone());
let mut server = EditorServer::new(config).unwrap();
server.initialize_editor().unwrap();
let editor = server.editor_mut().unwrap();
editor
.handle_key(
crossterm::event::KeyCode::Char('s'),
crossterm::event::KeyModifiers::NONE,
)
.unwrap();
editor
.handle_key(
crossterm::event::KeyCode::Char('c'),
crossterm::event::KeyModifiers::NONE,
)
.unwrap();
editor
.handle_key(
crossterm::event::KeyCode::Char('r'),
crossterm::event::KeyModifiers::NONE,
)
.unwrap();
let content = editor.active_state().buffer.to_string().unwrap_or_default();
assert!(content.contains("scr"), "Session 1 should have typed text");
editor.end_recovery_session().unwrap();
editor.save_workspace().unwrap();
}
{
let config = make_server_config(&session_name, project_dir.clone(), dir_context.clone());
let mut server = EditorServer::new(config).unwrap();
server.initialize_editor().unwrap();
let editor = server.editor().unwrap();
let content = editor.active_state().buffer.to_string().unwrap_or_default();
assert!(
content.contains("scr"),
"Session 2: should have restored unnamed buffer content, got: {:?}",
content
);
}
}
#[test]
fn test_editor_server_opens_files_after_initialize() {
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("project");
std::fs::create_dir(&project_dir).unwrap();
let file1 = project_dir.join("first.txt");
let file2 = project_dir.join("second.txt");
std::fs::write(&file1, "content of first").unwrap();
std::fs::write(&file2, "content of second").unwrap();
let dir_context = DirectoryContext::for_testing(temp_dir.path());
let session_name = unique_session_name("openfiles");
let config = make_server_config(&session_name, project_dir.clone(), dir_context);
let mut server = EditorServer::new(config).unwrap();
server.initialize_editor().unwrap();
let editor = server.editor_mut().unwrap();
editor.queue_file_open(file1.clone(), None, None, None, None, None, None);
editor.queue_file_open(file2.clone(), None, None, None, None, None, None);
editor.process_pending_file_opens();
let content = editor.active_state().buffer.to_string().unwrap_or_default();
assert!(
content.contains("content of second"),
"Active buffer should be second.txt, got: {:?}",
content
);
}
#[test]
fn test_editor_server_opens_files_on_top_of_restored_workspace() {
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("project");
std::fs::create_dir(&project_dir).unwrap();
let file1 = project_dir.join("existing.txt");
let file2 = project_dir.join("new_file.txt");
std::fs::write(&file1, "existing content").unwrap();
std::fs::write(&file2, "new file content").unwrap();
let dir_context = DirectoryContext::for_testing(temp_dir.path());
let session_name = unique_session_name("restore-plus-open");
{
let config = make_server_config(&session_name, project_dir.clone(), dir_context.clone());
let mut server = EditorServer::new(config).unwrap();
server.initialize_editor().unwrap();
let editor = server.editor_mut().unwrap();
editor.queue_file_open(file1.clone(), None, None, None, None, None, None);
editor.process_pending_file_opens();
editor.end_recovery_session().unwrap();
editor.save_workspace().unwrap();
}
{
let config = make_server_config(&session_name, project_dir.clone(), dir_context.clone());
let mut server = EditorServer::new(config).unwrap();
server.initialize_editor().unwrap();
let editor = server.editor_mut().unwrap();
let content = editor.active_state().buffer.to_string().unwrap_or_default();
assert!(
content.contains("existing content"),
"Workspace should have restored existing.txt, got: {:?}",
content
);
editor.queue_file_open(file2.clone(), None, None, None, None, None, None);
editor.process_pending_file_opens();
let content = editor.active_state().buffer.to_string().unwrap_or_default();
assert!(
content.contains("new file content"),
"Active buffer should be new_file.txt, got: {:?}",
content
);
}
}