on master help sign in
refactor helpers, use new test helpers
84bbe6bSkyler Hawthorne
helix-term/tests/integration.rs+75−123
@@ -1,92 +1,22 @@
1#[cfg(feature = "integration")]
1#[cfg(feature = "integration")]
2mod integration {
2mod integration {
3+ mod helpers;
4+
3 use std::path::PathBuf;
5 use std::path::PathBuf;
4
6
5− use helix_core::{syntax::AutoPairConfig, Position, Selection, Transaction};
7+ use helix_core::{syntax::AutoPairConfig, Position, Selection};
6− use helix_term::{application::Application, args::Args, config::Config};
8+ use helix_term::{args::Args, config::Config};
7− use helix_view::{doc, input::parse_macro};
8
9
9− use crossterm::event::{Event, KeyEvent};
10 use indoc::indoc;
10 use indoc::indoc;
11
11
12− pub struct TestCase {
12+ use self::helpers::*;
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− }
76
13
77 #[tokio::test]
14 #[tokio::test]
78 async fn hello_world() -> anyhow::Result<()> {
15 async fn hello_world() -> anyhow::Result<()> {
79 test_key_sequence_text_result(
16 test_key_sequence_text_result(
80 Args::default(),
17 Args::default(),
81 Config::default(),
18 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(),
19+ ("#[\n|]#", "ihello world<esc>", "hello world#[|\n]#"),
87− out_text: "hello world\n".into(),
88− out_selection: Selection::single(12, 11),
89− },
90 )?;
20 )?;
91
21
92 Ok(())
22 Ok(())
@@ -109,42 +39,79 @@ mod integration {
109 test_key_sequence_text_result(
39 test_key_sequence_text_result(
110 Args::default(),
40 Args::default(),
111 Config::default(),
41 Config::default(),
112− TestCase {
42+ ("#[\n|]#", "i", "#[|\n]#"),
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− },
119 )?;
43 )?;
120
44
121 test_key_sequence_text_result(
45 test_key_sequence_text_result(
122 Args::default(),
46 Args::default(),
123 Config::default(),
47 Config::default(),
124− TestCase {
48+ ("#[\n|]#", "i<esc>", "#[|\n]#"),
125− in_text: "\n".into(),
49+ )?;
126− in_selection: Selection::single(0, 1),
50+
51+ test_key_sequence_text_result(
52+ Args::default(),
53+ Config::default(),
127− in_keys: "i<esc>i".into(),
54+ ("#[\n|]#", "i<esc>i", "#[|\n]#"),
128− out_text: "\n".into(),
129− out_selection: Selection::single(1, 0),
130− },
131 )?;
55 )?;
132
56
133 Ok(())
57 Ok(())
134 }
58 }
135
59
60+ /// Range direction is preserved when escaping insert mode to normal
136 #[tokio::test]
61 #[tokio::test]
137 async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
62 async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
138 test_key_sequence_text_result(
63 test_key_sequence_text_result(
139 Args::default(),
64 Args::default(),
140 Config::default(),
65 Config::default(),
141− TestCase {
66+ ("#[f|]#oo\n", "vll<A-;><esc>", "#[|foo]#\n"),
142− in_text: "\n".into(),
67+ )?;
143− in_selection: Selection::single(0, 1),
68+
144− in_keys: "i".into(),
69+ test_key_sequence_text_result(
145− out_text: "\n".into(),
70+ Args::default(),
146− out_selection: Selection::single(1, 0),
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+ },
147− },
114+ ),
148 )?;
115 )?;
149
116
150 Ok(())
117 Ok(())
@@ -155,13 +122,7 @@ mod integration {
155 test_key_sequence_text_result(
122 test_key_sequence_text_result(
156 Args::default(),
123 Args::default(),
157 Config::default(),
124 Config::default(),
158− TestCase {
125+ ("#[\n|]#", "i(<esc>", "(#[|)]#\n"),
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− },
165 )?;
126 )?;
166
127
167 test_key_sequence_text_result(
128 test_key_sequence_text_result(
@@ -173,39 +134,30 @@ mod integration {
173 },
134 },
174 ..Default::default()
135 ..Default::default()
175 },
136 },
176− TestCase {
137+ ("#[\n|]#", "i(<esc>", "(#[|\n]#"),
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− },
183 )?;
138 )?;
184
139
185 Ok(())
140 Ok(())
186 }
141 }
187
142
188 #[tokio::test]
143 #[tokio::test]
189− async fn auto_indent_rs() -> anyhow::Result<()> {
144+ async fn auto_indent_c() -> anyhow::Result<()> {
190 test_key_sequence_text_result(
145 test_key_sequence_text_result(
191 Args {
146 Args {
192 files: vec![(PathBuf::from("foo.c"), Position::default())],
147 files: vec![(PathBuf::from("foo.c"), Position::default())],
193 ..Default::default()
148 ..Default::default()
194 },
149 },
195 Config::default(),
150 Config::default(),
196− TestCase {
151+ // switches to append mode?
152+ (
197− in_text: "void foo() {}\n".into(),
153+ "void foo() {#[|}]#\n",
198− in_selection: Selection::single(13, 12),
199− in_keys: "i<ret><esc>".into(),
154+ "i<ret><esc>",
200− out_text: indoc! {r#"
155+ indoc! {"\
201 void foo() {
156 void foo() {
202−
157+ #[|\n]#\
203 }
158 }
204− "#}
159+ "},
205− .trim_start()
206− .into(),
207− out_selection: Selection::single(16, 15),
208− },
160+ ),
209 )?;
161 )?;
210
162
211 Ok(())
163 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+}