@@ -1,461 +0,0 @@
11− "github.com/kujtimiihoxha/opencode/internal/lsp"
12− "github.com/stretchr/testify/assert"
13− "github.com/stretchr/testify/require"
16−func TestEditTool_Info(t *testing.T) {
17− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
20− assert.Equal(t, EditToolName, info.Name)
21− assert.NotEmpty(t, info.Description)
22− assert.Contains(t, info.Parameters, "file_path")
23− assert.Contains(t, info.Parameters, "old_string")
24− assert.Contains(t, info.Parameters, "new_string")
25− assert.Contains(t, info.Required, "file_path")
26− assert.Contains(t, info.Required, "old_string")
27− assert.Contains(t, info.Required, "new_string")
30−func TestEditTool_Run(t *testing.T) {
31− // Create a temporary directory for testing
32− tempDir, err := os.MkdirTemp("", "edit_tool_test")
33− require.NoError(t, err)
34− defer os.RemoveAll(tempDir)
36− t.Run("creates a new file successfully", func(t *testing.T) {
37− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
39− filePath := filepath.Join(tempDir, "new_file.txt")
40− content := "This is a test content"
42− params := EditParams{
48− paramsJSON, err := json.Marshal(params)
49− require.NoError(t, err)
53− Input: string(paramsJSON),
56− response, err := tool.Run(context.Background(), call)
57− require.NoError(t, err)
58− assert.Contains(t, response.Content, "File created")
60− // Verify file was created with correct content
61− fileContent, err := os.ReadFile(filePath)
62− require.NoError(t, err)
63− assert.Equal(t, content, string(fileContent))
66− t.Run("creates file with nested directories", func(t *testing.T) {
67− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
69− filePath := filepath.Join(tempDir, "nested/dirs/new_file.txt")
70− content := "Content in nested directory"
72− params := EditParams{
78− paramsJSON, err := json.Marshal(params)
79− require.NoError(t, err)
83− Input: string(paramsJSON),
86− response, err := tool.Run(context.Background(), call)
87− require.NoError(t, err)
88− assert.Contains(t, response.Content, "File created")
90− // Verify file was created with correct content
91− fileContent, err := os.ReadFile(filePath)
92− require.NoError(t, err)
93− assert.Equal(t, content, string(fileContent))
96− t.Run("fails to create file that already exists", func(t *testing.T) {
97− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
99− // Create a file first
100− filePath := filepath.Join(tempDir, "existing_file.txt")
101− initialContent := "Initial content"
102− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
103− require.NoError(t, err)
105− // Try to create the same file
106− params := EditParams{
109− NewString: "New content",
112− paramsJSON, err := json.Marshal(params)
113− require.NoError(t, err)
117− Input: string(paramsJSON),
120− response, err := tool.Run(context.Background(), call)
121− require.NoError(t, err)
122− assert.Contains(t, response.Content, "file already exists")
125− t.Run("fails to create file when path is a directory", func(t *testing.T) {
126− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
128− // Create a directory
129− dirPath := filepath.Join(tempDir, "test_dir")
130− err := os.Mkdir(dirPath, 0o755)
131− require.NoError(t, err)
133− // Try to create a file with the same path as the directory
134− params := EditParams{
137− NewString: "Some content",
140− paramsJSON, err := json.Marshal(params)
141− require.NoError(t, err)
145− Input: string(paramsJSON),
148− response, err := tool.Run(context.Background(), call)
149− require.NoError(t, err)
150− assert.Contains(t, response.Content, "path is a directory")
153− t.Run("replaces content successfully", func(t *testing.T) {
154− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
156− // Create a file first
157− filePath := filepath.Join(tempDir, "replace_content.txt")
158− initialContent := "Line 1\nLine 2\nLine 3\nLine 4\nLine 5"
159− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
160− require.NoError(t, err)
162− // Record the file read to avoid modification time check failure
163− recordFileRead(filePath)
166− oldString := "Line 2\nLine 3"
167− newString := "Line 2 modified\nLine 3 modified"
168− params := EditParams{
170− OldString: oldString,
171− NewString: newString,
174− paramsJSON, err := json.Marshal(params)
175− require.NoError(t, err)
179− Input: string(paramsJSON),
182− response, err := tool.Run(context.Background(), call)
183− require.NoError(t, err)
184− assert.Contains(t, response.Content, "Content replaced")
186− // Verify file was updated with correct content
187− expectedContent := "Line 1\nLine 2 modified\nLine 3 modified\nLine 4\nLine 5"
188− fileContent, err := os.ReadFile(filePath)
189− require.NoError(t, err)
190− assert.Equal(t, expectedContent, string(fileContent))
193− t.Run("deletes content successfully", func(t *testing.T) {
194− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
196− // Create a file first
197− filePath := filepath.Join(tempDir, "delete_content.txt")
198− initialContent := "Line 1\nLine 2\nLine 3\nLine 4\nLine 5"
199− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
200− require.NoError(t, err)
202− // Record the file read to avoid modification time check failure
203− recordFileRead(filePath)
206− oldString := "Line 2\nLine 3\n"
207− params := EditParams{
209− OldString: oldString,
213− paramsJSON, err := json.Marshal(params)
214− require.NoError(t, err)
218− Input: string(paramsJSON),
221− response, err := tool.Run(context.Background(), call)
222− require.NoError(t, err)
223− assert.Contains(t, response.Content, "Content deleted")
225− // Verify file was updated with correct content
226− expectedContent := "Line 1\nLine 4\nLine 5"
227− fileContent, err := os.ReadFile(filePath)
228− require.NoError(t, err)
229− assert.Equal(t, expectedContent, string(fileContent))
232− t.Run("handles invalid parameters", func(t *testing.T) {
233− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
237− Input: "invalid json",
240− response, err := tool.Run(context.Background(), call)
241− require.NoError(t, err)
242− assert.Contains(t, response.Content, "invalid parameters")
245− t.Run("handles missing file_path", func(t *testing.T) {
246− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
248− params := EditParams{
254− paramsJSON, err := json.Marshal(params)
255− require.NoError(t, err)
259− Input: string(paramsJSON),
262− response, err := tool.Run(context.Background(), call)
263− require.NoError(t, err)
264− assert.Contains(t, response.Content, "file_path is required")
267− t.Run("handles file not found", func(t *testing.T) {
268− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
270− filePath := filepath.Join(tempDir, "non_existent_file.txt")
271− params := EditParams{
273− OldString: "old content",
274− NewString: "new content",
277− paramsJSON, err := json.Marshal(params)
278− require.NoError(t, err)
282− Input: string(paramsJSON),
285− response, err := tool.Run(context.Background(), call)
286− require.NoError(t, err)
287− assert.Contains(t, response.Content, "file not found")
290− t.Run("handles old_string not found in file", func(t *testing.T) {
291− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
293− // Create a file first
294− filePath := filepath.Join(tempDir, "content_not_found.txt")
295− initialContent := "Line 1\nLine 2\nLine 3"
296− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
297− require.NoError(t, err)
299− // Record the file read to avoid modification time check failure
300− recordFileRead(filePath)
302− // Try to replace content that doesn't exist
303− params := EditParams{
305− OldString: "This content does not exist",
306− NewString: "new content",
309− paramsJSON, err := json.Marshal(params)
310− require.NoError(t, err)
314− Input: string(paramsJSON),
317− response, err := tool.Run(context.Background(), call)
318− require.NoError(t, err)
319− assert.Contains(t, response.Content, "old_string not found in file")
322− t.Run("handles multiple occurrences of old_string", func(t *testing.T) {
323− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
325− // Create a file with duplicate content
326− filePath := filepath.Join(tempDir, "duplicate_content.txt")
327− initialContent := "Line 1\nDuplicate\nLine 3\nDuplicate\nLine 5"
328− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
329− require.NoError(t, err)
331− // Record the file read to avoid modification time check failure
332− recordFileRead(filePath)
334− // Try to replace content that appears multiple times
335− params := EditParams{
337− OldString: "Duplicate",
338− NewString: "Replaced",
341− paramsJSON, err := json.Marshal(params)
342− require.NoError(t, err)
346− Input: string(paramsJSON),
349− response, err := tool.Run(context.Background(), call)
350− require.NoError(t, err)
351− assert.Contains(t, response.Content, "appears multiple times")
354− t.Run("handles file modified since last read", func(t *testing.T) {
355− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
358− filePath := filepath.Join(tempDir, "modified_file.txt")
359− initialContent := "Initial content"
360− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
361− require.NoError(t, err)
363− // Record an old read time
364− fileRecordMutex.Lock()
365− fileRecords[filePath] = fileRecord{
367− readTime: time.Now().Add(-1 * time.Hour),
369− fileRecordMutex.Unlock()
371− // Try to update the file
372− params := EditParams{
374− OldString: "Initial",
375− NewString: "Updated",
378− paramsJSON, err := json.Marshal(params)
379− require.NoError(t, err)
383− Input: string(paramsJSON),
386− response, err := tool.Run(context.Background(), call)
387− require.NoError(t, err)
388− assert.Contains(t, response.Content, "has been modified since it was last read")
390− // Verify file was not modified
391− fileContent, err := os.ReadFile(filePath)
392− require.NoError(t, err)
393− assert.Equal(t, initialContent, string(fileContent))
396− t.Run("handles file not read before editing", func(t *testing.T) {
397− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(true), newMockFileHistoryService())
400− filePath := filepath.Join(tempDir, "not_read_file.txt")
401− initialContent := "Initial content"
402− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
403− require.NoError(t, err)
405− // Try to update the file without reading it first
406− params := EditParams{
408− OldString: "Initial",
409− NewString: "Updated",
412− paramsJSON, err := json.Marshal(params)
413− require.NoError(t, err)
417− Input: string(paramsJSON),
420− response, err := tool.Run(context.Background(), call)
421− require.NoError(t, err)
422− assert.Contains(t, response.Content, "you must read the file before editing it")
425− t.Run("handles permission denied", func(t *testing.T) {
426− tool := NewEditTool(make(map[string]*lsp.Client), newMockPermissionService(false), newMockFileHistoryService())
429− filePath := filepath.Join(tempDir, "permission_denied.txt")
430− initialContent := "Initial content"
431− err := os.WriteFile(filePath, []byte(initialContent), 0o644)
432− require.NoError(t, err)
434− // Record the file read to avoid modification time check failure
435− recordFileRead(filePath)
437− // Try to update the file
438− params := EditParams{
440− OldString: "Initial",
441− NewString: "Updated",
444− paramsJSON, err := json.Marshal(params)
445− require.NoError(t, err)
449− Input: string(paramsJSON),
452− response, err := tool.Run(context.Background(), call)
453− require.NoError(t, err)
454− assert.Contains(t, response.Content, "permission denied")
456− // Verify file was not modified
457− fileContent, err := os.ReadFile(filePath)
458− require.NoError(t, err)
459− assert.Equal(t, initialContent, string(fileContent))