Skip to main content
Glama
validation.test.js5.64 kB
import { describe, it, expect } from 'vitest'; import { z } from 'zod'; import { validateToolInput } from '../validation.js'; describe('validateToolInput', () => { const testSchema = z.object({ name: z.string().min(1), count: z.number().int().positive(), }); describe('valid input', () => { it('should return success with validated data for valid input', () => { const result = validateToolInput(testSchema, { name: 'test', count: 5 }, 'test_tool'); expect(result.success).toBe(true); expect(result.data).toEqual({ name: 'test', count: 5 }); }); it('should not include errorResponse on success', () => { const result = validateToolInput(testSchema, { name: 'test', count: 5 }, 'test_tool'); expect(result.success).toBe(true); expect(result).not.toHaveProperty('errorResponse'); }); }); describe('invalid input', () => { it('should return error response for invalid input', () => { const result = validateToolInput(testSchema, { name: '', count: -1 }, 'test_tool'); expect(result.success).toBe(false); expect(result.errorResponse.isError).toBe(true); expect(result.errorResponse.content[0].type).toBe('text'); }); it('should include tool name in error context', () => { const result = validateToolInput(testSchema, {}, 'ghost_create_tag'); expect(result.success).toBe(false); const errorText = result.errorResponse.content[0].text; expect(errorText).toContain('ghost_create_tag'); expect(errorText).toContain('Validation failed'); }); it('should include VALIDATION_ERROR code in response', () => { const result = validateToolInput(testSchema, { name: '' }, 'test_tool'); expect(result.success).toBe(false); const errorText = result.errorResponse.content[0].text; expect(errorText).toContain('VALIDATION_ERROR'); }); it('should include structured error information', () => { const result = validateToolInput(testSchema, { name: '' }, 'test_tool'); expect(result.success).toBe(false); const errorObj = JSON.parse(result.errorResponse.content[0].text); expect(errorObj.name).toBe('ValidationError'); expect(errorObj.code).toBe('VALIDATION_ERROR'); expect(errorObj.statusCode).toBe(400); expect(errorObj.message).toContain('Validation failed'); }); }); describe('edge cases', () => { it('should handle undefined input', () => { const result = validateToolInput(testSchema, undefined, 'test_tool'); expect(result.success).toBe(false); expect(result.errorResponse.isError).toBe(true); }); it('should handle null input', () => { const result = validateToolInput(testSchema, null, 'test_tool'); expect(result.success).toBe(false); expect(result.errorResponse.isError).toBe(true); }); it('should handle empty object input', () => { const result = validateToolInput(testSchema, {}, 'test_tool'); expect(result.success).toBe(false); expect(result.errorResponse.isError).toBe(true); }); }); describe('schema transforms', () => { it('should apply schema transforms and return transformed data', () => { const transformSchema = z.object({ value: z.string().transform((s) => s.toUpperCase()), }); const result = validateToolInput(transformSchema, { value: 'test' }, 'test_tool'); expect(result.success).toBe(true); expect(result.data.value).toBe('TEST'); }); it('should apply default values from schema', () => { const defaultSchema = z.object({ name: z.string(), enabled: z.boolean().default(true), }); const result = validateToolInput(defaultSchema, { name: 'test' }, 'test_tool'); expect(result.success).toBe(true); expect(result.data.enabled).toBe(true); }); }); describe('partial schemas', () => { it('should work with partial schemas', () => { const partialSchema = testSchema.partial(); const result = validateToolInput(partialSchema, {}, 'test_tool'); expect(result.success).toBe(true); expect(result.data).toEqual({}); }); it('should still validate provided fields in partial schemas', () => { const partialSchema = testSchema.partial(); const result = validateToolInput(partialSchema, { count: -1 }, 'test_tool'); expect(result.success).toBe(false); expect(result.errorResponse.isError).toBe(true); }); }); describe('refinement schemas', () => { it('should handle schema refinements and return error', () => { const refinedSchema = z .object({ id: z.string().optional(), slug: z.string().optional(), }) .refine((data) => data.id || data.slug, { message: 'Either id or slug is required', }); const result = validateToolInput(refinedSchema, {}, 'test_tool'); expect(result.success).toBe(false); expect(result.errorResponse.isError).toBe(true); const errorObj = JSON.parse(result.errorResponse.content[0].text); expect(errorObj.code).toBe('VALIDATION_ERROR'); }); it('should pass validation when refinement is satisfied', () => { const refinedSchema = z .object({ id: z.string().optional(), slug: z.string().optional(), }) .refine((data) => data.id || data.slug, { message: 'Either id or slug is required', }); const result = validateToolInput(refinedSchema, { id: 'abc123' }, 'test_tool'); expect(result.success).toBe(true); }); }); });

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/jgardner04/Ghost-MCP-Server'

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