import { describe, expect, it } from 'vitest' import { panesAfterConnectionStateChange, resolveTerminalInputTargets, shouldBroadcastTerminalInput, shouldCollapseTerminalSplitForOverlay, } from '../../src/utils/terminalPanes' const panes = [ { id: 'left', shellId: 'shell-1' }, { id: 'starting', shellId: null }, { id: 'right', shellId: 'shell-3' }, ] describe('terminal pane input routing', () => { it('routes normal input only to the source pane', () => { expect(resolveTerminalInputTargets(panes, 'right', false)).toEqual(['shell-3']) }) it('routes broadcast input to every ready shell in pane order', () => { expect(resolveTerminalInputTargets(panes, 'left', true)).toEqual(['shell-1', 'shell-3']) }) it('does not write when the source pane has no ready shell', () => { expect(resolveTerminalInputTargets(panes, 'starting', false)).toEqual([]) expect(resolveTerminalInputTargets(panes, 'missing', false)).toEqual([]) }) it('broadcasts from both SSH and local terminals when enabled', () => { expect(shouldBroadcastTerminalInput(true, true, 'local')).toBe(true) expect(shouldBroadcastTerminalInput(true, false, 'ssh-connection')).toBe(true) expect(shouldBroadcastTerminalInput(true, false, null)).toBe(false) expect(shouldBroadcastTerminalInput(false, false, 'ssh-connection')).toBe(false) }) }) describe('panesAfterConnectionStateChange', () => { const split = [ { id: 'pane-a', shellId: 'shell-old', closed: { reason: 'stale' } }, { id: 'pane-b', shellId: 'shell-2' }, { id: 'pane-c', shellId: 'shell-3' }, ] it('clears every split shell when the pooled session drops', () => { const next = panesAfterConnectionStateChange(split, 'reconnecting', 'shell-new') expect(next.map((pane) => pane.shellId)).toEqual([null, null, null]) expect(next.every((pane) => pane.closed == null)).toBe(true) expect(next.map((pane) => pane.id)).toEqual(['pane-a', 'pane-b', 'pane-c']) }) it('rebinds the primary pane to the new shell after reconnect', () => { const cleared = panesAfterConnectionStateChange(split, 'disconnected', null) const next = panesAfterConnectionStateChange(cleared, 'connected', 'shell-new') expect(next[0].shellId).toBe('shell-new') expect(next[1].shellId).toBeNull() expect(next[2].shellId).toBeNull() }) it('keeps the split layout in memory while collapsing the overlay visually', () => { expect( shouldCollapseTerminalSplitForOverlay({ connectionState: 'disconnected', needsReconnect: true, showSuspendedOverlay: false, }) ).toBe(true) expect( shouldCollapseTerminalSplitForOverlay({ connectionState: 'connected', needsReconnect: false, showSuspendedOverlay: false, }) ).toBe(false) expect(panesAfterConnectionStateChange(split, 'disconnected', null).map((pane) => pane.id)).toEqual([ 'pane-a', 'pane-b', 'pane-c', ]) }) })