1
+ -- luacheck: globals expect
2
+ require (" tests.busted_setup" )
3
+
4
+ describe (" mini.files selection handling" , function ()
5
+ local selection
6
+ local mock_vim
7
+ local mock_logger
8
+ local mock_claudecode_main
9
+
10
+ local function setup_mocks ()
11
+ -- Clear modules
12
+ package.loaded [" claudecode.selection" ] = nil
13
+ package.loaded [" claudecode.logger" ] = nil
14
+ package.loaded [" claudecode" ] = nil
15
+
16
+ -- Mock logger
17
+ mock_logger = {
18
+ debug = function () end ,
19
+ warn = function () end ,
20
+ error = function () end ,
21
+ }
22
+ package.loaded [" claudecode.logger" ] = mock_logger
23
+
24
+ -- Mock main claudecode module
25
+ mock_claudecode_main = {
26
+ state = {
27
+ server = {
28
+ -- Mock server object
29
+ }
30
+ },
31
+ send_at_mention = function (file_path , start_line , end_line , source )
32
+ -- Mock successful at-mention sending
33
+ return true , nil
34
+ end
35
+ }
36
+ package.loaded [" claudecode" ] = mock_claudecode_main
37
+
38
+ -- Mock vim
39
+ mock_vim = {
40
+ api = {
41
+ nvim_get_current_buf = function ()
42
+ return 42 -- Mock buffer ID
43
+ end ,
44
+ nvim_buf_get_name = function (buf_id )
45
+ if buf_id == 42 then
46
+ return " minifiles://42//Users/test/project/test.lua"
47
+ end
48
+ return " /Users/test/project/test.lua"
49
+ end ,
50
+ nvim_get_mode = function ()
51
+ return { mode = " V" }
52
+ end ,
53
+ nvim_win_get_cursor = function ()
54
+ return { 1 , 0 }
55
+ end ,
56
+ nvim_buf_get_lines = function ()
57
+ return { " line 1" , " line 2" , " line 3" }
58
+ end ,
59
+ },
60
+ fn = {
61
+ getpos = function (mark )
62
+ if mark == " v" then
63
+ return { 0 , 1 , 1 , 0 }
64
+ end
65
+ return { 0 , 0 , 0 , 0 }
66
+ end ,
67
+ visualmode = function ()
68
+ return " V"
69
+ end ,
70
+ },
71
+ loop = {
72
+ now = function ()
73
+ return 1000
74
+ end ,
75
+ new_timer = function ()
76
+ return {
77
+ start = function () end ,
78
+ stop = function () end ,
79
+ close = function () end ,
80
+ }
81
+ end ,
82
+ },
83
+ schedule_wrap = function (fn )
84
+ return fn
85
+ end ,
86
+ deepcopy = function (obj )
87
+ return obj
88
+ end ,
89
+ }
90
+
91
+ _G .vim = mock_vim
92
+ end
93
+
94
+ before_each (function ()
95
+ setup_mocks ()
96
+ selection = require (" claudecode.selection" )
97
+ end )
98
+
99
+ describe (" get_visual_selection" , function ()
100
+ it (" should extract filesystem path from mini.files buffer path" , function ()
101
+ -- Mock visual mode
102
+ mock_vim .api .nvim_get_mode = function ()
103
+ return { mode = " V" }
104
+ end
105
+
106
+ local result = selection .get_visual_selection ()
107
+
108
+ expect (result ).to_be_table ()
109
+ expect (result .filePath ).to_be (" /Users/test/project/test.lua" )
110
+ expect (result .fileUrl ).to_be (" file:///Users/test/project/test.lua" )
111
+ expect (result .text ).to_be (" line 1\n line 2\n line 3" )
112
+ end )
113
+ end )
114
+
115
+ describe (" get_cursor_position" , function ()
116
+ it (" should extract filesystem path from mini.files buffer path" , function ()
117
+ local result = selection .get_cursor_position ()
118
+
119
+ expect (result ).to_be_table ()
120
+ expect (result .filePath ).to_be (" /Users/test/project/test.lua" )
121
+ expect (result .fileUrl ).to_be (" file:///Users/test/project/test.lua" )
122
+ expect (result .text ).to_be (" " )
123
+ expect (result .selection .isEmpty ).to_be (true )
124
+ end )
125
+ end )
126
+
127
+ describe (" get_range_selection" , function ()
128
+ it (" should extract filesystem path from mini.files buffer path" , function ()
129
+ local result = selection .get_range_selection (1 , 3 )
130
+
131
+ expect (result ).to_be_table ()
132
+ expect (result .filePath ).to_be (" /Users/test/project/test.lua" )
133
+ expect (result .fileUrl ).to_be (" file:///Users/test/project/test.lua" )
134
+ expect (result .text ).to_be (" line 1\n line 2\n line 3" )
135
+ end )
136
+ end )
137
+
138
+ describe (" send_at_mention_for_visual_selection" , function ()
139
+ it (" should handle path comparison with mini.files buffer paths" , function ()
140
+ -- Setup: latest selection has filesystem path, current buffer has mini.files path
141
+ selection .state .latest_selection = {
142
+ filePath = " /Users/test/project/test.lua" ,
143
+ text = " selected text" ,
144
+ selection = {
145
+ start = { line = 0 , character = 0 },
146
+ [" end" ] = { line = 2 , character = 10 },
147
+ isEmpty = false
148
+ }
149
+ }
150
+ selection .state .tracking_enabled = true
151
+
152
+ local result = selection .send_at_mention_for_visual_selection ()
153
+
154
+ expect (result ).to_be (true )
155
+ end )
156
+
157
+ it (" should warn when paths don't match after extraction" , function ()
158
+ -- Setup: selection path doesn't match current buffer path even after extraction
159
+ selection .state .latest_selection = {
160
+ filePath = " /Users/test/project/different_file.lua" ,
161
+ text = " selected text" ,
162
+ selection = {
163
+ start = { line = 0 , character = 0 },
164
+ [" end" ] = { line = 2 , character = 10 },
165
+ isEmpty = false
166
+ }
167
+ }
168
+ selection .state .tracking_enabled = true
169
+
170
+ local warn_called = false
171
+ local warn_message = " "
172
+ mock_logger .warn = function (module , message )
173
+ warn_called = true
174
+ warn_message = message
175
+ end
176
+
177
+ local result = selection .send_at_mention_for_visual_selection ()
178
+
179
+ expect (result ).to_be (false )
180
+ expect (warn_called ).to_be (true )
181
+ expect (warn_message ).to_match (" Tracked selection is for" )
182
+ expect (warn_message ).to_match (" different_file.lua" )
183
+ expect (warn_message ).to_match (" test.lua" )
184
+ end )
185
+
186
+ it (" should handle normal filesystem paths correctly" , function ()
187
+ -- Test with normal filesystem paths (not mini.files)
188
+ mock_vim .api .nvim_buf_get_name = function ()
189
+ return " /Users/test/project/normal_file.lua"
190
+ end
191
+
192
+ selection .state .latest_selection = {
193
+ filePath = " /Users/test/project/normal_file.lua" ,
194
+ text = " selected text" ,
195
+ selection = {
196
+ start = { line = 0 , character = 0 },
197
+ [" end" ] = { line = 2 , character = 10 },
198
+ isEmpty = false
199
+ }
200
+ }
201
+ selection .state .tracking_enabled = true
202
+
203
+ local result = selection .send_at_mention_for_visual_selection ()
204
+
205
+ expect (result ).to_be (true )
206
+ end )
207
+
208
+ it (" should handle various mini.files path formats" , function ()
209
+ local test_cases = {
210
+ { buffer_path = " minifiles://42/Users/test/file.lua" , expected = " Users/test/file.lua" },
211
+ { buffer_path = " minifiles://42//Users/test/file.lua" , expected = " /Users/test/file.lua" },
212
+ { buffer_path = " minifiles://123///Users/test/file.lua" , expected = " //Users/test/file.lua" },
213
+ }
214
+
215
+ for _ , test_case in ipairs (test_cases ) do
216
+ mock_vim .api .nvim_buf_get_name = function ()
217
+ return test_case .buffer_path
218
+ end
219
+
220
+ selection .state .latest_selection = {
221
+ filePath = test_case .expected ,
222
+ text = " selected text" ,
223
+ selection = {
224
+ start = { line = 0 , character = 0 },
225
+ [" end" ] = { line = 2 , character = 10 },
226
+ isEmpty = false
227
+ }
228
+ }
229
+ selection .state .tracking_enabled = true
230
+
231
+ local result = selection .send_at_mention_for_visual_selection ()
232
+
233
+ expect (result ).to_be (true )
234
+ end
235
+ end )
236
+ end )
237
+ end )
0 commit comments