mirror of https://github.com/helix-editor/helix
add integration test for persistent state
parent
554f0f891d
commit
c3ed498dc9
@ -0,0 +1,142 @@
|
||||
use super::*;
|
||||
use helix_term::{config::Config, keymap};
|
||||
use helix_view::editor;
|
||||
use std::{fs::File, io::Read};
|
||||
use tempfile::{NamedTempFile, TempPath};
|
||||
|
||||
fn init_persistence_files() -> anyhow::Result<(TempPath, TempPath, TempPath, TempPath)> {
|
||||
let command_file = NamedTempFile::new()?;
|
||||
let command_path = command_file.into_temp_path();
|
||||
helix_loader::initialize_command_histfile(Some(command_path.to_path_buf()));
|
||||
|
||||
let search_file = NamedTempFile::new()?;
|
||||
let search_path = search_file.into_temp_path();
|
||||
helix_loader::initialize_search_histfile(Some(search_path.to_path_buf()));
|
||||
|
||||
let file_file = NamedTempFile::new()?;
|
||||
let file_path = file_file.into_temp_path();
|
||||
helix_loader::initialize_file_histfile(Some(file_path.to_path_buf()));
|
||||
|
||||
let clipboard_file = NamedTempFile::new()?;
|
||||
let clipboard_path = clipboard_file.into_temp_path();
|
||||
helix_loader::initialize_clipboard_file(Some(clipboard_path.to_path_buf()));
|
||||
|
||||
Ok((command_path, search_path, file_path, clipboard_path))
|
||||
}
|
||||
|
||||
fn config_with_persistence() -> Config {
|
||||
let mut editor_config = editor::Config::default();
|
||||
editor_config.persistence.old_files = true;
|
||||
editor_config.persistence.commands = true;
|
||||
editor_config.persistence.search = true;
|
||||
editor_config.persistence.clipboard = true;
|
||||
editor_config.persistence.search_trim = 3;
|
||||
|
||||
Config {
|
||||
theme: None,
|
||||
keys: keymap::default(),
|
||||
editor: editor_config,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_persistence() -> anyhow::Result<()> {
|
||||
let (_, search_histfile_path, _, _) = init_persistence_files()?;
|
||||
let mut file = tempfile::NamedTempFile::new()?;
|
||||
|
||||
// Session 1:
|
||||
// open a new file,
|
||||
// add a newline, then a,
|
||||
// write-quit
|
||||
test_key_sequence(
|
||||
&mut helpers::AppBuilder::new()
|
||||
.with_config(config_with_persistence())
|
||||
.with_file(file.path(), None)
|
||||
.build()?,
|
||||
// TODO: remove the h with a bugfix?
|
||||
Some("oa<esc>h:wq<ret>"),
|
||||
// Some(&|app| {
|
||||
// assert!(!app.editor.is_err(), "error: {:?}", app.editor.get_status());
|
||||
// }),
|
||||
None,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Sanity check contents of file after first session
|
||||
helpers::assert_file_has_content(&mut file, "\na\n")?;
|
||||
|
||||
// Session 2:
|
||||
// open same file,
|
||||
// add newline, then b,
|
||||
// copy the line
|
||||
// search for "a"
|
||||
// go back down to b
|
||||
// use last command
|
||||
test_key_sequence(
|
||||
&mut helpers::AppBuilder::new()
|
||||
.with_config(config_with_persistence())
|
||||
.with_file(file.path(), None)
|
||||
.build()?,
|
||||
Some("ob<esc>xy/a<ret>j:<up><ret>"),
|
||||
None,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// This verifies both that the file position was persisted (since the b is inserted after the
|
||||
// a), and the command history (":<up>" resolves to the ":wq" from session 1)
|
||||
helpers::assert_file_has_content(&mut file, "\na\nb\n")?;
|
||||
|
||||
// Session 3:
|
||||
// open same file,
|
||||
// paste
|
||||
// use last search
|
||||
// append a
|
||||
// search for "1", "2", and "3" in sequence.
|
||||
// use last command
|
||||
test_key_sequence(
|
||||
&mut helpers::AppBuilder::new()
|
||||
.with_config(config_with_persistence())
|
||||
.with_file(file.path(), None)
|
||||
.build()?,
|
||||
Some("p/<up><ret>aa<esc>/1<ret>/2<ret>/3<ret>:<up><ret>"),
|
||||
None,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// This verifies search history was persisted ("/<up>" resolves to "/a" from session 2), and
|
||||
// the clipboard was persisted (paste pastes the "b\n" copied in session 2)
|
||||
helpers::assert_file_has_content(&mut file, "\naa\nb\nb\n")?;
|
||||
|
||||
// Session 4:
|
||||
// open same file
|
||||
// use last command
|
||||
test_key_sequence(
|
||||
&mut helpers::AppBuilder::new()
|
||||
.with_config(config_with_persistence())
|
||||
.with_file(file.path(), None)
|
||||
.build()?,
|
||||
Some(":<up><ret>"),
|
||||
None,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// NOTE: This time we check the search history file, instead of the edited file
|
||||
let mut search_histfile = File::open(search_histfile_path)?;
|
||||
let mut search_histfile_contents = String::new();
|
||||
search_histfile.read_to_string(&mut search_histfile_contents)?;
|
||||
// This verifies that trimming the persistent state files is working correctly, because
|
||||
// session 3 sent more searches (4: "/a", "/1", "/2", "/3") than the trim limit (3), so when
|
||||
// session 4 starts, it should perform a trim, removing the oldest entry ("/a") while leaving
|
||||
// the other 3 intact.
|
||||
// The weird looking format of the string is because persistence data is encoded using bincode.
|
||||
assert_eq!(
|
||||
search_histfile_contents,
|
||||
"\u{1}\0\0\0\0\0\0\01\u{1}\0\0\0\0\0\0\02\u{1}\0\0\0\0\0\0\03"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue