Skip to main content
Glama
execution.integration.test.ts8.67 kB
import { AgentExecutor, createExecutionConfig } from 'src/execution/AgentExecutor' import type { ExecutionParams } from 'src/types/ExecutionParams' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' // Mock child_process module for integration testing vi.mock('node:child_process', () => ({ spawn: vi.fn(), })) // Import the mocked module to get references import { spawn as mockSpawn } from 'node:child_process' describe('AgentExecutor Integration', () => { let executor: AgentExecutor beforeEach(() => { vi.clearAllMocks() const testConfig = createExecutionConfig('cursor') executor = new AgentExecutor(testConfig) // Setup spawn mock for integration tests mockSpawn.mockImplementation((cmd: string, args: string[], options: any) => { // Extract the prompt which should be the last argument after -p flag const promptIndex = args.indexOf('-p') const prompt = promptIndex >= 0 && promptIndex < args.length - 1 ? args[promptIndex + 1] : '' const isNonexistentAgent = prompt.includes('nonexistent-agent') const isTestAgent = prompt.includes('test-agent') || prompt.includes('integration-test-agent') const mockProcess = { stdin: { end: vi.fn(), }, stdout: { on: vi.fn((event, callback) => { if (event === 'data') { if (isTestAgent) { // Success case - simulate cursor type:result response (synchronous for test stability) callback( Buffer.from( `${JSON.stringify({ type: 'result', data: 'Integration test execution success', })}\n` ) ) } else if (isNonexistentAgent) { // Don't send successful data for nonexistent agents } else { // Default success - cursor type:result format (synchronous for test stability) callback( Buffer.from( `${JSON.stringify({ type: 'result', data: 'Default integration execution', })}\n` ) ) } } }), }, stderr: { on: vi.fn((event, callback) => { if (event === 'data' && isNonexistentAgent) { // Synchronous for test stability callback(Buffer.from('Agent not found')) } }), }, on: vi.fn((event, callback) => { if (event === 'close') { const exitCode = isNonexistentAgent ? 1 : 0 // Synchronous for test stability callback(exitCode) } else if (event === 'error' && isNonexistentAgent) { // Synchronous for test stability callback(new Error('Integration execution failed')) } else if (event === 'exit') { // Synchronous for test stability callback() } }), kill: vi.fn(), } return mockProcess as any }) }) afterEach(() => { vi.restoreAllMocks() }) describe('end-to-end execution flow', () => { it('should execute complete flow from params enhancement to result collection', async () => { const originalParams: ExecutionParams = { agent: 'integration-test-agent', prompt: 'Perform integration test task', cwd: '/tmp/integration', extra_args: ['--verbose'], } // This test verifies the complete integration flow: // 1. Execution method is selected (always spawn) // 2. Agent is executed with formatted prompt // 3. Results are collected with performance metrics const result = await executor.executeAgent(originalParams) expect(result).toEqual({ stdout: expect.any(String), stderr: expect.any(String), exitCode: expect.any(Number), executionTime: expect.any(Number), hasResult: expect.any(Boolean), resultJson: expect.any(Object), }) // Verify basic execution properties expect(result.exitCode).toBeDefined() // Verify performance monitoring expect(result.executionTime).toBeGreaterThanOrEqual(0) expect(result.executionTime).toBeGreaterThanOrEqual(0) }) it('should use spawn method for all prompt sizes', async () => { const smallPromptParams: ExecutionParams = { agent: 'test-agent', prompt: 'Small task', cwd: '/tmp', } const largePromptParams: ExecutionParams = { agent: 'test-agent', prompt: 'Large complex task requiring extensive output and detailed analysis'.repeat(100), cwd: '/tmp', } const smallResult = await executor.executeAgent(smallPromptParams) const largeResult = await executor.executeAgent(largePromptParams) // Verify spawn is used for all cases expect(smallResult.exitCode).toBeDefined() expect(largeResult.exitCode).toBeDefined() }) it('should handle execution errors', async () => { const params: ExecutionParams = { agent: 'nonexistent-agent', prompt: 'This will fail', cwd: '/invalid/path', } const result = await executor.executeAgent(params) // Verify error is properly captured expect(result.exitCode).not.toBe(0) expect(result.stderr).toBeTruthy() // Verify performance metrics are still collected for failed executions expect(result.executionTime).toBeGreaterThanOrEqual(0) expect(result.exitCode).toBeDefined() }) }) describe('execution method selection integration', () => { it('should use spawn method for all prompts', async () => { const params: ExecutionParams = { agent: 'quick-helper', prompt: 'Quick help', cwd: '/tmp', } const result = await executor.executeAgent(params) expect(result.exitCode).toBeDefined() expect(result.executionTime).toBeGreaterThanOrEqual(0) }) it('should use spawn method for large prompts with recursion prevention', async () => { const params: ExecutionParams = { agent: 'detailed-analyzer', prompt: 'Provide comprehensive analysis with detailed explanations and code examples'.repeat(200), cwd: '/tmp', } const result = await executor.executeAgent(params) expect(result.exitCode).toBeDefined() expect(result.executionTime).toBeGreaterThanOrEqual(0) }) }) describe('performance monitoring integration', () => { it('should track performance across different prompt sizes', async () => { const smallParams: ExecutionParams = { agent: 'fast-agent', prompt: 'Quick task', cwd: '/tmp', } const largeParams: ExecutionParams = { agent: 'thorough-agent', prompt: 'Detailed analysis requiring large output'.repeat(300), cwd: '/tmp', } const smallResult = await executor.executeAgent(smallParams) const largeResult = await executor.executeAgent(largeParams) // Both should have performance metrics expect(smallResult.executionTime).toBeGreaterThanOrEqual(0) expect(largeResult.executionTime).toBeGreaterThanOrEqual(0) // Both use spawn method (no exec method anymore) expect(smallResult.exitCode).toBeDefined() expect(largeResult.exitCode).toBeDefined() // Output size estimation should differ expect(smallResult.executionTime).toBeGreaterThanOrEqual(0) expect(largeResult.executionTime).toBeGreaterThanOrEqual(0) }) }) describe('error boundary integration', () => { it('should handle direct execution without enhancement errors', async () => { const params: ExecutionParams = { agent: 'test-agent', prompt: 'Test direct execution', cwd: '/tmp', } // Direct execution should work without enhancement layer const result = await executor.executeAgent(params) // Should not throw and return valid result expect(result).toBeDefined() expect(result.exitCode).toBeDefined() expect(typeof result.executionTime).toBe('number') }) it('should handle both enhancement and execution errors appropriately', async () => { const invalidParams: ExecutionParams = { agent: '', prompt: '', cwd: '/tmp', } // This should fail at the parameter validation level await expect(executor.executeAgent(invalidParams)).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/shinpr/sub-agents-mcp'

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