Skip to main content
Glama

1MCP Server

urlGenerator.test.ts14.1 kB
import { AgentConfigManager } from '@src/core/server/agentConfig.js'; import { PresetManager } from '@src/domains/preset/manager/presetManager.js'; import logger from '@src/logger/logger.js'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { UrlGenerator } from './urlGenerator.js'; // Mock dependencies vi.mock('@src/core/server/agentConfig.js'); vi.mock('../config/presetManager.js'); vi.mock('@src/logger/logger.js'); const mockAgentConfig = AgentConfigManager as any; const mockPresetManager = PresetManager as any; describe('UrlGenerator', () => { let urlGenerator: UrlGenerator; let mockAgentConfigInstance: any; let mockPresetManagerInstance: any; beforeEach(() => { vi.clearAllMocks(); // Mock AgentConfigManager mockAgentConfigInstance = { getUrl: vi.fn().mockReturnValue('http://localhost:3050'), getStreambleHttpUrl: vi.fn().mockReturnValue('http://localhost:3050'), isAuthEnabled: vi.fn().mockReturnValue(false), }; mockAgentConfig.getInstance = vi.fn().mockReturnValue(mockAgentConfigInstance); // Mock PresetManager mockPresetManagerInstance = { hasPreset: vi.fn(), getPreset: vi.fn(), validatePreset: vi.fn(), }; mockPresetManager.getInstance = vi.fn().mockReturnValue(mockPresetManagerInstance); urlGenerator = new UrlGenerator(); }); describe('generatePresetUrl', () => { it('should generate URL with preset parameter', () => { const url = urlGenerator.generatePresetUrl('development'); expect(url).toBe('http://localhost:3050/?preset=development'); expect(logger.debug).toHaveBeenCalledWith('Generated preset URL', { presetName: 'development', url: 'http://localhost:3050/?preset=development', }); }); it('should handle preset names with special characters', () => { const url = urlGenerator.generatePresetUrl('dev-staging_v2'); expect(url).toBe('http://localhost:3050/?preset=dev-staging_v2'); }); }); describe('generateTagFilterUrl', () => { it('should generate URL with tag-filter parameter', () => { const url = urlGenerator.generateTagFilterUrl('web+api-test'); expect(url).toBe('http://localhost:3050/?tag-filter=web%2Bapi-test'); expect(logger.debug).toHaveBeenCalledWith('Generated tag filter URL', { tagFilter: 'web+api-test', url: 'http://localhost:3050/?tag-filter=web%2Bapi-test', }); }); }); describe('generateTagsUrl', () => { it('should generate URL with tags parameter (deprecated)', () => { const url = urlGenerator.generateTagsUrl(['web', 'api', 'database']); expect(url).toBe('http://localhost:3050/?tags=web%2Capi%2Cdatabase'); expect(logger.debug).toHaveBeenCalledWith('Generated tags URL (deprecated)', { tags: ['web', 'api', 'database'], url: 'http://localhost:3050/?tags=web%2Capi%2Cdatabase', }); }); it('should handle empty tags array', () => { const url = urlGenerator.generateTagsUrl([]); expect(url).toBe('http://localhost:3050/?tags='); }); }); describe('generateUrl', () => { beforeEach(() => { mockPresetManagerInstance.hasPreset.mockReturnValue(true); }); it('should prioritize preset over other options', () => { const url = urlGenerator.generateUrl({ preset: 'development', tagFilter: 'web+api', tags: ['web', 'api'], }); expect(url).toBe('http://localhost:3050/?preset=development'); }); it('should use tag-filter when no preset', () => { const url = urlGenerator.generateUrl({ tagFilter: 'web+api', tags: ['web', 'api'], }); expect(url).toBe('http://localhost:3050/?tag-filter=web%2Bapi'); }); it('should use tags when no preset or tag-filter', () => { const url = urlGenerator.generateUrl({ tags: ['web', 'api'], }); expect(url).toBe('http://localhost:3050/?tags=web%2Capi'); }); it('should generate base URL when no filtering options', () => { const url = urlGenerator.generateUrl({}); expect(url).toBe('http://localhost:3050/'); }); it('should add custom parameters', () => { const url = urlGenerator.generateUrl({ preset: 'development', customParams: { sessionId: 'test-session', debug: 'true', }, }); expect(url).toBe('http://localhost:3050/?preset=development&sessionId=test-session&debug=true'); }); it('should throw error for non-existent preset', () => { mockPresetManagerInstance.hasPreset.mockReturnValue(false); expect(() => urlGenerator.generateUrl({ preset: 'nonexistent' })).toThrow("Preset 'nonexistent' not found"); }); it('should include auth parameters when enabled', () => { mockAgentConfigInstance.isAuthEnabled.mockReturnValue(true); const url = urlGenerator.generateUrl({ preset: 'development', includeAuth: true, }); // Note: Auth parameters would be added here in actual implementation expect(url).toBe('http://localhost:3050/?preset=development'); }); it('should log generation details', () => { const options = { preset: 'development', customParams: { debug: 'true' }, }; urlGenerator.generateUrl(options); expect(logger.debug).toHaveBeenCalledWith('Generated URL', { options, url: 'http://localhost:3050/?preset=development&debug=true', baseUrl: 'http://localhost:3050', }); }); }); describe('validateAndGeneratePresetUrl', () => { it('should validate and generate URL for valid preset', async () => { const mockPreset = { name: 'development', strategy: 'or' as const, servers: ['server1'], tagExpression: 'web,api', created: '2025-01-01T00:00:00Z', lastModified: '2025-01-01T00:00:00Z', }; mockPresetManagerInstance.hasPreset.mockReturnValue(true); mockPresetManagerInstance.getPreset.mockReturnValue(mockPreset); mockPresetManagerInstance.validatePreset.mockResolvedValue({ isValid: true, errors: [], warnings: [], }); const result = await urlGenerator.validateAndGeneratePresetUrl('development'); expect(result).toEqual({ url: 'http://localhost:3050/?preset=development', valid: true, }); }); it('should return error for non-existent preset', async () => { mockPresetManagerInstance.hasPreset.mockReturnValue(false); const result = await urlGenerator.validateAndGeneratePresetUrl('nonexistent'); expect(result).toEqual({ url: '', valid: false, error: "Preset 'nonexistent' not found", }); }); it('should return error for invalid preset configuration', async () => { mockPresetManagerInstance.hasPreset.mockReturnValue(true); mockPresetManagerInstance.getPreset.mockReturnValue(null); const result = await urlGenerator.validateAndGeneratePresetUrl('invalid'); expect(result).toEqual({ url: '', valid: false, error: "Preset 'invalid' configuration is invalid", }); }); it('should return validation errors', async () => { const mockPreset = { name: 'invalid', strategy: 'or' as const, servers: [], tagExpression: '', created: '2025-01-01T00:00:00Z', lastModified: '2025-01-01T00:00:00Z', }; mockPresetManagerInstance.hasPreset.mockReturnValue(true); mockPresetManagerInstance.getPreset.mockReturnValue(mockPreset); mockPresetManagerInstance.validatePreset.mockResolvedValue({ isValid: false, errors: ['No servers specified', 'Empty tag expression'], warnings: [], }); const result = await urlGenerator.validateAndGeneratePresetUrl('invalid'); expect(result).toEqual({ url: '', valid: false, error: 'Preset validation failed: No servers specified; Empty tag expression', }); }); it('should handle validation errors gracefully', async () => { mockPresetManagerInstance.hasPreset.mockReturnValue(true); mockPresetManagerInstance.getPreset.mockImplementation(() => { throw new Error('Unexpected error'); }); const result = await urlGenerator.validateAndGeneratePresetUrl('error'); expect(result).toEqual({ url: '', valid: false, error: 'Failed to generate URL: Unexpected error', }); expect(logger.error).toHaveBeenCalledWith( 'URL validation and generation failed', expect.objectContaining({ presetName: 'error' }), ); }); }); describe('parseUrl', () => { it('should parse URL with preset parameter', () => { const result = urlGenerator.parseUrl('http://localhost:3050/?preset=development&debug=true'); expect(result).toEqual({ preset: 'development', otherParams: { debug: 'true' }, }); }); it('should parse URL with tag-filter parameter', () => { const result = urlGenerator.parseUrl('http://localhost:3050/?tag-filter=web%2Bapi&sessionId=test'); expect(result).toEqual({ tagFilter: 'web+api', otherParams: { sessionId: 'test' }, }); }); it('should parse URL with tags parameter', () => { const result = urlGenerator.parseUrl('http://localhost:3050/?tags=web%2Capi%2Cdatabase'); expect(result).toEqual({ tags: ['web', 'api', 'database'], otherParams: {}, }); }); it('should handle URL with no parameters', () => { const result = urlGenerator.parseUrl('http://localhost:3050/'); expect(result).toEqual({ otherParams: {}, }); }); it('should handle invalid URL gracefully', () => { const result = urlGenerator.parseUrl('not-a-valid-url'); expect(result).toEqual({ otherParams: {}, }); expect(logger.error).toHaveBeenCalledWith( 'Failed to parse URL', expect.objectContaining({ url: 'not-a-valid-url' }), ); }); it('should prioritize preset over other filtering parameters', () => { const result = urlGenerator.parseUrl('http://localhost:3050/?preset=dev&tag-filter=web&tags=api'); expect(result).toEqual({ preset: 'dev', otherParams: {}, }); }); it('should handle empty tags parameter', () => { const result = urlGenerator.parseUrl('http://localhost:3050/?tags='); // Empty tags parameter should not set tags property expect(result).toEqual({ otherParams: {}, }); }); }); describe('utility methods', () => { describe('getBaseUrl', () => { it('should return base URL without parameters', () => { const url = urlGenerator.getBaseUrl(); expect(url).toBe('http://localhost:3050'); }); }); describe('isPresetUrl', () => { it('should return true for URL with preset parameter', () => { const result = urlGenerator.isPresetUrl('http://localhost:3050/?preset=development'); expect(result).toBe(true); }); it('should return false for URL without preset parameter', () => { const result = urlGenerator.isPresetUrl('http://localhost:3050/?tags=web,api'); expect(result).toBe(false); }); it('should return false for invalid URL', () => { const result = urlGenerator.isPresetUrl('invalid-url'); expect(result).toBe(false); }); }); describe('extractPresetName', () => { it('should extract preset name from URL', () => { const result = urlGenerator.extractPresetName('http://localhost:3050/?preset=development&debug=true'); expect(result).toBe('development'); }); it('should return null for URL without preset', () => { const result = urlGenerator.extractPresetName('http://localhost:3050/?tags=web,api'); expect(result).toBeNull(); }); it('should return null for invalid URL', () => { const result = urlGenerator.extractPresetName('invalid-url'); expect(result).toBeNull(); }); }); describe('generateConnectionString', () => { it('should generate connection string for MCP clients', () => { mockPresetManagerInstance.hasPreset.mockReturnValue(true); const connectionString = urlGenerator.generateConnectionString({ preset: 'development', }); expect(connectionString).toBe('http://localhost:3050/?preset=development'); }); it('should handle empty options', () => { const connectionString = urlGenerator.generateConnectionString(); expect(connectionString).toBe('http://localhost:3050/'); }); }); }); describe('integration with different base URLs', () => { it('should work with HTTPS URLs', () => { mockAgentConfigInstance.getUrl.mockReturnValue('https://api.example.com:8443'); mockAgentConfigInstance.getStreambleHttpUrl.mockReturnValue('https://api.example.com:8443'); const url = urlGenerator.generatePresetUrl('production'); expect(url).toBe('https://api.example.com:8443/?preset=production'); }); it('should work with URLs containing paths', () => { mockAgentConfigInstance.getUrl.mockReturnValue('http://localhost:3050/api/v1'); mockAgentConfigInstance.getStreambleHttpUrl.mockReturnValue('http://localhost:3050/api/v1'); const url = urlGenerator.generatePresetUrl('development'); expect(url).toBe('http://localhost:3050/api/v1?preset=development'); }); it('should handle URLs with existing query parameters', () => { mockAgentConfigInstance.getUrl.mockReturnValue('http://localhost:3050/?version=v1'); mockAgentConfigInstance.getStreambleHttpUrl.mockReturnValue('http://localhost:3050/?version=v1'); const url = urlGenerator.generatePresetUrl('development'); expect(url).toBe('http://localhost:3050/?version=v1&preset=development'); }); }); });

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/1mcp-app/agent'

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