mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 01:57:57 +00:00
103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const { getSshGitProviderMock, gitExecFileAsyncMock } = vi.hoisted(() => ({
|
|
getSshGitProviderMock: vi.fn(),
|
|
gitExecFileAsyncMock: vi.fn()
|
|
}))
|
|
|
|
vi.mock('../providers/ssh-git-dispatch', () => ({
|
|
getSshGitProvider: getSshGitProviderMock,
|
|
SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE: 'SSH Git provider unavailable',
|
|
sshGitProviderMissingError: () => new Error('SSH Git provider unavailable')
|
|
}))
|
|
|
|
vi.mock('./runner', () => ({ gitExecFileAsync: gitExecFileAsyncMock }))
|
|
|
|
import { SshHostNotServedError } from '../providers/ssh-host-not-served-error'
|
|
import {
|
|
assertRemoteUrlReadable,
|
|
isTransientGitProbeError,
|
|
readRemoteUrl,
|
|
REMOTE_URL_PROBE_TIMEOUT_MS
|
|
} from './remote-url-probe'
|
|
|
|
describe('remote URL probe', () => {
|
|
beforeEach(() => {
|
|
getSshGitProviderMock.mockReset()
|
|
gitExecFileAsyncMock.mockReset()
|
|
})
|
|
|
|
it('bounds local and WSL remote reads with the shared timeout', async () => {
|
|
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'git@github.com:acme/orca.git\n' })
|
|
|
|
await expect(
|
|
readRemoteUrl({ repoPath: '/repo', wslDistro: 'Ubuntu' }, 'upstream')
|
|
).resolves.toContain('github.com')
|
|
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote', 'get-url', 'upstream'], {
|
|
cwd: '/repo',
|
|
timeout: REMOTE_URL_PROBE_TIMEOUT_MS,
|
|
wslDistro: 'Ubuntu'
|
|
})
|
|
|
|
await expect(readRemoteUrl({ repoPath: '/repo' }, 'origin')).resolves.toContain('github.com')
|
|
|
|
expect(gitExecFileAsyncMock).toHaveBeenLastCalledWith(['remote', 'get-url', 'origin'], {
|
|
cwd: '/repo',
|
|
timeout: REMOTE_URL_PROBE_TIMEOUT_MS
|
|
})
|
|
})
|
|
|
|
it('bounds the SSH remote read with the same deadline as the local one', async () => {
|
|
const exec = vi.fn(
|
|
async (_args: string[], _cwd: string, _options?: { signal?: AbortSignal }) => ({
|
|
stdout: 'git@github.com:acme/orca.git\n'
|
|
})
|
|
)
|
|
getSshGitProviderMock.mockReturnValue({ exec })
|
|
|
|
await expect(
|
|
readRemoteUrl({ repoPath: '/repo', connectionId: 'ssh-1' }, 'origin')
|
|
).resolves.toContain('github.com')
|
|
|
|
const [args, cwd, options] = exec.mock.calls[0]
|
|
expect(args).toEqual(['remote', 'get-url', 'origin'])
|
|
expect(cwd).toBe('/repo')
|
|
// The relay bounds each phase separately and resets on every frame, so only a
|
|
// signal spans the whole round trip.
|
|
expect(options?.signal).toBeInstanceOf(AbortSignal)
|
|
expect(options?.signal?.aborted).toBe(false)
|
|
})
|
|
|
|
it('reports a probe cut off by its deadline as unavailable, not as an answer', async () => {
|
|
const aborted = new Error('Request was cancelled')
|
|
aborted.name = 'AbortError'
|
|
gitExecFileAsyncMock.mockRejectedValue(aborted)
|
|
|
|
expect(isTransientGitProbeError(aborted)).toBe(true)
|
|
await expect(assertRemoteUrlReadable({ repoPath: '/repo' })).rejects.toBe(aborted)
|
|
})
|
|
|
|
it('rethrows a timed-out local probe so callers can report unavailable', async () => {
|
|
const timeout = new Error('git timed out.')
|
|
gitExecFileAsyncMock.mockRejectedValue(timeout)
|
|
|
|
expect(isTransientGitProbeError(timeout)).toBe(true)
|
|
await expect(assertRemoteUrlReadable({ repoPath: '/repo' })).rejects.toBe(timeout)
|
|
})
|
|
|
|
it('accepts a stable missing remote as a readable, empty repository state', async () => {
|
|
gitExecFileAsyncMock.mockRejectedValue(new Error("fatal: No such remote 'origin'"))
|
|
|
|
await expect(assertRemoteUrlReadable({ repoPath: '/repo' })).resolves.toBeUndefined()
|
|
})
|
|
|
|
it('does not turn an SSH target into a false readable result', async () => {
|
|
getSshGitProviderMock.mockReturnValue({ exec: vi.fn() })
|
|
|
|
await expect(
|
|
assertRemoteUrlReadable({ repoPath: '/repo', connectionId: 'ssh-1' })
|
|
).rejects.toThrow(SshHostNotServedError)
|
|
})
|
|
})
|