Skip to main content
Glama
ValidateCollectionHandler.test.ts6.72 kB
import { McpError } from '@modelcontextprotocol/sdk/types.js'; import { describe, test, expect, beforeEach, vi } from 'vitest'; import type { IBrunoCLI } from '../../../interfaces.js'; import * as security from '../../../security.js'; import { ValidateCollectionHandler } from '../../../tools/handlers/ValidateCollectionHandler.js'; vi.mock('../../../security.js', async () => { const actual = await vi.importActual('../../../security.js'); return { ...actual, validateToolParameters: vi.fn(), maskSecretsInError: vi.fn((error: Error) => error.message) }; }); describe('ValidateCollectionHandler', () => { let handler: ValidateCollectionHandler; let mockBrunoCLI: IBrunoCLI; const mockValidResult = { valid: true, errors: [], warnings: [], summary: { hasBrunoJson: true, totalRequests: 10, validRequests: 10, invalidRequests: 0, environments: 3 } }; const mockInvalidResult = { valid: false, errors: ['Missing bruno.json', 'Invalid request syntax in Get Users.bru'], warnings: ['Unused environment variable'], summary: { hasBrunoJson: false, totalRequests: 5, validRequests: 3, invalidRequests: 2, environments: 0 } }; beforeEach(() => { vi.clearAllMocks(); mockBrunoCLI = { isAvailable: vi.fn(), listRequests: vi.fn(), listEnvironments: vi.fn(), runRequest: vi.fn(), runCollection: vi.fn(), getRequestDetails: vi.fn(), validateCollection: vi.fn().mockResolvedValue(mockValidResult), validateEnvironment: vi.fn() }; handler = new ValidateCollectionHandler(mockBrunoCLI); vi.mocked(security.validateToolParameters).mockResolvedValue({ valid: true, errors: [] }); }); test('should return correct tool name', () => { expect(handler.getName()).toBe('bruno_validate_collection'); }); test('should validate a valid collection successfully', async () => { const result = await handler.handle({ collectionPath: '/valid/path/to/collection' }); expect(security.validateToolParameters).toHaveBeenCalledWith({ collectionPath: '/valid/path/to/collection' }); expect(mockBrunoCLI.validateCollection).toHaveBeenCalledWith('/valid/path/to/collection'); expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe('text'); expect((result.content[0] as any).text).toContain('✅ Collection is valid'); expect((result.content[0] as any).text).toContain('🎉 Collection is ready to use!'); }); test('should display validation summary correctly', async () => { const result = await handler.handle({ collectionPath: '/valid/path' }); const output = (result.content[0] as any).text; expect(output).toContain('bruno.json: ✓ Found'); expect(output).toContain('Total Requests: 10'); expect(output).toContain('Valid Requests: 10'); expect(output).toContain('Invalid Requests: 0'); expect(output).toContain('Environments: 3'); }); test('should handle invalid collection with errors', async () => { mockBrunoCLI.validateCollection = vi.fn().mockResolvedValue(mockInvalidResult); const result = await handler.handle({ collectionPath: '/invalid/path' }); const output = (result.content[0] as any).text; expect(output).toContain('❌ Collection has errors'); expect(output).toContain('bruno.json: ✗ Missing'); expect(output).toContain('Missing bruno.json'); expect(output).toContain('Invalid request syntax'); expect(output).not.toContain('🎉 Collection is ready to use!'); }); test('should display warnings when present', async () => { const resultWithWarnings = { ...mockValidResult, warnings: ['Unused environment variable: OLD_API', 'Deprecated syntax in request'] }; mockBrunoCLI.validateCollection = vi.fn().mockResolvedValue(resultWithWarnings); const result = await handler.handle({ collectionPath: '/valid/path' }); const output = (result.content[0] as any).text; expect(output).toContain('Warnings:'); expect(output).toContain('⚠️ Unused environment variable'); expect(output).toContain('⚠️ Deprecated syntax'); }); test('should throw McpError when validation fails', async () => { vi.mocked(security.validateToolParameters).mockResolvedValue({ valid: false, errors: ['Invalid collection path'] }); await expect( handler.handle({ collectionPath: '/invalid/path' }) ).rejects.toThrow(McpError); await expect( handler.handle({ collectionPath: '/invalid/path' }) ).rejects.toThrow('Invalid collection path'); }); test('should throw McpError on Bruno CLI failure', async () => { mockBrunoCLI.validateCollection = vi.fn().mockRejectedValue( new Error('Collection not found') ); await expect( handler.handle({ collectionPath: '/valid/path' }) ).rejects.toThrow(McpError); await expect( handler.handle({ collectionPath: '/valid/path' }) ).rejects.toThrow('Failed to validate collection'); }); test('should call maskSecretsInError on errors', async () => { const error = new Error('Error with SECRET=abc123'); mockBrunoCLI.validateCollection = vi.fn().mockRejectedValue(error); vi.mocked(security.maskSecretsInError).mockReturnValue('Error with SECRET=***'); await expect( handler.handle({ collectionPath: '/valid/path' }) ).rejects.toThrow(); expect(security.maskSecretsInError).toHaveBeenCalledWith(error); }); test('should show success message for valid collection without warnings', async () => { const result = await handler.handle({ collectionPath: '/valid/path' }); expect((result.content[0] as any).text).toContain('🎉 Collection is ready to use!'); }); test('should not show success message for valid collection with warnings', async () => { const resultWithWarnings = { ...mockValidResult, warnings: ['Some warning'] }; mockBrunoCLI.validateCollection = vi.fn().mockResolvedValue(resultWithWarnings); const result = await handler.handle({ collectionPath: '/valid/path' }); expect((result.content[0] as any).text).not.toContain('🎉 Collection is ready to use!'); }); test('should throw error for missing collectionPath parameter', async () => { await expect(handler.handle({})).rejects.toThrow(); }); test('should throw error for invalid parameter types', async () => { await expect(handler.handle({ collectionPath: 123 })).rejects.toThrow(); await expect(handler.handle({ collectionPath: null })).rejects.toThrow(); }); });

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/jcr82/bruno-mcp-server'

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