@@ -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(())