@wonderwhy-er/desktop-commander
Version:
MCP server for terminal operations and file editing
76 lines (75 loc) • 3.98 kB
JavaScript
import { expect } from 'chai';
import { describe, it } from 'mocha';
import { REPLSessionManager } from './REPLSessionManager';
import * as sinon from 'sinon';
describe('REPLSessionManager', () => {
// Create a mock terminal manager for testing
const createMockTerminalManager = () => {
return {
executeCommand: sinon.stub().resolves({ pid: 12345 }),
sendInputToProcess: sinon.stub().returns(true),
getNewOutput: sinon.stub().returns('test output\n> '),
terminateProcess: sinon.stub().resolves(true)
};
};
it('should create a new instance', () => {
const terminalManager = createMockTerminalManager();
const manager = new REPLSessionManager(terminalManager);
expect(manager).to.be.an.instanceOf(REPLSessionManager);
});
it('should create a new session', async () => {
const terminalManager = createMockTerminalManager();
const manager = new REPLSessionManager(terminalManager);
const pid = await manager.createSession('node');
expect(pid).to.equal(12345);
expect(terminalManager.executeCommand.calledOnce).to.be.true;
});
it('should send and read REPL output', async () => {
const terminalManager = createMockTerminalManager();
const manager = new REPLSessionManager(terminalManager);
const result = await manager.sendAndReadREPL(12345, 'console.log("hello")', 'node', 1000);
expect(result.success).to.be.true;
expect(terminalManager.sendInputToProcess.calledOnce).to.be.true;
expect(terminalManager.getNewOutput.called).to.be.true;
});
it('should detect when output is complete', () => {
const terminalManager = createMockTerminalManager();
const manager = new REPLSessionManager(terminalManager);
// Node.js prompt
expect(manager.isOutputComplete('test\n> ', 'node')).to.be.true;
// Python prompt
expect(manager.isOutputComplete('test\n>>> ', 'python')).to.be.true;
// Incomplete output
expect(manager.isOutputComplete('test\n', 'node')).to.be.false;
});
it('should calculate timeout based on code complexity', () => {
const terminalManager = createMockTerminalManager();
const manager = new REPLSessionManager(terminalManager);
const simpleTimeout = manager.calculateTimeout('x = 1');
const loopTimeout = manager.calculateTimeout('for (let i = 0; i < 10; i++) { console.log(i); }');
const importTimeout = manager.calculateTimeout('import math\nimport os\nimport sys');
expect(loopTimeout).to.be.greaterThan(simpleTimeout);
expect(importTimeout).to.be.greaterThan(simpleTimeout);
});
it('should clean output', () => {
const terminalManager = createMockTerminalManager();
const manager = new REPLSessionManager(terminalManager);
const nodeOutput = manager.cleanOutput('x = 1\n> ', 'x = 1', 'node');
const pythonOutput = manager.cleanOutput('>>> x = 1\n>>> ', 'x = 1', 'python');
expect(nodeOutput).to.not.include('>');
expect(pythonOutput).to.not.include('>>>');
});
it('should handle multi-line code', async () => {
const terminalManager = createMockTerminalManager();
const manager = new REPLSessionManager(terminalManager);
// Mock implementation for Python indentation
terminalManager.getNewOutput.onFirstCall().returns('>>> ');
terminalManager.getNewOutput.onSecondCall().returns('... ');
terminalManager.getNewOutput.onThirdCall().returns('... ');
terminalManager.getNewOutput.onCall(3).returns('result\n>>> ');
const multilineCode = 'for i in range(5):\n print(i)';
const result = await manager.handleMultilineCode(12345, multilineCode, 'python', 1000);
expect(result.success).to.be.true;
expect(terminalManager.sendInputToProcess.callCount).to.be.at.least(2);
});
});