@@ -1,457 +0,0 @@
1−package tools
2−
3−import (
4− "context"
5− "encoding/json"
6− "os"
7− "path/filepath"
8− "strings"
9− "testing"
10−
11− "github.com/stretchr/testify/assert"
12− "github.com/stretchr/testify/require"
13−)
14−
15−func TestLsTool_Info(t *testing.T) {
16− tool := NewLsTool()
17− info := tool.Info()
18−
19− assert.Equal(t, LSToolName, info.Name)
20− assert.NotEmpty(t, info.Description)
21− assert.Contains(t, info.Parameters, "path")
22− assert.Contains(t, info.Parameters, "ignore")
23− assert.Contains(t, info.Required, "path")
24−}
25−
26−func TestLsTool_Run(t *testing.T) {
27− // Create a temporary directory for testing
28− tempDir, err := os.MkdirTemp("", "ls_tool_test")
29− require.NoError(t, err)
30− defer os.RemoveAll(tempDir)
31−
32− // Create a test directory structure
33− testDirs := []string{
34− "dir1",
35− "dir2",
36− "dir2/subdir1",
37− "dir2/subdir2",
38− "dir3",
39− "dir3/.hidden_dir",
40− "__pycache__",
41− }
42−
43− testFiles := []string{
44− "file1.txt",
45− "file2.txt",
46− "dir1/file3.txt",
47− "dir2/file4.txt",
48− "dir2/subdir1/file5.txt",
49− "dir2/subdir2/file6.txt",
50− "dir3/file7.txt",
51− "dir3/.hidden_file.txt",
52− "__pycache__/cache.pyc",
53− ".hidden_root_file.txt",
54− }
55−
56− // Create directories
57− for _, dir := range testDirs {
58− dirPath := filepath.Join(tempDir, dir)
59− err := os.MkdirAll(dirPath, 0o755)
60− require.NoError(t, err)
61− }
62−
63− // Create files
64− for _, file := range testFiles {
65− filePath := filepath.Join(tempDir, file)
66− err := os.WriteFile(filePath, []byte("test content"), 0o644)
67− require.NoError(t, err)
68− }
69−
70− t.Run("lists directory successfully", func(t *testing.T) {
71− tool := NewLsTool()
72− params := LSParams{
73− Path: tempDir,
74− }
75−
76− paramsJSON, err := json.Marshal(params)
77− require.NoError(t, err)
78−
79− call := ToolCall{
80− Name: LSToolName,
81− Input: string(paramsJSON),
82− }
83−
84− response, err := tool.Run(context.Background(), call)
85− require.NoError(t, err)
86−
87− // Check that visible directories and files are included
88− assert.Contains(t, response.Content, "dir1")
89− assert.Contains(t, response.Content, "dir2")
90− assert.Contains(t, response.Content, "dir3")
91− assert.Contains(t, response.Content, "file1.txt")
92− assert.Contains(t, response.Content, "file2.txt")
93−
94− // Check that hidden files and directories are not included
95− assert.NotContains(t, response.Content, ".hidden_dir")
96− assert.NotContains(t, response.Content, ".hidden_file.txt")
97− assert.NotContains(t, response.Content, ".hidden_root_file.txt")
98−
99− // Check that __pycache__ is not included
100− assert.NotContains(t, response.Content, "__pycache__")
101− })
102−
103− t.Run("handles non-existent path", func(t *testing.T) {
104− tool := NewLsTool()
105− params := LSParams{
106− Path: filepath.Join(tempDir, "non_existent_dir"),
107− }
108−
109− paramsJSON, err := json.Marshal(params)
110− require.NoError(t, err)
111−
112− call := ToolCall{
113− Name: LSToolName,
114− Input: string(paramsJSON),
115− }
116−
117− response, err := tool.Run(context.Background(), call)
118− require.NoError(t, err)
119− assert.Contains(t, response.Content, "path does not exist")
120− })
121−
122− t.Run("handles empty path parameter", func(t *testing.T) {
123− // For this test, we need to mock the config.WorkingDirectory function
124− // Since we can't easily do that, we'll just check that the response doesn't contain an error message
125−
126− tool := NewLsTool()
127− params := LSParams{
128− Path: "",
129− }
130−
131− paramsJSON, err := json.Marshal(params)
132− require.NoError(t, err)
133−
134− call := ToolCall{
135− Name: LSToolName,
136− Input: string(paramsJSON),
137− }
138−
139− response, err := tool.Run(context.Background(), call)
140− require.NoError(t, err)
141−
142− // The response should either contain a valid directory listing or an error
143− // We'll just check that it's not empty
144− assert.NotEmpty(t, response.Content)
145− })
146−
147− t.Run("handles invalid parameters", func(t *testing.T) {
148− tool := NewLsTool()
149− call := ToolCall{
150− Name: LSToolName,
151− Input: "invalid json",
152− }
153−
154− response, err := tool.Run(context.Background(), call)
155− require.NoError(t, err)
156− assert.Contains(t, response.Content, "error parsing parameters")
157− })
158−
159− t.Run("respects ignore patterns", func(t *testing.T) {
160− tool := NewLsTool()
161− params := LSParams{
162− Path: tempDir,
163− Ignore: []string{"file1.txt", "dir1"},
164− }
165−
166− paramsJSON, err := json.Marshal(params)
167− require.NoError(t, err)
168−
169− call := ToolCall{
170− Name: LSToolName,
171− Input: string(paramsJSON),
172− }
173−
174− response, err := tool.Run(context.Background(), call)
175− require.NoError(t, err)
176−
177− // The output format is a tree, so we need to check for specific patterns
178− // Check that file1.txt is not directly mentioned
179− assert.NotContains(t, response.Content, "- file1.txt")
180−
181− // Check that dir1/ is not directly mentioned
182− assert.NotContains(t, response.Content, "- dir1/")
183− })
184−
185− t.Run("handles relative path", func(t *testing.T) {
186− // Save original working directory
187− origWd, err := os.Getwd()
188− require.NoError(t, err)
189− defer func() {
190− os.Chdir(origWd)
191− }()
192−
193− // Change to a directory above the temp directory
194− parentDir := filepath.Dir(tempDir)
195− err = os.Chdir(parentDir)
196− require.NoError(t, err)
197−
198− tool := NewLsTool()
199− params := LSParams{
200− Path: filepath.Base(tempDir),
201− }
202−
203− paramsJSON, err := json.Marshal(params)
204− require.NoError(t, err)
205−
206− call := ToolCall{
207− Name: LSToolName,
208− Input: string(paramsJSON),
209− }
210−
211− response, err := tool.Run(context.Background(), call)
212− require.NoError(t, err)
213−
214− // Should list the temp directory contents
215− assert.Contains(t, response.Content, "dir1")
216− assert.Contains(t, response.Content, "file1.txt")
217− })
218−}
219−
220−func TestShouldSkip(t *testing.T) {
221− testCases := []struct {
222− name string
223− path string
224− ignorePatterns []string
225− expected bool
226− }{
227− {
228− name: "hidden file",
229− path: "/path/to/.hidden_file",
230− ignorePatterns: []string{},
231− expected: true,
232− },
233− {
234− name: "hidden directory",
235− path: "/path/to/.hidden_dir",
236− ignorePatterns: []string{},
237− expected: true,
238− },
239− {
240− name: "pycache directory",
241− path: "/path/to/__pycache__/file.pyc",
242− ignorePatterns: []string{},
243− expected: true,
244− },
245− {
246− name: "node_modules directory",
247− path: "/path/to/node_modules/package",
248− ignorePatterns: []string{},
249− expected: false, // The shouldSkip function doesn't directly check for node_modules in the path
250− },
251− {
252− name: "normal file",
253− path: "/path/to/normal_file.txt",
254− ignorePatterns: []string{},
255− expected: false,
256− },
257− {
258− name: "normal directory",
259− path: "/path/to/normal_dir",
260− ignorePatterns: []string{},
261− expected: false,
262− },
263− {
264− name: "ignored by pattern",
265− path: "/path/to/ignore_me.txt",
266− ignorePatterns: []string{"ignore_*.txt"},
267− expected: true,
268− },
269− {
270− name: "not ignored by pattern",
271− path: "/path/to/keep_me.txt",
272− ignorePatterns: []string{"ignore_*.txt"},
273− expected: false,
274− },
275− }
276−
277− for _, tc := range testCases {
278− t.Run(tc.name, func(t *testing.T) {
279− result := shouldSkip(tc.path, tc.ignorePatterns)
280− assert.Equal(t, tc.expected, result)
281− })
282− }
283−}
284−
285−func TestCreateFileTree(t *testing.T) {
286− paths := []string{
287− "/path/to/file1.txt",
288− "/path/to/dir1/file2.txt",
289− "/path/to/dir1/subdir/file3.txt",
290− "/path/to/dir2/file4.txt",
291− }
292−
293− tree := createFileTree(paths)
294−
295− // Check the structure of the tree
296− assert.Len(t, tree, 1) // Should have one root node
297−
298− // Check the root node
299− rootNode := tree[0]
300− assert.Equal(t, "path", rootNode.Name)
301− assert.Equal(t, "directory", rootNode.Type)
302− assert.Len(t, rootNode.Children, 1)
303−
304− // Check the "to" node
305− toNode := rootNode.Children[0]
306− assert.Equal(t, "to", toNode.Name)
307− assert.Equal(t, "directory", toNode.Type)
308− assert.Len(t, toNode.Children, 3) // file1.txt, dir1, dir2
309−
310− // Find the dir1 node
311− var dir1Node *TreeNode
312− for _, child := range toNode.Children {
313− if child.Name == "dir1" {
314− dir1Node = child
315− break
316− }
317− }
318−
319− require.NotNil(t, dir1Node)
320− assert.Equal(t, "directory", dir1Node.Type)
321− assert.Len(t, dir1Node.Children, 2) // file2.txt and subdir
322−}
323−
324−func TestPrintTree(t *testing.T) {
325− // Create a simple tree
326− tree := []*TreeNode{
327− {
328− Name: "dir1",
329− Path: "dir1",
330− Type: "directory",
331− Children: []*TreeNode{
332− {
333− Name: "file1.txt",
334− Path: "dir1/file1.txt",
335− Type: "file",
336− },
337− {
338− Name: "subdir",
339− Path: "dir1/subdir",
340− Type: "directory",
341− Children: []*TreeNode{
342− {
343− Name: "file2.txt",
344− Path: "dir1/subdir/file2.txt",
345− Type: "file",
346− },
347− },
348− },
349− },
350− },
351− {
352− Name: "file3.txt",
353− Path: "file3.txt",
354− Type: "file",
355− },
356− }
357−
358− result := printTree(tree, "/root")
359−
360− // Check the output format
361− assert.Contains(t, result, "- /root/")
362− assert.Contains(t, result, " - dir1/")
363− assert.Contains(t, result, " - file1.txt")
364− assert.Contains(t, result, " - subdir/")
365− assert.Contains(t, result, " - file2.txt")
366− assert.Contains(t, result, " - file3.txt")
367−}
368−
369−func TestListDirectory(t *testing.T) {
370− // Create a temporary directory for testing
371− tempDir, err := os.MkdirTemp("", "list_directory_test")
372− require.NoError(t, err)
373− defer os.RemoveAll(tempDir)
374−
375− // Create a test directory structure
376− testDirs := []string{
377− "dir1",
378− "dir1/subdir1",
379− ".hidden_dir",
380− }
381−
382− testFiles := []string{
383− "file1.txt",
384− "file2.txt",
385− "dir1/file3.txt",
386− "dir1/subdir1/file4.txt",
387− ".hidden_file.txt",
388− }
389−
390− // Create directories
391− for _, dir := range testDirs {
392− dirPath := filepath.Join(tempDir, dir)
393− err := os.MkdirAll(dirPath, 0o755)
394− require.NoError(t, err)
395− }
396−
397− // Create files
398− for _, file := range testFiles {
399− filePath := filepath.Join(tempDir, file)
400− err := os.WriteFile(filePath, []byte("test content"), 0o644)
401− require.NoError(t, err)
402− }
403−
404− t.Run("lists files with no limit", func(t *testing.T) {
405− files, truncated, err := listDirectory(tempDir, []string{}, 1000)
406− require.NoError(t, err)
407− assert.False(t, truncated)
408−
409− // Check that visible files and directories are included
410− containsPath := func(paths []string, target string) bool {
411− targetPath := filepath.Join(tempDir, target)
412− for _, path := range paths {
413− if strings.HasPrefix(path, targetPath) {
414− return true
415− }
416− }
417− return false
418− }
419−
420− assert.True(t, containsPath(files, "dir1"))
421− assert.True(t, containsPath(files, "file1.txt"))
422− assert.True(t, containsPath(files, "file2.txt"))
423− assert.True(t, containsPath(files, "dir1/file3.txt"))
424−
425− // Check that hidden files and directories are not included
426− assert.False(t, containsPath(files, ".hidden_dir"))
427− assert.False(t, containsPath(files, ".hidden_file.txt"))
428− })
429−
430− t.Run("respects limit and returns truncated flag", func(t *testing.T) {
431− files, truncated, err := listDirectory(tempDir, []string{}, 2)
432− require.NoError(t, err)
433− assert.True(t, truncated)
434− assert.Len(t, files, 2)
435− })
436−
437− t.Run("respects ignore patterns", func(t *testing.T) {
438− files, truncated, err := listDirectory(tempDir, []string{"*.txt"}, 1000)
439− require.NoError(t, err)
440− assert.False(t, truncated)
441−
442− // Check that no .txt files are included
443− for _, file := range files {
444− assert.False(t, strings.HasSuffix(file, ".txt"), "Found .txt file: %s", file)
445− }
446−
447− // But directories should still be included
448− containsDir := false
449− for _, file := range files {
450− if strings.Contains(file, "dir1") {
451− containsDir = true
452− break
453− }
454− }
455− assert.True(t, containsDir)
456− })
457−}