@@ -5,12 +5,23 @@ describe("Tool: get_diagnostics", function()
5
5
6
6
before_each (function ()
7
7
package.loaded [" claudecode.tools.get_diagnostics" ] = nil
8
+ package.loaded [" claudecode.logger" ] = nil
9
+
10
+ -- Mock the logger module
11
+ package.loaded [" claudecode.logger" ] = {
12
+ debug = function () end ,
13
+ error = function () end ,
14
+ info = function () end ,
15
+ warn = function () end ,
16
+ }
17
+
8
18
get_diagnostics_handler = require (" claudecode.tools.get_diagnostics" ).handler
9
19
10
20
_G .vim = _G .vim or {}
11
21
_G .vim .lsp = _G .vim .lsp or {} -- Ensure vim.lsp exists for the check
12
22
_G .vim .diagnostic = _G .vim .diagnostic or {}
13
23
_G .vim .api = _G .vim .api or {}
24
+ _G .vim .fn = _G .vim .fn or {}
14
25
15
26
-- Default mocks
16
27
_G .vim .diagnostic .get = spy .new (function ()
@@ -19,12 +30,34 @@ describe("Tool: get_diagnostics", function()
19
30
_G .vim .api .nvim_buf_get_name = spy .new (function (bufnr )
20
31
return " /path/to/file_for_buf_" .. tostring (bufnr ) .. " .lua"
21
32
end )
33
+ _G .vim .json .encode = spy .new (function (obj )
34
+ return vim .inspect (obj ) -- Use vim.inspect as a simple serialization
35
+ end )
36
+ _G .vim .fn .bufnr = spy .new (function (filepath )
37
+ -- Mock buffer lookup
38
+ if filepath == " /test/file.lua" then
39
+ return 1
40
+ end
41
+ return - 1 -- File not open
42
+ end )
43
+ _G .vim .uri_to_fname = spy .new (function (uri )
44
+ -- Realistic mock that matches vim.uri_to_fname behavior
45
+ if uri :sub (1 , 7 ) == " file://" then
46
+ return uri :sub (8 )
47
+ end
48
+ -- Real vim.uri_to_fname throws an error for URIs without proper scheme
49
+ error (" URI must contain a scheme: " .. uri )
50
+ end )
22
51
end )
23
52
24
53
after_each (function ()
25
54
package.loaded [" claudecode.tools.get_diagnostics" ] = nil
55
+ package.loaded [" claudecode.logger" ] = nil
26
56
_G .vim .diagnostic .get = nil
27
57
_G .vim .api .nvim_buf_get_name = nil
58
+ _G .vim .json .encode = nil
59
+ _G .vim .fn .bufnr = nil
60
+ _G .vim .uri_to_fname = nil
28
61
-- Note: We don't nullify _G.vim.lsp or _G.vim.diagnostic entirely
29
62
-- as they are checked for existence.
30
63
end )
@@ -33,9 +66,9 @@ describe("Tool: get_diagnostics", function()
33
66
local success , result = pcall (get_diagnostics_handler , {})
34
67
expect (success ).to_be_true ()
35
68
expect (result ).to_be_table ()
36
- expect (result .diagnostics ).to_be_table ()
37
- expect (# result .diagnostics ).to_be (0 )
38
- assert .spy (_G .vim .diagnostic .get ).was_called_with (0 )
69
+ expect (result .content ).to_be_table ()
70
+ expect (# result .content ).to_be (0 )
71
+ assert .spy (_G .vim .diagnostic .get ).was_called_with (nil )
39
72
end )
40
73
41
74
it (" should return formatted diagnostics if available" , function ()
@@ -49,19 +82,24 @@ describe("Tool: get_diagnostics", function()
49
82
50
83
local success , result = pcall (get_diagnostics_handler , {})
51
84
expect (success ).to_be_true ()
52
- expect (result .diagnostics ).to_be_table ()
53
- expect (# result .diagnostics ).to_be (2 )
85
+ expect (result .content ).to_be_table ()
86
+ expect (# result .content ).to_be (2 )
87
+
88
+ -- Check that results are MCP content items
89
+ expect (result .content [1 ].type ).to_be (" text" )
90
+ expect (result .content [2 ].type ).to_be (" text" )
54
91
55
- expect (result .diagnostics [1 ].file ).to_be (" /path/to/file_for_buf_1.lua" )
56
- expect (result .diagnostics [1 ].line ).to_be (10 )
57
- expect (result .diagnostics [1 ].character ).to_be (5 )
58
- expect (result .diagnostics [1 ].severity ).to_be (1 )
59
- expect (result .diagnostics [1 ].message ).to_be (" Error message 1" )
60
- expect (result .diagnostics [1 ].source ).to_be (" linter1" )
92
+ -- Verify JSON encoding was called with correct structure
93
+ assert .spy (_G .vim .json .encode ).was_called (2 )
61
94
62
- expect (result .diagnostics [2 ].file ).to_be (" /path/to/file_for_buf_2.lua" )
63
- expect (result .diagnostics [2 ].severity ).to_be (2 )
64
- expect (result .diagnostics [2 ].message ).to_be (" Warning message 2" )
95
+ -- Check the first diagnostic was encoded with 1-indexed values
96
+ local first_call_args = _G .vim .json .encode .calls [1 ].vals [1 ]
97
+ expect (first_call_args .filePath ).to_be (" /path/to/file_for_buf_1.lua" )
98
+ expect (first_call_args .line ).to_be (11 ) -- 10 + 1 for 1-indexing
99
+ expect (first_call_args .character ).to_be (6 ) -- 5 + 1 for 1-indexing
100
+ expect (first_call_args .severity ).to_be (1 )
101
+ expect (first_call_args .message ).to_be (" Error message 1" )
102
+ expect (first_call_args .source ).to_be (" linter1" )
65
103
66
104
assert .spy (_G .vim .api .nvim_buf_get_name ).was_called_with (1 )
67
105
assert .spy (_G .vim .api .nvim_buf_get_name ).was_called_with (2 )
@@ -87,8 +125,12 @@ describe("Tool: get_diagnostics", function()
87
125
88
126
local success , result = pcall (get_diagnostics_handler , {})
89
127
expect (success ).to_be_true ()
90
- expect (# result .diagnostics ).to_be (1 )
91
- expect (result .diagnostics [1 ].file ).to_be (" /path/to/file1.lua" )
128
+ expect (# result .content ).to_be (1 )
129
+
130
+ -- Verify only the diagnostic with a file path was included
131
+ assert .spy (_G .vim .json .encode ).was_called (1 )
132
+ local encoded_args = _G .vim .json .encode .calls [1 ].vals [1 ]
133
+ expect (encoded_args .filePath ).to_be (" /path/to/file1.lua" )
92
134
end )
93
135
94
136
it (" should error if vim.diagnostic.get is not available" , function ()
@@ -98,7 +140,7 @@ describe("Tool: get_diagnostics", function()
98
140
expect (err ).to_be_table ()
99
141
expect (err .code ).to_be (- 32000 )
100
142
assert_contains (err .message , " Feature unavailable" )
101
- assert_contains (err .data , " LSP or vim.diagnostic.get not available" )
143
+ assert_contains (err .data , " Diagnostics not available in this editor version/configuration. " )
102
144
end )
103
145
104
146
it (" should error if vim.diagnostic is not available" , function ()
@@ -120,4 +162,49 @@ describe("Tool: get_diagnostics", function()
120
162
expect (success ).to_be_false ()
121
163
expect (err .code ).to_be (- 32000 )
122
164
end )
165
+
166
+ it (" should filter diagnostics by URI when provided" , function ()
167
+ local mock_diagnostics = {
168
+ { bufnr = 1 , lnum = 10 , col = 5 , severity = 1 , message = " Error in file1" , source = " linter1" },
169
+ }
170
+ _G .vim .diagnostic .get = spy .new (function (bufnr )
171
+ if bufnr == 1 then
172
+ return mock_diagnostics
173
+ end
174
+ return {}
175
+ end )
176
+ _G .vim .api .nvim_buf_get_name = spy .new (function (bufnr )
177
+ if bufnr == 1 then
178
+ return " /test/file.lua"
179
+ end
180
+ return " "
181
+ end )
182
+
183
+ local success , result = pcall (get_diagnostics_handler , { uri = " file:///test/file.lua" })
184
+ expect (success ).to_be_true ()
185
+ expect (# result .content ).to_be (1 )
186
+
187
+ -- Should have used vim.uri_to_fname to convert URI to file path
188
+ assert .spy (_G .vim .uri_to_fname ).was_called_with (" file:///test/file.lua" )
189
+ assert .spy (_G .vim .diagnostic .get ).was_called_with (1 )
190
+ assert .spy (_G .vim .fn .bufnr ).was_called_with (" /test/file.lua" )
191
+ end )
192
+
193
+ it (" should error for URI of unopened file" , function ()
194
+ _G .vim .fn .bufnr = spy .new (function ()
195
+ return - 1 -- File not open
196
+ end )
197
+
198
+ local success , err = pcall (get_diagnostics_handler , { uri = " file:///unknown/file.lua" })
199
+ expect (success ).to_be_false ()
200
+ expect (err ).to_be_table ()
201
+ expect (err .code ).to_be (- 32001 )
202
+ expect (err .message ).to_be (" File not open" )
203
+ assert_contains (err .data , " File must be open to retrieve diagnostics: /unknown/file.lua" )
204
+
205
+ -- Should have used vim.uri_to_fname and checked for buffer but not called vim.diagnostic.get
206
+ assert .spy (_G .vim .uri_to_fname ).was_called_with (" file:///unknown/file.lua" )
207
+ assert .spy (_G .vim .fn .bufnr ).was_called_with (" /unknown/file.lua" )
208
+ assert .spy (_G .vim .diagnostic .get ).was_not_called ()
209
+ end )
123
210
end )
0 commit comments