Skip to content

Commit 5dd2196

Browse files
committed
Update terminal tests for multi-instance support
- Completely rewrite terminal_spec.lua to test instances table instead of single bufnr - Add comprehensive tests for multi-instance functionality: - Instance creation and management - Git root vs current directory as instance identifier - Buffer name sanitization for special characters - Invalid buffer cleanup from instances table - Add tests for single-instance mode using 'global' key - Update force_insert_mode tests to work with instances table - All tests validate both single and multi-instance behavior
1 parent d5e3c62 commit 5dd2196

1 file changed

Lines changed: 171 additions & 56 deletions

File tree

tests/spec/terminal_spec.lua

Lines changed: 171 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ describe('terminal module', function()
4848
return 42
4949
end
5050

51+
-- Mock vim.fn.getcwd
52+
_G.vim.fn.getcwd = function()
53+
return '/test/current/dir'
54+
end
55+
5156
-- Mock vim.api.nvim_win_close
5257
_G.vim.api.nvim_win_close = function(win_id, force)
5358
-- Remove the window from win_ids
@@ -78,12 +83,14 @@ describe('terminal module', function()
7883
},
7984
git = {
8085
use_git_root = true,
86+
multi_instance = true,
8187
},
8288
}
8389

8490
claude_code = {
8591
claude_code = {
86-
bufnr = nil,
92+
instances = {},
93+
current_instance = nil,
8794
saved_updatetime = nil,
8895
},
8996
}
@@ -95,10 +102,11 @@ describe('terminal module', function()
95102
}
96103
end)
97104

