1mod neovim_backed_binding_test_context;
2mod neovim_backed_test_context;
3mod neovim_connection;
4mod vim_binding_test_context;
5mod vim_test_context;
6
7use command_palette::CommandPalette;
8use editor::DisplayPoint;
9pub use neovim_backed_binding_test_context::*;
10pub use neovim_backed_test_context::*;
11pub use vim_binding_test_context::*;
12pub use vim_test_context::*;
13
14use indoc::indoc;
15use search::BufferSearchBar;
16
17use crate::state::Mode;
18
19#[gpui::test]
20async fn test_initially_disabled(cx: &mut gpui::TestAppContext) {
21 let mut cx = VimTestContext::new(cx, false).await;
22 cx.simulate_keystrokes(["h", "j", "k", "l"]);
23 cx.assert_editor_state("hjklˇ");
24}
25
26#[gpui::test]
27async fn test_neovim(cx: &mut gpui::TestAppContext) {
28 let mut cx = NeovimBackedTestContext::new(cx).await;
29
30 cx.simulate_shared_keystroke("i").await;
31 cx.assert_state_matches().await;
32 cx.simulate_shared_keystrokes([
33 "shift-T", "e", "s", "t", " ", "t", "e", "s", "t", "escape", "0", "d", "w",
34 ])
35 .await;
36 cx.assert_state_matches().await;
37 cx.assert_editor_state("ˇtest");
38}
39
40#[gpui::test]
41async fn test_toggle_through_settings(cx: &mut gpui::TestAppContext) {
42 let mut cx = VimTestContext::new(cx, true).await;
43
44 cx.simulate_keystroke("i");
45 assert_eq!(cx.mode(), Mode::Insert);
46
47 // Editor acts as though vim is disabled
48 cx.disable_vim();
49 cx.simulate_keystrokes(["h", "j", "k", "l"]);
50 cx.assert_editor_state("hjklˇ");
51
52 // Selections aren't changed if editor is blurred but vim-mode is still disabled.
53 cx.set_state("«hjklˇ»", Mode::Normal);
54 cx.assert_editor_state("«hjklˇ»");
55 cx.update_editor(|_, cx| cx.blur());
56 cx.assert_editor_state("«hjklˇ»");
57 cx.update_editor(|_, cx| cx.focus_self());
58 cx.assert_editor_state("«hjklˇ»");
59
60 // Enabling dynamically sets vim mode again and restores normal mode
61 cx.enable_vim();
62 assert_eq!(cx.mode(), Mode::Normal);
63 cx.simulate_keystrokes(["h", "h", "h", "l"]);
64 assert_eq!(cx.buffer_text(), "hjkl".to_owned());
65 cx.assert_editor_state("hˇjkl");
66 cx.simulate_keystrokes(["i", "T", "e", "s", "t"]);
67 cx.assert_editor_state("hTestˇjkl");
68
69 // Disabling and enabling resets to normal mode
70 assert_eq!(cx.mode(), Mode::Insert);
71 cx.disable_vim();
72 cx.enable_vim();
73 assert_eq!(cx.mode(), Mode::Normal);
74}
75
76#[gpui::test]
77async fn test_buffer_search(cx: &mut gpui::TestAppContext) {
78 let mut cx = VimTestContext::new(cx, true).await;
79
80 cx.set_state(
81 indoc! {"
82 The quick brown
83 fox juˇmps over
84 the lazy dog"},
85 Mode::Normal,
86 );
87 cx.simulate_keystroke("/");
88
89 let search_bar = cx.workspace(|workspace, cx| {
90 workspace
91 .active_pane()
92 .read(cx)
93 .toolbar()
94 .read(cx)
95 .item_of_type::<BufferSearchBar>()
96 .expect("Buffer search bar should be deployed")
97 });
98
99 search_bar.read_with(cx.cx, |bar, cx| {
100 assert_eq!(bar.query_editor.read(cx).text(cx), "");
101 })
102}
103
104#[gpui::test]
105async fn test_count_down(cx: &mut gpui::TestAppContext) {
106 let mut cx = VimTestContext::new(cx, true).await;
107
108 cx.set_state(indoc! {"aˇa\nbb\ncc\ndd\nee"}, Mode::Normal);
109 cx.simulate_keystrokes(["2", "down"]);
110 cx.assert_editor_state("aa\nbb\ncˇc\ndd\nee");
111 cx.simulate_keystrokes(["9", "down"]);
112 cx.assert_editor_state("aa\nbb\ncc\ndd\neˇe");
113}
114
115#[gpui::test]
116async fn test_end_of_document_710(cx: &mut gpui::TestAppContext) {
117 let mut cx = VimTestContext::new(cx, true).await;
118
119 // goes to end by default
120 cx.set_state(indoc! {"aˇa\nbb\ncc"}, Mode::Normal);
121 cx.simulate_keystrokes(["shift-g"]);
122 cx.assert_editor_state("aa\nbb\ncˇc");
123
124 // can go to line 1 (https://github.com/zed-industries/community/issues/710)
125 cx.simulate_keystrokes(["1", "shift-g"]);
126 cx.assert_editor_state("aˇa\nbb\ncc");
127}
128
129#[gpui::test]
130async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
131 let mut cx = VimTestContext::new(cx, true).await;
132
133 // works in normal mode
134 cx.set_state(indoc! {"aa\nbˇb\ncc"}, Mode::Normal);
135 cx.simulate_keystrokes([">", ">"]);
136 cx.assert_editor_state("aa\n bˇb\ncc");
137 cx.simulate_keystrokes(["<", "<"]);
138 cx.assert_editor_state("aa\nbˇb\ncc");
139
140 // works in visuial mode
141 cx.simulate_keystrokes(["shift-v", "down", ">"]);
142 cx.assert_editor_state("aa\n b«b\n cˇ»c");
143}
144
145#[gpui::test]
146async fn test_escape_command_palette(cx: &mut gpui::TestAppContext) {
147 let mut cx = VimTestContext::new(cx, true).await;
148
149 cx.set_state("aˇbc\n", Mode::Normal);
150 cx.simulate_keystrokes(["i", "cmd-shift-p"]);
151
152 assert!(cx.workspace(|workspace, _| workspace.modal::<CommandPalette>().is_some()));
153 cx.simulate_keystroke("escape");
154 assert!(!cx.workspace(|workspace, _| workspace.modal::<CommandPalette>().is_some()));
155 cx.assert_state("aˇbc\n", Mode::Insert);
156}
157
158#[gpui::test]
159async fn test_selection_on_search(cx: &mut gpui::TestAppContext) {
160 let mut cx = VimTestContext::new(cx, true).await;
161
162 cx.set_state(indoc! {"aa\nbˇb\ncc\ncc\ncc\n"}, Mode::Normal);
163 cx.simulate_keystrokes(["/", "c", "c"]);
164
165 let search_bar = cx.workspace(|workspace, cx| {
166 workspace
167 .active_pane()
168 .read(cx)
169 .toolbar()
170 .read(cx)
171 .item_of_type::<BufferSearchBar>()
172 .expect("Buffer search bar should be deployed")
173 });
174
175 search_bar.read_with(cx.cx, |bar, cx| {
176 assert_eq!(bar.query_editor.read(cx).text(cx), "cc");
177 });
178
179 // wait for the query editor change event to fire.
180 search_bar.next_notification(&cx).await;
181
182 cx.update_editor(|editor, cx| {
183 let highlights = editor.all_background_highlights(cx);
184 assert_eq!(3, highlights.len());
185 assert_eq!(
186 DisplayPoint::new(2, 0)..DisplayPoint::new(2, 2),
187 highlights[0].0
188 )
189 });
190 cx.simulate_keystrokes(["enter"]);
191
192 cx.assert_state(indoc! {"aa\nbb\nˇcc\ncc\ncc\n"}, Mode::Normal);
193 cx.simulate_keystrokes(["n"]);
194 cx.assert_state(indoc! {"aa\nbb\ncc\nˇcc\ncc\n"}, Mode::Normal);
195 cx.simulate_keystrokes(["shift-n"]);
196 cx.assert_state(indoc! {"aa\nbb\nˇcc\ncc\ncc\n"}, Mode::Normal);
197}