486 lines
16 KiB
Rust
486 lines
16 KiB
Rust
use ::insta::assert_snapshot;
|
|
use ::std::collections::HashMap;
|
|
|
|
use crate::panes::PositionAndSize;
|
|
use crate::tests::fakes::FakeInputOutput;
|
|
use crate::tests::possible_tty_inputs::Bytes;
|
|
use crate::tests::utils::get_output_frame_snapshots;
|
|
use crate::{start, Opt};
|
|
|
|
use crate::tests::utils::commands::{COMMAND_TOGGLE, QUIT};
|
|
|
|
/*
|
|
* These tests are general compatibility tests for non-trivial scenarios running in the terminal.
|
|
* They use fake TTY input replicated from these scenarios (and so don't actually interact with the
|
|
* OS).
|
|
*
|
|
* They work like this:
|
|
* - receive fake TTY input containing various VTE instructions.
|
|
* - run that output through mosaic so it interprets it and creates its state based on it
|
|
* - read that state into a Human-readable snapshot and compare it to the expected snapshot for
|
|
* this scenario.
|
|
*
|
|
*/
|
|
|
|
fn get_fake_os_input(fake_win_size: &PositionAndSize, fixture_name: &str) -> FakeInputOutput {
|
|
let mut tty_inputs = HashMap::new();
|
|
let fixture_bytes = Bytes::from_file_in_fixtures(&fixture_name);
|
|
tty_inputs.insert(fake_win_size.columns as u16, fixture_bytes);
|
|
FakeInputOutput::new(fake_win_size.clone()).with_tty_inputs(tty_inputs)
|
|
}
|
|
|
|
#[test]
|
|
pub fn run_bandwhich_from_fish_shell() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "fish_and_bandwhich";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn fish_tab_completion_options() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "fish_tab_completion_options";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn fish_select_tab_completion_options() {
|
|
// the difference between this and the previous test is that here we press <TAB>
|
|
// twice, meaning the selection moves between the options and the command line
|
|
// changes.
|
|
// this is not clearly seen in the snapshot because it does not include styles,
|
|
// but we can see the command line change and the cursor staying in place
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "fish_select_tab_completion_options";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn vim_scroll_region_down() {
|
|
// here we test a case where vim defines the scroll region as lesser than the screen row count
|
|
// and then scrolls down
|
|
// the region is defined here by vim as 1-26 (there are 28 rows)
|
|
// then the cursor is moved to line 26 and a new line is added
|
|
// what should happen is that the first line in the scroll region (1) is deleted
|
|
// and an empty line is inserted in the last scroll region line (26)
|
|
// this tests also has other steps afterwards that fills the line with the next line in the
|
|
// file
|
|
// experience appear to the user
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "vim_scroll_region_down";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]); // quit (ctrl-q)
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn vim_ctrl_d() {
|
|
// in vim ctrl-d moves down half a page
|
|
// in this case, it sends the terminal the csi 'M' directive, which tells it to delete X (13 in
|
|
// this case) lines inside the scroll region and push the other lines up
|
|
// what happens here is that 13 lines are deleted and instead 13 empty lines are added at the
|
|
// end of the scroll region
|
|
// vim makes sure to fill these empty lines with the rest of the file
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "vim_ctrl_d";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn vim_ctrl_u() {
|
|
// in vim ctrl-u moves up half a page
|
|
// in this case, it sends the terminal the csi 'L' directive, which tells it to insert X (13 in
|
|
// this case) lines at the cursor, pushing away (deleting) the last line in the scroll region
|
|
// this causes the effect of scrolling up X lines (vim replaces the lines with the ones in the
|
|
// file above the current content)
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "vim_ctrl_u";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn htop() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "htop";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn htop_scrolling() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "htop_scrolling";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn htop_right_scrolling() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "htop_right_scrolling";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn vim_overwrite() {
|
|
// this tests the vim overwrite message
|
|
// to recreate:
|
|
// * open a file in vim
|
|
// * open the same file in another window
|
|
// * change the file in the other window and save
|
|
// * change the file in the original vim window and save
|
|
// * confirm you would like to change the file by pressing 'y' and then ENTER
|
|
// * if everything looks fine, this test passed :)
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "vim_overwrite";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn clear_scroll_region() {
|
|
// this tests the scroll region used by eg. vim is cleared properly
|
|
// this means that when vim exits, we get back the previous scroll
|
|
// buffer
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "clear_scroll_region";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn display_tab_characters_properly() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "tab_characters";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn neovim_insert_mode() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "nvim_insert";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn bash_cursor_linewrap() {
|
|
// this test makes sure that when we enter a command that is beyond the screen border, that it
|
|
// immediately goes down one line
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 116,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "bash_cursor_linewrap";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn fish_paste_multiline() {
|
|
// here we paste a multiline command in fish shell, making sure we support it
|
|
// going up and changing the colors of our line-wrapped pasted text
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 149,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "fish_paste_multiline";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn git_log() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 149,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "git_log";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn git_diff_scrollup() {
|
|
// this tests makes sure that when we have a git diff that exceeds the screen size
|
|
// we are able to scroll up
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 149,
|
|
rows: 28,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "git_diff_scrollup";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
pub fn emacs_longbuf() {
|
|
let fake_win_size = PositionAndSize {
|
|
columns: 284,
|
|
rows: 60,
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let fixture_name = "emacs_longbuf_tutorial";
|
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
|
fake_input_output.add_terminal_input(&[&COMMAND_TOGGLE, &COMMAND_TOGGLE, &QUIT]);
|
|
start(Box::new(fake_input_output.clone()), Opt::default());
|
|
let output_frames = fake_input_output
|
|
.stdout_writer
|
|
.output_frames
|
|
.lock()
|
|
.unwrap();
|
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
|
for snapshot in snapshots {
|
|
assert_snapshot!(snapshot);
|
|
}
|
|
}
|