import { afterEach, describe, expect, it, vi } from 'vitest' import { usePoolStore } from '../../src/stores/connection/poolStore' import type { PooledConnection } from '../../src/stores/connection/types' function connection(connectionId: string): PooledConnection { return { connectionId, config: { host: 'opsbase.cn', port: 55555, username: 'root' }, state: 'connected', refCount: 1, tabIds: new Set(['tab-a']), activeTabId: 'tab-a', shellIds: new Set(['shell-a']), sftpIds: new Set(), stats: { connectedAt: Date.now(), lastActivityAt: Date.now(), bytesTransferred: 0, commandsExecuted: 0 }, keepaliveInterval: 1, reconnectAttempts: 0, maxReconnectAttempts: 3, } } afterEach(() => usePoolStore.setState({ connections: new Map() })) describe('native connection close', () => { it('removes the stale renderer connection without another SSH disconnect', () => { const clearIntervalSpy = vi.spyOn(window, 'clearInterval') usePoolStore.setState({ connections: new Map([['native-gone', connection('native-gone')]]) }) usePoolStore.getState().forgetNativeConnection('native-gone') expect(usePoolStore.getState().connections.has('native-gone')).toBe(false) expect(clearIntervalSpy).toHaveBeenCalled() clearIntervalSpy.mockRestore() }) it('keeps tunnel listeners when the pooled SSH connection is reconnecting', async () => { const disconnect = window.opsxApi?.sshDisconnect as ReturnType disconnect.mockClear() usePoolStore.setState({ connections: new Map([['conn-1', connection('conn-1')]]) }) await usePoolStore.getState().disconnectConnection('conn-1', 'auto reconnect cleanup', { retainForwards: true, }) expect(disconnect).toHaveBeenCalledWith('conn-1', { retainForwards: true, reason: 'auto reconnect cleanup' }) }) it('stops tunnel listeners when the last tab releases the pooled SSH connection', async () => { const disconnect = window.opsxApi?.sshDisconnect as ReturnType disconnect.mockClear() usePoolStore.setState({ connections: new Map([['conn-1', connection('conn-1')]]) }) await usePoolStore.getState().disconnectConnection('conn-1', 'no refs') expect(disconnect).toHaveBeenCalledWith('conn-1', { retainForwards: false, reason: 'no refs' }) }) })