systemprompt-mcp-interview
Version:
A specialized Model Context Protocol (MCP) server that enables AI-powered interview roleplay scenarios
287 lines (286 loc) • 12.9 kB
JavaScript
import { handleListTools, handleToolCall } from "../tool-handlers.js";
import { SystemPromptService } from "../../services/systemprompt-service.js";
// Mock the SystemPromptService
jest.mock("../../services/systemprompt-service.js");
describe("Tool Handlers", () => {
let mockSystemPromptService;
beforeEach(() => {
// Clear all mocks before each test
jest.clearAllMocks();
// Setup mock implementation
mockSystemPromptService = {
createPrompt: jest.fn(),
editPrompt: jest.fn(),
createBlock: jest.fn(),
editBlock: jest.fn(),
};
// Replace the service instance with our mock
SystemPromptService.mockImplementation(() => mockSystemPromptService);
});
describe("handleListTools", () => {
let tools;
beforeEach(() => {
const result = handleListTools();
tools = result.tools;
});
it("should return all available tools with their schemas", () => {
expect(tools).toHaveLength(4);
expect(tools.map((t) => t.name)).toEqual([
"create_prompt",
"edit_prompt",
"create_block",
"edit_block",
]);
// Verify each tool has required properties
tools.forEach((tool) => {
expect(tool).toHaveProperty("name");
expect(tool).toHaveProperty("description");
expect(tool).toHaveProperty("inputSchema");
expect(tool.inputSchema).toHaveProperty("type", "object");
expect(tool.inputSchema).toHaveProperty("properties");
expect(tool.inputSchema).toHaveProperty("required");
});
});
it("should have valid create_prompt schema", () => {
const createPrompt = tools.find((t) => t.name === "create_prompt");
expect(createPrompt?.inputSchema.required).toContain("instruction");
expect(createPrompt?.inputSchema.required).toContain("input");
expect(createPrompt?.inputSchema.required).toContain("output");
expect(createPrompt?.inputSchema.required).toContain("metadata");
const props = createPrompt?.inputSchema.properties;
expect(props?.instruction.required).toContain("static");
expect(props?.input.required).toContain("name");
expect(props?.input.required).toContain("description");
expect(props?.input.required).toContain("type");
expect(props?.output.required).toContain("name");
expect(props?.output.required).toContain("description");
expect(props?.output.required).toContain("type");
expect(props?.metadata.required).toContain("title");
expect(props?.metadata.required).toContain("description");
});
it("should have valid edit_prompt schema", () => {
const editPrompt = tools.find((t) => t.name === "edit_prompt");
expect(editPrompt?.inputSchema.required).toContain("uuid");
expect(editPrompt?.inputSchema.properties).toHaveProperty("instruction");
expect(editPrompt?.inputSchema.properties).toHaveProperty("input");
expect(editPrompt?.inputSchema.properties).toHaveProperty("output");
expect(editPrompt?.inputSchema.properties).toHaveProperty("metadata");
});
it("should have valid create_block schema", () => {
const createBlock = tools.find((t) => t.name === "create_block");
expect(createBlock?.inputSchema.required).toContain("content");
expect(createBlock?.inputSchema.required).toContain("metadata");
expect(createBlock?.inputSchema.properties.prefix.pattern).toBe("^[a-zA-Z_]+$");
expect(createBlock?.inputSchema.properties.metadata.required).toContain("title");
expect(createBlock?.inputSchema.properties.metadata.required).toContain("description");
});
it("should have valid edit_block schema", () => {
const editBlock = tools.find((t) => t.name === "edit_block");
expect(editBlock?.inputSchema.required).toContain("uuid");
expect(editBlock?.inputSchema.properties).toHaveProperty("content");
expect(editBlock?.inputSchema.properties).toHaveProperty("prefix");
expect(editBlock?.inputSchema.properties).toHaveProperty("metadata");
expect(editBlock?.inputSchema.properties.prefix.pattern).toBe("^[a-zA-Z_]+$");
});
});
describe("handleToolCall", () => {
describe("create_prompt", () => {
const validPromptData = {
instruction: {
static: "Test instruction",
state: "Test state",
dynamic: "Test dynamic",
},
input: {
name: "test_input",
description: "Test input description",
type: ["message"],
},
output: {
name: "test_output",
description: "Test output description",
type: ["message"],
},
metadata: {
title: "Test prompt",
description: "Test description",
tag: ["test"],
},
};
it("should create a prompt successfully", async () => {
const mockResult = {
id: "test-uuid",
...validPromptData,
_link: "test-link",
metadata: {
...validPromptData.metadata,
created: "2024-01-01",
updated: "2024-01-01",
version: 1,
status: "draft",
author: "test",
log_message: "Created",
},
};
mockSystemPromptService.createPrompt.mockResolvedValue(mockResult);
const result = await handleToolCall({
params: {
name: "create_prompt",
arguments: validPromptData,
},
});
expect(mockSystemPromptService.createPrompt).toHaveBeenCalledWith(validPromptData);
expect(result.content[0].text).toBe(`Created prompt with ID: ${mockResult.id}`);
expect(result._meta.prompt).toEqual(mockResult);
});
});
describe("edit_prompt", () => {
const validEditData = {
uuid: "test-uuid",
instruction: {
static: "Updated instruction",
},
metadata: {
title: "Updated title",
description: "Test description",
},
};
it("should edit a prompt successfully", async () => {
const mockResult = {
id: "test-uuid",
instruction: { static: "Updated instruction" },
input: {
name: "test_input",
description: "Test input description",
type: ["message"],
},
output: {
name: "test_output",
description: "Test output description",
type: ["message"],
},
metadata: {
title: "Updated title",
description: "Test description",
created: "2024-01-01",
updated: "2024-01-01",
version: 1,
status: "draft",
author: "test",
log_message: "Updated",
},
_link: "test-link",
};
mockSystemPromptService.editPrompt.mockResolvedValue(mockResult);
const result = await handleToolCall({
params: {
name: "edit_prompt",
arguments: validEditData,
},
});
expect(mockSystemPromptService.editPrompt).toHaveBeenCalledWith(validEditData.uuid, expect.objectContaining({
instruction: validEditData.instruction,
metadata: validEditData.metadata,
}));
expect(result.content[0].text).toBe(`Updated prompt with ID: ${mockResult.id}`);
expect(result._meta.prompt).toEqual(mockResult);
});
});
describe("create_block", () => {
const validBlockData = {
content: "Test block content",
prefix: "test_block",
metadata: {
title: "Test block",
description: "Test description",
tag: ["test"],
},
};
it("should create a block successfully", async () => {
const mockResult = {
id: "test-uuid",
...validBlockData,
_link: "test-link",
metadata: {
...validBlockData.metadata,
created: "2024-01-01",
updated: "2024-01-01",
version: 1,
status: "draft",
author: "test",
log_message: "Created",
},
};
mockSystemPromptService.createBlock.mockResolvedValue(mockResult);
const result = await handleToolCall({
params: {
name: "create_block",
arguments: validBlockData,
},
});
expect(mockSystemPromptService.createBlock).toHaveBeenCalledWith(validBlockData);
expect(result.content[0].text).toBe(`Created block with ID: ${mockResult.id}`);
expect(result._meta.block).toEqual(mockResult);
});
});
describe("edit_block", () => {
const validEditData = {
uuid: "test-uuid",
content: "Updated content",
metadata: {
title: "Updated title",
description: "Test description",
},
};
it("should edit a block successfully", async () => {
const mockResult = {
id: "test-uuid",
content: "Updated content",
metadata: {
title: "Updated title",
description: "Test description",
created: "2024-01-01",
updated: "2024-01-01",
version: 1,
status: "draft",
author: "test",
log_message: "Updated",
},
_link: "test-link",
};
mockSystemPromptService.editBlock.mockResolvedValue(mockResult);
const result = await handleToolCall({
params: {
name: "edit_block",
arguments: validEditData,
},
});
expect(mockSystemPromptService.editBlock).toHaveBeenCalledWith(validEditData.uuid, expect.objectContaining({
content: validEditData.content,
metadata: validEditData.metadata,
}));
expect(result.content[0].text).toBe(`Updated block with ID: ${mockResult.id}`);
expect(result._meta.block).toEqual(mockResult);
});
});
describe("error handling", () => {
it("should throw error for unknown tool", async () => {
await expect(handleToolCall({
params: {
name: "unknown_tool",
arguments: {},
},
})).rejects.toThrow("Unknown tool");
});
it("should propagate service errors", async () => {
mockSystemPromptService.createPrompt.mockRejectedValue(new Error("Service error"));
await expect(handleToolCall({
params: {
name: "create_prompt",
arguments: {},
},
})).rejects.toThrow("Service error");
});
});
});
});