- README.md: list definition/references/diagnostics + multi_edit in the tools overview; add a Code intelligence (LSP) section (lazy per-language servers, required binaries, post-edit sync, freshness wait); add a lspServers config example. - src/tools/codeIntel.test.ts: mock lspManager and assert each tool dispatches the right args (path/cwd, 1-indexed positions, includeDeclaration default true) and returns the manager result verbatim — no servers spawned. 7 tests. Verified: typecheck clean, 263 tests pass (+7).
68 lines
2.9 KiB
TypeScript
68 lines
2.9 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
// The LSP tools (definition/references/diagnostics) are thin dispatchers over lspManager. We mock
|
|
// the manager functions so the tests run without spawning a language server, and assert each tool
|
|
// forwards the right arguments (path resolved against cwd, 1-indexed→handled by the manager,
|
|
// includeDeclaration default) and returns the manager's result verbatim.
|
|
|
|
vi.mock("../codeintel/lspManager.js", () => ({
|
|
getDefinition: vi.fn(async () => ({ definitions: [{ path: "/abs/a.ts", line: 3, column: 5 }] })),
|
|
getReferences: vi.fn(async () => ({ references: [{ path: "/abs/a.ts", line: 3, column: 5 }] })),
|
|
getDiagnostics: vi.fn(async () => ({
|
|
diagnostics: [{ path: "/abs/a.ts", line: 1, column: 1, severity: "error", message: "oops" }],
|
|
})),
|
|
}));
|
|
|
|
import { definitionTool, referencesTool, diagnosticsTool } from "./codeIntel.js";
|
|
import { getDefinition, getReferences, getDiagnostics } from "../codeintel/lspManager.js";
|
|
|
|
const ctx = { cwd: "/proj" };
|
|
|
|
describe("definition tool", () => {
|
|
beforeEach(() => vi.clearAllMocks());
|
|
|
|
it("forwards path/line/column/cwd to getDefinition and returns its result", async () => {
|
|
const out = await definitionTool.handler({ path: "src/a.ts", line: 3, column: 5 }, ctx);
|
|
expect(getDefinition).toHaveBeenCalledWith("src/a.ts", 3, 5, "/proj");
|
|
expect(out).toEqual({ definitions: [{ path: "/abs/a.ts", line: 3, column: 5 }] });
|
|
});
|
|
|
|
it("is read-only (no permission prompt)", () => {
|
|
expect(definitionTool.mutating).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("references tool", () => {
|
|
beforeEach(() => vi.clearAllMocks());
|
|
|
|
it("defaults includeDeclaration to true when omitted", async () => {
|
|
await referencesTool.handler({ path: "src/a.ts", line: 3, column: 5 }, ctx);
|
|
expect(getReferences).toHaveBeenCalledWith("src/a.ts", 3, 5, "/proj", true);
|
|
});
|
|
|
|
it("passes an explicit includeDeclaration through", async () => {
|
|
await referencesTool.handler({ path: "src/a.ts", line: 3, column: 5, include_declaration: false }, ctx);
|
|
expect(getReferences).toHaveBeenCalledWith("src/a.ts", 3, 5, "/proj", false);
|
|
});
|
|
|
|
it("returns the manager's references result", async () => {
|
|
const out = await referencesTool.handler({ path: "src/a.ts", line: 3, column: 5 }, ctx);
|
|
expect(out).toEqual({ references: [{ path: "/abs/a.ts", line: 3, column: 5 }] });
|
|
});
|
|
});
|
|
|
|
describe("diagnostics tool", () => {
|
|
beforeEach(() => vi.clearAllMocks());
|
|
|
|
it("forwards path/cwd to getDiagnostics and returns its result", async () => {
|
|
const out = await diagnosticsTool.handler({ path: "src/a.ts" }, ctx);
|
|
expect(getDiagnostics).toHaveBeenCalledWith("src/a.ts", "/proj");
|
|
expect(out).toEqual({
|
|
diagnostics: [{ path: "/abs/a.ts", line: 1, column: 1, severity: "error", message: "oops" }],
|
|
});
|
|
});
|
|
|
|
it("is read-only", () => {
|
|
expect(diagnosticsTool.mutating).toBe(false);
|
|
});
|
|
}); |