Skip to main content
Glama
story5-terminal-methods.test.ts7.78 kB
import { SSHConnectionManager } from "../src/ssh-connection-manager"; /* eslint-disable @typescript-eslint/no-explicit-any */ describe("Story 5: Terminal Interaction Methods - Simple Unit Tests", () => { let sshManager: SSHConnectionManager; beforeEach(() => { sshManager = new SSHConnectionManager(8080); }); afterEach(() => { sshManager.cleanup(); }); describe("sendTerminalInput method", () => { it("should throw error for non-existent session", () => { expect(() => { sshManager.sendTerminalInput("nonexistent", "test command"); }).toThrow("Session 'nonexistent' not found"); }); it("should throw error when shell not ready", () => { // Create session data but don't mark shell as ready const sessionData = { isShellReady: false, shellChannel: null, connection: { lastActivity: new Date() }, client: { destroy: jest.fn() }, config: {}, outputBuffer: [], outputListeners: [], startTime: new Date(), commandsExecuted: 0, }; (sshManager as any).connections.set("not-ready", sessionData); expect(() => { sshManager.sendTerminalInput("not-ready", "test"); }).toThrow("Shell session not ready for connection 'not-ready'"); }); it("should call write on shell channel when ready", () => { const mockChannel = { write: jest.fn(), end: jest.fn() }; const sessionData = { isShellReady: true, shellChannel: mockChannel, connection: { lastActivity: new Date() }, client: { destroy: jest.fn() }, config: {}, outputBuffer: [], outputListeners: [], startTime: new Date(), commandsExecuted: 0, }; (sshManager as any).connections.set("ready-session", sessionData); sshManager.sendTerminalInput("ready-session", "echo hello\n"); expect(mockChannel.write).toHaveBeenCalledWith("echo hello\n"); }); }); describe("sendTerminalSignal method", () => { let mockChannel: any; let sessionData: any; beforeEach(() => { mockChannel = { write: jest.fn(), end: jest.fn() }; sessionData = { isShellReady: true, shellChannel: mockChannel, connection: { lastActivity: new Date() }, client: { destroy: jest.fn() }, config: {}, outputBuffer: [], outputListeners: [], startTime: new Date(), commandsExecuted: 0, }; (sshManager as any).connections.set("signal-test", sessionData); }); it("should send SIGINT as Ctrl+C character (\\x03)", () => { sshManager.sendTerminalSignal("signal-test", "SIGINT"); expect(mockChannel.write).toHaveBeenCalledWith("\x03"); }); it("should send SIGTERM as Ctrl+D character (\\x04)", () => { sshManager.sendTerminalSignal("signal-test", "SIGTERM"); expect(mockChannel.write).toHaveBeenCalledWith("\x04"); }); it("should send SIGQUIT as Ctrl+D character (\\x04)", () => { sshManager.sendTerminalSignal("signal-test", "SIGQUIT"); expect(mockChannel.write).toHaveBeenCalledWith("\x04"); }); it("should send SIGTSTP as Ctrl+Z character (\\x1A)", () => { sshManager.sendTerminalSignal("signal-test", "SIGTSTP"); expect(mockChannel.write).toHaveBeenCalledWith("\x1A"); }); it("should be case insensitive for signal names", () => { sshManager.sendTerminalSignal("signal-test", "sigint"); expect(mockChannel.write).toHaveBeenCalledWith("\x03"); mockChannel.write.mockClear(); sshManager.sendTerminalSignal("signal-test", "SigTerm"); expect(mockChannel.write).toHaveBeenCalledWith("\x04"); }); it("should throw error for unsupported signal", () => { expect(() => { sshManager.sendTerminalSignal("signal-test", "UNSUPPORTED"); }).toThrow("Unsupported signal: UNSUPPORTED"); }); it("should throw error for non-existent session", () => { expect(() => { sshManager.sendTerminalSignal("nonexistent", "SIGINT"); }).toThrow("Session 'nonexistent' not found"); }); }); describe("resizeTerminal method", () => { let mockChannel: any; let sessionData: any; beforeEach(() => { mockChannel = { setWindow: jest.fn(), end: jest.fn() }; sessionData = { isShellReady: true, shellChannel: mockChannel, connection: { lastActivity: new Date() }, client: { destroy: jest.fn() }, config: {}, outputBuffer: [], outputListeners: [], startTime: new Date(), commandsExecuted: 0, }; (sshManager as any).connections.set("resize-test", sessionData); }); it("should call setWindow with correct parameters (rows, cols, 0, 0)", () => { sshManager.resizeTerminal("resize-test", 80, 24); expect(mockChannel.setWindow).toHaveBeenCalledWith(24, 80, 0, 0); }); it("should validate minimum dimensions", () => { expect(() => { sshManager.resizeTerminal("resize-test", 0, 24); }).toThrow( "Invalid terminal dimensions: cols and rows must be between 1 and 1000", ); expect(() => { sshManager.resizeTerminal("resize-test", 80, 0); }).toThrow( "Invalid terminal dimensions: cols and rows must be between 1 and 1000", ); }); it("should validate maximum dimensions", () => { expect(() => { sshManager.resizeTerminal("resize-test", 1001, 24); }).toThrow( "Invalid terminal dimensions: cols and rows must be between 1 and 1000", ); expect(() => { sshManager.resizeTerminal("resize-test", 80, 1001); }).toThrow( "Invalid terminal dimensions: cols and rows must be between 1 and 1000", ); }); it("should handle resize errors and wrap them", () => { mockChannel.setWindow.mockImplementation(() => { throw new Error("SSH resize failed"); }); expect(() => { sshManager.resizeTerminal("resize-test", 80, 24); }).toThrow("Failed to resize terminal: SSH resize failed"); }); it("should throw error for non-existent session", () => { expect(() => { sshManager.resizeTerminal("nonexistent", 80, 24); }).toThrow("Session 'nonexistent' not found"); }); it("should accept various valid dimensions", () => { // Test minimum valid dimensions sshManager.resizeTerminal("resize-test", 1, 1); expect(mockChannel.setWindow).toHaveBeenCalledWith(1, 1, 0, 0); // Test maximum valid dimensions mockChannel.setWindow.mockClear(); sshManager.resizeTerminal("resize-test", 1000, 1000); expect(mockChannel.setWindow).toHaveBeenCalledWith(1000, 1000, 0, 0); // Test typical terminal dimensions mockChannel.setWindow.mockClear(); sshManager.resizeTerminal("resize-test", 120, 40); expect(mockChannel.setWindow).toHaveBeenCalledWith(40, 120, 0, 0); }); }); describe("Interface compliance", () => { it("should implement all required terminal interaction methods", () => { expect(typeof sshManager.sendTerminalInput).toBe("function"); expect(typeof sshManager.sendTerminalSignal).toBe("function"); expect(typeof sshManager.resizeTerminal).toBe("function"); }); it("should maintain existing interface methods", () => { expect(typeof sshManager.getTerminalHistory).toBe("function"); expect(typeof sshManager.addTerminalOutputListener).toBe("function"); expect(typeof sshManager.removeTerminalOutputListener).toBe("function"); // Dashboard functionality removed per spec compliance expect(typeof sshManager.hasSession).toBe("function"); }); }); });

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/LightspeedDMS/ssh-mcp'

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