Skip to main content
Glama
tool-definitions.test.ts14.6 kB
/** * @fileoverview Tests for tool definitions and schemas */ import { z } from 'zod'; import { projectsToolSchema, qualityMetricsToolSchema, updateMetricThresholdToolSchema, updateMetricSettingToolSchema, complianceReportToolSchema, projectIssuesToolSchema, runsToolSchema, runToolSchema, recentRunIssuesToolSchema, dependencyVulnerabilitiesToolSchema, toolSchemas, } from '../../server/tool-definitions.js'; // Helper function to parse input with ZodRawShape function parseInput(schema: { inputSchema?: z.ZodRawShape | z.ZodSchema }, input: unknown) { if (!schema.inputSchema) return undefined; // Check if it's already a ZodSchema (has safeParse method) if ('safeParse' in schema.inputSchema) { return (schema.inputSchema as z.ZodSchema).safeParse(input); } // Otherwise, wrap it in z.object() return z.object(schema.inputSchema as z.ZodRawShape).safeParse(input); } describe('Tool Definitions', () => { describe('projectsToolSchema', () => { it('should have correct name and description', () => { expect(projectsToolSchema.name).toBe('projects'); expect(projectsToolSchema.description).toContain('List all available DeepSource projects'); }); it('should have empty input schema', () => { expect(projectsToolSchema.inputSchema).toBeDefined(); const result = parseInput(projectsToolSchema, {}); expect(result?.success).toBe(true); expect(result?.data).toEqual({}); }); it('should have output schema', () => { expect(projectsToolSchema.outputSchema).toBeDefined(); }); }); describe('qualityMetricsToolSchema', () => { it('should have correct name and description', () => { expect(qualityMetricsToolSchema.name).toBe('quality_metrics'); expect(qualityMetricsToolSchema.description).toContain('quality metrics'); }); it('should validate valid input', () => { const validInput = { projectKey: 'test-project', shortcodeIn: ['LCV', 'BCV'], }; const result = parseInput(qualityMetricsToolSchema, validInput); expect(result?.success).toBe(true); }); it('should validate input with only projectKey', () => { const validInput = { projectKey: 'test-project', }; const result = parseInput(qualityMetricsToolSchema, validInput); expect(result?.success).toBe(true); }); it('should reject input without projectKey', () => { const invalidInput = { shortcodeIn: ['LCV'], }; const result = parseInput(qualityMetricsToolSchema, invalidInput); expect(result?.success).toBe(false); }); it('should reject invalid metric shortcodes', () => { const invalidInput = { projectKey: 'test-project', shortcodeIn: ['INVALID'], }; const result = parseInput(qualityMetricsToolSchema, invalidInput); expect(result?.success).toBe(false); }); }); describe('updateMetricThresholdToolSchema', () => { it('should have correct name and description', () => { expect(updateMetricThresholdToolSchema.name).toBe('update_metric_threshold'); expect(updateMetricThresholdToolSchema.description).toContain('Update the threshold'); }); it('should validate valid input with threshold', () => { const validInput = { projectKey: 'test-project', repositoryId: 'repo-123', metricShortcode: 'LCV', metricKey: 'line-coverage', thresholdValue: 80, }; const result = parseInput(updateMetricThresholdToolSchema, validInput); expect(result?.success).toBe(true); }); it('should validate input with null threshold', () => { const validInput = { projectKey: 'test-project', repositoryId: 'repo-123', metricShortcode: 'TCV', metricKey: 'test-coverage', thresholdValue: null, }; const result = parseInput(updateMetricThresholdToolSchema, validInput); expect(result?.success).toBe(true); }); it('should reject missing required fields', () => { const invalidInput = { projectKey: 'test-project', metricShortcode: 'LCV', }; const result = parseInput(updateMetricThresholdToolSchema, invalidInput); expect(result?.success).toBe(false); }); }); describe('updateMetricSettingToolSchema', () => { it('should have correct name and description', () => { expect(updateMetricSettingToolSchema.name).toBe('update_metric_setting'); expect(updateMetricSettingToolSchema.description).toContain('Update the settings'); }); it('should validate valid input', () => { const validInput = { projectKey: 'test-project', repositoryId: 'repo-123', metricShortcode: 'DCV', isReported: true, isThresholdEnforced: false, }; const result = parseInput(updateMetricSettingToolSchema, validInput); expect(result?.success).toBe(true); }); it('should reject non-boolean values', () => { const invalidInput = { projectKey: 'test-project', repositoryId: 'repo-123', metricShortcode: 'DCV', isReported: 'yes', isThresholdEnforced: 0, }; const result = parseInput(updateMetricSettingToolSchema, invalidInput); expect(result?.success).toBe(false); }); }); describe('complianceReportToolSchema', () => { it('should have correct name and description', () => { expect(complianceReportToolSchema.name).toBe('compliance_report'); expect(complianceReportToolSchema.description).toContain('security compliance reports'); }); it('should validate valid report types', () => { const validTypes = [ 'OWASP_TOP_10', 'SANS_TOP_25', 'MISRA_C', 'CODE_COVERAGE', 'CODE_HEALTH_TREND', 'ISSUE_DISTRIBUTION', 'ISSUES_PREVENTED', 'ISSUES_AUTOFIXED', ]; validTypes.forEach((reportType) => { const input = { projectKey: 'test-project', reportType, }; const result = parseInput(complianceReportToolSchema, input); expect(result?.success).toBe(true); }); }); it('should reject invalid report type', () => { const invalidInput = { projectKey: 'test-project', reportType: 'INVALID_TYPE', }; const result = parseInput(complianceReportToolSchema, invalidInput); expect(result?.success).toBe(false); }); }); describe('projectIssuesToolSchema', () => { it('should have correct name and description', () => { expect(projectIssuesToolSchema.name).toBe('project_issues'); expect(projectIssuesToolSchema.description).toContain('Get issues from a DeepSource project'); }); it('should validate input with all optional fields', () => { const validInput = { projectKey: 'test-project', analyzerIn: ['python', 'javascript'], tags: ['security', 'performance'], path: 'src/main.py', first: 10, after: 'cursor123', }; const result = parseInput(projectIssuesToolSchema, validInput); expect(result?.success).toBe(true); }); it('should validate input with only required fields', () => { const validInput = { projectKey: 'test-project', }; const result = parseInput(projectIssuesToolSchema, validInput); expect(result?.success).toBe(true); }); it('should accept negative pagination values (schema limitation)', () => { const invalidInput = { projectKey: 'test-project', first: -5, }; const result = parseInput(projectIssuesToolSchema, invalidInput); // Note: The schema uses z.number() without validation, so negative values pass // This is a known limitation in the schema expect(result?.success).toBe(true); }); }); describe('runsToolSchema', () => { it('should have correct name and description', () => { expect(runsToolSchema.name).toBe('runs'); expect(runsToolSchema.description).toContain('List analysis runs'); }); it('should validate input with analyzer filter', () => { const validInput = { projectKey: 'test-project', analyzerIn: ['test-coverage', 'javascript'], last: 20, before: 'cursor456', }; const result = parseInput(runsToolSchema, validInput); expect(result?.success).toBe(true); }); it('should validate both forward and backward pagination', () => { const forwardInput = { projectKey: 'test-project', first: 10, after: 'cursorA', }; const backwardInput = { projectKey: 'test-project', last: 10, before: 'cursorB', }; expect(parseInput(runsToolSchema, forwardInput)?.success).toBe(true); expect(parseInput(runsToolSchema, backwardInput)?.success).toBe(true); }); }); describe('runToolSchema', () => { it('should have correct name and description', () => { expect(runToolSchema.name).toBe('run'); expect(runToolSchema.description).toBe( 'Get a specific analysis run by its runUid or commitOid' ); }); it('should validate input with runUid', () => { const validInput = { projectKey: 'test-project', runIdentifier: 'run-uid-123', }; const result = parseInput(runToolSchema, validInput); expect(result?.success).toBe(true); }); it('should validate input with commitOid', () => { const validInput = { projectKey: 'test-project', runIdentifier: 'abc123def456', isCommitOid: true, }; const result = parseInput(runToolSchema, validInput); expect(result?.success).toBe(true); }); it('should validate input with isCommitOid false', () => { const validInput = { projectKey: 'test-project', runIdentifier: 'run-uid-456', isCommitOid: false, }; const result = parseInput(runToolSchema, validInput); expect(result?.success).toBe(true); }); }); describe('recentRunIssuesToolSchema', () => { it('should have correct name and description', () => { expect(recentRunIssuesToolSchema.name).toBe('recent_run_issues'); expect(recentRunIssuesToolSchema.description).toContain('most recent analysis run'); }); it('should validate input with branch name', () => { const validInput = { projectKey: 'test-project', branchName: 'feature/new-feature', first: 50, }; const result = parseInput(recentRunIssuesToolSchema, validInput); expect(result?.success).toBe(true); }); it('should require both projectKey and branchName', () => { const missingBranch = { projectKey: 'test-project', }; const missingProject = { branchName: 'main', }; expect(parseInput(recentRunIssuesToolSchema, missingBranch)?.success).toBe(false); expect(parseInput(recentRunIssuesToolSchema, missingProject)?.success).toBe(false); }); }); describe('dependencyVulnerabilitiesToolSchema', () => { it('should have correct name and description', () => { expect(dependencyVulnerabilitiesToolSchema.name).toBe('dependency_vulnerabilities'); expect(dependencyVulnerabilitiesToolSchema.description).toContain( 'dependency vulnerabilities' ); }); it('should validate input with pagination', () => { const validInput = { projectKey: 'test-project', first: 25, after: 'vuln-cursor', }; const result = parseInput(dependencyVulnerabilitiesToolSchema, validInput); expect(result?.success).toBe(true); }); it('should validate input with only projectKey', () => { const validInput = { projectKey: 'test-project', }; const result = parseInput(dependencyVulnerabilitiesToolSchema, validInput); expect(result?.success).toBe(true); }); }); describe('toolSchemas array', () => { it('should contain all 10 tool schemas', () => { expect(toolSchemas).toHaveLength(10); }); it('should contain all defined schemas', () => { const toolNames = toolSchemas.map((schema) => schema.name); expect(toolNames).toContain('projects'); expect(toolNames).toContain('quality_metrics'); expect(toolNames).toContain('update_metric_threshold'); expect(toolNames).toContain('update_metric_setting'); expect(toolNames).toContain('compliance_report'); expect(toolNames).toContain('project_issues'); expect(toolNames).toContain('runs'); expect(toolNames).toContain('run'); expect(toolNames).toContain('recent_run_issues'); expect(toolNames).toContain('dependency_vulnerabilities'); }); it('should have valid schemas for all tools', () => { toolSchemas.forEach((schema) => { expect(schema.name).toBeTruthy(); expect(schema.description).toBeTruthy(); expect(typeof schema.name).toBe('string'); expect(typeof schema.description).toBe('string'); }); }); }); describe('Schema edge cases', () => { it('should handle empty arrays in filters', () => { const input = { projectKey: 'test-project', analyzerIn: [], tags: [], }; const result = parseInput(projectIssuesToolSchema, input); expect(result?.success).toBe(true); }); it('should handle very long project keys', () => { // projectsToolSchema has empty input schema expect(projectsToolSchema.inputSchema).toBeDefined(); const result = parseInput(projectsToolSchema, {}); expect(result?.success).toBe(true); expect(result?.data).toEqual({}); }); it('should handle special characters in strings', () => { const input = { projectKey: 'test-project-@#$%', path: '/path/with spaces/and-special!@#$%.py', }; const result = parseInput(projectIssuesToolSchema, input); expect(result?.success).toBe(true); }); it('should validate metric shortcodes strictly', () => { const validShortcodes = ['LCV', 'BCV', 'DCV', 'DDP', 'SCV', 'TCV', 'CMP']; validShortcodes.forEach((code) => { const input = { projectKey: 'test', shortcodeIn: [code], }; const result = parseInput(qualityMetricsToolSchema, input); 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/sapientpants/deepsource-mcp-server'

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