Skip to main content
Glama
toolWrapper.test.js8.65 kB
import { vi } from "vitest"; import { withErrorHandling, withValidation, validators, errorHandler, formatSuccessResponse, formatErrorResponse, toolWrapper, } from "@/utils/toolWrapper.js"; describe("toolWrapper utilities", () => { describe("withErrorHandling", () => { it("should wrap function with error handling", async () => { const mockFn = vi.fn().mockResolvedValue("success"); const wrappedFn = withErrorHandling("test_operation", mockFn); const result = await wrappedFn("arg1", "arg2"); expect(mockFn).toHaveBeenCalledWith("arg1", "arg2"); expect(result).toBe("success"); }); it("should handle errors with operation prefix", async () => { const mockFn = vi.fn().mockRejectedValue(new Error("Original error")); const wrappedFn = withErrorHandling("test_operation", mockFn); await expect(wrappedFn()).rejects.toThrow("test_operation: Original error"); }); it("should handle synchronous functions", async () => { const mockFn = vi.fn().mockReturnValue("sync result"); const wrappedFn = withErrorHandling("test_operation", mockFn); const result = await wrappedFn(); expect(result).toBe("sync result"); }); it("should handle non-Error objects", async () => { const mockFn = vi.fn().mockRejectedValue("string error"); const wrappedFn = withErrorHandling("test_operation", mockFn); await expect(wrappedFn()).rejects.toThrow("test_operation: string error"); }); }); describe("withValidation", () => { it("should validate parameters before execution", async () => { const mockValidator = vi.fn(); const mockFn = vi.fn().mockResolvedValue("success"); const wrappedFn = withValidation("test_operation", mockValidator, mockFn); const result = await wrappedFn("arg1", "arg2"); expect(mockValidator).toHaveBeenCalledWith("arg1", "arg2"); expect(mockFn).toHaveBeenCalledWith("arg1", "arg2"); expect(result).toBe("success"); }); it("should handle validation errors", async () => { const mockValidator = vi.fn().mockImplementation(() => { throw new Error("Validation failed"); }); const mockFn = vi.fn(); const wrappedFn = withValidation("test_operation", mockValidator, mockFn); await expect(wrappedFn()).rejects.toThrow("test_operation: Validation failed"); expect(mockFn).not.toHaveBeenCalled(); }); it("should handle execution errors after validation", async () => { const mockValidator = vi.fn(); const mockFn = vi.fn().mockRejectedValue(new Error("Execution failed")); const wrappedFn = withValidation("test_operation", mockValidator, mockFn); await expect(wrappedFn()).rejects.toThrow("test_operation: Execution failed"); }); }); describe("validators", () => { describe("requireSite", () => { it("should pass when client is provided", () => { const mockClient = {}; expect(() => validators.requireSite(mockClient, {})).not.toThrow(); }); it("should throw when client is missing", () => { expect(() => validators.requireSite(null, {})).toThrow("WordPress client is required"); expect(() => validators.requireSite(undefined, {})).toThrow("WordPress client is required"); }); }); describe("requireId", () => { it("should pass when id is provided", () => { expect(() => validators.requireId({ id: "123" })).not.toThrow(); expect(() => validators.requireId({ id: 123 })).not.toThrow(); }); it("should throw when id is missing", () => { expect(() => validators.requireId({})).toThrow("ID parameter is required"); expect(() => validators.requireId({ id: null })).toThrow("ID parameter is required"); expect(() => validators.requireId({ id: undefined })).toThrow("ID parameter is required"); }); }); describe("requireNonEmpty", () => { it("should pass when value is not empty", () => { expect(() => validators.requireNonEmpty("test", "field")).not.toThrow(); expect(() => validators.requireNonEmpty(123, "field")).not.toThrow(); expect(() => validators.requireNonEmpty([], "field")).not.toThrow(); }); it("should throw when value is empty", () => { expect(() => validators.requireNonEmpty("", "field")).toThrow("field cannot be empty"); expect(() => validators.requireNonEmpty(" ", "field")).toThrow("field cannot be empty"); expect(() => validators.requireNonEmpty(null, "field")).toThrow("field cannot be empty"); expect(() => validators.requireNonEmpty(undefined, "field")).toThrow("field cannot be empty"); }); }); describe("requireFields", () => { it("should pass when all fields are provided", () => { const params = { name: "test", age: 25, active: true }; expect(() => validators.requireFields(params, ["name", "age"])).not.toThrow(); }); it("should throw when required field is missing", () => { const params = { name: "test" }; expect(() => validators.requireFields(params, ["name", "age"])).toThrow("age is required"); }); it("should throw when required field is null or undefined", () => { const params = { name: "test", age: null }; expect(() => validators.requireFields(params, ["name", "age"])).toThrow("age is required"); }); }); }); describe("errorHandler decorator", () => { it("should be available as a function", () => { expect(typeof errorHandler).toBe("function"); }); }); describe("formatSuccessResponse", () => { it("should return content as-is", () => { const content = "test content"; const result = formatSuccessResponse(content); expect(result).toBe(content); }); it("should handle objects", () => { const content = { message: "success" }; const result = formatSuccessResponse(content); expect(result).toBe(content); }); }); describe("formatErrorResponse", () => { it("should throw formatted error", () => { const error = new Error("Test error"); expect(() => formatErrorResponse("test_operation", error)).toThrow("test_operation: Test error"); }); it("should handle non-Error objects", () => { expect(() => formatErrorResponse("test_operation", "string error")).toThrow("test_operation: string error"); }); }); describe("toolWrapper", () => { it("should execute function successfully", async () => { const mockFn = vi.fn().mockResolvedValue("success"); const result = await toolWrapper(mockFn); expect(mockFn).toHaveBeenCalled(); expect(result).toBe("success"); }); it("should handle function errors", async () => { const mockFn = vi.fn().mockRejectedValue(new Error("Function error")); await expect(toolWrapper(mockFn)).rejects.toThrow("Function error"); }); it("should handle synchronous functions", async () => { const mockFn = vi.fn().mockReturnValue("sync result"); const result = await toolWrapper(mockFn); expect(result).toBe("sync result"); }); it("should handle non-Error objects", async () => { const mockFn = vi.fn().mockRejectedValue("string error"); await expect(toolWrapper(mockFn)).rejects.toThrow("string error"); }); }); describe("integration scenarios", () => { it("should combine withErrorHandling and validators", async () => { const mockFn = vi.fn().mockResolvedValue("success"); const wrappedFn = withErrorHandling("test_operation", mockFn); // Test with validator const validatedFn = withValidation("test_operation", validators.requireSite, wrappedFn); const result = await validatedFn({}, {}); expect(result).toBe("success"); }); it("should handle complex error scenarios", async () => { const mockFn = vi.fn().mockImplementation((params) => { if (params.trigger === "validation") { throw new Error("Validation failed"); } else if (params.trigger === "execution") { throw new Error("Execution failed"); } return "success"; }); const wrappedFn = withErrorHandling("test_operation", mockFn); await expect(wrappedFn({ trigger: "validation" })).rejects.toThrow("test_operation: Validation failed"); await expect(wrappedFn({ trigger: "execution" })).rejects.toThrow("test_operation: Execution failed"); const result = await wrappedFn({ trigger: "success" }); expect(result).toBe("success"); }); }); });

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/docdyhr/mcp-wordpress'

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