Browse Source

test: cover zellij current tab pane mode

Matheus Nogueira 2 months ago
parent
commit
b895306f75
1 changed files with 126 additions and 0 deletions
  1. 126 0
      src/multiplexer/zellij/index.test.ts

+ 126 - 0
src/multiplexer/zellij/index.test.ts

@@ -0,0 +1,126 @@
+import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test';
+
+type SpawnResult = {
+  exited: Promise<number>;
+  stdout: () => Promise<string>;
+  stderr: () => Promise<string>;
+  kill: () => boolean;
+  exitCode: number | null;
+  proc: never;
+};
+
+const crossSpawnMock = mock((_command: string[]) => createSpawnResult());
+
+mock.module('../../utils/compat', () => ({
+  crossSpawn: crossSpawnMock,
+}));
+
+let importCounter = 0;
+
+function createSpawnResult(
+  exitCode = 0,
+  stdout = '',
+  stderr = '',
+): SpawnResult {
+  return {
+    exited: Promise.resolve(exitCode),
+    stdout: () => Promise.resolve(stdout),
+    stderr: () => Promise.resolve(stderr),
+    kill: () => true,
+    exitCode,
+    proc: {} as never,
+  };
+}
+
+async function importFreshZellij() {
+  return import(`./index?test=${importCounter++}`);
+}
+
+function commands(): string[][] {
+  return crossSpawnMock.mock.calls.map((call) => call[0] as string[]);
+}
+
+describe('ZellijMultiplexer', () => {
+  const originalZellij = process.env.ZELLIJ;
+
+  beforeEach(() => {
+    process.env.ZELLIJ = '1';
+
+    crossSpawnMock.mockReset();
+    crossSpawnMock.mockImplementation((command: string[]) => {
+      if (command[0] === 'which') {
+        return createSpawnResult(0, '/usr/bin/zellij\n');
+      }
+      if (command.includes('new-pane')) {
+        return createSpawnResult(0, 'terminal_2\n');
+      }
+      return createSpawnResult();
+    });
+  });
+
+  afterEach(() => {
+    process.env.ZELLIJ = originalZellij;
+  });
+
+  test('current-tab mode spawns a pane in the active tab', async () => {
+    const { ZellijMultiplexer } = await importFreshZellij();
+    const zellij = new ZellijMultiplexer('main-vertical', 60, 'current-tab');
+
+    const result = await zellij.spawnPane(
+      'session-1',
+      'Current tab worker',
+      'http://localhost:4096',
+      '/repo',
+    );
+
+    expect(result).toEqual({ success: true, paneId: 'terminal_2' });
+
+    const allCommands = commands();
+    const newPaneCommand = allCommands.find((command) =>
+      command.includes('new-pane'),
+    );
+
+    expect(newPaneCommand).toEqual([
+      '/usr/bin/zellij',
+      'action',
+      'new-pane',
+      '--name',
+      'Current tab worker',
+      '--close-on-exit',
+      '--',
+      'sh',
+      '-lc',
+      "opencode attach 'http://localhost:4096' --session 'session-1' --dir '/repo'",
+    ]);
+    expect(allCommands.some((command) => command.includes('new-tab'))).toBe(
+      false,
+    );
+    expect(
+      allCommands.some((command) => command.includes('go-to-tab-by-id')),
+    ).toBe(false);
+  });
+
+  test('current-tab mode reports failure when zellij does not return a terminal pane id', async () => {
+    const { ZellijMultiplexer } = await importFreshZellij();
+    const zellij = new ZellijMultiplexer('main-vertical', 60, 'current-tab');
+
+    crossSpawnMock.mockImplementation((command: string[]) => {
+      if (command[0] === 'which') {
+        return createSpawnResult(0, '/usr/bin/zellij\n');
+      }
+      if (command.includes('new-pane')) {
+        return createSpawnResult(0, 'plugin_2\n');
+      }
+      return createSpawnResult();
+    });
+
+    const result = await zellij.spawnPane(
+      'session-1',
+      'Current tab worker',
+      'http://localhost:4096',
+      '/repo',
+    );
+
+    expect(result).toEqual({ success: false });
+  });
+});