mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
Deletes ssh-system-fallback.ts and the re-export lines in ssh-config-parser.ts, ssh-connection.ts, system-ssh-file-binary-transfer.ts and ssh-remote-powershell.ts; importers name the real modules. SshConnection tests mock each real module, keeping the parser stub that holds ~/.ssh/config out.
80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { resolveWithSshG } from './ssh-g-config-resolution'
|
|
import { runProcess } from '@orca/process-host'
|
|
|
|
vi.mock('os', () => ({
|
|
homedir: () => '/home/testuser'
|
|
}))
|
|
|
|
// Why mock the chokepoint and not child_process: the point of routing this
|
|
// probe through runProcess is that the spawn shape (windowsHide, timeout,
|
|
// argv quoting) is no longer this module's decision, so the test must not
|
|
// re-assert it here. @orca/process-host owns that contract.
|
|
vi.mock('@orca/process-host', () => ({
|
|
runProcess: vi.fn()
|
|
}))
|
|
|
|
const ok = (stdout: string) => ({ code: 0, signal: null, stdout, stderr: '', timedOut: false })
|
|
|
|
describe('resolveWithSshG', () => {
|
|
beforeEach(() => {
|
|
vi.mocked(runProcess).mockReset()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers()
|
|
})
|
|
|
|
it('returns parsed config on success', async () => {
|
|
vi.mocked(runProcess).mockResolvedValue(ok('hostname 10.0.0.1\nuser admin\nport 22'))
|
|
|
|
const result = await resolveWithSshG('myhost')
|
|
expect(result).toBeDefined()
|
|
expect(result!.hostname).toBe('10.0.0.1')
|
|
expect(result!.user).toBe('admin')
|
|
})
|
|
|
|
it('calls ssh -G with the given host under a bounded timeout', async () => {
|
|
vi.mocked(runProcess).mockResolvedValue(ok('hostname example.com\nport 22'))
|
|
|
|
await resolveWithSshG('testserver')
|
|
expect(runProcess).toHaveBeenCalledWith({
|
|
program: 'ssh',
|
|
args: ['-G', '--', 'testserver'],
|
|
timeoutMs: 5000
|
|
})
|
|
})
|
|
|
|
it('returns null when ssh -G fails', async () => {
|
|
vi.mocked(runProcess).mockResolvedValue({
|
|
code: 255,
|
|
signal: null,
|
|
stdout: '',
|
|
stderr: 'ssh not found',
|
|
timedOut: false
|
|
})
|
|
|
|
expect(await resolveWithSshG('myhost')).toBeNull()
|
|
})
|
|
|
|
it('returns null when ssh -G could not be started', async () => {
|
|
vi.mocked(runProcess).mockRejectedValue(new Error('ENOENT'))
|
|
|
|
expect(await resolveWithSshG('myhost')).toBeNull()
|
|
})
|
|
|
|
it('returns null when ssh -G never reports completion', async () => {
|
|
// Why not fake timers any more: the deadline is runProcess's, and it
|
|
// reports the outcome as data rather than by leaving the promise pending.
|
|
vi.mocked(runProcess).mockResolvedValue({
|
|
code: null,
|
|
signal: 'SIGTERM',
|
|
stdout: '',
|
|
stderr: '',
|
|
timedOut: true
|
|
})
|
|
|
|
expect(await resolveWithSshG('stuck-host')).toBeNull()
|
|
})
|
|
})
|