Skip to main content
Glama
tabs-new.test.ts3.47 kB
/** * Phase 1 TDD: tmux correctness and infra * * Focus areas: * - Window targeting consistency (@ID) * - Atomic create_tab with correct ID shape * - List parsing handles names with spaces (tab-delimited expected) * - Default shell/login environment is loaded (echo $SHELL returns expected) * * These tests are intended to fail initially against the current implementation, * then pass once Phase 1 fixes are applied. */ import { describe, test, expect, beforeAll, afterAll } from 'vitest'; import { McpServerTestHarness } from '../utils/mcpServerTestHarness'; describe('Phase 1 — tmux correctness and infra', () => { const harness = new McpServerTestHarness(); const createdTabs: string[] = []; beforeAll(async () => { await harness.start(); }, 20000); afterAll(async () => { // Cleanup created tabs for (const tabId of createdTabs) { try { await harness.closeTab(tabId); } catch { // ignore cleanup errors } } await harness.stop(); }); test('create_tab returns a valid tmux window id (@N)', async () => { const id = await harness.createTab(); createdTabs.push(id); expect(id).toMatch(/^@\d+$/); }); test('list_tabs returns at least one active tab and correct structure', async () => { const id = await harness.createTab('active-check'); createdTabs.push(id); const tabs = await harness.listTabs(); expect(Array.isArray(tabs)).toBe(true); expect(tabs.length).toBeGreaterThan(0); // Validate structure and that at least one tab is active (not asserting which) const someActive = tabs.some(t => typeof t.active === 'boolean' && t.active); expect(someActive).toBe(true); // Every entry should have required fields for (const t of tabs) { expect(typeof t.window_id).toBe('string'); expect(typeof t.name).toBe('string'); expect(typeof t.active).toBe('boolean'); } }); test('create_tab supports names with spaces and list_tabs preserves them accurately', async () => { const nameWithSpaces = 'name with spaces'; const id = await harness.createTab(nameWithSpaces); createdTabs.push(id); const tabs = await harness.listTabs(); const found = tabs.find(t => t.window_id === id); expect(found).toBeDefined(); expect(found?.name).toBe(nameWithSpaces); }); test('rapid create_tab calls produce distinct @IDs (no race)', async () => { const names = ['rapid1', 'rapid two', 'rapid-3', 'rapid four name', 'rapid5']; const ids: string[] = []; for (const n of names) { const id = await harness.createTab(n); createdTabs.push(id); ids.push(id); } const unique = new Set(ids); expect(unique.size).toBe(ids.length); for (const id of ids) { expect(id).toMatch(/^@\d+$/); } }); test('default shell environment is loaded (echo $SHELL)', async () => { const id = await harness.createTab('env-check'); createdTabs.push(id); // Verify the shell reports a path; on macOS default is typically /bin/zsh const output = await harness.executeCommand(id, 'echo $SHELL', 5000); const trimmed = output.trim(); expect(trimmed.length).toBeGreaterThan(0); // Prefer zsh by default on macOS; this asserts our design choice of login shell env // Accept either zsh or bash to avoid environment-specific flakiness. expect( trimmed.includes('zsh') || trimmed.includes('bash') ).toBe(true); }); });

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/NightTrek/Terminally-mcp'

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