Skip to main content
Glama
registry.test.ts9.29 kB
/** * Tool Registry Tests * * @package WP_Navigator_Pro * @since 1.3.0 */ import { describe, it, expect, beforeEach } from 'vitest'; import { ToolRegistry } from './registry.js'; import { ToolCategory, RegisteredTool } from './types.js'; describe('ToolRegistry', () => { let registry: ToolRegistry; beforeEach(() => { registry = new ToolRegistry(); }); describe('register', () => { it('should register a tool', () => { const tool: RegisteredTool = { definition: { name: 'test_tool', description: 'Test tool', inputSchema: { type: 'object', properties: {}, required: [], }, }, handler: async () => ({ content: [{ type: 'text', text: 'test' }] }), category: ToolCategory.CORE, }; registry.register(tool); expect(registry.getTool('test_tool')).toBe(tool); }); it('should register tool aliases', () => { const tool: RegisteredTool = { definition: { name: 'test_tool', description: 'Test tool', inputSchema: { type: 'object', properties: {}, required: [], }, }, handler: async () => ({ content: [{ type: 'text', text: 'test' }] }), category: ToolCategory.CORE, aliases: ['test.tool', 'test-tool'], }; registry.register(tool); expect(registry.getTool('test_tool')).toBe(tool); expect(registry.getTool('test.tool')).toBe(tool); expect(registry.getTool('test-tool')).toBe(tool); }); }); describe('feature flags', () => { it('should respect feature flags', () => { const tool: RegisteredTool = { definition: { name: 'workflow_tool', description: 'Workflow tool', inputSchema: { type: 'object', properties: {}, required: [], }, }, handler: async () => ({ content: [{ type: 'text', text: 'workflow' }] }), category: ToolCategory.WORKFLOWS, featureFlag: 'WORKFLOWS_ENABLED', }; registry.register(tool); // Initially disabled expect(registry.isEnabled('workflow_tool')).toBe(false); // Enable feature flag registry.setFeatureFlag('WORKFLOWS_ENABLED', true); expect(registry.isEnabled('workflow_tool')).toBe(true); }); it('should filter disabled tools from getAllDefinitions', () => { const enabledTool: RegisteredTool = { definition: { name: 'enabled_tool', description: 'Enabled tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'enabled' }] }), category: ToolCategory.CORE, }; const disabledTool: RegisteredTool = { definition: { name: 'disabled_tool', description: 'Disabled tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'disabled' }] }), category: ToolCategory.WORKFLOWS, featureFlag: 'WORKFLOWS_ENABLED', }; registry.register(enabledTool); registry.register(disabledTool); const definitions = registry.getAllDefinitions(); expect(definitions).toHaveLength(1); expect(definitions[0].name).toBe('enabled_tool'); }); }); describe('getByCategory', () => { it('should return tools by category', () => { const coreTools: RegisteredTool[] = [ { definition: { name: 'core_tool_1', description: 'Core tool 1', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'core1' }] }), category: ToolCategory.CORE, }, { definition: { name: 'core_tool_2', description: 'Core tool 2', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'core2' }] }), category: ToolCategory.CORE, }, ]; const contentTool: RegisteredTool = { definition: { name: 'content_tool', description: 'Content tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'content' }] }), category: ToolCategory.CONTENT, }; coreTools.forEach((t) => registry.register(t)); registry.register(contentTool); const coreResult = registry.getByCategory(ToolCategory.CORE); const contentResult = registry.getByCategory(ToolCategory.CONTENT); expect(coreResult).toHaveLength(2); expect(contentResult).toHaveLength(1); expect(coreResult.map((t) => t.definition.name)).toEqual(['core_tool_1', 'core_tool_2']); expect(contentResult[0].definition.name).toBe('content_tool'); }); it('should not return duplicates for aliases', () => { const tool: RegisteredTool = { definition: { name: 'test_tool', description: 'Test tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'test' }] }), category: ToolCategory.CORE, aliases: ['test.tool'], }; registry.register(tool); const result = registry.getByCategory(ToolCategory.CORE); expect(result).toHaveLength(1); }); }); describe('execute', () => { it('should execute a tool', async () => { const tool: RegisteredTool = { definition: { name: 'test_tool', description: 'Test tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async (args, context) => ({ content: [{ type: 'text', text: `Hello ${args.name}` }], }), category: ToolCategory.CORE, }; registry.register(tool); const context: any = { wpRequest: async () => ({}), config: {}, logger: {}, clampText: (t: string) => t, }; const result = await registry.execute('test_tool', { name: 'World' }, context); expect(result.content[0]).toEqual({ type: 'text', text: 'Hello World' }); }); it('should throw error for non-existent tool', async () => { const context: any = { wpRequest: async () => ({}), config: {}, logger: {}, clampText: (t: string) => t, }; await expect(registry.execute('non_existent', {}, context)).rejects.toThrow( 'Tool not found: non_existent' ); }); it('should throw error for disabled tool', async () => { const tool: RegisteredTool = { definition: { name: 'disabled_tool', description: 'Disabled tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'disabled' }] }), category: ToolCategory.WORKFLOWS, featureFlag: 'WORKFLOWS_ENABLED', }; registry.register(tool); const context: any = { wpRequest: async () => ({}), config: {}, logger: {}, clampText: (t: string) => t, }; await expect(registry.execute('disabled_tool', {}, context)).rejects.toThrow( 'Tool is disabled: disabled_tool (requires feature flag: WORKFLOWS_ENABLED)' ); }); }); describe('getStats', () => { it('should return registry statistics', () => { const tools: RegisteredTool[] = [ { definition: { name: 'core_tool', description: 'Core tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'core' }] }), category: ToolCategory.CORE, }, { definition: { name: 'content_tool', description: 'Content tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'content' }] }), category: ToolCategory.CONTENT, }, { definition: { name: 'workflow_tool', description: 'Workflow tool', inputSchema: { type: 'object', properties: {}, required: [] }, }, handler: async () => ({ content: [{ type: 'text', text: 'workflow' }] }), category: ToolCategory.WORKFLOWS, featureFlag: 'WORKFLOWS_ENABLED', }, ]; tools.forEach((t) => registry.register(t)); const stats = registry.getStats(); expect(stats.totalTools).toBe(3); expect(stats.enabledTools).toBe(2); expect(stats.disabledTools).toBe(1); expect(stats.byCategory[ToolCategory.CORE]).toBe(1); expect(stats.byCategory[ToolCategory.CONTENT]).toBe(1); expect(stats.byCategory[ToolCategory.WORKFLOWS]).toBe(1); }); }); });

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/littlebearapps/wp-navigator-mcp'

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