fileditor-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,213 @@
1
+ import { ReadFileHandler } from '../src/handlers/readFile.js';
2
+ import { FileUtils } from '../src/utils/fileUtils.js';
3
+ import { describe, it, beforeEach, afterEach } from 'node:test';
4
+ import assert from 'node:assert';
5
+ import fs from 'fs/promises';
6
+ import { join } from 'path';
7
+ import { existsSync } from 'fs';
8
+
9
+ /**
10
+ * Test suite for ReadFileHandler.
11
+ * Tests the file reading functionality.
12
+ */
13
+ describe('ReadFileHandler', () => {
14
+
15
+ const testDir = './test_files_read';
16
+ const testFile1 = join(testDir, 'test1.txt');
17
+ const testFile2 = join(testDir, 'test2.txt');
18
+ const testContent1 = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5';
19
+ const testContent2 = 'File 2 Line 1\nFile 2 Line 2\nFile 2 Line 3';
20
+
21
+ beforeEach(async () => {
22
+ // Set up test workspace
23
+ FileUtils.setWorkspaceRoot(process.cwd());
24
+
25
+ // Create test directory and files
26
+ if (!existsSync(testDir)) {
27
+ await fs.mkdir(testDir, { recursive: true });
28
+ }
29
+ await fs.writeFile(testFile1, testContent1, 'utf8');
30
+ await fs.writeFile(testFile2, testContent2, 'utf8');
31
+ });
32
+
33
+ afterEach(async () => {
34
+ // Clean up test files
35
+ try {
36
+ if (existsSync(testFile1)) await fs.unlink(testFile1);
37
+ if (existsSync(testFile2)) await fs.unlink(testFile2);
38
+ if (existsSync(testDir)) await fs.rmdir(testDir);
39
+ } catch (error) {
40
+ console.warn('Failed to clean up test files:', error.message);
41
+ }
42
+ });
43
+
44
+ describe('Single file reading', () => {
45
+
46
+ it('should successfully read a complete file', async () => {
47
+ const args = { path: testFile1 };
48
+
49
+ const result = await ReadFileHandler.handle(args);
50
+
51
+ assert.strictEqual(result.content[0].type, 'text');
52
+ const text = result.content[0].text;
53
+ assert.ok(text.includes('1 | Line 1'));
54
+ assert.ok(text.includes('2 | Line 2'));
55
+ assert.ok(text.includes('5 | Line 5'));
56
+ });
57
+
58
+ it('should support line range reading', async () => {
59
+ const args = {
60
+ path: testFile1,
61
+ line_range: '2-4'
62
+ };
63
+
64
+ const result = await ReadFileHandler.handle(args);
65
+
66
+ assert.strictEqual(result.content[0].type, 'text');
67
+ const text = result.content[0].text;
68
+ assert.ok(text.includes('2 | Line 2'));
69
+ assert.ok(text.includes('3 | Line 3'));
70
+ assert.ok(text.includes('4 | Line 4'));
71
+ assert.ok(!text.includes('1 | Line 1'));
72
+ assert.ok(!text.includes('5 | Line 5'));
73
+ });
74
+
75
+ it('should handle single line range', async () => {
76
+ const args = {
77
+ path: testFile1,
78
+ line_range: '3-3'
79
+ };
80
+
81
+ const result = await ReadFileHandler.handle(args);
82
+
83
+ assert.strictEqual(result.content[0].type, 'text');
84
+ const text = result.content[0].text;
85
+ assert.ok(text.includes('3 | Line 3'));
86
+ assert.ok(!text.includes('2 | Line 2'));
87
+ assert.ok(!text.includes('4 | Line 4'));
88
+ });
89
+
90
+ it('should throw an error when the file does not exist', async () => {
91
+ const args = { path: './nonexistent.txt' };
92
+
93
+ await assert.rejects(
94
+ () => ReadFileHandler.handle(args),
95
+ (error) => error.message.includes('Failed to read file(s)')
96
+ );
97
+ });
98
+
99
+ it('should handle invalid line range format', async () => {
100
+ const args = {
101
+ path: testFile1,
102
+ line_range: 'invalid-range'
103
+ };
104
+
105
+ await assert.rejects(
106
+ () => ReadFileHandler.handle(args),
107
+ (error) => error.message.includes('Failed to read file(s)')
108
+ );
109
+ });
110
+
111
+ });
112
+
113
+ describe('Multiple file reading', () => {
114
+
115
+ it('should successfully read multiple files', async () => {
116
+ const args = { path: [testFile1, testFile2] };
117
+
118
+ const result = await ReadFileHandler.handle(args);
119
+
120
+ assert.strictEqual(result.content[0].type, 'text');
121
+ const text = result.content[0].text;
122
+ assert.ok(text.includes('Successfully read 2 file(s)'));
123
+ assert.ok(text.includes(testFile1));
124
+ assert.ok(text.includes(testFile2));
125
+ assert.ok(text.includes('Line 1'));
126
+ assert.ok(text.includes('File 2 Line 1'));
127
+ });
128
+
129
+ it('should handle cases where some files do not exist', async () => {
130
+ const args = { path: [testFile1, './nonexistent.txt', testFile2] };
131
+
132
+ const result = await ReadFileHandler.handle(args);
133
+
134
+ assert.strictEqual(result.content[0].type, 'text');
135
+ const text = result.content[0].text;
136
+ assert.ok(text.includes('Successfully read 2 file(s)'));
137
+ assert.ok(text.includes('Errors encountered'));
138
+ assert.ok(text.includes('nonexistent.txt'));
139
+ });
140
+
141
+ it('should throw an error when all files do not exist', async () => {
142
+ const args = { path: ['./nonexistent1.txt', './nonexistent2.txt'] };
143
+
144
+ await assert.rejects(
145
+ () => ReadFileHandler.handle(args),
146
+ (error) => error.message.includes('Failed to read any files')
147
+ );
148
+ });
149
+
150
+ it('should handle an empty file array', async () => {
151
+ const args = { path: [] };
152
+
153
+ await assert.rejects(
154
+ () => ReadFileHandler.handle(args),
155
+ (error) => error.message.includes('Failed to read any files')
156
+ );
157
+ });
158
+
159
+ });
160
+
161
+ describe('Edge cases', () => {
162
+
163
+ it('should handle empty files', async () => {
164
+ const emptyFile = join(testDir, 'empty.txt');
165
+ await fs.writeFile(emptyFile, '', 'utf8');
166
+
167
+ const args = { path: emptyFile };
168
+
169
+ const result = await ReadFileHandler.handle(args);
170
+
171
+ assert.strictEqual(result.content[0].type, 'text');
172
+ // Empty files should return empty content or just the line number format
173
+
174
+ await fs.unlink(emptyFile);
175
+ });
176
+
177
+ it('should handle line range reading for large files', async () => {
178
+ const bigContent = Array.from({ length: 1000 }, (_, i) => `Line ${i + 1}`).join('\n');
179
+ const bigFile = join(testDir, 'big.txt');
180
+ await fs.writeFile(bigFile, bigContent, 'utf8');
181
+
182
+ const args = {
183
+ path: bigFile,
184
+ line_range: '500-505'
185
+ };
186
+
187
+ const result = await ReadFileHandler.handle(args);
188
+
189
+ assert.strictEqual(result.content[0].type, 'text');
190
+ const text = result.content[0].text;
191
+ assert.ok(text.includes('500 | Line 500'));
192
+ assert.ok(text.includes('505 | Line 505'));
193
+ assert.ok(!text.includes('499 | Line 499'));
194
+ assert.ok(!text.includes('506 | Line 506'));
195
+
196
+ await fs.unlink(bigFile);
197
+ });
198
+
199
+ it('should handle line numbers outside the file range', async () => {
200
+ const args = {
201
+ path: testFile1,
202
+ line_range: '10-20'
203
+ };
204
+
205
+ await assert.rejects(
206
+ () => ReadFileHandler.handle(args),
207
+ (error) => error.message.includes('Failed to read file(s)')
208
+ );
209
+ });
210
+
211
+ });
212
+
213
+ });