From 84bbe6b8f3aa23f3f9f1d8b38844efba6af17b41 Mon Sep 17 00:00:00 2001 From: Skyler Hawthorne Date: Sat, 16 Apr 2022 22:05:45 -0400 Subject: [PATCH] refactor helpers, use new test helpers --- helix-term/tests/integration.rs | 198 +++++++++--------------- helix-term/tests/integration/helpers.rs | 87 +++++++++++ 2 files changed, 162 insertions(+), 123 deletions(-) create mode 100644 helix-term/tests/integration/helpers.rs diff --git a/helix-term/tests/integration.rs b/helix-term/tests/integration.rs index 58883d40..a32eebf5 100644 --- a/helix-term/tests/integration.rs +++ b/helix-term/tests/integration.rs @@ -1,92 +1,22 @@ #[cfg(feature = "integration")] mod integration { + mod helpers; + use std::path::PathBuf; - use helix_core::{syntax::AutoPairConfig, Position, Selection, Transaction}; - use helix_term::{application::Application, args::Args, config::Config}; - use helix_view::{doc, input::parse_macro}; + use helix_core::{syntax::AutoPairConfig, Position, Selection}; + use helix_term::{args::Args, config::Config}; - use crossterm::event::{Event, KeyEvent}; use indoc::indoc; - pub struct TestCase { - pub in_text: String, - pub in_selection: Selection, - pub in_keys: String, - pub out_text: String, - pub out_selection: Selection, - } - - fn test_key_sequence( - app: Option, - test_case: &TestCase, - test_fn: &dyn Fn(&mut Application), - ) -> anyhow::Result<()> { - let mut app = - app.unwrap_or_else(|| Application::new(Args::default(), Config::default()).unwrap()); - - let (view, doc) = helix_view::current!(app.editor); - let sel = doc.selection(view.id).clone(); - - // replace the initial text with the input text - doc.apply( - &Transaction::change_by_selection(&doc.text(), &sel, |_| { - (0, doc.text().len_chars(), Some((&test_case.in_text).into())) - }) - .with_selection(test_case.in_selection.clone()), - view.id, - ); - - let input_keys = parse_macro(&test_case.in_keys)? - .into_iter() - .map(|key_event| Event::Key(KeyEvent::from(key_event))); - - for key in input_keys { - app.handle_terminal_events(Ok(key)); - } - - test_fn(&mut app); - - Ok(()) - } - - /// Use this for very simple test cases where there is one input - /// document, selection, and sequence of key presses, and you just - /// want to verify the resulting document and selection. - fn test_key_sequence_text_result( - args: Args, - config: Config, - test_case: TestCase, - ) -> anyhow::Result<()> { - let app = Application::new(args, config).unwrap(); - - test_key_sequence(Some(app), &test_case, &|app| { - let doc = doc!(app.editor); - assert_eq!(&test_case.out_text, doc.text()); - - let mut selections: Vec<_> = doc.selections().values().cloned().collect(); - assert_eq!(1, selections.len()); - - let sel = selections.pop().unwrap(); - assert_eq!(test_case.out_selection, sel); - })?; - - Ok(()) - } + use self::helpers::*; #[tokio::test] async fn hello_world() -> anyhow::Result<()> { test_key_sequence_text_result( Args::default(), Config::default(), - TestCase { - in_text: "\n".into(), - in_selection: Selection::single(0, 1), - // TODO: fix incorrect selection on new doc - in_keys: "ihello world".into(), - out_text: "hello world\n".into(), - out_selection: Selection::single(12, 11), - }, + ("#[\n|]#", "ihello world", "hello world#[|\n]#"), )?; Ok(()) @@ -109,42 +39,79 @@ mod integration { test_key_sequence_text_result( Args::default(), Config::default(), - TestCase { - in_text: "\n".into(), - in_selection: Selection::single(0, 1), - in_keys: "i".into(), - out_text: "\n".into(), - out_selection: Selection::single(1, 0), - }, + ("#[\n|]#", "i", "#[|\n]#"), )?; test_key_sequence_text_result( Args::default(), Config::default(), - TestCase { - in_text: "\n".into(), - in_selection: Selection::single(0, 1), - in_keys: "ii".into(), - out_text: "\n".into(), - out_selection: Selection::single(1, 0), - }, + ("#[\n|]#", "i", "#[|\n]#"), + )?; + + test_key_sequence_text_result( + Args::default(), + Config::default(), + ("#[\n|]#", "ii", "#[|\n]#"), )?; Ok(()) } + /// Range direction is preserved when escaping insert mode to normal #[tokio::test] async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> { test_key_sequence_text_result( Args::default(), Config::default(), - TestCase { - in_text: "\n".into(), - in_selection: Selection::single(0, 1), - in_keys: "i".into(), - out_text: "\n".into(), - out_selection: Selection::single(1, 0), - }, + ("#[f|]#oo\n", "vll", "#[|foo]#\n"), + )?; + + test_key_sequence_text_result( + Args::default(), + Config::default(), + ( + indoc! {"\ + #[f|]#oo + #(b|)#ar" + }, + "vll", + indoc! {"\ + #[|foo]# + #(|bar)#" + }, + ), + )?; + + test_key_sequence_text_result( + Args::default(), + Config::default(), + ( + indoc! {"\ + #[f|]#oo + #(b|)#ar" + }, + "a", + indoc! {"\ + #[fo|]#o + #(ba|)#r" + }, + ), + )?; + + test_key_sequence_text_result( + Args::default(), + Config::default(), + ( + indoc! {"\ + #[f|]#oo + #(b|)#ar" + }, + "a", + indoc! {"\ + #[f|]#oo + #(b|)#ar" + }, + ), )?; Ok(()) @@ -155,13 +122,7 @@ mod integration { test_key_sequence_text_result( Args::default(), Config::default(), - TestCase { - in_text: "\n".into(), - in_selection: Selection::single(0, 1), - in_keys: "i(".into(), - out_text: "()\n".into(), - out_selection: Selection::single(2, 1), - }, + ("#[\n|]#", "i(", "(#[|)]#\n"), )?; test_key_sequence_text_result( @@ -173,39 +134,30 @@ mod integration { }, ..Default::default() }, - TestCase { - in_text: "\n".into(), - in_selection: Selection::single(0, 1), - in_keys: "i(".into(), - out_text: "(\n".into(), - out_selection: Selection::single(2, 1), - }, + ("#[\n|]#", "i(", "(#[|\n]#"), )?; Ok(()) } #[tokio::test] - async fn auto_indent_rs() -> anyhow::Result<()> { + async fn auto_indent_c() -> anyhow::Result<()> { test_key_sequence_text_result( Args { files: vec![(PathBuf::from("foo.c"), Position::default())], ..Default::default() }, Config::default(), - TestCase { - in_text: "void foo() {}\n".into(), - in_selection: Selection::single(13, 12), - in_keys: "i".into(), - out_text: indoc! {r#" + // switches to append mode? + ( + "void foo() {#[|}]#\n", + "i", + indoc! {"\ void foo() { - + #[|\n]#\ } - "#} - .trim_start() - .into(), - out_selection: Selection::single(16, 15), - }, + "}, + ), )?; Ok(()) diff --git a/helix-term/tests/integration/helpers.rs b/helix-term/tests/integration/helpers.rs new file mode 100644 index 00000000..d22bcc3c --- /dev/null +++ b/helix-term/tests/integration/helpers.rs @@ -0,0 +1,87 @@ +use crossterm::event::{Event, KeyEvent}; +use helix_core::{test, Selection, Transaction}; +use helix_term::{application::Application, args::Args, config::Config}; +use helix_view::{doc, input::parse_macro}; + +#[derive(Clone, Debug)] +pub struct TestCase { + pub in_text: String, + pub in_selection: Selection, + pub in_keys: String, + pub out_text: String, + pub out_selection: Selection, +} + +impl> From<(S, S, S)> for TestCase { + fn from((input, keys, output): (S, S, S)) -> Self { + let (in_text, in_selection) = test::print(&input.into()); + let (out_text, out_selection) = test::print(&output.into()); + + TestCase { + in_text, + in_selection, + in_keys: keys.into(), + out_text, + out_selection, + } + } +} + +pub fn test_key_sequence>( + app: Option, + test_case: T, + test_fn: &dyn Fn(&mut Application), +) -> anyhow::Result<()> { + let test_case = test_case.into(); + let mut app = + app.unwrap_or_else(|| Application::new(Args::default(), Config::default()).unwrap()); + + let (view, doc) = helix_view::current!(app.editor); + let sel = doc.selection(view.id).clone(); + + // replace the initial text with the input text + doc.apply( + &Transaction::change_by_selection(&doc.text(), &sel, |_| { + (0, doc.text().len_chars(), Some((&test_case.in_text).into())) + }) + .with_selection(test_case.in_selection.clone()), + view.id, + ); + + let input_keys = parse_macro(&test_case.in_keys)? + .into_iter() + .map(|key_event| Event::Key(KeyEvent::from(key_event))); + + for key in input_keys { + app.handle_terminal_events(Ok(key)); + } + + test_fn(&mut app); + + Ok(()) +} + +/// Use this for very simple test cases where there is one input +/// document, selection, and sequence of key presses, and you just +/// want to verify the resulting document and selection. +pub fn test_key_sequence_text_result>( + args: Args, + config: Config, + test_case: T, +) -> anyhow::Result<()> { + let test_case = test_case.into(); + let app = Application::new(args, config).unwrap(); + + test_key_sequence(Some(app), test_case.clone(), &|app| { + let doc = doc!(app.editor); + assert_eq!(&test_case.out_text, doc.text()); + + let mut selections: Vec<_> = doc.selections().values().cloned().collect(); + assert_eq!(1, selections.len()); + + let sel = selections.pop().unwrap(); + assert_eq!(test_case.out_selection, sel); + })?; + + Ok(()) +}