98-
describe('toggle', function()
99-
it('should open terminal window when Claude Code is not running', function()
100-
-- Claude Code is not running (bufnr is nil)
101-
claude_code.claude_code.bufnr = nil
105+
describe('toggle with multi-instance enabled', function()
106+
it('should create new instance when none exists', function()
107+
-- No instances exist
108+
claude_code.claude_code.instances = {}
109+
claude_code.claude_code.current_instance = nil
102110

103111
-- Call toggle
104112
terminal.toggle(claude_code, config, git)
@@ -122,36 +130,43 @@ describe('terminal module', function()
122130
assert.is_true(resize_cmd_found, 'Resize command should be called')
123131
assert.is_true(terminal_cmd_found, 'Terminal command should be called')
124132

125-
-- Buffer number should be set
126-
assert.is_not_nil(claude_code.claude_code.bufnr, 'Claude Code buffer number should be set')
133+
-- Current instance should be set
134+
assert.is_not_nil(claude_code.claude_code.current_instance, 'Current instance should be set')
135+
136+
-- Instance should be created in instances table
137+
local current_instance = claude_code.claude_code.current_instance
138+
assert.is_not_nil(claude_code.claude_code.instances[current_instance], 'Instance buffer should be set')
127139
end)
128140

129-
it('should use git root when configured', function()
130-
-- Claude Code is not running (bufnr is nil)
131-
claude_code.claude_code.bufnr = nil
132-
133-
-- Set git config to use root
141+
it('should use git root as instance identifier when use_git_root is true', function()
142+
-- Configure to use git root
134143
config.git.use_git_root = true
144+
config.git.multi_instance = true
135145

136146
-- Call toggle
137147
terminal.toggle(claude_code, config, git)
138148

139-
-- Check that git root was used in terminal command
140-
local git_root_cmd_found = false
149+
-- Current instance should be git root
150+
assert.are.equal('/test/git/root', claude_code.claude_code.current_instance)
151+
end)
141152

142-
for _, cmd in ipairs(vim_cmd_calls) do
143-
if cmd:match('terminal pushd /test/git/root && ' .. config.command .. ' && popd') then
144-
git_root_cmd_found = true
145-
break
146-
end
147-
end
153+
it('should use current directory as instance identifier when use_git_root is false', function()
154+
-- Configure to use current directory
155+
config.git.use_git_root = false
156+
config.git.multi_instance = true
148157

149-
assert.is_true(git_root_cmd_found, 'Terminal command should include git root')
158+
-- Call toggle
159+
terminal.toggle(claude_code, config, git)
160+
161+
-- Current instance should be current directory
162+
assert.are.equal('/test/current/dir', claude_code.claude_code.current_instance)
150163
end)
151164

152-
it('should close window when Claude Code is visible', function()
153-
-- Claude Code is running and visible
154-
claude_code.claude_code.bufnr = 42
165+
it('should close window when instance is visible', function()
166+
-- Setup existing instance
167+
local instance_id = '/test/git/root'
168+
claude_code.claude_code.instances[instance_id] = 42
169+
claude_code.claude_code.current_instance = instance_id
155170
win_ids = { 100, 101 } -- Windows displaying the buffer
156171

157172
-- Create a function to clear the win_ids array
@@ -168,9 +183,11 @@ describe('terminal module', function()
168183
assert.are.equal(0, #win_ids, 'Windows should be closed')
169184
end)
170185

171-
it('should reopen window when Claude Code exists but is hidden', function()
172-
-- Claude Code is running but not visible
173-
claude_code.claude_code.bufnr = 42
186+
it('should reopen window when instance exists but is hidden', function()
187+
-- Setup existing instance that's not visible
188+
local instance_id = '/test/git/root'
189+
claude_code.claude_code.instances[instance_id] = 42
190+
claude_code.claude_code.current_instance = instance_id
174191
win_ids = {} -- No windows displaying the buffer
175192

176193
-- Call toggle
@@ -195,13 +212,98 @@ describe('terminal module', function()
195212
assert.is_true(resize_cmd_found, 'Resize command should be called')
196213
assert.is_true(buffer_cmd_found, 'Buffer command should be called with correct buffer number')
197214
end)
215+
216+
it('should create buffer with sanitized name for multi-instance', function()
217+
-- Use an instance ID with special characters
218+
config.git.use_git_root = false
219+
config.git.multi_instance = true
220+
221+
-- Mock getcwd to return path with special characters
222+
_G.vim.fn.getcwd = function()
223+
return '/test/path with spaces/and-symbols!'
224+
end
225+
226+
-- Call toggle
227+
terminal.toggle(claude_code, config, git)
228+
229+
-- Check that file command was called with sanitized name
230+
local file_cmd_found = false
231+
for _, cmd in ipairs(vim_cmd_calls) do
232+
if cmd:match('file claude%-code%-.*') then
233+
file_cmd_found = true
234+
-- Ensure no special characters remain
235+
assert.is_false(cmd:match('[^%w%-_]'), 'Buffer name should not contain special characters')
236+
break
237+
end
238+
end
239+
240+
assert.is_true(file_cmd_found, 'File command should be called with sanitized buffer name')
241+
end)
242+
243+
it('should clean up invalid buffers from instances table', function()
244+
-- Setup invalid buffer in instances
245+
local instance_id = '/test/git/root'
246+
claude_code.claude_code.instances[instance_id] = 999 -- Invalid buffer number
247+
248+
-- Mock nvim_buf_is_valid to return false for this buffer
249+
_G.vim.api.nvim_buf_is_valid = function(bufnr)
250+
return bufnr ~= 999
251+
end
252+
253+
-- Call toggle
254+
terminal.toggle(claude_code, config, git)
255+
256+
-- Invalid buffer should be cleaned up
257+
assert.is_nil(claude_code.claude_code.instances[instance_id], 'Invalid buffer should be cleaned up')
258+
end)
259+
end)
260+
261+
describe('toggle with multi-instance disabled', function()
262+
before_each(function()
263+
config.git.multi_instance = false
264+
end)
265+
266+
it('should use global instance when multi-instance is disabled', function()
267+
-- Call toggle
268+
terminal.toggle(claude_code, config, git)
269+
270+
-- Current instance should be "global"
271+
assert.are.equal('global', claude_code.claude_code.current_instance)
272+
end)
273+
274+
it('should create single global instance', function()
275+
-- Call toggle
276+
terminal.toggle(claude_code, config, git)
277+
278+
-- Check that global instance is created
279+
assert.is_not_nil(claude_code.claude_code.instances['global'], 'Global instance should be created')
280+
end)
281+
end)
282+
283+
describe('git root usage', function()
284+
it('should use git root when configured', function()
285+
-- Set git config to use root
286+
config.git.use_git_root = true
287+
288+
-- Call toggle
289+
terminal.toggle(claude_code, config, git)
290+
291+
-- Check that git root was used in terminal command
292+
local git_root_cmd_found = false
293+
294+
for _, cmd in ipairs(vim_cmd_calls) do
295+
if cmd:match('terminal pushd /test/git/root && ' .. config.command .. ' && popd') then
296+
git_root_cmd_found = true
297+
break
298+
end
299+
end
300+
301+
assert.is_true(git_root_cmd_found, 'Terminal command should include git root')
302+
end)
198303
end)
199304

200305
describe('start_in_normal_mode option', function()
201306
it('should not enter insert mode when start_in_normal_mode is true', function()
202-
-- Claude Code is not running (bufnr is nil)
203-
claude_code.claude_code.bufnr = nil
204-
205307
-- Set start_in_normal_mode to true
206308
config.window.start_in_normal_mode = true
207309

@@ -224,9 +326,6 @@ describe('terminal module', function()
224326
end)
225327

226328
it('should enter insert mode when start_in_normal_mode is false', function()
227-
-- Claude Code is not running (bufnr is nil)
228-
claude_code.claude_code.bufnr = nil
229-
230329
-- Set start_in_normal_mode to false
231330
config.window.start_in_normal_mode = false
232331

@@ -251,43 +350,59 @@ describe('terminal module', function()
251350

252351
describe('force_insert_mode', function()
253352
it('should check insert mode conditions in terminal buffer', function()
353+
-- Setup mock with instances table
354+
local mock_claude_code = {
355+
claude_code = {
356+
instances = {
357+
['/test/instance'] = 1,
358+
},
359+
current_instance = '/test/instance',
360+
},
361+
}
362+
local mock_config = {
363+
window = {
364+
start_in_normal_mode = false,
365+
},
366+
}
367+
254368
-- For this test, we'll just verify that the function can be called without error
255369
local success, _ = pcall(function()
256-
-- Setup minimal mock
257-
local mock_claude_code = {
258-
claude_code = {
259-
bufnr = 1,
260-
},
261-
}
262-
local mock_config = {
263-
window = {
264-
start_in_normal_mode = false,
265-
},
266-
}
267370
terminal.force_insert_mode(mock_claude_code, mock_config)
268371
end)
269372

270373
assert.is_true(success, 'Force insert mode function should run without error')
271374
end)
272375

273376
it('should handle non-terminal buffers correctly', function()
377+
-- Setup mock with instances table but different current buffer
378+
local mock_claude_code = {
379+
claude_code = {
380+
instances = {
381+
['/test/instance'] = 2,
382+
},
383+
current_instance = '/test/instance',
384+
},
385+
}
386+
local mock_config = {
387+
window = {
388+
start_in_normal_mode = false,
389+
},
390+
}
391+
392+
-- Mock bufnr to return different buffer
393+
_G.vim.fn.bufnr = function(pattern)
394+
if pattern == '%' then
395+
return 1 -- Different from instances buffer
396+
end
397+
return 1
398+
end
399+
274400
-- For this test, we'll just verify that the function can be called without error
275401
local success, _ = pcall(function()
276-
-- Setup minimal mock that's different from terminal buffer
277-
local mock_claude_code = {
278-
claude_code = {
279-
bufnr = 2,
280-
},
281-
}
282-
local mock_config = {
283-
window = {
284-
start_in_normal_mode = false,
285-
},
286-
}
287402
terminal.force_insert_mode(mock_claude_code, mock_config)
288403
end)
289404

290405
assert.is_true(success, 'Force insert mode function should run without error')
291406
end)
292407
end)
293-
end)
408+
end)

0 commit comments

Comments
 (0)