// src/tools/file/read.test.ts // Copyright (C) 2025 DTP Technologies, LLC // All Rights Reserved import { describe, it, expect, beforeEach } from "vitest"; import { FileReadTool } from "./read.js"; describe("FileReadTool", () => { let tool: FileReadTool; let mockSession: any; beforeEach(() => { tool = new FileReadTool(); mockSession = { _id: "test-session-id", user: "test-user-id", }; }); describe("definition", () => { it("should have correct tool name", () => { expect(tool.definition.function.name).toBe("file_read"); }); it("should have correct definition structure for AI clients", () => { const def = tool.definition; expect(def.type).toBe("function"); expect(def.function).toBeDefined(); expect(def.function.name).toBe("file_read"); expect(def.function.description).toBeDefined(); expect(def.function.parameters).toBeDefined(); const params = def.function.parameters as any; expect(params.type).toBe("object"); expect(params.properties).toBeDefined(); expect(params.properties.path).toBeDefined(); expect(params.required).toContain("path"); }); }); describe("execute", () => { it("should return error for missing path", async () => { const result = await tool.execute({ session: mockSession }, { path: "" }); expect(result).toContain("MISSING_PARAMETER"); expect(result).toContain("File path must not be empty"); }); it("should return error for non-existent file", async () => { const result = await tool.execute( { session: mockSession }, { path: "non/existent/file.txt" }, ); expect(result).toContain("NOT_FOUND"); expect(result).toContain("File not found"); }); it("should successfully read README.md", async () => { const result = await tool.execute( { session: mockSession }, { path: "README.md" }, ); // Result is now plain text with header metadata expect(result).toContain("PATH: README.md"); expect(result).toContain("TOTAL LINES:"); expect(result).toContain("LINES SHOWN:"); expect(result).toContain("FILE OPERATION: read"); expect(result).toContain("Gadget Code"); }); it("should read file with line numbers", async () => { const result = await tool.execute( { session: mockSession }, { path: "README.md" }, ); // Result is plain text - content is after the "---" separator expect(result).toContain("Gadget Code"); const lines = result.split("\n"); const firstContentLine = lines.find((l: string) => l.includes("Gadget Code"), ); expect(firstContentLine).toBeDefined(); if (firstContentLine) { expect(firstContentLine).toMatch(/^\d+:/); } }); it("should respect line range parameters", async () => { const result = await tool.execute( { session: mockSession }, { path: "README.md", startLine: 1, endLine: 3 }, ); // Result is plain text - check for line range in output expect(result).toContain("lines 1-3"); const lines = result.split("\n").filter((l: string) => l.match(/^\d+: /)); expect(lines.length).toBeLessThanOrEqual(3); }); }); describe("response format for AI clients", () => { it("should return a string that can be used in message content", async () => { const result = await tool.execute( { session: mockSession }, { path: "README.md" }, ); expect(typeof result).toBe("string"); expect(result.length).toBeGreaterThan(0); }); it("should return plain text with header metadata", async () => { const result = await tool.execute( { session: mockSession }, { path: "README.md" }, ); // Verify plain text format with header expect(result).toMatch(/^PATH:/m); expect(result).toContain("TOTAL LINES:"); expect(result).toContain("LINES SHOWN:"); expect(result).toContain("FILE OPERATION: read"); expect(result).toContain("---"); }); }); });