summaryrefslogtreecommitdiffhomepage
path: root/packages/lsp/src/tool.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/lsp/src/tool.test.ts')
-rw-r--r--packages/lsp/src/tool.test.ts492
1 files changed, 246 insertions, 246 deletions
diff --git a/packages/lsp/src/tool.test.ts b/packages/lsp/src/tool.test.ts
index efd1514..e4c72ed 100644
--- a/packages/lsp/src/tool.test.ts
+++ b/packages/lsp/src/tool.test.ts
@@ -3,274 +3,274 @@ import type { LspManager } from "./manager.js";
import { createLspTool } from "./tool.js";
function stubManager(overrides?: Partial<LspManager>): LspManager {
- return {
- status: async () => [],
- getClient: () => undefined,
- shutdownAll: () => {},
- ...overrides,
- } as unknown as LspManager;
+ return {
+ status: async () => [],
+ getClient: () => undefined,
+ shutdownAll: () => {},
+ ...overrides,
+ } as unknown as LspManager;
}
describe("tool", () => {
- it("diagnostics formats errors", async () => {
- const tool = createLspTool(stubManager());
- const result = await tool.execute(
- { operation: "diagnostics", path: "test.ts" },
- {
- toolCallId: "test",
- onOutput: () => {},
- signal: AbortSignal.timeout(5000),
- log: {
- debug: () => {},
- info: () => {},
- warn: () => {},
- error: () => {},
- child: () => ({}) as never,
- span: () => ({}) as never,
- },
- cwd: "/project",
- },
- );
- expect(result.isError).toBe(true);
- expect(result.content).toContain("No language server configured");
- });
+ it("diagnostics formats errors", async () => {
+ const tool = createLspTool(stubManager());
+ const result = await tool.execute(
+ { operation: "diagnostics", path: "test.ts" },
+ {
+ toolCallId: "test",
+ onOutput: () => {},
+ signal: AbortSignal.timeout(5000),
+ log: {
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
+ child: () => ({}) as never,
+ span: () => ({}) as never,
+ },
+ cwd: "/project",
+ },
+ );
+ expect(result.isError).toBe(true);
+ expect(result.content).toContain("No language server configured");
+ });
- it("position ops convert 1-based to 0-based", async () => {
- let receivedPosition: { line: number; character: number } | null = null;
+ it("position ops convert 1-based to 0-based", async () => {
+ let receivedPosition: { line: number; character: number } | null = null;
- const mockClient = {
- getState: () => "connected" as const,
- getStateError: () => undefined,
- request: async (method: string, params: unknown) => {
- if (method === "textDocument/hover") {
- receivedPosition = (params as { position: { line: number; character: number } }).position;
- return { contents: { value: "hover result" } };
- }
- return null;
- },
- waitForDiagnostics: async () => "",
- };
+ const mockClient = {
+ getState: () => "connected" as const,
+ getStateError: () => undefined,
+ request: async (method: string, params: unknown) => {
+ if (method === "textDocument/hover") {
+ receivedPosition = (params as { position: { line: number; character: number } }).position;
+ return { contents: { value: "hover result" } };
+ }
+ return null;
+ },
+ waitForDiagnostics: async () => "",
+ };
- const tool = createLspTool(
- stubManager({
- status: async () => [
- {
- id: "ts",
- name: "TypeScript",
- root: "/project",
- extensions: [".ts"],
- state: "connected",
- },
- ],
- getClient: () => mockClient as never,
- }),
- );
+ const tool = createLspTool(
+ stubManager({
+ status: async () => [
+ {
+ id: "ts",
+ name: "TypeScript",
+ root: "/project",
+ extensions: [".ts"],
+ state: "connected",
+ },
+ ],
+ getClient: () => mockClient as never,
+ }),
+ );
- const result = await tool.execute(
- { operation: "hover", path: "test.ts", line: 5, character: 10 },
- {
- toolCallId: "test",
- onOutput: () => {},
- signal: AbortSignal.timeout(5000),
- log: {
- debug: () => {},
- info: () => {},
- warn: () => {},
- error: () => {},
- child: () => ({}) as never,
- span: () => ({}) as never,
- },
- cwd: "/project",
- },
- );
+ const result = await tool.execute(
+ { operation: "hover", path: "test.ts", line: 5, character: 10 },
+ {
+ toolCallId: "test",
+ onOutput: () => {},
+ signal: AbortSignal.timeout(5000),
+ log: {
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
+ child: () => ({}) as never,
+ span: () => ({}) as never,
+ },
+ cwd: "/project",
+ },
+ );
- expect(receivedPosition).toEqual({ line: 4, character: 9 });
- expect(result.content).toBe("hover result");
- });
+ expect(receivedPosition).toEqual({ line: 4, character: 9 });
+ expect(result.content).toBe("hover result");
+ });
- it("path resolved against ctx.cwd", async () => {
- let receivedUri: string | null = null;
+ it("path resolved against ctx.cwd", async () => {
+ let receivedUri: string | null = null;
- const mockClient = {
- getState: () => "connected" as const,
- getStateError: () => undefined,
- request: async (method: string, params: unknown) => {
- if (method === "textDocument/hover") {
- receivedUri = (params as { textDocument: { uri: string } }).textDocument.uri;
- return { contents: { value: "ok" } };
- }
- return null;
- },
- waitForDiagnostics: async () => "",
- };
+ const mockClient = {
+ getState: () => "connected" as const,
+ getStateError: () => undefined,
+ request: async (method: string, params: unknown) => {
+ if (method === "textDocument/hover") {
+ receivedUri = (params as { textDocument: { uri: string } }).textDocument.uri;
+ return { contents: { value: "ok" } };
+ }
+ return null;
+ },
+ waitForDiagnostics: async () => "",
+ };
- const tool = createLspTool(
- stubManager({
- status: async () => [
- {
- id: "ts",
- name: "TypeScript",
- root: "/project",
- extensions: [".ts"],
- state: "connected",
- },
- ],
- getClient: () => mockClient as never,
- }),
- );
+ const tool = createLspTool(
+ stubManager({
+ status: async () => [
+ {
+ id: "ts",
+ name: "TypeScript",
+ root: "/project",
+ extensions: [".ts"],
+ state: "connected",
+ },
+ ],
+ getClient: () => mockClient as never,
+ }),
+ );
- await tool.execute(
- { operation: "hover", path: "src/test.ts", line: 1, character: 1 },
- {
- toolCallId: "test",
- onOutput: () => {},
- signal: AbortSignal.timeout(5000),
- log: {
- debug: () => {},
- info: () => {},
- warn: () => {},
- error: () => {},
- child: () => ({}) as never,
- span: () => ({}) as never,
- },
- cwd: "/project",
- },
- );
+ await tool.execute(
+ { operation: "hover", path: "src/test.ts", line: 1, character: 1 },
+ {
+ toolCallId: "test",
+ onOutput: () => {},
+ signal: AbortSignal.timeout(5000),
+ log: {
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
+ child: () => ({}) as never,
+ span: () => ({}) as never,
+ },
+ cwd: "/project",
+ },
+ );
- expect(receivedUri).toBe("file:///project/src/test.ts");
- });
+ expect(receivedUri).toBe("file:///project/src/test.ts");
+ });
- it("position op without line/character returns isError", async () => {
- const tool = createLspTool(
- stubManager({
- status: async () => [
- {
- id: "ts",
- name: "TypeScript",
- root: "/project",
- extensions: [".ts"],
- state: "connected",
- },
- ],
- }),
- );
+ it("position op without line/character returns isError", async () => {
+ const tool = createLspTool(
+ stubManager({
+ status: async () => [
+ {
+ id: "ts",
+ name: "TypeScript",
+ root: "/project",
+ extensions: [".ts"],
+ state: "connected",
+ },
+ ],
+ }),
+ );
- const result = await tool.execute(
- { operation: "hover", path: "test.ts" },
- {
- toolCallId: "test",
- onOutput: () => {},
- signal: AbortSignal.timeout(5000),
- log: {
- debug: () => {},
- info: () => {},
- warn: () => {},
- error: () => {},
- child: () => ({}) as never,
- span: () => ({}) as never,
- },
- cwd: "/project",
- },
- );
+ const result = await tool.execute(
+ { operation: "hover", path: "test.ts" },
+ {
+ toolCallId: "test",
+ onOutput: () => {},
+ signal: AbortSignal.timeout(5000),
+ log: {
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
+ child: () => ({}) as never,
+ span: () => ({}) as never,
+ },
+ cwd: "/project",
+ },
+ );
- expect(result.isError).toBe(true);
- expect(result.content).toContain("requires both");
- });
+ expect(result.isError).toBe(true);
+ expect(result.content).toContain("requires both");
+ });
- it("diagnostics op: a server that times out is skipped with a raise-to-user notice", async () => {
- const mockClient = {
- getState: () => "connected" as const,
- getStateError: () => undefined,
- request: async () => null,
- waitForDiagnostics: async () => ({ formatted: "", slow: false, timedOut: true }),
- };
+ it("diagnostics op: a server that times out is skipped with a raise-to-user notice", async () => {
+ const mockClient = {
+ getState: () => "connected" as const,
+ getStateError: () => undefined,
+ request: async () => null,
+ waitForDiagnostics: async () => ({ formatted: "", slow: false, timedOut: true }),
+ };
- const tool = createLspTool(
- stubManager({
- status: async () => [
- {
- id: "steep",
- name: "Steep",
- root: "/project",
- extensions: [".rb"],
- state: "connected",
- },
- ],
- getClient: () => mockClient as never,
- }),
- );
+ const tool = createLspTool(
+ stubManager({
+ status: async () => [
+ {
+ id: "steep",
+ name: "Steep",
+ root: "/project",
+ extensions: [".rb"],
+ state: "connected",
+ },
+ ],
+ getClient: () => mockClient as never,
+ }),
+ );
- const result = await tool.execute(
- { operation: "diagnostics", path: "game.rb" },
- {
- toolCallId: "test",
- onOutput: () => {},
- signal: AbortSignal.timeout(5000),
- log: {
- debug: () => {},
- info: () => {},
- warn: () => {},
- error: () => {},
- child: () => ({}) as never,
- span: () => ({}) as never,
- },
- cwd: "/project",
- },
- );
+ const result = await tool.execute(
+ { operation: "diagnostics", path: "game.rb" },
+ {
+ toolCallId: "test",
+ onOutput: () => {},
+ signal: AbortSignal.timeout(5000),
+ log: {
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
+ child: () => ({}) as never,
+ span: () => ({}) as never,
+ },
+ cwd: "/project",
+ },
+ );
- expect(result.isError).not.toBe(true);
- expect(result.content).toContain("[Steep]");
- expect(result.content).toContain("took too long");
- expect(result.content).toContain(">10s");
- expect(result.content).toContain("raise this to the user");
- });
+ expect(result.isError).not.toBe(true);
+ expect(result.content).toContain("[Steep]");
+ expect(result.content).toContain("took too long");
+ expect(result.content).toContain(">10s");
+ expect(result.content).toContain("raise this to the user");
+ });
- it("diagnostics op: responding servers' diagnostics are merged, tagged by source", async () => {
- const mockClient = {
- getState: () => "connected" as const,
- getStateError: () => undefined,
- request: async () => null,
- waitForDiagnostics: async () => ({
- formatted: "ERROR L1:1: boom",
- slow: false,
- timedOut: false,
- }),
- };
+ it("diagnostics op: responding servers' diagnostics are merged, tagged by source", async () => {
+ const mockClient = {
+ getState: () => "connected" as const,
+ getStateError: () => undefined,
+ request: async () => null,
+ waitForDiagnostics: async () => ({
+ formatted: "ERROR L1:1: boom",
+ slow: false,
+ timedOut: false,
+ }),
+ };
- const tool = createLspTool(
- stubManager({
- status: async () => [
- {
- id: "steep",
- name: "Steep",
- root: "/project",
- extensions: [".rb"],
- state: "connected",
- },
- ],
- getClient: () => mockClient as never,
- }),
- );
+ const tool = createLspTool(
+ stubManager({
+ status: async () => [
+ {
+ id: "steep",
+ name: "Steep",
+ root: "/project",
+ extensions: [".rb"],
+ state: "connected",
+ },
+ ],
+ getClient: () => mockClient as never,
+ }),
+ );
- const result = await tool.execute(
- { operation: "diagnostics", path: "game.rb" },
- {
- toolCallId: "test",
- onOutput: () => {},
- signal: AbortSignal.timeout(5000),
- log: {
- debug: () => {},
- info: () => {},
- warn: () => {},
- error: () => {},
- child: () => ({}) as never,
- span: () => ({}) as never,
- },
- cwd: "/project",
- },
- );
+ const result = await tool.execute(
+ { operation: "diagnostics", path: "game.rb" },
+ {
+ toolCallId: "test",
+ onOutput: () => {},
+ signal: AbortSignal.timeout(5000),
+ log: {
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
+ child: () => ({}) as never,
+ span: () => ({}) as never,
+ },
+ cwd: "/project",
+ },
+ );
- expect(result.content).toContain("[Steep]");
- expect(result.content).toContain("boom");
- });
+ expect(result.content).toContain("[Steep]");
+ expect(result.content).toContain("boom");
+ });
});