mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-23 16:36:23 +00:00
The SSH modules predate the stricter lint config that landed on main (curly, no-empty, perfectionist sorting, prettier). Mechanical lint:fix + fmt pass, empty catch blocks filled with the codebase's void-0 convention, and inline no-control-regex disables on the three deliberate control-char patterns (same pattern as lib/ansi.ts).
100 lines
3 KiB
TypeScript
100 lines
3 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
|
|
import { applyConnectionChange, commitConnectionFailure, resolveTerminalConnection } from './connection-apply'
|
|
|
|
function deferred() {
|
|
let resolve!: () => void
|
|
|
|
const promise = new Promise<void>(done => {
|
|
resolve = done
|
|
})
|
|
|
|
return { promise, resolve }
|
|
}
|
|
|
|
describe('applyConnectionChange', () => {
|
|
it.each([['SSH A to SSH B'], ['SSH to Cloud'], ['Cloud to SSH']])(
|
|
'serializes %s behind bootstrap rollback before teardown and apply',
|
|
async () => {
|
|
const gate = deferred()
|
|
const events: string[] = []
|
|
|
|
const run = applyConnectionChange({
|
|
cancelAndWait: async () => {
|
|
events.push('cancel')
|
|
await gate.promise
|
|
events.push('drained')
|
|
},
|
|
isPrimary: true,
|
|
scope: '',
|
|
sendApplied: () => events.push('applied'),
|
|
stopPool: vi.fn(),
|
|
teardownPrimary: async () => {
|
|
events.push('primary')
|
|
},
|
|
teardownSsh: async () => {
|
|
events.push('ssh')
|
|
}
|
|
})
|
|
|
|
await Promise.resolve()
|
|
expect(events).toEqual(['cancel'])
|
|
gate.resolve()
|
|
await run
|
|
expect(events).toEqual(['cancel', 'drained', 'ssh', 'primary', 'applied'])
|
|
}
|
|
)
|
|
|
|
it('tears down only a non-primary scope without applying the primary connection', async () => {
|
|
const events: string[] = []
|
|
await applyConnectionChange({
|
|
cancelAndWait: async scope => {
|
|
events.push(`cancel:${scope}`)
|
|
},
|
|
isPrimary: false,
|
|
scope: 'worker',
|
|
sendApplied: () => events.push('applied'),
|
|
stopPool: scope => events.push(`pool:${scope}`),
|
|
teardownPrimary: async () => {
|
|
events.push('primary')
|
|
},
|
|
teardownSsh: async scope => {
|
|
events.push(`ssh:${scope}`)
|
|
}
|
|
})
|
|
expect(events).toEqual(['cancel:worker', 'ssh:worker', 'pool:worker'])
|
|
})
|
|
})
|
|
|
|
describe('resolveTerminalConnection', () => {
|
|
it('joins an in-flight backend before resolving the SSH terminal target', async () => {
|
|
const target = { ssh: {}, scope: '' }
|
|
const getTarget = vi.fn().mockReturnValueOnce('pending').mockReturnValueOnce(target)
|
|
const ensureBackend = vi.fn(async () => undefined)
|
|
|
|
await expect(resolveTerminalConnection(getTarget, ensureBackend)).resolves.toBe(target)
|
|
expect(ensureBackend).toHaveBeenCalledOnce()
|
|
})
|
|
|
|
it('does not start a local terminal while configured SSH remains unavailable', async () => {
|
|
await expect(
|
|
resolveTerminalConnection(
|
|
() => 'pending',
|
|
async () => undefined
|
|
)
|
|
).rejects.toThrow('not ready')
|
|
})
|
|
})
|
|
|
|
describe('commitConnectionFailure', () => {
|
|
it('prevents a stale bootstrap from publishing failure state', () => {
|
|
const stale = Promise.resolve('stale')
|
|
const current = Promise.resolve('current')
|
|
const commit = vi.fn()
|
|
|
|
expect(commitConnectionFailure(current, stale, commit)).toBe(false)
|
|
expect(commit).not.toHaveBeenCalled()
|
|
expect(commitConnectionFailure(current, current, commit)).toBe(true)
|
|
expect(commit).toHaveBeenCalledOnce()
|
|
})
|
|
})
|