learning_ai_common_plat/services/mcp-server/src/modules/tools/registry.test.ts

85 lines
2.7 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { z } from 'zod';
import { registerTool, getTool, listTools } from './registry.js';
describe('tool registry', () => {
it('registers and retrieves a tool by name', () => {
registerTool({
name: 'test.hello',
description: 'A test tool',
requiredRole: 'viewer',
inputSchema: z.object({ name: z.string() }),
async execute(args) {
return { hello: args.name };
},
});
const tool = getTool('test.hello');
expect(tool).toBeDefined();
expect(tool?.name).toBe('test.hello');
expect(tool?.requiredRole).toBe('viewer');
});
it('listTools returns all registered tools with meta', () => {
const all = listTools();
const found = all.find(t => t.name === 'test.hello');
expect(found).toBeDefined();
expect(found?.description).toBe('A test tool');
expect(found?.inputSchema).toHaveProperty('type', 'object');
});
it('getTool returns undefined for unknown tool', () => {
expect(getTool('does.not.exist')).toBeUndefined();
});
it('zodToJsonSchema emits correct types for boolean/number/array fields', () => {
registerTool({
name: 'test.types',
description: 'Type test',
requiredRole: 'viewer',
inputSchema: z.object({
flag: z.boolean(),
count: z.coerce.number(),
tags: z.array(z.string()),
label: z.string().optional(),
enabled: z.boolean().default(false),
}),
async execute(args) {
return args;
},
});
const tool = listTools().find(t => t.name === 'test.types');
const props = (tool?.inputSchema as { properties: Record<string, { type: string }> })
.properties;
expect(props.flag.type).toBe('boolean');
expect(props.count.type).toBe('number');
expect(props.tags.type).toBe('array');
expect(props.label.type).toBe('string');
// ZodDefault should unwrap to boolean, not 'string'
expect(props.enabled.type).toBe('boolean');
// optional + default fields should NOT be in required
const required = tool?.inputSchema.required as string[];
expect(required).toContain('flag');
expect(required).toContain('count');
expect(required).not.toContain('label');
expect(required).not.toContain('enabled');
});
});
describe('tool execute', () => {
it('executes with validated args', async () => {
registerTool({
name: 'test.echo',
description: 'Echo',
requiredRole: 'admin',
inputSchema: z.object({ value: z.string() }),
async execute(args) {
return { echoed: args.value };
},
});
const tool = getTool('test.echo')!;
const result = await tool.execute({ value: 'ping' }, {} as never);
expect(result).toEqual({ echoed: 'ping' });
});
});