mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-02-06 05:23:08 +00:00
fix: cleanup stale references and update tests after tool removal
- Remove handleListAvailableTools dead code from handlers-n8n-manager.ts - Update error messages to reference n8n_health_check(mode="diagnostic") instead of n8n_diagnostic - Update tool counts in diagnostic messages (14 doc tools, 31 total) - Fix error-handling.test.ts to use valid tools (search_nodes, tools_documentation) - Remove obsolete list-tools.test.ts integration tests - Remove unused ListToolsResponse type from response-types.ts - Update tools.ts QUICK REFERENCE to remove list_nodes references - Update tools-documentation.ts to remove references to removed tools - Update tool-docs files to remove stale relatedTools references - Fix tools.test.ts to not test removed tools (list_nodes, list_ai_tools, etc.) - Fix parameter-validation.test.ts to not test removed tools - Update handlers-n8n-manager.test.ts error message expectations All 399 MCP unit tests now pass. Conceived by Romuald Członkowski - www.aiadvisors.pl/en 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -84,16 +84,16 @@ describe('MCP Error Handling', () => {
|
||||
|
||||
describe('Tool-Specific Errors', () => {
|
||||
describe('Node Discovery Errors', () => {
|
||||
it('should handle invalid category filter', async () => {
|
||||
const response = await client.callTool({ name: 'list_nodes', arguments: {
|
||||
category: 'invalid_category'
|
||||
it('should handle search with no matching results', async () => {
|
||||
const response = await client.callTool({ name: 'search_nodes', arguments: {
|
||||
query: 'xyznonexistentnode123'
|
||||
} });
|
||||
|
||||
// Should return empty array, not error
|
||||
const result = JSON.parse((response as any).content[0].text);
|
||||
expect(result).toHaveProperty('nodes');
|
||||
expect(Array.isArray(result.nodes)).toBe(true);
|
||||
expect(result.nodes).toHaveLength(0);
|
||||
expect(result).toHaveProperty('results');
|
||||
expect(Array.isArray(result.results)).toBe(true);
|
||||
expect(result.results).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle invalid search mode', async () => {
|
||||
@@ -279,9 +279,9 @@ describe('MCP Error Handling', () => {
|
||||
|
||||
for (let i = 0; i < requestCount; i++) {
|
||||
promises.push(
|
||||
client.callTool({ name: 'list_nodes', arguments: {
|
||||
limit: 1,
|
||||
category: i % 2 === 0 ? 'trigger' : 'transform'
|
||||
client.callTool({ name: 'search_nodes', arguments: {
|
||||
query: i % 2 === 0 ? 'webhook' : 'http',
|
||||
limit: 1
|
||||
} })
|
||||
);
|
||||
}
|
||||
@@ -320,13 +320,13 @@ describe('MCP Error Handling', () => {
|
||||
describe('Timeout Scenarios', () => {
|
||||
it('should handle rapid sequential requests', async () => {
|
||||
const start = Date.now();
|
||||
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await client.callTool({ name: 'get_database_statistics', arguments: {} });
|
||||
await client.callTool({ name: 'tools_documentation', arguments: {} });
|
||||
}
|
||||
|
||||
const duration = Date.now() - start;
|
||||
|
||||
|
||||
// Should complete reasonably quickly (under 5 seconds)
|
||||
expect(duration).toBeLessThan(5000);
|
||||
});
|
||||
@@ -410,25 +410,25 @@ describe('MCP Error Handling', () => {
|
||||
}
|
||||
|
||||
// Should still work
|
||||
const response = await client.callTool({ name: 'list_nodes', arguments: { limit: 1 } });
|
||||
const response = await client.callTool({ name: 'search_nodes', arguments: { query: 'webhook', limit: 1 } });
|
||||
expect(response).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle mixed success and failure', async () => {
|
||||
const promises = [
|
||||
client.callTool({ name: 'list_nodes', arguments: { limit: 5 } }),
|
||||
client.callTool({ name: 'search_nodes', arguments: { query: 'webhook', limit: 5 } }),
|
||||
client.callTool({ name: 'get_node', arguments: { nodeType: 'invalid' } }).catch(e => ({ error: e })),
|
||||
client.callTool({ name: 'get_database_statistics', arguments: {} }),
|
||||
client.callTool({ name: 'tools_documentation', arguments: {} }),
|
||||
client.callTool({ name: 'search_nodes', arguments: { query: '' } }).catch(e => ({ error: e })),
|
||||
client.callTool({ name: 'list_ai_tools', arguments: {} })
|
||||
client.callTool({ name: 'get_node', arguments: { nodeType: 'nodes-base.httpRequest' } })
|
||||
];
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
|
||||
|
||||
// Some should succeed, some should fail
|
||||
const successes = results.filter(r => !('error' in r));
|
||||
const failures = results.filter(r => 'error' in r);
|
||||
|
||||
|
||||
expect(successes.length).toBeGreaterThan(0);
|
||||
expect(failures.length).toBeGreaterThan(0);
|
||||
});
|
||||
@@ -436,14 +436,14 @@ describe('MCP Error Handling', () => {
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle empty responses gracefully', async () => {
|
||||
const response = await client.callTool({ name: 'list_nodes', arguments: {
|
||||
category: 'nonexistent_category'
|
||||
const response = await client.callTool({ name: 'search_nodes', arguments: {
|
||||
query: 'xyznonexistentnode12345'
|
||||
} });
|
||||
|
||||
const result = JSON.parse((response as any).content[0].text);
|
||||
expect(result).toHaveProperty('nodes');
|
||||
expect(Array.isArray(result.nodes)).toBe(true);
|
||||
expect(result.nodes).toHaveLength(0);
|
||||
expect(result).toHaveProperty('results');
|
||||
expect(Array.isArray(result.results)).toBe(true);
|
||||
expect(result.results).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle special characters in parameters', async () => {
|
||||
@@ -469,14 +469,15 @@ describe('MCP Error Handling', () => {
|
||||
|
||||
it('should handle null and undefined gracefully', async () => {
|
||||
// Most tools should handle missing optional params
|
||||
const response = await client.callTool({ name: 'list_nodes', arguments: {
|
||||
const response = await client.callTool({ name: 'search_nodes', arguments: {
|
||||
query: 'webhook',
|
||||
limit: undefined as any,
|
||||
category: null as any
|
||||
mode: null as any
|
||||
} });
|
||||
|
||||
const result = JSON.parse((response as any).content[0].text);
|
||||
expect(result).toHaveProperty('nodes');
|
||||
expect(Array.isArray(result.nodes)).toBe(true);
|
||||
expect(result).toHaveProperty('results');
|
||||
expect(Array.isArray(result.results)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
/**
|
||||
* Integration Tests: handleListAvailableTools
|
||||
*
|
||||
* Tests tool listing functionality.
|
||||
* Covers tool discovery and configuration status.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { createMcpContext } from '../utils/mcp-context';
|
||||
import { InstanceContext } from '../../../../src/types/instance-context';
|
||||
import { handleListAvailableTools } from '../../../../src/mcp/handlers-n8n-manager';
|
||||
import { ListToolsResponse } from '../utils/response-types';
|
||||
|
||||
describe('Integration: handleListAvailableTools', () => {
|
||||
let mcpContext: InstanceContext;
|
||||
|
||||
beforeEach(() => {
|
||||
mcpContext = createMcpContext();
|
||||
});
|
||||
|
||||
// ======================================================================
|
||||
// List All Tools
|
||||
// ======================================================================
|
||||
|
||||
describe('Tool Listing', () => {
|
||||
it('should list all available tools organized by category', async () => {
|
||||
const response = await handleListAvailableTools(mcpContext);
|
||||
|
||||
expect(response.success).toBe(true);
|
||||
expect(response.data).toBeDefined();
|
||||
|
||||
const data = response.data as ListToolsResponse;
|
||||
|
||||
// Verify tools array exists
|
||||
expect(data).toHaveProperty('tools');
|
||||
expect(Array.isArray(data.tools)).toBe(true);
|
||||
expect(data.tools.length).toBeGreaterThan(0);
|
||||
|
||||
// Verify tool categories
|
||||
const categories = data.tools.map((cat: any) => cat.category);
|
||||
expect(categories).toContain('Workflow Management');
|
||||
expect(categories).toContain('Execution Management');
|
||||
expect(categories).toContain('System');
|
||||
|
||||
// Verify each category has tools
|
||||
data.tools.forEach(category => {
|
||||
expect(category).toHaveProperty('category');
|
||||
expect(category).toHaveProperty('tools');
|
||||
expect(Array.isArray(category.tools)).toBe(true);
|
||||
expect(category.tools.length).toBeGreaterThan(0);
|
||||
|
||||
// Verify each tool has required fields
|
||||
category.tools.forEach(tool => {
|
||||
expect(tool).toHaveProperty('name');
|
||||
expect(tool).toHaveProperty('description');
|
||||
expect(typeof tool.name).toBe('string');
|
||||
expect(typeof tool.description).toBe('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should include API configuration status', async () => {
|
||||
const response = await handleListAvailableTools(mcpContext);
|
||||
|
||||
expect(response.success).toBe(true);
|
||||
const data = response.data as ListToolsResponse;
|
||||
|
||||
// Verify configuration status
|
||||
expect(data).toHaveProperty('apiConfigured');
|
||||
expect(typeof data.apiConfigured).toBe('boolean');
|
||||
|
||||
// Since tests run with API configured, should be true
|
||||
expect(data.apiConfigured).toBe(true);
|
||||
|
||||
// Verify configuration details are present when configured
|
||||
if (data.apiConfigured) {
|
||||
expect(data).toHaveProperty('configuration');
|
||||
expect(data.configuration).toBeDefined();
|
||||
expect(data.configuration).toHaveProperty('apiUrl');
|
||||
expect(data.configuration).toHaveProperty('timeout');
|
||||
expect(data.configuration).toHaveProperty('maxRetries');
|
||||
}
|
||||
});
|
||||
|
||||
it('should include API limitations information', async () => {
|
||||
const response = await handleListAvailableTools(mcpContext);
|
||||
|
||||
expect(response.success).toBe(true);
|
||||
const data = response.data as ListToolsResponse;
|
||||
|
||||
// Verify limitations are documented
|
||||
expect(data).toHaveProperty('limitations');
|
||||
expect(Array.isArray(data.limitations)).toBe(true);
|
||||
expect(data.limitations.length).toBeGreaterThan(0);
|
||||
|
||||
// Verify limitations are informative strings
|
||||
data.limitations.forEach(limitation => {
|
||||
expect(typeof limitation).toBe('string');
|
||||
expect(limitation.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// Common known limitations
|
||||
const limitationsText = data.limitations.join(' ');
|
||||
expect(limitationsText).toContain('Cannot execute workflows directly');
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================
|
||||
// Workflow Management Tools
|
||||
// ======================================================================
|
||||
|
||||
describe('Workflow Management Tools', () => {
|
||||
it('should include all workflow management tools', async () => {
|
||||
const response = await handleListAvailableTools(mcpContext);
|
||||
const data = response.data as ListToolsResponse;
|
||||
|
||||
const workflowCategory = data.tools.find(cat => cat.category === 'Workflow Management');
|
||||
expect(workflowCategory).toBeDefined();
|
||||
|
||||
const toolNames = workflowCategory!.tools.map(t => t.name);
|
||||
|
||||
// Core workflow tools
|
||||
expect(toolNames).toContain('n8n_create_workflow');
|
||||
expect(toolNames).toContain('n8n_get_workflow');
|
||||
expect(toolNames).toContain('n8n_update_workflow');
|
||||
expect(toolNames).toContain('n8n_delete_workflow');
|
||||
expect(toolNames).toContain('n8n_list_workflows');
|
||||
|
||||
// Enhanced workflow tools
|
||||
expect(toolNames).toContain('n8n_get_workflow_details');
|
||||
expect(toolNames).toContain('n8n_get_workflow_structure');
|
||||
expect(toolNames).toContain('n8n_get_workflow_minimal');
|
||||
expect(toolNames).toContain('n8n_validate_workflow');
|
||||
expect(toolNames).toContain('n8n_autofix_workflow');
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================
|
||||
// Execution Management Tools
|
||||
// ======================================================================
|
||||
|
||||
describe('Execution Management Tools', () => {
|
||||
it('should include all execution management tools', async () => {
|
||||
const response = await handleListAvailableTools(mcpContext);
|
||||
const data = response.data as ListToolsResponse;
|
||||
|
||||
const executionCategory = data.tools.find(cat => cat.category === 'Execution Management');
|
||||
expect(executionCategory).toBeDefined();
|
||||
|
||||
const toolNames = executionCategory!.tools.map(t => t.name);
|
||||
|
||||
expect(toolNames).toContain('n8n_trigger_webhook_workflow');
|
||||
expect(toolNames).toContain('n8n_get_execution');
|
||||
expect(toolNames).toContain('n8n_list_executions');
|
||||
expect(toolNames).toContain('n8n_delete_execution');
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================
|
||||
// System Tools
|
||||
// ======================================================================
|
||||
|
||||
describe('System Tools', () => {
|
||||
it('should include system tools', async () => {
|
||||
const response = await handleListAvailableTools(mcpContext);
|
||||
const data = response.data as ListToolsResponse;
|
||||
|
||||
const systemCategory = data.tools.find(cat => cat.category === 'System');
|
||||
expect(systemCategory).toBeDefined();
|
||||
|
||||
const toolNames = systemCategory!.tools.map(t => t.name);
|
||||
|
||||
expect(toolNames).toContain('n8n_health_check');
|
||||
expect(toolNames).toContain('n8n_list_available_tools');
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================
|
||||
// Response Format Verification
|
||||
// ======================================================================
|
||||
|
||||
describe('Response Format', () => {
|
||||
it('should return complete tool list response structure', async () => {
|
||||
const response = await handleListAvailableTools(mcpContext);
|
||||
|
||||
expect(response.success).toBe(true);
|
||||
expect(response.data).toBeDefined();
|
||||
|
||||
const data = response.data as ListToolsResponse;
|
||||
|
||||
// Verify all required fields
|
||||
expect(data).toHaveProperty('tools');
|
||||
expect(data).toHaveProperty('apiConfigured');
|
||||
expect(data).toHaveProperty('limitations');
|
||||
|
||||
// Verify optional configuration field
|
||||
if (data.apiConfigured) {
|
||||
expect(data).toHaveProperty('configuration');
|
||||
}
|
||||
|
||||
// Verify data types
|
||||
expect(Array.isArray(data.tools)).toBe(true);
|
||||
expect(typeof data.apiConfigured).toBe('boolean');
|
||||
expect(Array.isArray(data.limitations)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -19,29 +19,6 @@ export interface HealthCheckResponse {
|
||||
[key: string]: any; // Allow dynamic property access for optional field checks
|
||||
}
|
||||
|
||||
export interface ToolDefinition {
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface ToolCategory {
|
||||
category: string;
|
||||
tools: ToolDefinition[];
|
||||
}
|
||||
|
||||
export interface ApiConfiguration {
|
||||
apiUrl: string;
|
||||
timeout: number;
|
||||
maxRetries: number;
|
||||
}
|
||||
|
||||
export interface ListToolsResponse {
|
||||
tools: ToolCategory[];
|
||||
apiConfigured: boolean;
|
||||
configuration?: ApiConfiguration | null;
|
||||
limitations: string[];
|
||||
}
|
||||
|
||||
export interface ApiStatus {
|
||||
configured: boolean;
|
||||
connected: boolean;
|
||||
|
||||
@@ -1031,7 +1031,7 @@ describe('handlers-n8n-manager', () => {
|
||||
'1. Verify n8n instance is running',
|
||||
'2. Check N8N_API_URL is correct',
|
||||
'3. Verify N8N_API_KEY has proper permissions',
|
||||
'4. Run n8n_diagnostic for detailed analysis',
|
||||
'4. Run n8n_health_check with mode="diagnostic" for detailed analysis',
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -399,24 +399,11 @@ describe('Parameter Validation', () => {
|
||||
expect(result).toEqual({ docs: 'test' });
|
||||
});
|
||||
|
||||
it('should allow list_nodes with no parameters', async () => {
|
||||
const result = await server.testExecuteTool('list_nodes', {});
|
||||
expect(result).toEqual({ nodes: [] });
|
||||
});
|
||||
|
||||
it('should allow list_ai_tools with no parameters', async () => {
|
||||
const result = await server.testExecuteTool('list_ai_tools', {});
|
||||
expect(result).toEqual({ tools: [] });
|
||||
});
|
||||
|
||||
it('should allow get_database_statistics with no parameters', async () => {
|
||||
const result = await server.testExecuteTool('get_database_statistics', {});
|
||||
expect(result).toEqual({ stats: {} });
|
||||
});
|
||||
|
||||
it('should allow list_tasks with no parameters', async () => {
|
||||
const result = await server.testExecuteTool('list_tasks', {});
|
||||
expect(result).toEqual({ tasks: [] });
|
||||
it('should allow tools_documentation with no parameters', async () => {
|
||||
const result = await server.testExecuteTool('tools_documentation', {});
|
||||
expect(result).toBeDefined();
|
||||
// tools_documentation returns an object with documentation content
|
||||
expect(typeof result).toBe('object');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -476,8 +463,8 @@ describe('Parameter Validation', () => {
|
||||
{ name: 'get_node_documentation', args: {}, expected: 'Missing required parameters for get_node_documentation: nodeType' },
|
||||
{ name: 'search_node_properties', args: {}, expected: 'Missing required parameters for search_node_properties: nodeType, query' },
|
||||
// Note: get_node_for_task removed in v2.15.0
|
||||
// Note: get_node_as_tool_info removed in v2.25.0
|
||||
{ name: 'get_property_dependencies', args: {}, expected: 'Missing required parameters for get_property_dependencies: nodeType' },
|
||||
{ name: 'get_node_as_tool_info', args: {}, expected: 'Missing required parameters for get_node_as_tool_info: nodeType' },
|
||||
{ name: 'get_template', args: {}, expected: 'Missing required parameters for get_template: templateId' },
|
||||
];
|
||||
|
||||
|
||||
@@ -78,31 +78,6 @@ describe('n8nDocumentationToolsFinal', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('list_nodes', () => {
|
||||
const tool = n8nDocumentationToolsFinal.find(t => t.name === 'list_nodes');
|
||||
|
||||
it('should exist', () => {
|
||||
expect(tool).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have correct schema properties', () => {
|
||||
const properties = tool?.inputSchema.properties;
|
||||
expect(properties).toHaveProperty('package');
|
||||
expect(properties).toHaveProperty('category');
|
||||
expect(properties).toHaveProperty('developmentStyle');
|
||||
expect(properties).toHaveProperty('isAITool');
|
||||
expect(properties).toHaveProperty('limit');
|
||||
});
|
||||
|
||||
it('should have correct defaults', () => {
|
||||
expect(tool?.inputSchema.properties.limit.default).toBe(50);
|
||||
});
|
||||
|
||||
it('should have proper enum values', () => {
|
||||
expect(tool?.inputSchema.properties.developmentStyle.enum).toEqual(['declarative', 'programmatic']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get_node', () => {
|
||||
const tool = n8nDocumentationToolsFinal.find(t => t.name === 'get_node');
|
||||
|
||||
@@ -205,7 +180,6 @@ describe('n8nDocumentationToolsFinal', () => {
|
||||
|
||||
it('should include examples or key information in descriptions', () => {
|
||||
const toolsWithExamples = [
|
||||
'list_nodes',
|
||||
'get_node',
|
||||
'search_nodes',
|
||||
'get_node_documentation'
|
||||
@@ -250,14 +224,14 @@ describe('n8nDocumentationToolsFinal', () => {
|
||||
describe('Tool Categories Coverage', () => {
|
||||
it('should have tools for all major categories', () => {
|
||||
const categories = {
|
||||
discovery: ['list_nodes', 'search_nodes', 'list_ai_tools'],
|
||||
discovery: ['search_nodes'],
|
||||
configuration: ['get_node', 'get_node_documentation'],
|
||||
validation: ['validate_node_operation', 'validate_workflow', 'validate_node_minimal'],
|
||||
templates: ['list_tasks', 'search_templates', 'list_templates', 'get_template', 'list_node_templates'], // get_node_for_task removed in v2.15.0
|
||||
templates: ['search_templates', 'get_template', 'list_node_templates', 'get_templates_for_task', 'search_templates_by_metadata'],
|
||||
documentation: ['tools_documentation']
|
||||
};
|
||||
|
||||
Object.entries(categories).forEach(([category, expectedTools]) => {
|
||||
Object.entries(categories).forEach(([_category, expectedTools]) => {
|
||||
expectedTools.forEach(toolName => {
|
||||
const tool = n8nDocumentationToolsFinal.find(t => t.name === toolName);
|
||||
expect(tool).toBeDefined();
|
||||
@@ -294,13 +268,15 @@ describe('n8nDocumentationToolsFinal', () => {
|
||||
});
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle tools with no parameters', () => {
|
||||
const toolsWithNoParams = ['list_ai_tools', 'get_database_statistics'];
|
||||
|
||||
toolsWithNoParams.forEach(toolName => {
|
||||
it('should handle tools with optional parameters only', () => {
|
||||
// Tools where all parameters are optional
|
||||
const toolsWithOptionalParams = ['tools_documentation'];
|
||||
|
||||
toolsWithOptionalParams.forEach(toolName => {
|
||||
const tool = n8nDocumentationToolsFinal.find(t => t.name === toolName);
|
||||
expect(tool).toBeDefined();
|
||||
expect(Object.keys(tool?.inputSchema.properties || {}).length).toBe(0);
|
||||
// These tools have properties but no required array or empty required array
|
||||
expect(tool?.inputSchema.required === undefined || tool?.inputSchema.required?.length === 0).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -318,37 +294,6 @@ describe('n8nDocumentationToolsFinal', () => {
|
||||
});
|
||||
|
||||
describe('New Template Tools', () => {
|
||||
describe('list_templates', () => {
|
||||
const tool = n8nDocumentationToolsFinal.find(t => t.name === 'list_templates');
|
||||
|
||||
it('should exist and be properly defined', () => {
|
||||
expect(tool).toBeDefined();
|
||||
expect(tool?.description).toContain('minimal data');
|
||||
});
|
||||
|
||||
it('should have correct parameters', () => {
|
||||
expect(tool?.inputSchema.properties).toHaveProperty('limit');
|
||||
expect(tool?.inputSchema.properties).toHaveProperty('offset');
|
||||
expect(tool?.inputSchema.properties).toHaveProperty('sortBy');
|
||||
|
||||
const limitParam = tool?.inputSchema.properties.limit;
|
||||
expect(limitParam.type).toBe('number');
|
||||
expect(limitParam.minimum).toBe(1);
|
||||
expect(limitParam.maximum).toBe(100);
|
||||
|
||||
const offsetParam = tool?.inputSchema.properties.offset;
|
||||
expect(offsetParam.type).toBe('number');
|
||||
expect(offsetParam.minimum).toBe(0);
|
||||
|
||||
const sortByParam = tool?.inputSchema.properties.sortBy;
|
||||
expect(sortByParam.enum).toEqual(['views', 'created_at', 'name']);
|
||||
});
|
||||
|
||||
it('should have no required parameters', () => {
|
||||
expect(tool?.inputSchema.required).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('get_template (enhanced)', () => {
|
||||
const tool = n8nDocumentationToolsFinal.find(t => t.name === 'get_template');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user