Skip to main content
Glama
by wei
search-posts.test.ts5.08 kB
/** * Contract Tests: search-posts tool * * Tests input validation and output schema compliance for the search-posts tool. * These tests verify the tool's contract without making real API calls. */ import { describe, expect, it } from "vitest"; import { searchPostsTool } from "../../src/tools/search-posts.js"; import { SearchPostsInputSchema } from "../../src/utils/validators.js"; describe("search-posts tool contract", () => { describe("Input Validation", () => { it("should accept valid minimal input with query only", () => { const input = { query: "AI" }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(true); }); it("should accept valid input with all parameters", () => { const input = { query: "Python", tags: ["story"], numericFilters: ["points>=100"], page: 0, hitsPerPage: 20, }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(true); }); it("should reject empty query string", () => { const input = { query: "" }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(false); }); it("should reject missing query parameter", () => { const input = { page: 0 }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(false); }); it("should accept optional tags array", () => { const input = { query: "test", tags: ["story", "comment"] }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(true); }); it("should reject negative page number", () => { const input = { query: "test", page: -1 }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(false); }); it("should accept page 0 (first page)", () => { const input = { query: "test", page: 0 }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(true); }); it("should reject hitsPerPage less than 1", () => { const input = { query: "test", hitsPerPage: 0 }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(false); }); it("should reject hitsPerPage greater than 1000", () => { const input = { query: "test", hitsPerPage: 1001 }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(false); }); it("should accept hitsPerPage within valid range (1-1000)", () => { const input = { query: "test", hitsPerPage: 50 }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(true); }); it("should accept multiple numeric filters", () => { const input = { query: "test", numericFilters: ["points>=100", "num_comments>=50"], }; const result = SearchPostsInputSchema.safeParse(input); expect(result.success).toBe(true); }); it("should apply default values for optional parameters", () => { const input = { query: "test" }; const result = SearchPostsInputSchema.parse(input); expect(result.page).toBe(0); expect(result.hitsPerPage).toBe(20); }); }); describe("Output Schema", () => { it("should return error result for invalid input", async () => { const result = await searchPostsTool({ query: "" }); expect(result.isError).toBe(true); expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe("text"); }); it("should return properly structured error for validation failure", async () => { const result = await searchPostsTool({ page: -1 }); expect(result.isError).toBe(true); const content = result.content[0]; if (content.type === "text") { expect(content.text).toContain("Validation error"); } }); it("should handle missing required parameters gracefully", async () => { const result = await searchPostsTool({}); expect(result.isError).toBe(true); const content = result.content[0]; if (content.type === "text") { expect(content.text).toContain("query"); } }); }); describe("Tool Metadata", () => { it("should have correct tool name", async () => { // Import metadata separately to test it const { searchPostsToolMetadata } = await import("../../src/tools/search-posts.js"); expect(searchPostsToolMetadata.name).toBe("search-posts"); }); it("should have comprehensive description", async () => { const { searchPostsToolMetadata } = await import("../../src/tools/search-posts.js"); expect(searchPostsToolMetadata.description).toBeTruthy(); expect(searchPostsToolMetadata.description.length).toBeGreaterThan(50); }); it("should have properly defined input schema", async () => { const { searchPostsToolMetadata } = await import("../../src/tools/search-posts.js"); expect(searchPostsToolMetadata.inputSchema).toBeDefined(); expect(searchPostsToolMetadata.inputSchema.type).toBe("object"); expect(searchPostsToolMetadata.inputSchema.properties).toHaveProperty("query"); expect(searchPostsToolMetadata.inputSchema.required).toContain("query"); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wei/hn-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server