@@ -5,12 +5,23 @@ describe("Tool: get_diagnostics", function()
55
66 before_each (function ()
77 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+
818 get_diagnostics_handler = require (" claudecode.tools.get_diagnostics" ).handler
919
1020 _G .vim = _G .vim or {}
1121 _G .vim .lsp = _G .vim .lsp or {} -- Ensure vim.lsp exists for the check
1222 _G .vim .diagnostic = _G .vim .diagnostic or {}
1323 _G .vim .api = _G .vim .api or {}
24+ _G .vim .fn = _G .vim .fn or {}
1425
1526 -- Default mocks
1627 _G .vim .diagnostic .get = spy .new (function ()
@@ -19,12 +30,34 @@ describe("Tool: get_diagnostics", function()
1930 _G .vim .api .nvim_buf_get_name = spy .new (function (bufnr )
2031 return " /path/to/file_for_buf_" .. tostring (bufnr ) .. " .lua"
2132 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 )
2251 end )
2352
2453 after_each (function ()
2554 package.loaded [" claudecode.tools.get_diagnostics" ] = nil
55+ package.loaded [" claudecode.logger" ] = nil
2656 _G .vim .diagnostic .get = nil
2757 _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
2861 -- Note: We don't nullify _G.vim.lsp or _G.vim.diagnostic entirely
2962 -- as they are checked for existence.
3063 end )
@@ -33,9 +66,9 @@ describe("Tool: get_diagnostics", function()
3366 local success , result = pcall (get_diagnostics_handler , {})
3467 expect (success ).to_be_true ()
3568 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 )
3972 end )
4073
4174 it (" should return formatted diagnostics if available" , function ()
@@ -49,19 +82,24 @@ describe("Tool: get_diagnostics", function()
4982
5083 local success , result = pcall (get_diagnostics_handler , {})
5184 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" )
5491
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 )
6194
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" )
65103
66104 assert .spy (_G .vim .api .nvim_buf_get_name ).was_called_with (1 )
67105 assert .spy (_G .vim .api .nvim_buf_get_name ).was_called_with (2 )
@@ -87,8 +125,12 @@ describe("Tool: get_diagnostics", function()
87125
88126 local success , result = pcall (get_diagnostics_handler , {})
89127 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" )
92134 end )
93135
94136 it (" should error if vim.diagnostic.get is not available" , function ()
@@ -98,7 +140,7 @@ describe("Tool: get_diagnostics", function()
98140 expect (err ).to_be_table ()
99141 expect (err .code ).to_be (- 32000 )
100142 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. " )
102144 end )
103145
104146 it (" should error if vim.diagnostic is not available" , function ()
@@ -120,4 +162,49 @@ describe("Tool: get_diagnostics", function()
120162 expect (success ).to_be_false ()
121163 expect (err .code ).to_be (- 32000 )
122164 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 )
123210end )
0 commit comments