Skip to main content
Glama
GetRequestDetailsHandler.test.ts7.95 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 { GetRequestDetailsHandler } from '../../../tools/handlers/GetRequestDetailsHandler.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('GetRequestDetailsHandler', () => { let handler: GetRequestDetailsHandler; let mockBrunoCLI: IBrunoCLI; const mockRequestDetails = { name: 'Get Users', method: 'GET', url: 'https://api.example.com/users', auth: 'bearer', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer {{API_KEY}}' }, metadata: { type: 'http', seq: 1 } }; const mockRequestWithBody = { name: 'Create User', method: 'POST', url: 'https://api.example.com/users', auth: 'none', headers: { 'Content-Type': 'application/json' }, body: { type: 'json', content: '{"name": "John Doe", "email": "john@example.com"}' }, metadata: { type: 'http', seq: 2 } }; const mockRequestWithTests = { name: 'Get User by ID', method: 'GET', url: 'https://api.example.com/users/1', auth: 'none', headers: {}, tests: [ 'expect(res.status).toBe(200);', 'expect(res.body).toHaveProperty(\'id\');' ], metadata: { type: 'http', seq: 3 } }; beforeEach(() => { vi.clearAllMocks(); mockBrunoCLI = { isAvailable: vi.fn(), listRequests: vi.fn(), listEnvironments: vi.fn(), runRequest: vi.fn(), runCollection: vi.fn(), getRequestDetails: vi.fn().mockResolvedValue(mockRequestDetails), validateCollection: vi.fn(), validateEnvironment: vi.fn() }; handler = new GetRequestDetailsHandler(mockBrunoCLI); vi.mocked(security.validateToolParameters).mockResolvedValue({ valid: true, errors: [] }); }); test('should return correct tool name', () => { expect(handler.getName()).toBe('bruno_get_request_details'); }); test('should get request details successfully', async () => { const result = await handler.handle({ collectionPath: '/valid/path/to/collection', requestName: 'Get Users' }); expect(security.validateToolParameters).toHaveBeenCalledWith({ collectionPath: '/valid/path/to/collection', requestName: 'Get Users' }); expect(mockBrunoCLI.getRequestDetails).toHaveBeenCalledWith( '/valid/path/to/collection', 'Get Users' ); expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe('text'); }); test('should display request method and URL', async () => { const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Get Users' }); const output = (result.content[0] as any).text; expect(output).toContain('Method: GET'); expect(output).toContain('URL: https://api.example.com/users'); expect(output).toContain('Auth: bearer'); }); test('should display request headers', async () => { const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Get Users' }); const output = (result.content[0] as any).text; expect(output).toContain('Headers:'); expect(output).toContain('Content-Type: application/json'); expect(output).toContain('Authorization: Bearer {{API_KEY}}'); }); test('should display request body when present', async () => { mockBrunoCLI.getRequestDetails = vi.fn().mockResolvedValue(mockRequestWithBody); const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Create User' }); const output = (result.content[0] as any).text; expect(output).toContain('Body Type: json'); expect(output).toContain('Body Content:'); expect(output).toContain('"name": "John Doe"'); }); test('should indicate when body is not present', async () => { const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Get Users' }); const output = (result.content[0] as any).text; expect(output).toContain('Body: none'); }); test('should display tests when present', async () => { mockBrunoCLI.getRequestDetails = vi.fn().mockResolvedValue(mockRequestWithTests); const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Get User by ID' }); const output = (result.content[0] as any).text; expect(output).toContain('Tests: 2'); expect(output).toContain('expect(res.status).toBe(200);'); expect(output).toContain('expect(res.body).toHaveProperty'); }); test('should indicate when tests are not present', async () => { const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Get Users' }); const output = (result.content[0] as any).text; expect(output).toContain('Tests: none'); }); test('should display metadata', async () => { const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Get Users' }); const output = (result.content[0] as any).text; expect(output).toContain('Metadata:'); expect(output).toContain('Type: http'); expect(output).toContain('Sequence: 1'); }); test('should handle multiline body content with indentation', async () => { const requestWithMultilineBody = { ...mockRequestWithBody, body: { type: 'json', content: '{\n "name": "John Doe",\n "email": "john@example.com"\n}' } }; mockBrunoCLI.getRequestDetails = vi.fn().mockResolvedValue(requestWithMultilineBody); const result = await handler.handle({ collectionPath: '/valid/path', requestName: 'Create User' }); const output = (result.content[0] as any).text; expect(output).toContain('Body Content:'); // Each line should be indented expect(output).toMatch(/\n {2}\{/); expect(output).toMatch(/\n {4}"name":/); }); test('should throw McpError when validation fails', async () => { vi.mocked(security.validateToolParameters).mockResolvedValue({ valid: false, errors: ['Invalid parameters'] }); await expect( handler.handle({ collectionPath: '/invalid/path', requestName: 'Test' }) ).rejects.toThrow(McpError); }); test('should throw McpError on Bruno CLI failure', async () => { mockBrunoCLI.getRequestDetails = vi.fn().mockRejectedValue( new Error('Request not found') ); await expect( handler.handle({ collectionPath: '/valid/path', requestName: 'NonExistent' }) ).rejects.toThrow(McpError); }); test('should call maskSecretsInError on errors', async () => { const error = new Error('Error with SECRET=abc123'); mockBrunoCLI.getRequestDetails = vi.fn().mockRejectedValue(error); vi.mocked(security.maskSecretsInError).mockReturnValue('Error with SECRET=***'); await expect( handler.handle({ collectionPath: '/valid/path', requestName: 'Test' }) ).rejects.toThrow(); expect(security.maskSecretsInError).toHaveBeenCalledWith(error); }); test('should throw error for missing required parameters', async () => { await expect(handler.handle({})).rejects.toThrow(); await expect(handler.handle({ collectionPath: '/path' })).rejects.toThrow(); await expect(handler.handle({ requestName: 'Test' })).rejects.toThrow(); }); test('should throw error for invalid parameter types', async () => { await expect( handler.handle({ collectionPath: 123, requestName: 'Test' }) ).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