on master help sign in
refactor helpers, use new test helpers
commit84bbe6b8f3aa23f3f9f1d8b38844efba6af17b41 authorSkyler Hawthorne <skyler@dead10ck.com> dateSat 16 Apr 2022, 22:05 (5 years ago) parent0f3c10a
2 files changed+162−123
helix-term/tests/integration.rs+75−123 helix-term/tests/integration/helpers.rs+87
helix-term/tests/integration.rs+75−123
@@ -1,92 +1,22 @@
11#[cfg(feature = "integration")]
22mod integration {
3+ mod helpers;
4+
35 use std::path::PathBuf;
46
5− use helix_core::{syntax::AutoPairConfig, Position, Selection, Transaction};
6− use helix_term::{application::Application, args::Args, config::Config};
7− use helix_view::{doc, input::parse_macro};
7+ use helix_core::{syntax::AutoPairConfig, Position, Selection};
8+ use helix_term::{args::Args, config::Config};
89
9− use crossterm::event::{Event, KeyEvent};
1010 use indoc::indoc;
1111
12− pub struct TestCase {
13− pub in_text: String,
14− pub in_selection: Selection,
15− pub in_keys: String,
16− pub out_text: String,
17− pub out_selection: Selection,
18− }
19−
20− fn test_key_sequence(
21− app: Option<Application>,
22− test_case: &TestCase,
23− test_fn: &dyn Fn(&mut Application),
24− ) -> anyhow::Result<()> {
25− let mut app =
26− app.unwrap_or_else(|| Application::new(Args::default(), Config::default()).unwrap());
27−
28− let (view, doc) = helix_view::current!(app.editor);
29− let sel = doc.selection(view.id).clone();
30−
31− // replace the initial text with the input text
32− doc.apply(
33− &Transaction::change_by_selection(&doc.text(), &sel, |_| {
34− (0, doc.text().len_chars(), Some((&test_case.in_text).into()))
35− })
36− .with_selection(test_case.in_selection.clone()),
37− view.id,
38− );
39−
40− let input_keys = parse_macro(&test_case.in_keys)?
41− .into_iter()
42− .map(|key_event| Event::Key(KeyEvent::from(key_event)));
43−
44− for key in input_keys {
45− app.handle_terminal_events(Ok(key));
46− }
47−
48− test_fn(&mut app);
49−
50− Ok(())
51− }
52−
53− /// Use this for very simple test cases where there is one input
54− /// document, selection, and sequence of key presses, and you just
55− /// want to verify the resulting document and selection.
56− fn test_key_sequence_text_result(
57− args: Args,
58− config: Config,
59− test_case: TestCase,
60− ) -> anyhow::Result<()> {
61− let app = Application::new(args, config).unwrap();
62−
63− test_key_sequence(Some(app), &test_case, &|app| {
64− let doc = doc!(app.editor);
65− assert_eq!(&test_case.out_text, doc.text());
66−
67− let mut selections: Vec<_> = doc.selections().values().cloned().collect();
68− assert_eq!(1, selections.len());
69−
70− let sel = selections.pop().unwrap();
71− assert_eq!(test_case.out_selection, sel);
72− })?;
73−
74− Ok(())
75− }
12+ use self::helpers::*;
7613
7714 #[tokio::test]
7815 async fn hello_world() -> anyhow::Result<()> {
7916 test_key_sequence_text_result(
8017 Args::default(),
8118 Config::default(),
82− TestCase {
83− in_text: "\n".into(),
84− in_selection: Selection::single(0, 1),
85− // TODO: fix incorrect selection on new doc
86− in_keys: "ihello world<esc>".into(),
87− out_text: "hello world\n".into(),
88− out_selection: Selection::single(12, 11),
89− },
19+ ("#[\n|]#", "ihello world<esc>", "hello world#[|\n]#"),
9020 )?;
9121
9222 Ok(())
@@ -109,42 +39,79 @@ mod integration {
10939 test_key_sequence_text_result(
11040 Args::default(),
11141 Config::default(),
112− TestCase {
113− in_text: "\n".into(),
114− in_selection: Selection::single(0, 1),
115− in_keys: "i".into(),
116− out_text: "\n".into(),
117− out_selection: Selection::single(1, 0),
118− },
42+ ("#[\n|]#", "i", "#[|\n]#"),
11943 )?;
12044
12145 test_key_sequence_text_result(
12246 Args::default(),
12347 Config::default(),
124− TestCase {
125− in_text: "\n".into(),
126− in_selection: Selection::single(0, 1),
127− in_keys: "i<esc>i".into(),
128− out_text: "\n".into(),
129− out_selection: Selection::single(1, 0),
130− },
48+ ("#[\n|]#", "i<esc>", "#[|\n]#"),
49+ )?;
50+
51+ test_key_sequence_text_result(
52+ Args::default(),
53+ Config::default(),
54+ ("#[\n|]#", "i<esc>i", "#[|\n]#"),
13155 )?;
13256
13357 Ok(())
13458 }
13559
60+ /// Range direction is preserved when escaping insert mode to normal
13661 #[tokio::test]
13762 async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
13863 test_key_sequence_text_result(
13964 Args::default(),
14065 Config::default(),
141− TestCase {
142− in_text: "\n".into(),
143− in_selection: Selection::single(0, 1),
144− in_keys: "i".into(),
145− out_text: "\n".into(),
146− out_selection: Selection::single(1, 0),
147− },
66+ ("#[f|]#oo\n", "vll<A-;><esc>", "#[|foo]#\n"),
67+ )?;
68+
69+ test_key_sequence_text_result(
70+ Args::default(),
71+ Config::default(),
72+ (
73+ indoc! {"\
74+ #[f|]#oo
75+ #(b|)#ar"
76+ },
77+ "vll<A-;><esc>",
78+ indoc! {"\
79+ #[|foo]#
80+ #(|bar)#"
81+ },
82+ ),
83+ )?;
84+
85+ test_key_sequence_text_result(
86+ Args::default(),
87+ Config::default(),
88+ (
89+ indoc! {"\
90+ #[f|]#oo
91+ #(b|)#ar"
92+ },
93+ "a",
94+ indoc! {"\
95+ #[fo|]#o
96+ #(ba|)#r"
97+ },
98+ ),
99+ )?;
100+
101+ test_key_sequence_text_result(
102+ Args::default(),
103+ Config::default(),
104+ (
105+ indoc! {"\
106+ #[f|]#oo
107+ #(b|)#ar"
108+ },
109+ "a<esc>",
110+ indoc! {"\
111+ #[f|]#oo
112+ #(b|)#ar"
113+ },
114+ ),
148115 )?;
149116
150117 Ok(())
@@ -155,13 +122,7 @@ mod integration {
155122 test_key_sequence_text_result(
156123 Args::default(),
157124 Config::default(),
158− TestCase {
159− in_text: "\n".into(),
160− in_selection: Selection::single(0, 1),
161− in_keys: "i(<esc>".into(),
162− out_text: "()\n".into(),
163− out_selection: Selection::single(2, 1),
164− },
125+ ("#[\n|]#", "i(<esc>", "(#[|)]#\n"),
165126 )?;
166127
167128 test_key_sequence_text_result(
@@ -173,39 +134,30 @@ mod integration {
173134 },
174135 ..Default::default()
175136 },
176− TestCase {
177− in_text: "\n".into(),
178− in_selection: Selection::single(0, 1),
179− in_keys: "i(<esc>".into(),
180− out_text: "(\n".into(),
181− out_selection: Selection::single(2, 1),
182− },
137+ ("#[\n|]#", "i(<esc>", "(#[|\n]#"),
183138 )?;
184139
185140 Ok(())
186141 }
187142
188143 #[tokio::test]
189− async fn auto_indent_rs() -> anyhow::Result<()> {
144+ async fn auto_indent_c() -> anyhow::Result<()> {
190145 test_key_sequence_text_result(
191146 Args {
192147 files: vec![(PathBuf::from("foo.c"), Position::default())],
193148 ..Default::default()
194149 },
195150 Config::default(),
196− TestCase {
197− in_text: "void foo() {}\n".into(),
198− in_selection: Selection::single(13, 12),
199− in_keys: "i<ret><esc>".into(),
200− out_text: indoc! {r#"
151+ // switches to append mode?
152+ (
153+ "void foo() {#[|}]#\n",
154+ "i<ret><esc>",
155+ indoc! {"\
201156 void foo() {
202−
157+ #[|\n]#\
203158 }
204− "#}
205− .trim_start()
206− .into(),
207− out_selection: Selection::single(16, 15),
208− },
159+ "},
160+ ),
209161 )?;
210162
211163 Ok(())
helix-term/tests/integration/helpers.rsnew file+87
@@ -0,0 +1,87 @@
1+use crossterm::event::{Event, KeyEvent};
2+use helix_core::{test, Selection, Transaction};
3+use helix_term::{application::Application, args::Args, config::Config};
4+use helix_view::{doc, input::parse_macro};
5+
6+#[derive(Clone, Debug)]
7+pub struct TestCase {
8+ pub in_text: String,
9+ pub in_selection: Selection,
10+ pub in_keys: String,
11+ pub out_text: String,
12+ pub out_selection: Selection,
13+}
14+
15+impl<S: Into<String>> From<(S, S, S)> for TestCase {
16+ fn from((input, keys, output): (S, S, S)) -> Self {
17+ let (in_text, in_selection) = test::print(&input.into());
18+ let (out_text, out_selection) = test::print(&output.into());
19+
20+ TestCase {
21+ in_text,
22+ in_selection,
23+ in_keys: keys.into(),
24+ out_text,
25+ out_selection,
26+ }
27+ }
28+}
29+
30+pub fn test_key_sequence<T: Into<TestCase>>(
31+ app: Option<Application>,
32+ test_case: T,
33+ test_fn: &dyn Fn(&mut Application),
34+) -> anyhow::Result<()> {
35+ let test_case = test_case.into();
36+ let mut app =
37+ app.unwrap_or_else(|| Application::new(Args::default(), Config::default()).unwrap());
38+
39+ let (view, doc) = helix_view::current!(app.editor);
40+ let sel = doc.selection(view.id).clone();
41+
42+ // replace the initial text with the input text
43+ doc.apply(
44+ &Transaction::change_by_selection(&doc.text(), &sel, |_| {
45+ (0, doc.text().len_chars(), Some((&test_case.in_text).into()))
46+ })
47+ .with_selection(test_case.in_selection.clone()),
48+ view.id,
49+ );
50+
51+ let input_keys = parse_macro(&test_case.in_keys)?
52+ .into_iter()
53+ .map(|key_event| Event::Key(KeyEvent::from(key_event)));
54+
55+ for key in input_keys {
56+ app.handle_terminal_events(Ok(key));
57+ }
58+
59+ test_fn(&mut app);
60+
61+ Ok(())
62+}
63+
64+/// Use this for very simple test cases where there is one input
65+/// document, selection, and sequence of key presses, and you just
66+/// want to verify the resulting document and selection.
67+pub fn test_key_sequence_text_result<T: Into<TestCase>>(
68+ args: Args,
69+ config: Config,
70+ test_case: T,
71+) -> anyhow::Result<()> {
72+ let test_case = test_case.into();
73+ let app = Application::new(args, config).unwrap();
74+
75+ test_key_sequence(Some(app), test_case.clone(), &|app| {
76+ let doc = doc!(app.editor);
77+ assert_eq!(&test_case.out_text, doc.text());
78+
79+ let mut selections: Vec<_> = doc.selections().values().cloned().collect();
80+ assert_eq!(1, selections.len());
81+
82+ let sel = selections.pop().unwrap();
83+ assert_eq!(test_case.out_selection, sel);
84+ })?;
85+
86+ Ok(())
87+}