UNPKG

@measey/mycoder-agent

Version:

Agent module for mycoder - an AI-powered software development assistant

179 lines 7.95 kB
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { listShellsTool } from './listShells'; import { shellStartTool } from './shellStart'; import { ShellStatus, ShellTracker } from './ShellTracker'; /** * Create a more realistic test that simulates running multiple commands * and verifies the shell tracker's state * * TODO: These tests are currently skipped due to issues with the test setup. * They should be revisited and fixed in a future update. */ describe('ShellTracker integration', () => { // Create a real ShellTracker instance let shellTracker; // Store event handlers for each process // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type const eventHandlers = {}; // Mock process const mockProcess = { on: vi.fn(), stdout: { on: vi.fn() }, stderr: { on: vi.fn() }, }; // Mock child_process vi.mock('child_process', () => ({ spawn: vi.fn().mockImplementation(() => { // Set up event handler capture mockProcess.on.mockImplementation((event, handler) => { eventHandlers[event] = handler; return mockProcess; }); return mockProcess; }), })); // Create mock logger const mockLogger = { log: vi.fn(), debug: vi.fn(), error: vi.fn(), warn: vi.fn(), info: vi.fn(), }; // Create mock context function const createMockContext = () => ({ logger: mockLogger, workingDirectory: '/test', headless: false, userSession: false, tokenTracker: { trackTokens: vi.fn() }, githubMode: false, provider: 'anthropic', maxTokens: 4000, temperature: 0, agentTracker: { registerAgent: vi.fn() }, shellTracker: shellTracker, browserTracker: { registerSession: vi.fn() }, }); beforeEach(() => { vi.clearAllMocks(); shellTracker = new ShellTracker('test-agent'); Object.keys(eventHandlers).forEach((key) => delete eventHandlers[key]); }); afterEach(() => { vi.resetAllMocks(); }); // TODO: Fix these tests it.skip('should correctly track multiple shell commands with different completion times', async () => { // Setup shellTracker to track multiple commands let shellIdCounter = 0; vi.spyOn(shellTracker, 'registerShell').mockImplementation((command) => { const shellId = `shell-${++shellIdCounter}`; const shell = { shellId, status: ShellStatus.RUNNING, startTime: new Date(), metadata: { command }, }; shellTracker['shells'].set(shellId, shell); return shellId; }); // Start first command const cmd1Promise = shellStartTool.execute({ command: 'echo hello', description: 'Command 1', timeout: 0 }, createMockContext()); // Await first result (in async mode) const result1 = await cmd1Promise; expect(result1.mode).toBe('async'); // Start second command const cmd2Promise = shellStartTool.execute({ command: 'ls -la', description: 'Command 2', timeout: 0 }, createMockContext()); // Await second result (in async mode) const result2 = await cmd2Promise; expect(result2.mode).toBe('async'); // Start third command const cmd3Promise = shellStartTool.execute({ command: 'find . -name "*.js"', description: 'Command 3', timeout: 0 }, createMockContext()); // Await third result (in async mode) const result3 = await cmd3Promise; expect(result3.mode).toBe('async'); // Check that all 3 shells are registered as running expect(shellTracker.getShells(ShellStatus.RUNNING).length).toBe(3); // Complete the first command with successful exit eventHandlers['exit']?.(0, null); // Update the shell status manually since we're mocking the event handlers shellTracker.updateShellStatus('shell-1', ShellStatus.COMPLETED, { exitCode: 0, }); // Complete the second command with an error eventHandlers['exit']?.(1, null); // Update the shell status manually shellTracker.updateShellStatus('shell-2', ShellStatus.ERROR, { exitCode: 1, }); // Check shell statuses before the third command completes expect(shellTracker.getShells(ShellStatus.RUNNING).length).toBe(1); expect(shellTracker.getShells(ShellStatus.COMPLETED).length).toBe(1); expect(shellTracker.getShells(ShellStatus.ERROR).length).toBe(1); // Complete the third command with success eventHandlers['exit']?.(0, null); // Update the shell status manually shellTracker.updateShellStatus('shell-3', ShellStatus.COMPLETED, { exitCode: 0, }); // Check final shell statuses expect(shellTracker.getShells(ShellStatus.RUNNING).length).toBe(0); expect(shellTracker.getShells(ShellStatus.COMPLETED).length).toBe(2); expect(shellTracker.getShells(ShellStatus.ERROR).length).toBe(1); // Verify listShells tool correctly reports the statuses const listResult = await listShellsTool.execute({}, createMockContext()); expect(listResult.shells.length).toBe(3); expect(listResult.shells.filter((s) => s.status === ShellStatus.RUNNING).length).toBe(0); expect(listResult.shells.filter((s) => s.status === ShellStatus.COMPLETED) .length).toBe(2); expect(listResult.shells.filter((s) => s.status === ShellStatus.ERROR).length).toBe(1); }); it.skip('should handle commands that transition from sync to async mode', async () => { // Setup shellTracker to track the command vi.spyOn(shellTracker, 'registerShell').mockImplementation((command) => { const shellId = 'test-shell-id'; const shell = { shellId, status: ShellStatus.RUNNING, startTime: new Date(), metadata: { command }, }; shellTracker['shells'].set(shellId, shell); return shellId; }); // Force async mode by using a modified version of the tool with timeout=0 const modifiedShellStartTool = { ...shellStartTool, execute: async (params, context) => { // Force timeout to 0 to ensure async mode const result = await shellStartTool.execute({ ...params, timeout: 0 }, context); return result; }, }; // Start a command with forced async mode const cmdPromise = modifiedShellStartTool.execute({ command: 'long-running-command', description: 'Long command', timeout: 100, }, createMockContext()); // Check that the shell is registered as running expect(shellTracker.getShells(ShellStatus.RUNNING).length).toBe(1); // Get the result (which will be in async mode) const result = await cmdPromise; // Verify it went into async mode expect(result.mode).toBe('async'); // Shell should still be marked as running expect(shellTracker.getShells(ShellStatus.RUNNING).length).toBe(1); // Now complete the command eventHandlers['exit']?.(0, null); // Update the shell status manually shellTracker.updateShellStatus('test-shell-id', ShellStatus.COMPLETED, { exitCode: 0, }); // Verify the shell is now marked as completed expect(shellTracker.getShells(ShellStatus.RUNNING).length).toBe(0); expect(shellTracker.getShells(ShellStatus.COMPLETED).length).toBe(1); }); }); //# sourceMappingURL=shellTrackerIntegration.test.js.map