feat: add more tests for tool built-ins (#5)

This commit is contained in:
Charles Packer
2025-10-25 11:33:30 -07:00
committed by GitHub
parent dd773bf285
commit da2c50cbeb
19 changed files with 792 additions and 1 deletions

View File

@@ -41,11 +41,16 @@ jobs:
bun-version: 1.3.0
- name: Install dependencies
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bun install
- name: Lint
run: bun run lint
- name: Run tests
run: bun test
- name: Build bundle
run: bun run build

View File

@@ -36,6 +36,8 @@ jobs:
bun-version: 1.3.0
- name: Install dependencies
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bun install
- name: Build bundle

View File

@@ -21,7 +21,8 @@
"publishConfig": {
"access": "public"
},
"dependencies": {
"dependencies": {},
"optionalDependencies": {
"@vscode/ripgrep": "^1.17.0"
},
"devDependencies": {

View File

@@ -0,0 +1,65 @@
/**
* Test filesystem utilities
* Provides helpers for creating temporary test directories and files
*/
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
export class TestDirectory {
public readonly path: string;
constructor() {
this.path = mkdtempSync(join(tmpdir(), "letta-test-"));
}
/**
* Create a file in the test directory
*/
createFile(relativePath: string, content: string): string {
const filePath = join(this.path, relativePath);
const dir = join(filePath, "..");
mkdirSync(dir, { recursive: true });
writeFileSync(filePath, content, "utf-8");
return filePath;
}
/**
* Create a binary file in the test directory
*/
createBinaryFile(relativePath: string, buffer: Buffer): string {
const filePath = join(this.path, relativePath);
const dir = join(filePath, "..");
mkdirSync(dir, { recursive: true });
writeFileSync(filePath, buffer);
return filePath;
}
/**
* Create a directory in the test directory
*/
createDir(relativePath: string): string {
const dirPath = join(this.path, relativePath);
mkdirSync(dirPath, { recursive: true });
return dirPath;
}
/**
* Get full path for a relative path
*/
resolve(relativePath: string): string {
return join(this.path, relativePath);
}
/**
* Clean up the test directory
*/
cleanup(): void {
try {
rmSync(this.path, { recursive: true, force: true });
} catch (error) {
console.warn(`Failed to cleanup test directory ${this.path}:`, error);
}
}
}

View File

@@ -208,6 +208,8 @@ test("Unknown command suggests exact match", () => {
// ============================================================================
test("Read outside working directory suggests directory pattern", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const context = analyzeApprovalContext(
"Read",
{ file_path: "/Users/test/docs/api.md" },
@@ -245,6 +247,8 @@ test("Write suggests session-only approval", () => {
});
test("Edit suggests directory pattern for project-level", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const context = analyzeApprovalContext(
"Edit",
{ file_path: "src/utils/helper.ts" },
@@ -258,6 +262,8 @@ test("Edit suggests directory pattern for project-level", () => {
});
test("Edit at project root suggests project pattern", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const context = analyzeApprovalContext(
"Edit",
{ file_path: "README.md" },
@@ -269,6 +275,8 @@ test("Edit at project root suggests project pattern", () => {
});
test("Glob outside working directory suggests directory pattern", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const context = analyzeApprovalContext(
"Glob",
{ path: "/Users/test/docs" },
@@ -280,6 +288,8 @@ test("Glob outside working directory suggests directory pattern", () => {
});
test("Grep outside working directory suggests directory pattern", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const context = analyzeApprovalContext(
"Grep",
{ path: "/Users/test/docs" },

View File

@@ -8,6 +8,7 @@ import type { PermissionRules } from "../permissions/types";
// ============================================================================
test("Read within working directory is auto-allowed", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const result = checkPermission(
"Read",
{ file_path: "src/test.ts" },
@@ -170,6 +171,7 @@ test("Deny directory blocks all files within", () => {
// ============================================================================
test("Allow rule for file outside working directory", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const permissions: PermissionRules = {
allow: ["Read(/Users/test/docs/**)"],
deny: [],
@@ -385,6 +387,7 @@ test("Allow takes precedence over ask", () => {
});
test("Ask takes precedence over default", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const permissions: PermissionRules = {
allow: [],
deny: [],
@@ -523,6 +526,7 @@ test("Parent directory traversal", () => {
});
test("Absolute path handling", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const permissions: PermissionRules = {
allow: [],
deny: ["Read(/etc/**)"],

View File

@@ -84,6 +84,8 @@ test("File pattern: any .ts file", () => {
});
test("File pattern: absolute path with // prefix", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
expect(
matchesFilePattern(
"Read(/Users/test/docs/api.md)",
@@ -94,6 +96,8 @@ test("File pattern: absolute path with // prefix", () => {
});
test("File pattern: tilde expansion", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const homedir = require("node:os").homedir();
expect(
matchesFilePattern(

View File

@@ -4,6 +4,7 @@ import { checkPermission } from "../permissions/checker";
import type { PermissionRules } from "../permissions/types";
test("Read within working directory is auto-allowed", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const result = checkPermission(
"Read",
{ file_path: "src/test.ts" },
@@ -16,6 +17,8 @@ test("Read within working directory is auto-allowed", () => {
});
test("Read outside working directory requires approval", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const result = checkPermission(
"Read",
{ file_path: "/Users/test/other-project/file.ts" },
@@ -98,6 +101,8 @@ test("Dangerous commands don't offer persistence", () => {
});
test("Read outside working directory suggests directory pattern", () => {
if (process.platform === "win32") return; // Skip on Windows - Unix paths
const context = analyzeApprovalContext(
"Read",
{ file_path: "/Users/test/docs/api.md" },

View File

@@ -0,0 +1,68 @@
import { describe, expect, test } from "bun:test";
import { bash } from "../../tools/impl/Bash";
import { bash_output } from "../../tools/impl/BashOutput";
import { kill_bash } from "../../tools/impl/KillBash";
describe("Bash background tools", () => {
test("starts background process and returns ID in text", async () => {
const result = await bash({
command: "echo 'test'",
description: "Test background",
run_in_background: true,
});
expect(result.content[0].text).toContain("background with ID:");
expect(result.content[0].text).toMatch(/bash_\d+/);
});
test("BashOutput retrieves output from background shell", async () => {
// Start background process
const startResult = await bash({
command: "echo 'background output'",
description: "Test background",
run_in_background: true,
});
// Extract bash_id from the response text
const match = startResult.content[0].text.match(/bash_(\d+)/);
expect(match).toBeDefined();
const bashId = `bash_${match![1]}`;
// Wait for command to complete
await new Promise((resolve) => setTimeout(resolve, 200));
// Retrieve output
const outputResult = await bash_output({ bash_id: bashId });
expect(outputResult.message).toContain("background output");
});
test("BashOutput handles non-existent bash_id gracefully", async () => {
const result = await bash_output({ bash_id: "nonexistent" });
expect(result.message).toContain("No background process found");
});
test("KillBash terminates background process", async () => {
// Start long-running process
const startResult = await bash({
command: "sleep 10",
description: "Test kill",
run_in_background: true,
});
const match = startResult.content[0].text.match(/bash_(\d+)/);
const bashId = `bash_${match![1]}`;
// Kill it (KillBash uses shell_id parameter)
const killResult = await kill_bash({ shell_id: bashId });
expect(killResult.killed).toBe(true);
});
test("KillBash handles non-existent shell_id", async () => {
const result = await kill_bash({ shell_id: "nonexistent" });
expect(result.killed).toBe(false);
});
});

View File

@@ -0,0 +1,81 @@
import { describe, expect, test } from "bun:test";
import { bash } from "../../tools/impl/Bash";
describe("Bash tool", () => {
test("executes simple command", async () => {
const result = await bash({
command: "echo 'Hello, World!'",
description: "Test echo",
});
expect(result.content).toBeDefined();
expect(result.content[0].text).toContain("Hello, World!");
expect(result.isError).toBeUndefined();
});
test("captures stderr in output", async () => {
const result = await bash({
command: "echo 'error message' >&2",
description: "Test stderr",
});
expect(result.content[0].text).toContain("error message");
});
test("returns error for failed command", async () => {
const result = await bash({
command: "exit 1",
description: "Test exit code",
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain("Exit code");
});
test("times out long-running command", async () => {
const result = await bash({
command: "sleep 10",
description: "Test timeout",
timeout: 100,
});
expect(result.isError).toBe(true);
expect(result.content[0].text).toContain("timed out");
}, 2000);
test("runs command in background mode", async () => {
const result = await bash({
command: "echo 'background'",
description: "Test background",
run_in_background: true,
});
expect(result.content[0].text).toContain("background with ID:");
expect(result.content[0].text).toMatch(/bash_\d+/);
});
test("handles complex commands with pipes", async () => {
// Skip on Windows - pipe syntax is different
if (process.platform === "win32") {
return;
}
const result = await bash({
command: "echo -e 'foo\\nbar\\nbaz' | grep bar",
description: "Test pipe",
});
expect(result.content[0].text).toContain("bar");
expect(result.content[0].text).not.toContain("foo");
});
test("lists background processes with /bashes command", async () => {
const result = await bash({
command: "/bashes",
description: "List processes",
});
expect(result.content).toBeDefined();
expect(result.content[0].text).toBeDefined();
});
});

View File

@@ -0,0 +1,68 @@
import { afterEach, describe, expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { edit } from "../../tools/impl/Edit";
import { TestDirectory } from "../helpers/testFs";
describe("Edit tool", () => {
let testDir: TestDirectory;
afterEach(() => {
testDir?.cleanup();
});
test("replaces a simple string", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "Hello, World!");
const result = await edit({
file_path: file,
old_string: "World",
new_string: "Bun",
});
expect(readFileSync(file, "utf-8")).toBe("Hello, Bun!");
expect(result.replacements).toBe(1);
});
test("throws error if old_string not found", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "Hello, World!");
await expect(
edit({
file_path: file,
old_string: "NotFound",
new_string: "Something",
}),
).rejects.toThrow(/not found/);
});
test("replaces only first occurrence without replace_all", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("duplicate.txt", "foo bar foo baz");
const result = await edit({
file_path: file,
old_string: "foo",
new_string: "qux",
});
expect(readFileSync(file, "utf-8")).toBe("qux bar foo baz");
expect(result.replacements).toBe(1);
});
test("replaces all occurrences with replace_all=true", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("duplicate.txt", "foo bar foo baz foo");
const result = await edit({
file_path: file,
old_string: "foo",
new_string: "qux",
replace_all: true,
});
expect(readFileSync(file, "utf-8")).toBe("qux bar qux baz qux");
expect(result.replacements).toBe(3);
});
});

View File

@@ -0,0 +1,27 @@
import { describe, expect, test } from "bun:test";
import { exit_plan_mode } from "../../tools/impl/ExitPlanMode";
describe("ExitPlanMode tool", () => {
test("returns approval message", async () => {
const result = await exit_plan_mode({
plan: "1. Do thing A\n2. Do thing B\n3. Profit",
});
expect(result.message).toBeDefined();
expect(result.message).toContain("approved");
});
test("handles empty plan", async () => {
const result = await exit_plan_mode({ plan: "" });
expect(result.message).toBeDefined();
});
test("accepts markdown formatted plan", async () => {
const plan = "## Steps\n- Step 1\n- Step 2\n\n**Important:** Read the docs";
const result = await exit_plan_mode({ plan });
expect(result.message).toBeDefined();
expect(result.message).toContain("approved");
});
});

View File

@@ -0,0 +1,47 @@
import { afterEach, describe, expect, test } from "bun:test";
import { glob } from "../../tools/impl/Glob";
import { TestDirectory } from "../helpers/testFs";
describe("Glob tool", () => {
let testDir: TestDirectory;
afterEach(() => {
testDir?.cleanup();
});
test("finds files by pattern", async () => {
testDir = new TestDirectory();
testDir.createFile("test.ts", "");
testDir.createFile("test.js", "");
testDir.createFile("README.md", "");
const result = await glob({ pattern: "*.ts", path: testDir.path });
// Use path separator that works on both Unix and Windows
const pathSep = process.platform === "win32" ? "\\" : "/";
const basenames = result.files.map((f) => f.split(pathSep).pop());
expect(basenames).toContain("test.ts");
expect(basenames).not.toContain("test.js");
expect(basenames).not.toContain("README.md");
});
test("finds files with wildcard patterns", async () => {
testDir = new TestDirectory();
testDir.createFile("src/index.ts", "");
testDir.createFile("src/utils/helper.ts", "");
testDir.createFile("test.js", "");
const result = await glob({ pattern: "**/*.ts", path: testDir.path });
expect(result.files.filter((f) => f.endsWith(".ts")).length).toBe(2);
});
test("returns empty array when no matches", async () => {
testDir = new TestDirectory();
testDir.createFile("test.txt", "");
const result = await glob({ pattern: "*.ts", path: testDir.path });
expect(result.files).toEqual([]);
});
});

View File

@@ -0,0 +1,59 @@
import { afterEach, describe, expect, test } from "bun:test";
import { grep } from "../../tools/impl/Grep";
import { TestDirectory } from "../helpers/testFs";
describe("Grep tool", () => {
let testDir: TestDirectory;
afterEach(() => {
testDir?.cleanup();
});
test("finds pattern in files (requires ripgrep)", async () => {
testDir = new TestDirectory();
testDir.createFile("test1.txt", "Hello World");
testDir.createFile("test2.txt", "Goodbye World");
testDir.createFile("test3.txt", "No match here");
try {
const result = await grep({
pattern: "World",
path: testDir.path,
output_mode: "files_with_matches",
});
expect(result.output).toContain("test1.txt");
expect(result.output).toContain("test2.txt");
expect(result.output).not.toContain("test3.txt");
} catch (error) {
// Ripgrep might not be available in test environment
if (error instanceof Error && error.message.includes("ENOENT")) {
console.log("Skipping grep test - ripgrep not available");
} else {
throw error;
}
}
});
test("case insensitive search with -i flag", async () => {
testDir = new TestDirectory();
testDir.createFile("test.txt", "Hello WORLD");
try {
const result = await grep({
pattern: "world",
path: testDir.path,
"-i": true,
output_mode: "content",
});
expect(result.output).toContain("WORLD");
} catch (error) {
if (error instanceof Error && error.message.includes("ENOENT")) {
console.log("Skipping grep test - ripgrep not available");
} else {
throw error;
}
}
});
});

View File

@@ -0,0 +1,48 @@
import { afterEach, describe, expect, test } from "bun:test";
import { ls } from "../../tools/impl/LS";
import { TestDirectory } from "../helpers/testFs";
describe("LS tool", () => {
let testDir: TestDirectory;
afterEach(() => {
testDir?.cleanup();
});
test("lists files and directories", async () => {
testDir = new TestDirectory();
testDir.createFile("file1.txt", "");
testDir.createFile("file2.txt", "");
testDir.createDir("subdir");
const result = await ls({ path: testDir.path });
expect(result.content[0].text).toContain("file1.txt");
expect(result.content[0].text).toContain("file2.txt");
expect(result.content[0].text).toContain("subdir/");
});
test("shows directories with trailing slash", async () => {
testDir = new TestDirectory();
testDir.createDir("folder");
testDir.createFile("file.txt", "");
const result = await ls({ path: testDir.path });
expect(result.content[0].text).toContain("folder/");
expect(result.content[0].text).toContain("file.txt");
});
test("throws error for non-existent directory", async () => {
await expect(ls({ path: "/nonexistent/directory" })).rejects.toThrow(
/Directory not found/,
);
});
test("throws error for file (not directory)", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("notadir.txt", "");
await expect(ls({ path: file })).rejects.toThrow(/Not a directory/);
});
});

View File

@@ -0,0 +1,43 @@
import { afterEach, describe, expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { multi_edit } from "../../tools/impl/MultiEdit";
import { TestDirectory } from "../helpers/testFs";
describe("MultiEdit tool", () => {
let testDir: TestDirectory;
afterEach(() => {
testDir?.cleanup();
});
test("applies multiple edits to a file", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "foo bar baz");
await multi_edit({
file_path: file,
edits: [
{ old_string: "foo", new_string: "FOO" },
{ old_string: "bar", new_string: "BAR" },
],
});
expect(readFileSync(file, "utf-8")).toBe("FOO BAR baz");
});
test("applies edits sequentially", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("test.txt", "aaa bbb");
const result = await multi_edit({
file_path: file,
edits: [
{ old_string: "aaa", new_string: "xxx" },
{ old_string: "bbb", new_string: "yyy" },
],
});
expect(readFileSync(file, "utf-8")).toBe("xxx yyy");
expect(result.edits_applied).toBe(2);
});
});

View File

@@ -0,0 +1,105 @@
import { afterEach, describe, expect, test } from "bun:test";
import { read } from "../../tools/impl/Read";
import { TestDirectory } from "../helpers/testFs";
describe("Read tool", () => {
let testDir: TestDirectory;
afterEach(() => {
testDir?.cleanup();
});
test("reads a basic text file", async () => {
testDir = new TestDirectory();
const file = testDir.createFile(
"test.txt",
"Hello, World!\nLine 2\nLine 3",
);
const result = await read({ file_path: file });
expect(result.content).toContain("Hello, World!");
expect(result.content).toContain("Line 2");
expect(result.content).toContain("Line 3");
});
test("reads UTF-8 file with Unicode characters", async () => {
testDir = new TestDirectory();
const content = "Hello 世界 🌍\n╔═══╗\n║ A ║\n╚═══╝";
const file = testDir.createFile("unicode.txt", content);
const result = await read({ file_path: file });
expect(result.content).toContain("世界");
expect(result.content).toContain("🌍");
expect(result.content).toContain("╔═══╗");
});
test("formats output with line numbers", async () => {
testDir = new TestDirectory();
const file = testDir.createFile("numbered.txt", "Line 1\nLine 2\nLine 3");
const result = await read({ file_path: file });
expect(result.content).toContain("1→Line 1");
expect(result.content).toContain("2→Line 2");
expect(result.content).toContain("3→Line 3");
});
test("respects offset parameter", async () => {
testDir = new TestDirectory();
const file = testDir.createFile(
"offset.txt",
"Line 1\nLine 2\nLine 3\nLine 4\nLine 5",
);
const result = await read({ file_path: file, offset: 2 });
expect(result.content).not.toContain("Line 1");
expect(result.content).not.toContain("Line 2");
expect(result.content).toContain("Line 3");
});
test("respects limit parameter", async () => {
testDir = new TestDirectory();
const file = testDir.createFile(
"limit.txt",
"Line 1\nLine 2\nLine 3\nLine 4\nLine 5",
);
const result = await read({ file_path: file, limit: 2 });
expect(result.content).toContain("Line 1");
expect(result.content).toContain("Line 2");
expect(result.content).not.toContain("Line 3");
});
test("detects binary files and throws error", async () => {
testDir = new TestDirectory();
const binaryBuffer = Buffer.from([0x00, 0x01, 0x02, 0x03, 0xff, 0xfe]);
const file = testDir.createBinaryFile("binary.bin", binaryBuffer);
await expect(read({ file_path: file })).rejects.toThrow(
/Cannot read binary file/,
);
});
test("reads TypeScript file with box-drawing characters", async () => {
testDir = new TestDirectory();
const tsContent = `// TypeScript file
const box = \`
┌─────────┐
│ Header │
└─────────┘
\`;
export default box;
`;
const file = testDir.createFile("ascii-art.ts", tsContent);
const result = await read({ file_path: file });
expect(result.content).toContain("┌─────────┐");
expect(result.content).toContain("│ Header │");
expect(result.content).toContain("TypeScript file");
});
});

View File

@@ -0,0 +1,98 @@
import { describe, expect, test } from "bun:test";
import { todo_write } from "../../tools/impl/TodoWrite";
describe("TodoWrite tool", () => {
test("accepts valid todos with all required fields", async () => {
const result = await todo_write({
todos: [
{ id: "1", content: "Task 1", status: "pending" },
{ id: "2", content: "Task 2", status: "in_progress" },
],
});
expect(result.message).toBeDefined();
expect(result.message).toContain("modified successfully");
});
test("requires id field", async () => {
await expect(
todo_write({
todos: [
// @ts-expect-error - testing invalid input
{ content: "Missing id", status: "pending" },
],
}),
).rejects.toThrow(/id string/);
});
test("requires content field", async () => {
await expect(
todo_write({
todos: [
// @ts-expect-error - testing invalid input
{ id: "1", status: "pending" },
],
}),
).rejects.toThrow(/content string/);
});
test("requires status field", async () => {
await expect(
todo_write({
todos: [
// @ts-expect-error - testing invalid input
{ id: "1", content: "Test" },
],
}),
).rejects.toThrow(/valid status/);
});
test("validates status values", async () => {
await expect(
todo_write({
todos: [
// @ts-expect-error - testing invalid status
{ id: "1", content: "Test", status: "invalid" },
],
}),
).rejects.toThrow(/valid status/);
});
test("handles empty todo list", async () => {
const result = await todo_write({ todos: [] });
expect(result.message).toBeDefined();
});
test("accepts optional priority field", async () => {
const result = await todo_write({
todos: [
{
id: "1",
content: "High priority task",
status: "pending",
priority: "high",
},
{
id: "2",
content: "Low priority task",
status: "pending",
priority: "low",
},
],
});
expect(result.message).toContain("modified successfully");
});
test("validates priority values", async () => {
await expect(
todo_write({
todos: [
// @ts-expect-error - testing invalid priority
{ id: "1", content: "Test", status: "pending", priority: "urgent" },
],
}),
).rejects.toThrow(/priority must be/);
});
});

View File

@@ -0,0 +1,51 @@
import { afterEach, describe, expect, test } from "bun:test";
import { existsSync, readFileSync } from "node:fs";
import { write } from "../../tools/impl/Write";
import { TestDirectory } from "../helpers/testFs";
describe("Write tool", () => {
let testDir: TestDirectory;
afterEach(() => {
testDir?.cleanup();
});
test("creates a new file", async () => {
testDir = new TestDirectory();
const filePath = testDir.resolve("new.txt");
await write({ file_path: filePath, content: "Hello, World!" });
expect(existsSync(filePath)).toBe(true);
expect(readFileSync(filePath, "utf-8")).toBe("Hello, World!");
});
test("overwrites existing file", async () => {
testDir = new TestDirectory();
const filePath = testDir.createFile("existing.txt", "Old content");
await write({ file_path: filePath, content: "New content" });
expect(readFileSync(filePath, "utf-8")).toBe("New content");
});
test("creates nested directories automatically", async () => {
testDir = new TestDirectory();
const filePath = testDir.resolve("nested/deep/file.txt");
await write({ file_path: filePath, content: "Nested file" });
expect(existsSync(filePath)).toBe(true);
expect(readFileSync(filePath, "utf-8")).toBe("Nested file");
});
test("writes UTF-8 content correctly", async () => {
testDir = new TestDirectory();
const filePath = testDir.resolve("unicode.txt");
const content = "Hello 世界 🌍\n╔═══╗";
await write({ file_path: filePath, content });
expect(readFileSync(filePath, "utf-8")).toBe(content);
});
});