import { FileReadTool } from '../../src/tools/builtin/FileReadTool'; import { ToolContext } from '../../src/tools/base/ToolHandler'; import * as fs from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; describe('FileReadTool', () => { let tool: FileReadTool; let testDir: string; let testFile: string; const testContent = 'Hello, World!\nThis is a test file.'; beforeAll(async () => { tool = new FileReadTool(); testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'test-')); testFile = path.join(testDir, 'test.txt'); await fs.writeFile(testFile, testContent); }); afterAll(async () => { await fs.rm(testDir, { recursive: true }); }); const createContext = (permissions: string[] = ['file:read']): ToolContext => ({ requestId: 'test-request', permissions, }); describe('execute', () => { it('should read file content successfully', async () => { const result = await tool.execute( { path: testFile }, createContext(), ); expect(result).toEqual({ content: testContent, size: Buffer.from(testContent).length, path: testFile, }); }); it('should handle different encodings', async () => { const binaryFile = path.join(testDir, 'binary.bin'); const binaryContent = Buffer.from([0x00, 0x01, 0x02, 0x03]); await fs.writeFile(binaryFile, binaryContent); const result = await tool.execute( { path: binaryFile, encoding: 'binary' }, createContext(), ); expect(result.content).toBe(binaryContent.toString('binary')); }); it('should throw error for non-existent file', async () => { await expect( tool.execute( { path: './non/existent/file.txt' }, createContext(), ), ).rejects.toThrow('File not found'); }); it('should throw error for directory', async () => { await expect( tool.execute( { path: testDir }, createContext(), ), ).rejects.toThrow('Path is not a file'); }); it('should throw error without permission', async () => { await expect( tool.execute( { path: testFile }, createContext([]), ), ).rejects.toThrow('Permission denied: file:read required'); }); it('should prevent directory traversal', async () => { await expect( tool.execute( { path: '../../../etc/passwd' }, createContext(), ), ).rejects.toThrow('Invalid path: directory traversal not allowed'); }); }); });