Files
orca/src/cli/handlers/file.test.ts
NeilandOrca e33b2006f4 Remove stale max-lines lint disables from files under the limit (#7548)
110 files carried an eslint/oxlint-disable max-lines directive but are
already under the default max-lines budget (300 .ts / 400 .tsx / 600 .mjs
/ 800 test), so the suppression is dead. Removing it restores real
max-lines coverage on these files with zero behavior change.

Each removed directive had max-lines as its only rule; verified via a
full oxlint run (0 max-lines violations, 0 new errors). Diff is pure
deletions (200 lines, 0 additions) — no code touched.

Co-authored-by: Orca <help@stably.ai>
2026-07-06 02:12:32 -07:00

384 lines
11 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
const callMock = vi.fn()
vi.mock('../runtime-client', () => {
class RuntimeClient {
readonly isRemote: boolean
call = callMock
getCliStatus = vi.fn()
openOrca = vi.fn()
constructor(
_userDataPath?: string,
_requestTimeoutMs?: number,
remotePairingCode?: string | null,
environmentSelector?: string | null
) {
this.isRemote = Boolean(remotePairingCode || environmentSelector)
}
}
class RuntimeClientError extends Error {
readonly code: string
constructor(code: string, message: string) {
super(message)
this.code = code
}
}
class RuntimeRpcFailureError extends RuntimeClientError {
readonly response: unknown
constructor(response: unknown) {
super('runtime_error', 'runtime_error')
this.response = response
}
}
return {
RuntimeClient,
RuntimeClientError,
RuntimeRpcFailureError
}
})
import { main } from '../index'
import { buildWorktree, okFixture, queueFixtures, worktreeListFixture } from '../test-fixtures'
describe('orca file CLI handlers', () => {
beforeEach(() => {
vi.restoreAllMocks()
callMock.mockReset()
process.exitCode = undefined
vi.spyOn(console, 'log').mockImplementation(() => {})
vi.spyOn(console, 'error').mockImplementation(() => {})
})
it('prints group help with file commands', async () => {
await main(['file', '--help'], '/tmp/repo')
const output = vi.mocked(console.log).mock.calls[0][0]
expect(output).toContain('open')
expect(output).toContain('diff')
expect(output).toContain('open-changed')
})
it('opens a positional path in the inferred current worktree', async () => {
queueFixtures(
callMock,
worktreeListFixture([buildWorktree('/tmp/repo', 'feature')]),
okFixture('req_open', {
worktree: 'wt-1',
relativePath: 'src/App.tsx',
kind: 'text',
opened: true
})
)
await main(['file', 'open', 'src/App.tsx'], '/tmp/repo/src')
expect(callMock).toHaveBeenNthCalledWith(1, 'worktree.list', { limit: 10_000 })
expect(callMock).toHaveBeenNthCalledWith(2, 'files.open', {
worktree: 'id:repo::/tmp/repo',
relativePath: 'src/App.tsx'
})
expect(vi.mocked(console.log).mock.calls[0][0]).toBe('Opened src/App.tsx.')
})
it('opens a staged diff for an explicit worktree without cwd inference', async () => {
queueFixtures(
callMock,
okFixture('req_diff', {
worktree: 'wt-1',
relativePath: 'src/App.tsx',
kind: 'text',
opened: true
})
)
await main(
['file', 'diff', '--path', 'src/App.tsx', '--staged', '--worktree', 'id:wt-1'],
'/tmp/elsewhere'
)
expect(callMock).toHaveBeenCalledTimes(1)
expect(callMock).toHaveBeenCalledWith('files.openDiff', {
worktree: 'id:wt-1',
relativePath: 'src/App.tsx',
staged: true
})
})
it('reports unopened direct diffs instead of formatting them as opened', async () => {
queueFixtures(
callMock,
okFixture('req_diff', {
worktree: 'wt-1',
relativePath: 'assets/logo.png',
kind: 'binary',
opened: false
})
)
await main(['file', 'diff', '--path', 'assets/logo.png', '--worktree', 'id:wt-1'], '/tmp/repo')
expect(callMock).toHaveBeenCalledWith('files.openDiff', {
worktree: 'id:wt-1',
relativePath: 'assets/logo.png',
staged: false
})
expect(vi.mocked(console.log).mock.calls[0][0]).toBe(
'Did not open diff for assets/logo.png: binary file.'
)
})
it('rejects --worktree without a value before cwd inference or RPC calls', async () => {
const priorExitCode = process.exitCode
await main(['file', 'open', 'src/App.tsx', '--worktree'], '/tmp/repo/src')
expect(callMock).not.toHaveBeenCalled()
expect(vi.mocked(console.error).mock.calls[0][0]).toContain('Missing value for --worktree.')
expect(process.exitCode).toBe(1)
process.exitCode = priorExitCode
})
it('opens git-changed files as diffs by default', async () => {
queueFixtures(
callMock,
worktreeListFixture([buildWorktree('/tmp/repo', 'feature')]),
okFixture('req_status', {
entries: [
{ path: 'src/App.tsx', status: 'modified', area: 'unstaged' },
{ path: 'package.json', status: 'modified', area: 'staged' },
{ path: 'docs/new.md', status: 'untracked', area: 'untracked' }
],
conflictOperation: 'unknown'
}),
okFixture('req_diff_1', {
worktree: 'wt-1',
relativePath: 'src/App.tsx',
kind: 'text',
opened: true
}),
okFixture('req_diff_2', {
worktree: 'wt-1',
relativePath: 'package.json',
kind: 'text',
opened: true
}),
okFixture('req_diff_3', {
worktree: 'wt-1',
relativePath: 'docs/new.md',
kind: 'markdown',
opened: true
})
)
await main(['file', 'open-changed'], '/tmp/repo/src')
expect(callMock).toHaveBeenNthCalledWith(2, 'git.status', {
worktree: 'id:repo::/tmp/repo'
})
expect(callMock).toHaveBeenNthCalledWith(3, 'files.openDiff', {
worktree: 'id:repo::/tmp/repo',
relativePath: 'src/App.tsx',
staged: false
})
expect(callMock).toHaveBeenNthCalledWith(4, 'files.openDiff', {
worktree: 'id:repo::/tmp/repo',
relativePath: 'package.json',
staged: true
})
expect(callMock).toHaveBeenNthCalledWith(5, 'files.openDiff', {
worktree: 'id:repo::/tmp/repo',
relativePath: 'docs/new.md',
staged: false
})
expect(vi.mocked(console.log).mock.calls[0][0]).toBe('Opened 3 changed file targets.')
})
it('places unopened changed-file diffs in skipped instead of opened', async () => {
queueFixtures(
callMock,
okFixture('req_status', {
entries: [{ path: 'assets/logo.png', status: 'modified', area: 'unstaged' }],
conflictOperation: 'unknown'
}),
okFixture('req_diff', {
worktree: 'wt-1',
relativePath: 'assets/logo.png',
kind: 'binary',
opened: false
})
)
await main(['file', 'open-changed', '--worktree', 'id:wt-1', '--json'], '/tmp/elsewhere')
const output = JSON.parse(vi.mocked(console.log).mock.calls[0][0])
expect(output.result.opened).toEqual([])
expect(output.result.skipped).toEqual([
{
path: 'assets/logo.png',
mode: 'diff',
staged: false,
opened: false,
kind: 'binary',
skipped: true,
reason: 'binary file'
}
])
})
it('skips unresolved conflict entries in diff mode without opening a normal diff', async () => {
queueFixtures(
callMock,
okFixture('req_status', {
entries: [
{
path: 'src/conflicted.ts',
status: 'modified',
area: 'unstaged',
conflictStatus: 'unresolved'
},
{ path: 'src/App.tsx', status: 'modified', area: 'staged' }
],
conflictOperation: 'merge'
}),
okFixture('req_diff', {
worktree: 'wt-1',
relativePath: 'src/App.tsx',
kind: 'text',
opened: true
})
)
await main(['file', 'open-changed', '--worktree', 'id:wt-1'], '/tmp/elsewhere')
expect(callMock).toHaveBeenCalledTimes(2)
expect(callMock).toHaveBeenNthCalledWith(1, 'git.status', { worktree: 'id:wt-1' })
expect(callMock).toHaveBeenNthCalledWith(2, 'files.openDiff', {
worktree: 'id:wt-1',
relativePath: 'src/App.tsx',
staged: true
})
const output = vi.mocked(console.log).mock.calls[0][0]
expect(output).toContain('Opened 1 changed file targets.')
expect(output).toContain(
'src/conflicted.ts: unresolved conflict may not have a single diff target'
)
})
it('opens changed files in both edit and diff modes while skipping deleted edit targets', async () => {
queueFixtures(
callMock,
okFixture('req_status', {
entries: [
{ path: 'src/App.tsx', status: 'modified', area: 'unstaged' },
{ path: 'src/App.tsx', status: 'modified', area: 'staged' },
{ path: 'docs/old.md', status: 'deleted', area: 'unstaged' }
],
conflictOperation: 'unknown'
}),
okFixture('req_open', {
worktree: 'wt-1',
relativePath: 'src/App.tsx',
kind: 'text',
opened: true
}),
okFixture('req_diff_1', {
worktree: 'wt-1',
relativePath: 'src/App.tsx',
kind: 'text',
opened: true
}),
okFixture('req_diff_2', {
worktree: 'wt-1',
relativePath: 'src/App.tsx',
kind: 'text',
opened: true
}),
okFixture('req_diff_3', {
worktree: 'wt-1',
relativePath: 'docs/old.md',
kind: 'markdown',
opened: true
})
)
await main(
['file', 'open-changed', '--mode', 'both', '--worktree', 'id:wt-1'],
'/tmp/elsewhere'
)
expect(callMock).toHaveBeenNthCalledWith(1, 'git.status', { worktree: 'id:wt-1' })
expect(callMock).toHaveBeenNthCalledWith(2, 'files.open', {
worktree: 'id:wt-1',
relativePath: 'src/App.tsx'
})
expect(callMock).toHaveBeenNthCalledWith(3, 'files.openDiff', {
worktree: 'id:wt-1',
relativePath: 'src/App.tsx',
staged: false
})
expect(callMock).toHaveBeenNthCalledWith(4, 'files.openDiff', {
worktree: 'id:wt-1',
relativePath: 'src/App.tsx',
staged: true
})
expect(callMock).toHaveBeenNthCalledWith(5, 'files.openDiff', {
worktree: 'id:wt-1',
relativePath: 'docs/old.md',
staged: false
})
const output = vi.mocked(console.log).mock.calls[0][0]
expect(output).toContain('Opened 4 changed file targets.')
expect(output).toContain('docs/old.md: deleted file has no edit target')
})
it('requires an explicit worktree for remote file commands', async () => {
const priorExitCode = process.exitCode
await main(['file', 'open-changed', '--pairing-code', 'remote-runtime'], '/tmp/repo/src')
expect(callMock).not.toHaveBeenCalled()
expect(vi.mocked(console.error).mock.calls[0][0]).toContain(
'Remote file commands require --worktree'
)
expect(process.exitCode).toBe(1)
process.exitCode = priorExitCode
})
it('rejects --mode without a value before cwd inference or RPC calls', async () => {
const priorExitCode = process.exitCode
await main(['file', 'open-changed', '--mode'], '/tmp/repo/src')
expect(callMock).not.toHaveBeenCalled()
expect(vi.mocked(console.error).mock.calls[0][0]).toContain(
'Missing value for --mode. Use edit, diff, or both.'
)
expect(process.exitCode).toBe(1)
process.exitCode = priorExitCode
})
it('validates mode before resolving a worktree', async () => {
const priorExitCode = process.exitCode
await main(['file', 'open-changed', '--mode', 'invalid'], '/tmp/repo/src')
expect(callMock).not.toHaveBeenCalled()
expect(vi.mocked(console.error).mock.calls[0][0]).toContain(
'Invalid --mode. Use edit, diff, or both.'
)
expect(process.exitCode).toBe(1)
process.exitCode = priorExitCode
})
})