test: remove 61 low-value runtime tests and five suites (#34431)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-10-27 07:30:16 -07:00
committed by GitHub
co-authored by OrcaWin
parent cb511d769e
commit dc57b3d6e8
15 changed files with 3 additions and 1709 deletions
+1 -1
View File
@@ -10855,7 +10855,7 @@
"commands": [
"pnpm exec vitest run --config config/vitest.config.ts src/main/ipc/settings.test.ts src/main/ipc/runtime-environments/runtime-environments-pairing.test.ts src/renderer/src/store/slices/settings.test.ts src/renderer/src/store/slices/browser.test.ts src/renderer/src/components/settings/browser-session-host-selection.test.ts src/renderer/src/components/settings/RuntimeEnvironmentsPane.test.ts src/renderer/src/components/status-bar/SshStatusSegment.test.ts src/renderer/src/components/sidebar/use-add-repo-host-selection.test.ts src/renderer/src/hooks/useIpcEvents-terminal-create-surfacing.test.ts src/renderer/src/web/web-preload-api-runtime-environment.test.ts --maxWorkers=1",
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list/listing/host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-catalog-reconciliation.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees-fetch-owner-routing.test.ts --maxWorkers=1",
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/use-add-repo-host-selection.test.ts src/renderer/src/components/sidebar/add-repo-browse-authority.test.ts src/renderer/src/components/sidebar/AddRepoDialogStepContent.test.tsx src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/runtime/runtime-server-directory-browser.test.ts src/renderer/src/store/slices/repos-paired-runtime-add.test.ts --maxWorkers=1",
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/use-add-repo-host-selection.test.ts src/renderer/src/components/sidebar/add-repo-browse-authority.test.ts src/renderer/src/components/sidebar/AddRepoDialogStepContent.test.tsx src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/store/slices/repos-paired-runtime-add.test.ts --maxWorkers=1",
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list/listing/host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-catalog-reconciliation.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees-fetch-owner-routing.test.ts src/renderer/src/runtime/web-runtime-session.test.ts --maxWorkers=1",
"pnpm run ensure:electron-runtime && npx playwright test tests/e2e/pr11346-selected-runtime-add.spec.ts --config tests/playwright.config.ts --project electron-headful --workers=1 --reporter=line",
"pnpm run ensure:electron-runtime && npx playwright test tests/e2e/pr11346-selected-runtime-add.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1 --reporter=line",
-5
View File
@@ -11235,7 +11235,6 @@
"src/renderer/src/runtime/runtime-hooks-client.test.ts": 132,
"src/renderer/src/runtime/runtime-host-account-sign-in-client.test.ts": 189,
"src/renderer/src/runtime/runtime-host-connection-state.test.ts": 35,
"src/renderer/src/runtime/runtime-host-contact-parity.test.ts": 40,
"src/renderer/src/runtime/runtime-host-contact-regained.test.ts": 408,
"src/renderer/src/runtime/runtime-jira-board-filter-compatibility.test.ts": 527,
"src/renderer/src/runtime/runtime-jira-client.test.ts": 347,
@@ -11245,8 +11244,6 @@
"src/renderer/src/runtime/runtime-jira-image-cache.test.ts": 1065,
"src/renderer/src/runtime/runtime-jira-image-client.test.ts": 140,
"src/renderer/src/runtime/runtime-jira-payload-stream.test.ts": 165,
"src/renderer/src/runtime/runtime-jira-saved-filter-state.test.ts": 162,
"src/renderer/src/runtime/runtime-jira-status-filters.test.ts": 199,
"src/renderer/src/runtime/runtime-jira-summary-generation-client.test.ts": 159,
"src/renderer/src/runtime/runtime-layout-client.test.ts": 109,
"src/renderer/src/runtime/runtime-legacy-inventory-budget.test.ts": 73,
@@ -11267,10 +11264,8 @@
"src/renderer/src/runtime/runtime-rpc-client-status-publication.test.ts": 234,
"src/renderer/src/runtime/runtime-rpc-client.test.ts": 129,
"src/renderer/src/runtime/runtime-rpc-result.test.ts": 44,
"src/renderer/src/runtime/runtime-server-directory-browser.test.ts": 150,
"src/renderer/src/runtime/runtime-skills-client.test.ts": 147,
"src/renderer/src/runtime/runtime-skills-delete-client.test.ts": 57,
"src/renderer/src/runtime/runtime-ssh-target-management.test.ts": 63,
"src/renderer/src/runtime/runtime-terminal-artifact-read.test.ts": 196,
"src/renderer/src/runtime/runtime-terminal-inspection.test.ts": 1950,
"src/renderer/src/runtime/runtime-terminal-stream.test.ts": 638,
@@ -3,10 +3,8 @@ import type { SshConnectionState, SshProviderEpoch } from '../../../shared/ssh-t
import { useAppStore } from '@/store'
import {
applyRuntimeEnvironmentSshStateChanged,
connectRuntimeEnvironmentSshTarget,
hydrateRuntimeEnvironmentSshState,
refreshRuntimeEnvironmentSshTargetMetadata,
resyncRuntimeEnvironmentSshTargets
refreshRuntimeEnvironmentSshTargetMetadata
} from './runtime-environment-ssh-state'
import { callRuntimeRpc } from './runtime-rpc-client'
@@ -74,52 +72,6 @@ beforeEach(() => {
})
describe('hydrateRuntimeEnvironmentSshState', () => {
it('populates the environment bucket with targets, tombstones, and per-target states', async () => {
const envId = nextEnvId()
installRpcResponses({
targets: [
{ id: 'ssh-1', label: 'devbox' },
{ id: 'ssh-2', label: 'buildbox' }
],
labels: { 'ssh-old': 'retired box' },
states: { 'ssh-1': connState('ssh-1', 'connected') }
})
await hydrateRuntimeEnvironmentSshState(envId)
const bucket = useAppStore.getState().sshStateByEnvironment.get(envId)
expect(bucket?.targetsHydrated).toBe(true)
expect(bucket?.targetLabels.get('ssh-1')).toBe('devbox')
expect(bucket?.removedTargetLabels.get('ssh-old')).toBe('retired box')
expect(bucket?.connectionStates.get('ssh-1')?.status).toBe('connected')
expect(bucket?.connectionStates.get('ssh-1')).toMatchObject({
providerEpoch: 'ssh-1-provider-epoch',
connectionGeneration: 7
})
// ssh-2 had no live state: absent, so reads fall back to 'disconnected'.
expect(bucket?.connectionStates.has('ssh-2')).toBe(false)
// Local maps stay untouched.
expect(useAppStore.getState().sshTargetLabels.size).toBe(0)
expect(useAppStore.getState().sshTargetsHydrated).toBe(false)
// Every call was routed to the owning environment.
for (const [target] of callRuntimeRpcMock.mock.calls) {
expect(target).toEqual({ kind: 'environment', environmentId: envId })
}
})
it('skips refetching when already hydrated unless forced', async () => {
const envId = nextEnvId()
installRpcResponses({ targets: [] })
await hydrateRuntimeEnvironmentSshState(envId)
const callsAfterFirst = callRuntimeRpcMock.mock.calls.length
await hydrateRuntimeEnvironmentSshState(envId)
expect(callRuntimeRpcMock.mock.calls.length).toBe(callsAfterFirst)
await hydrateRuntimeEnvironmentSshState(envId, { force: true })
expect(callRuntimeRpcMock.mock.calls.length).toBeGreaterThan(callsAfterFirst)
})
it('does not rerun when an ordinary refresh joins a forced hydration', async () => {
const envId = nextEnvId()
useAppStore
@@ -155,41 +107,6 @@ describe('hydrateRuntimeEnvironmentSshState', () => {
).toHaveLength(1)
})
it('hydrates without force after the environment bucket is marked stale', async () => {
const envId = nextEnvId()
useAppStore
.getState()
.setEnvironmentSshTargetsMetadata(envId, [{ id: 'ssh-old', label: 'old box' }])
useAppStore.getState().markEnvironmentSshStateStale(envId)
installRpcResponses({
targets: [{ id: 'ssh-new', label: 'new box' }],
states: { 'ssh-new': connState('ssh-new') }
})
await hydrateRuntimeEnvironmentSshState(envId)
const bucket = useAppStore.getState().sshStateByEnvironment.get(envId)
expect(bucket?.targetsHydrated).toBe(true)
expect(bucket?.targetLabels.get('ssh-new')).toBe('new box')
expect(bucket?.connectionStates.get('ssh-new')?.status).toBe('connected')
})
it('refreshes only target summaries when hydrated metadata is unchanged', async () => {
const envId = nextEnvId()
installRpcResponses({
targets: [{ id: 'ssh-1', label: 'devbox' }],
states: { 'ssh-1': connState('ssh-1') }
})
await hydrateRuntimeEnvironmentSshState(envId)
callRuntimeRpcMock.mockClear()
await refreshRuntimeEnvironmentSshTargetMetadata(envId)
expect(callRuntimeRpcMock.mock.calls.map(([, method]) => method)).toEqual([
'ssh.listTargetSummaries'
])
})
it('reads state for a labelled target the bucket never recorded a state for', async () => {
const envId = nextEnvId()
// A failed-connect resync can label a target without ever reading its state.
@@ -326,16 +243,6 @@ describe('hydrateRuntimeEnvironmentSshState', () => {
])
})
it('leaves the bucket un-hydrated when the host lacks the ssh RPC methods', async () => {
const envId = nextEnvId()
installRpcResponses({ failListTargets: true })
await expect(hydrateRuntimeEnvironmentSshState(envId)).rejects.toThrow()
const bucket = useAppStore.getState().sshStateByEnvironment.get(envId)
expect(bucket?.targetsHydrated ?? false).toBe(false)
})
it('still hydrates the target list when the removed-labels fetch fails', async () => {
const envId = nextEnvId()
installRpcResponses({
@@ -400,54 +307,9 @@ describe('hydrateRuntimeEnvironmentSshState', () => {
expect(useAppStore.getState().sshStateByEnvironment.has(envId)).toBe(false)
})
it('prunes connection state for targets removed by an authoritative refresh', async () => {
const envId = nextEnvId()
useAppStore.getState().setEnvironmentSshTargetsMetadata(envId, [
{ id: 'ssh-live', label: 'live box' },
{ id: 'ssh-removed', label: 'retired box' }
])
useAppStore
.getState()
.setEnvironmentSshConnectionState(envId, 'ssh-live', connState('ssh-live'))
useAppStore
.getState()
.setEnvironmentSshConnectionState(envId, 'ssh-removed', connState('ssh-removed'))
installRpcResponses({
targets: [{ id: 'ssh-live', label: 'live box' }],
states: { 'ssh-live': connState('ssh-live') }
})
await hydrateRuntimeEnvironmentSshState(envId, { force: true })
const bucket = useAppStore.getState().sshStateByEnvironment.get(envId)
expect(bucket?.targetLabels.has('ssh-removed')).toBe(false)
expect(bucket?.connectionStates.has('ssh-removed')).toBe(false)
expect(bucket?.connectionStates.get('ssh-live')?.status).toBe('connected')
})
})
describe('applyRuntimeEnvironmentSshStateChanged', () => {
it('applies a known target state directly into the owning bucket without RPC', () => {
const envId = nextEnvId()
useAppStore
.getState()
.setEnvironmentSshTargetsMetadata(envId, [{ id: 'ssh-1', label: 'devbox' }])
applyRuntimeEnvironmentSshStateChanged(envId, 'ssh-1', connState('ssh-1', 'disconnected'))
expect(
useAppStore.getState().sshStateByEnvironment.get(envId)?.connectionStates.get('ssh-1')
).toMatchObject({
status: 'disconnected',
providerEpoch: 'ssh-1-provider-epoch',
connectionGeneration: 7
})
expect(callRuntimeRpcMock).not.toHaveBeenCalled()
// Local map untouched.
expect(useAppStore.getState().sshConnectionStates.size).toBe(0)
})
it('rejects partial authority before retaining a runtime-owned state', () => {
const envId = nextEnvId()
useAppStore
@@ -502,95 +364,4 @@ describe('applyRuntimeEnvironmentSshStateChanged', () => {
expect(bucket?.connectionStates.has('ssh-gone')).toBe(false)
expect(bucket?.removedTargetLabels.get('ssh-gone')).toBe('old devbox')
})
it('picks up a just-added target through the forced refresh', async () => {
const envId = nextEnvId()
installRpcResponses({
targets: [{ id: 'ssh-new', label: 'fresh box' }],
states: { 'ssh-new': connState('ssh-new', 'connecting') }
})
applyRuntimeEnvironmentSshStateChanged(envId, 'ssh-new', connState('ssh-new', 'connecting'))
await vi.waitFor(() => {
expect(
useAppStore.getState().sshStateByEnvironment.get(envId)?.targetLabels.get('ssh-new')
).toBe('fresh box')
})
expect(
useAppStore.getState().sshStateByEnvironment.get(envId)?.connectionStates.get('ssh-new')
?.status
).toBe('connecting')
})
})
describe('connectRuntimeEnvironmentSshTarget', () => {
it('routes ssh.connect to the owning environment and mirrors the returned state', async () => {
const envId = nextEnvId()
callRuntimeRpcMock.mockResolvedValue({ state: connState('ssh-1', 'connected') } as never)
const state = await connectRuntimeEnvironmentSshTarget(envId, 'ssh-1')
expect(state?.status).toBe('connected')
expect(callRuntimeRpcMock).toHaveBeenCalledWith(
{ kind: 'environment', environmentId: envId },
'ssh.connect',
{ targetId: 'ssh-1' },
expect.anything()
)
expect(
useAppStore.getState().sshStateByEnvironment.get(envId)?.connectionStates.get('ssh-1')?.status
).toBe('connected')
expect(
useAppStore.getState().sshStateByEnvironment.get(envId)?.connectionStates.get('ssh-1')
).toMatchObject({
providerEpoch: 'ssh-1-provider-epoch',
connectionGeneration: 7
})
expect(useAppStore.getState().sshConnectionStates.size).toBe(0)
})
it('propagates connect failures without writing any state', async () => {
const envId = nextEnvId()
callRuntimeRpcMock.mockRejectedValue(new Error('SSH target not found'))
await expect(connectRuntimeEnvironmentSshTarget(envId, 'ssh-dead')).rejects.toThrow(
'SSH target not found'
)
expect(useAppStore.getState().sshStateByEnvironment.has(envId)).toBe(false)
})
})
describe('resyncRuntimeEnvironmentSshTargets', () => {
it('applies the target list even when the removed-labels refresh fails', async () => {
const envId = nextEnvId()
installRpcResponses({
targets: [{ id: 'ssh-live', label: 'devbox' }],
failRemovedLabels: true
})
await resyncRuntimeEnvironmentSshTargets(envId)
const bucket = useAppStore.getState().sshStateByEnvironment.get(envId)
expect(bucket?.targetLabels.get('ssh-live')).toBe('devbox')
expect(bucket?.targetsHydrated).toBe(true)
})
it('reads the connection state of a host re-added under a new target id', async () => {
const envId = nextEnvId()
useAppStore
.getState()
.setEnvironmentSshTargetsMetadata(envId, [{ id: 'ssh-old', label: 'devbox' }])
installRpcResponses({
targets: [{ id: 'ssh-new', label: 'devbox' }],
labels: { 'ssh-old': 'devbox' },
states: { 'ssh-new': connState('ssh-new') }
})
await resyncRuntimeEnvironmentSshTargets(envId)
const bucket = useAppStore.getState().sshStateByEnvironment.get(envId)
expect(bucket?.targetLabels.get('ssh-new')).toBe('devbox')
expect(bucket?.connectionStates.get('ssh-new')?.status).toBe('connected')
})
})
@@ -95,25 +95,6 @@ describe('runtime file client', () => {
expect(fsCancelDownloadedFile).not.toHaveBeenCalled()
})
it('does not open the save dialog when the remote chunk probe fails for transport reasons', async () => {
runtimeEnvironmentCall.mockRejectedValueOnce(new Error('connection dropped'))
await expect(
downloadRuntimeFile(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
'/remote/repo/archive.zip',
'archive.zip'
)
).rejects.toThrow('connection dropped')
expect(fsStartDownloadedFile).not.toHaveBeenCalled()
expect(fsSaveDownloadedFile).not.toHaveBeenCalled()
})
it('falls back to preview content when older remote runtimes lack chunked download', async () => {
fsSaveDownloadedFile.mockResolvedValue({
canceled: false,
@@ -205,40 +186,6 @@ describe('runtime file client', () => {
})
})
it('asks users to update older remote runtimes when preview fallback cannot download the file', async () => {
runtimeEnvironmentCall
.mockResolvedValueOnce({
id: 'chunk-1',
ok: false,
error: {
code: 'method_not_found',
message: 'Unknown method: files.readChunk'
},
_meta: { runtimeId: 'remote-runtime' }
})
.mockResolvedValueOnce({
id: 'preview-1',
ok: false,
error: { code: 'runtime_error', message: 'file_too_large' },
_meta: { runtimeId: 'remote-runtime' }
})
await expect(
downloadRuntimeFile(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
'/remote/repo/archive.zip',
'archive.zip'
)
).rejects.toThrow('Remote file download requires a newer Orca server')
expect(fsStartDownloadedFile).not.toHaveBeenCalled()
expect(fsSaveDownloadedFile).not.toHaveBeenCalled()
})
it('cancels the local temp download when a remote chunk fails', async () => {
fsStartDownloadedFile.mockResolvedValue({
canceled: false,
@@ -1,12 +1,9 @@
import { describe, expect, it, vi } from 'vitest'
import { describe, expect, it } from 'vitest'
import { importExternalPathsToRuntime } from './runtime-file-import-client'
import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision'
import {
fsImportExternalPaths,
fsStageExternalPathsForRuntimeUpload,
fsUploadExternalFileToRuntime,
runtimeEnvironmentCall,
runtimeEnvironmentTransportCall,
installRuntimeFileClientEnvironment
} from './runtime-file-client-test-harness'
@@ -59,251 +56,7 @@ function uploadRequests(): UploadRequest[] {
return fsUploadExternalFileToRuntime.mock.calls.flat()
}
const identityOf = (entry: Record<string, unknown>): Record<string, unknown> => ({
byteLength: entry.byteLength,
inode: entry.inode,
deviceId: entry.deviceId,
modifiedAtMs: entry.modifiedAtMs
})
describe('runtime file client', () => {
it('streams staged directory entries through main instead of sending base64 itself', async () => {
replaceRuntimeEnvironmentRevisions([{ id: 'env-1', createdAt: 1, pairingRevision: 17 }])
const logo = stagedFile('logo.png', 3, 101)
const large = stagedFile('large.bin', 40 * 1024 * 1024, 102)
fsStageExternalPathsForRuntimeUpload.mockResolvedValue({
sources: [
{
sourcePath: '/Users/me/assets',
status: 'staged',
name: 'assets',
kind: 'directory',
entries: [{ relativePath: '', kind: 'directory' }, logo, large]
}
]
})
runtimeEnvironmentCall
.mockResolvedValueOnce(notFoundResponse('stat-destination-miss'))
.mockResolvedValueOnce(okResponse('create-destination-dir'))
.mockResolvedValueOnce(notFoundResponse('stat-miss'))
.mockResolvedValueOnce(okResponse('create-dir'))
.mockResolvedValueOnce(okResponse('commit-upload'))
.mockResolvedValueOnce(okResponse('delete-temp'))
.mockResolvedValueOnce(okResponse('commit-large-upload'))
.mockResolvedValueOnce(okResponse('delete-large-temp'))
await expect(
importExternalPathsToRuntime(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
['/Users/me/assets'],
'/remote/repo/uploads'
)
).resolves.toEqual({
results: [
{
sourcePath: '/Users/me/assets',
status: 'imported',
destPath: '/remote/repo/uploads/assets',
kind: 'directory',
renamed: false
}
]
})
expect(fsStageExternalPathsForRuntimeUpload).toHaveBeenCalledWith({
sourcePaths: ['/Users/me/assets'],
nameExtensionlessImages: undefined
})
const transportCalls = runtimeEnvironmentTransportCall.mock.calls.map(([args]) => args)
expect(transportCalls.map((args) => args.method)).toEqual([
'status.get',
'status.get',
'files.stat',
'files.createDir',
'files.stat',
'files.createDirNoClobber',
'files.commitUpload',
'files.delete',
'files.commitUpload',
'files.delete'
])
// Why: the whole point of the change — no file body crosses this boundary.
expect(transportCalls.some((args) => String(args.method).startsWith('files.writeBase64'))).toBe(
false
)
expect(transportCalls.every((args) => args.expectedEnvironmentPairingRevision === 17)).toBe(
true
)
const uploads = uploadRequests()
expect(uploads).toHaveLength(2)
expect(uploads[0]?.relativePath).toMatch(/^uploads\/assets\/\.logo\.png\.orca-upload-/)
expect(uploads[0]).toEqual({
environmentId: 'env-1',
sourceRootPath: '/Users/me/assets',
entryRelativePath: 'logo.png',
expected: identityOf(logo),
worktree: 'id:wt-1',
relativePath: uploads[0]?.relativePath,
expectedExecutionHostId: 'local',
expectedSshTargetId: undefined,
expectedSshConnectionGeneration: undefined,
expectedEnvironmentPairingRevision: 17,
expectedEnvironmentRuntimeId: 'remote-runtime'
})
expect(uploads[1]).toMatchObject({
entryRelativePath: 'large.bin',
expected: identityOf(large)
})
expect(uploads[1]?.relativePath).toMatch(/^uploads\/assets\/\.large\.bin\.orca-upload-/)
expect(runtimeEnvironmentCall).toHaveBeenNthCalledWith(5, {
selector: 'env-1',
method: 'files.commitUpload',
params: {
worktree: 'id:wt-1',
tempRelativePath: uploads[0]?.relativePath,
finalRelativePath: 'uploads/assets/logo.png',
expectedExecutionHostId: 'local',
expectedSshTargetId: undefined,
expectedSshConnectionGeneration: undefined
},
timeoutMs: 30_000,
expectedEnvironmentPairingRevision: 17,
expectedEnvironmentRuntimeId: 'remote-runtime'
})
expect(runtimeEnvironmentCall).toHaveBeenNthCalledWith(6, {
selector: 'env-1',
method: 'files.delete',
params: {
worktree: 'id:wt-1',
relativePath: uploads[0]?.relativePath,
recursive: false,
expectedExecutionHostId: 'local',
expectedSshTargetId: undefined,
expectedSshConnectionGeneration: undefined
},
timeoutMs: 15_000,
expectedEnvironmentPairingRevision: 17,
expectedEnvironmentRuntimeId: 'remote-runtime'
})
expect(fsImportExternalPaths).not.toHaveBeenCalled()
})
it('forwards a single staged file with the identity staging measured', async () => {
const entry = stagedFile('', 40 * 1024 * 1024, 55)
fsStageExternalPathsForRuntimeUpload.mockResolvedValue({
sources: [
{
sourcePath: '/Users/me/large.bin',
status: 'staged',
name: 'large.bin',
kind: 'file',
entries: [entry]
}
]
})
runtimeEnvironmentCall
.mockResolvedValueOnce(notFoundResponse('stat-destination-miss'))
.mockResolvedValueOnce(okResponse('create-destination-dir'))
.mockResolvedValueOnce(notFoundResponse('stat-miss'))
.mockResolvedValueOnce(okResponse('commit-upload'))
.mockResolvedValueOnce(okResponse('delete-temp'))
await expect(
importExternalPathsToRuntime(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
['/Users/me/large.bin'],
'/remote/repo/uploads'
)
).resolves.toEqual({
results: [
{
sourcePath: '/Users/me/large.bin',
status: 'imported',
destPath: '/remote/repo/uploads/large.bin',
kind: 'file',
renamed: false
}
]
})
const upload = uploadRequests()[0]
expect(upload?.relativePath).toMatch(/^uploads\/\.large\.bin\.orca-upload-/)
expect(upload?.sourceRootPath).toBe('/Users/me/large.bin')
expect(upload?.entryRelativePath).toBe('')
expect(upload?.expected).toEqual(identityOf(entry))
expect(runtimeEnvironmentCall).not.toHaveBeenCalledWith(
expect.objectContaining({ method: 'files.writeBase64' })
)
expect(runtimeEnvironmentCall).not.toHaveBeenCalledWith(
expect.objectContaining({ method: 'files.writeBase64Chunk' })
)
})
it('does not commit an upload when the owner generation changes while it streams', async () => {
fsStageExternalPathsForRuntimeUpload.mockResolvedValue({
sources: [
{
sourcePath: '/Users/me/large.bin',
status: 'staged',
name: 'large.bin',
kind: 'file',
entries: [stagedFile('', 40 * 1024 * 1024, 55)]
}
]
})
runtimeEnvironmentCall
.mockResolvedValueOnce({
id: 'stat-destination',
ok: true,
result: { size: 0, isDirectory: true, mtime: 1 },
_meta: { runtimeId: 'remote-runtime' }
})
.mockResolvedValueOnce(notFoundResponse('stat-file-miss'))
let ownerChanged = false
fsUploadExternalFileToRuntime.mockImplementation(async () => {
ownerChanged = true
return { byteLength: 40 * 1024 * 1024 }
})
const assertCurrent = vi.fn(() => {
if (ownerChanged) {
throw new Error('runtime owner generation changed')
}
})
await expect(
importExternalPathsToRuntime(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
['/Users/me/large.bin'],
'/remote/repo/uploads',
{ assertCurrent }
)
).resolves.toMatchObject({
results: [{ status: 'failed', reason: 'runtime owner generation changed' }]
})
expect(runtimeEnvironmentCall.mock.calls.map((call) => call[0].method)).toEqual([
'files.stat',
'files.stat'
])
expect(runtimeEnvironmentCall).not.toHaveBeenCalledWith(
expect.objectContaining({ method: 'files.commitUpload' })
)
})
it('cleans up the staged temp path when the streamed upload fails', async () => {
fsStageExternalPathsForRuntimeUpload.mockResolvedValue({
sources: [
@@ -415,45 +168,4 @@ describe('runtime file client', () => {
expectedEnvironmentRuntimeId: 'remote-runtime'
})
})
it('keeps local external imports on filesystem IPC when no runtime is active', async () => {
fsImportExternalPaths.mockResolvedValue({
results: [
{
sourcePath: '/Users/me/readme.md',
status: 'imported',
destPath: '/repo/readme.md',
kind: 'file',
renamed: false
}
]
})
await importExternalPathsToRuntime(
{
target: { kind: 'local' as const },
worktreeId: 'wt-1',
worktreePath: '/repo',
connectionId: 'ssh-1',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 5
},
['/Users/me/readme.md'],
'/repo',
{ ensureDestinationDir: true }
)
expect(fsImportExternalPaths).toHaveBeenCalledWith({
sourcePaths: ['/Users/me/readme.md'],
destDir: '/repo',
connectionId: 'ssh-1',
expectedExecutionHostId: 'ssh:ssh-1',
ensureDir: true,
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 5
})
expect(fsStageExternalPathsForRuntimeUpload).not.toHaveBeenCalled()
expect(fsUploadExternalFileToRuntime).not.toHaveBeenCalled()
expect(runtimeEnvironmentCall).not.toHaveBeenCalled()
})
})
@@ -3,7 +3,6 @@ import {
copyRuntimePath,
createRuntimePath,
deleteRuntimePath,
readRuntimeDirectory,
renameRuntimePath,
writeRuntimeFile
} from './runtime-file-mutation-client'
@@ -17,8 +16,6 @@ import {
RUNTIME_PROTOCOL_VERSION
} from '../../../shared/protocol-version'
import {
fsReadFile,
fsWriteFile,
fsCopy,
fsCreateFile,
fsRename,
@@ -33,208 +30,6 @@ import {
installRuntimeFileClientEnvironment()
describe('runtime file client', () => {
it('routes create, rename, copy, and delete mutations through the selected runtime', async () => {
runtimeEnvironmentCall.mockResolvedValue({
id: 'rpc-1',
ok: true,
result: { ok: true },
_meta: { runtimeId: 'remote-runtime' }
})
const context = {
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 7
}
await createRuntimePath(context, '/remote/repo/src/new.ts', 'file')
await renameRuntimePath(context, '/remote/repo/src/new.ts', '/remote/repo/src/renamed.ts')
await copyRuntimePath(
context,
'/remote/repo/src/renamed.ts',
'/remote/repo/src/renamed copy.ts'
)
await deleteRuntimePath(context, '/remote/repo/src/renamed.ts', false)
expect(runtimeEnvironmentCall).toHaveBeenNthCalledWith(1, {
selector: 'env-1',
method: 'files.createFile',
params: {
worktree: 'id:wt-1',
relativePath: 'src/new.ts',
expectedExecutionHostId: 'ssh:ssh-1',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 7
},
timeoutMs: 15_000
})
expect(runtimeEnvironmentCall).toHaveBeenNthCalledWith(2, {
selector: 'env-1',
method: 'files.rename',
params: {
worktree: 'id:wt-1',
oldRelativePath: 'src/new.ts',
newRelativePath: 'src/renamed.ts',
expectedExecutionHostId: 'ssh:ssh-1',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 7
},
timeoutMs: 15_000
})
expect(runtimeEnvironmentCall).toHaveBeenNthCalledWith(3, {
selector: 'env-1',
method: 'files.copy',
params: {
worktree: 'id:wt-1',
sourceRelativePath: 'src/renamed.ts',
destinationRelativePath: 'src/renamed copy.ts',
expectedExecutionHostId: 'ssh:ssh-1',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 7
},
timeoutMs: 15_000
})
expect(runtimeEnvironmentCall).toHaveBeenNthCalledWith(4, {
selector: 'env-1',
method: 'files.delete',
params: {
worktree: 'id:wt-1',
relativePath: 'src/renamed.ts',
recursive: false,
expectedExecutionHostId: 'ssh:ssh-1',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 7
},
timeoutMs: 15_000
})
})
it('refuses HUB-local mutations before RPC when the HUB lacks ownership support', async () => {
runtimeEnvironmentTransportCall.mockImplementation((args: { method: string }) => {
if (args.method === 'status.get') {
return Promise.resolve({
id: 'status',
ok: true,
result: {
runtimeProtocolVersion: RUNTIME_PROTOCOL_VERSION,
minCompatibleRuntimeClientVersion: MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION,
capabilities: []
},
_meta: { runtimeId: 'old-hub-runtime' }
})
}
return runtimeEnvironmentCall(args)
})
await expect(
writeRuntimeFile(
{
target: { kind: 'environment' as const, environmentId: 'env-old-hub' },
worktreeId: 'wt-hub-local',
worktreePath: '/hub/repo',
expectedExecutionHostId: 'local'
},
'/hub/repo/readme.md',
'changed'
)
).rejects.toThrow(FILE_MUTATION_OWNERSHIP_UPDATE_REQUIRED_MESSAGE)
expect(runtimeEnvironmentTransportCall).toHaveBeenCalledWith({
selector: 'env-old-hub',
method: 'status.get',
timeoutMs: 15_000
})
expect(runtimeEnvironmentCall).not.toHaveBeenCalled()
expect(fsWriteFile).not.toHaveBeenCalled()
})
it('refuses nested SSH mutations before RPC when the HUB lacks ownership support', async () => {
runtimeEnvironmentTransportCall.mockImplementation((args: { method: string }) => {
if (args.method === 'status.get') {
return Promise.resolve({
id: 'status',
ok: true,
result: {
runtimeProtocolVersion: RUNTIME_PROTOCOL_VERSION,
minCompatibleRuntimeClientVersion: MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION,
capabilities: []
},
_meta: { runtimeId: 'old-hub-runtime' }
})
}
return runtimeEnvironmentCall(args)
})
await expect(
renameRuntimePath(
{
target: { kind: 'environment' as const, environmentId: 'env-old-hub' },
worktreeId: 'wt-nested-ssh',
worktreePath: '/ssh/repo',
connectionId: 'hub-ssh-1',
expectedExecutionHostId: 'ssh:hub-ssh-1',
expectedSshTargetId: 'hub-ssh-1',
expectedSshConnectionGeneration: 7
},
'/ssh/repo/old.md',
'/ssh/repo/new.md'
)
).rejects.toThrow(FILE_MUTATION_OWNERSHIP_UPDATE_REQUIRED_MESSAGE)
expect(runtimeEnvironmentTransportCall).toHaveBeenCalledWith({
selector: 'env-old-hub',
method: 'status.get',
timeoutMs: 15_000
})
expect(runtimeEnvironmentCall).not.toHaveBeenCalled()
expect(fsRename).not.toHaveBeenCalled()
})
it('keeps reads compatible with HUBs that lack mutation ownership support', async () => {
runtimeEnvironmentTransportCall.mockImplementation((args: { method: string }) => {
if (args.method === 'status.get') {
return Promise.resolve({
id: 'status',
ok: true,
result: {
runtimeProtocolVersion: RUNTIME_PROTOCOL_VERSION,
minCompatibleRuntimeClientVersion: MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION,
capabilities: []
},
_meta: { runtimeId: 'old-hub-runtime' }
})
}
return runtimeEnvironmentCall(args)
})
runtimeEnvironmentCall.mockResolvedValue({
id: 'read-dir',
ok: true,
result: [],
_meta: { runtimeId: 'old-hub-runtime' }
})
await expect(
readRuntimeDirectory(
{
target: { kind: 'environment' as const, environmentId: 'env-old-hub' },
worktreeId: 'wt-nested-ssh',
worktreePath: '/ssh/repo',
connectionId: 'hub-ssh-1'
},
'/ssh/repo'
)
).resolves.toEqual([])
expect(runtimeEnvironmentCall).toHaveBeenCalledWith({
selector: 'env-old-hub',
method: 'files.readDir',
params: { worktree: 'id:wt-nested-ssh', relativePath: '' },
timeoutMs: 15_000
})
expect(fsReadFile).not.toHaveBeenCalled()
})
it('refuses old-HUB imports before staging client-local files', async () => {
runtimeEnvironmentTransportCall.mockImplementation((args: { method: string }) => {
if (args.method === 'status.get') {
@@ -436,49 +231,4 @@ describe('runtime file client', () => {
expect(fsCreateFile).not.toHaveBeenCalled()
expect(runtimeEnvironmentCall).not.toHaveBeenCalled()
})
it('keeps copy operations on local filesystem IPC when no runtime is active', async () => {
await copyRuntimePath(
{
target: { kind: 'local' as const },
worktreeId: 'wt-1',
worktreePath: '/repo'
},
'/repo/a.md',
'/repo/a copy.md'
)
expect(fsCopy).toHaveBeenCalledWith({
sourcePath: '/repo/a.md',
destinationPath: '/repo/a copy.md',
connectionId: undefined,
expectedExecutionHostId: 'local'
})
expect(runtimeEnvironmentCall).not.toHaveBeenCalled()
})
it('preserves the SSH connection for copy operations when no runtime is active', async () => {
await copyRuntimePath(
{
target: { kind: 'local' as const },
worktreeId: 'wt-1',
worktreePath: '/repo',
connectionId: 'ssh-1',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 5
},
'/repo/a.md',
'/repo/a copy.md'
)
expect(fsCopy).toHaveBeenCalledWith({
sourcePath: '/repo/a.md',
destinationPath: '/repo/a copy.md',
connectionId: 'ssh-1',
expectedExecutionHostId: 'ssh:ssh-1',
expectedSshTargetId: 'ssh-1',
expectedSshConnectionGeneration: 5
})
expect(runtimeEnvironmentCall).not.toHaveBeenCalled()
})
})
@@ -1,7 +1,6 @@
import { describe, expect, it, vi } from 'vitest'
import { subscribeRuntimeFileChanges } from './runtime-file-watch-client'
import {
fsOnChanged,
runtimeEnvironmentCall,
runtimeEnvironmentSubscribe,
installRuntimeFileClientEnvironment
@@ -10,128 +9,6 @@ import {
installRuntimeFileClientEnvironment()
describe('runtime file client', () => {
it('uses the local fs changed stream when no runtime environment is active', async () => {
const unsubscribe = vi.fn()
const onPayload = vi.fn()
fsOnChanged.mockReturnValue(unsubscribe)
await expect(
subscribeRuntimeFileChanges(
{
target: { kind: 'local' as const },
worktreeId: 'wt-1',
worktreePath: '/repo'
},
onPayload
)
).resolves.toBe(unsubscribe)
expect(fsOnChanged).toHaveBeenCalledWith(onPayload)
expect(runtimeEnvironmentSubscribe).not.toHaveBeenCalled()
})
it('maps runtime file watch events back to fs changed payloads', async () => {
const onPayload = vi.fn()
const unsubscribe = vi.fn()
let onResponse: ((response: unknown) => void) | undefined
runtimeEnvironmentSubscribe.mockImplementation((_args, callbacks) => {
onResponse = callbacks.onResponse
return Promise.resolve({ unsubscribe, sendBinary: vi.fn() })
})
const stop = await subscribeRuntimeFileChanges(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
onPayload
)
expect(runtimeEnvironmentSubscribe).toHaveBeenCalledWith(
{
selector: 'env-1',
method: 'files.watch',
params: { worktree: 'id:wt-1', batchCadence: 'interval' },
timeoutMs: 15_000
},
expect.any(Object)
)
onResponse?.({
id: 'rpc-1',
ok: true,
result: {
type: 'changed',
worktree: 'id:wt-1',
events: [{ kind: 'update', absolutePath: '/remote/repo/readme.md' }]
},
_meta: { runtimeId: 'remote-runtime' }
})
expect(onPayload).toHaveBeenCalledWith({
worktreePath: '/remote/repo',
events: [{ kind: 'update', absolutePath: '/remote/repo/readme.md' }]
})
stop()
expect(unsubscribe).toHaveBeenCalled()
})
it('surfaces terminal watcher errors and allows a fresh subscription after stream end', async () => {
const onError = vi.fn()
const unsubscribe = vi.fn()
let callbacks: { onResponse: (response: unknown) => void; onClose: () => void } | undefined
runtimeEnvironmentSubscribe.mockImplementation((_args, nextCallbacks) => {
callbacks = nextCallbacks
return Promise.resolve({ unsubscribe, sendBinary: vi.fn() })
})
await subscribeRuntimeFileChanges(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
vi.fn(),
onError
)
callbacks?.onResponse({
id: 'rpc-error',
ok: true,
result: { type: 'error', message: 'file watcher process crashed repeatedly' },
_meta: { runtimeId: 'remote-runtime' }
})
callbacks?.onResponse({
id: 'rpc-end',
ok: true,
result: { type: 'end' },
_meta: { runtimeId: 'remote-runtime' }
})
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({ message: 'file watcher process crashed repeatedly' })
)
expect(unsubscribe).toHaveBeenCalledTimes(1)
await subscribeRuntimeFileChanges(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
vi.fn(),
vi.fn()
)
expect(runtimeEnvironmentSubscribe).toHaveBeenCalledTimes(2)
callbacks?.onResponse({
id: 'rpc-second-end',
ok: true,
result: { type: 'end' },
_meta: { runtimeId: 'remote-runtime' }
})
})
it('evicts a terminal watch before notifying error listeners that retry', async () => {
const callbacks: {
onResponse: (response: unknown) => void
@@ -311,76 +188,4 @@ describe('runtime file client', () => {
})
)
})
it('delegates stopped pre-ready web shared file watch cleanup to the subscription handle', async () => {
;(globalThis as { __ORCA_WEB_CLIENT__?: boolean }).__ORCA_WEB_CLIENT__ = true
const onPayload = vi.fn()
const unsubscribe = vi.fn()
let onResponse: ((response: unknown) => void) | undefined
runtimeEnvironmentSubscribe.mockImplementation((_args, callbacks) => {
onResponse = callbacks.onResponse
return Promise.resolve({ unsubscribe, sendBinary: vi.fn() })
})
const stop = await subscribeRuntimeFileChanges(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
onPayload
)
stop()
expect(unsubscribe).toHaveBeenCalledTimes(1)
expect(runtimeEnvironmentCall).not.toHaveBeenCalledWith(
expect.objectContaining({ method: 'files.unwatch' })
)
onResponse?.({
id: 'ready',
ok: true,
result: { type: 'ready', subscriptionId: 'files-watch-late' },
_meta: { runtimeId: 'remote-runtime' }
})
expect(unsubscribe).toHaveBeenCalledTimes(1)
expect(runtimeEnvironmentCall).not.toHaveBeenCalledWith(
expect.objectContaining({ method: 'files.unwatch' })
)
})
it('delegates stopped ready web shared file watch cleanup to the subscription handle', async () => {
;(globalThis as { __ORCA_WEB_CLIENT__?: boolean }).__ORCA_WEB_CLIENT__ = true
const onPayload = vi.fn()
const unsubscribe = vi.fn()
let onResponse: ((response: unknown) => void) | undefined
runtimeEnvironmentSubscribe.mockImplementation((_args, callbacks) => {
onResponse = callbacks.onResponse
return Promise.resolve({ unsubscribe, sendBinary: vi.fn() })
})
const stop = await subscribeRuntimeFileChanges(
{
target: { kind: 'environment' as const, environmentId: 'env-1' },
worktreeId: 'wt-1',
worktreePath: '/remote/repo'
},
onPayload
)
onResponse?.({
id: 'ready',
ok: true,
result: { type: 'ready', subscriptionId: 'files-watch-ready' },
_meta: { runtimeId: 'remote-runtime' }
})
stop()
expect(unsubscribe).toHaveBeenCalledTimes(1)
expect(runtimeEnvironmentCall).not.toHaveBeenCalledWith(
expect.objectContaining({ method: 'files.unwatch' })
)
})
})
@@ -2,7 +2,6 @@ import { describe, expect, it } from 'vitest'
import type { RuntimeHostStatusSnapshot } from '../../../shared/runtime-host-status'
import type { RuntimeStatus } from '../../../shared/runtime-types'
import {
isConnectedRuntimeHostState,
isDisconnectedRuntimeHostState,
runtimeHostConnectionState,
runtimeHostConnectionStateForEntry,
@@ -29,37 +28,6 @@ const windowClosedStatus = makeStatus({
})
describe('runtime host connection state', () => {
it('counts connected remote servers as connected hosts', () => {
// Connected means reachable, independent of active/default host; there is no separate available state.
expect(runtimeStatusForOverall('connected')).toBe('connected')
expect(isConnectedRuntimeHostState('connected')).toBe(true)
})
it('keeps reconnecting and disconnected remote servers out of the connected count', () => {
expect(runtimeStatusForOverall('reconnecting')).toBe('connecting')
expect(runtimeStatusForOverall('disconnected')).toBe('disconnected')
expect(isConnectedRuntimeHostState('reconnecting')).toBe(false)
expect(isConnectedRuntimeHostState('disconnected')).toBe(false)
})
it('distinguishes a connected transport from an unavailable runtime', () => {
expect(
runtimeHostConnectionState({
hasStatusEntry: true,
status: null,
transportStatus: 'connected'
})
).toBe('runtime-unavailable')
expect(runtimeStatusForOverall('runtime-unavailable')).toBe('connected')
expect(isConnectedRuntimeHostState('runtime-unavailable')).toBe(true)
})
it('still counts a workspace-window-closed remote server as a connected host', () => {
// Healthy transport remains connected; degraded runtime changes only wording (#12350).
expect(runtimeStatusForOverall('workspace-window-closed')).toBe('connected')
expect(isConnectedRuntimeHostState('workspace-window-closed')).toBe(true)
})
it('distinguishes a reachable host whose workspace window is closed', () => {
expect(runtimeHostConnectionState({ hasStatusEntry: true, status: windowClosedStatus })).toBe(
'workspace-window-closed'
@@ -192,27 +160,6 @@ describe('runtime host connection state for a recorded status entry', () => {
})
).toBe('reconnecting')
})
it('agrees with the status bar that a closed control channel is disconnected', () => {
expect(
runtimeHostConnectionStateForEntry({
status: makeStatus({ remoteControl: remoteControl('closed') })
})
).toBe('disconnected')
})
it('names only the disconnected verdict as disconnected', () => {
expect(isDisconnectedRuntimeHostState('disconnected')).toBe(true)
for (const state of [
'connected',
'checking',
'reconnecting',
'runtime-unavailable',
'workspace-window-closed'
] as const) {
expect(isDisconnectedRuntimeHostState(state)).toBe(false)
}
})
})
function remoteControl(
@@ -1,169 +0,0 @@
import { describe, expect, it } from 'vitest'
import {
isRuntimeHostContactRevoked,
type RuntimeHostStatusSnapshot
} from '../../../shared/runtime-host-status'
import {
isRuntimeHostContactRevokedVerdict,
lastRuntimeHostAnswer,
liveRuntimeHostStatus,
runtimeHostContactFromSnapshot
} from '../../../shared/runtime-host-contact'
import type { RuntimeStatus } from '../../../shared/runtime-types'
type Entry = {
status: RuntimeStatus | null
remoteControl?: RuntimeStatus['remoteControl'] | null
snapshot?: RuntimeHostStatusSnapshot
}
const VERIFICATIONS = ['checking', 'verified', 'unavailable', 'blocked'] as const
const TRANSPORTS = ['unknown', 'connecting', 'ready', 'disconnected'] as const
const RETIRED = [false, true] as const
const REMOTE_CONTROL_STATES = [
undefined,
'ready',
'awaiting_ready',
'awaiting_authenticated',
'reconnecting',
'closed'
] as const
function makeStatus(overrides: Partial<RuntimeStatus> = {}): RuntimeStatus {
return {
runtimeId: 'rt-1',
rendererGraphEpoch: 0,
graphStatus: 'ready',
authoritativeWindowId: 1,
liveTabCount: 0,
liveLeafCount: 0,
...overrides
}
}
function makeRemoteControl(
state: Exclude<(typeof REMOTE_CONTROL_STATES)[number], undefined>
): NonNullable<RuntimeStatus['remoteControl']> {
return {
state,
pendingRequestCount: 0,
subscriptionCount: 0,
reconnectAttempt: 0,
lastConnectedAt: null,
lastClose: null,
lastError: null
}
}
function makeSnapshot(
verification: (typeof VERIFICATIONS)[number],
transport: (typeof TRANSPORTS)[number],
retired: boolean,
answered: RuntimeStatus | null
): RuntimeHostStatusSnapshot {
return {
environmentId: 'env-a',
pairingRevision: 1,
sequence: 1,
checkedAt: 1,
status: answered,
verification,
transport,
...(retired ? { retired: true as const } : {})
}
}
/** Every entry shape the derivation can distinguish: 4 x 4 x 2, across each status/diagnostic. */
function* everySnapshotEntry(): Generator<{ label: string; entry: Entry }> {
for (const verification of VERIFICATIONS) {
for (const transport of TRANSPORTS) {
for (const retired of RETIRED) {
for (const answered of [null, makeStatus()] as const) {
for (const remoteControlState of REMOTE_CONTROL_STATES) {
// Store status exists only for verified unretired probes; enumerate reachable combinations, not an impossible cross-product.
const entryStatus = verification === 'verified' && !retired ? answered : null
const remoteControl = remoteControlState
? makeRemoteControl(remoteControlState)
: undefined
yield {
label: `${verification}/${transport}/retired=${retired}/answered=${answered !== null}/rc=${remoteControlState ?? 'none'}`,
entry: {
status: entryStatus,
...(remoteControl ? { remoteControl } : {}),
snapshot: makeSnapshot(verification, transport, retired, answered)
}
}
}
}
}
}
}
}
describe('the revoked predicate and the contact verdict stay in step', () => {
it('keeps the revoked predicate and the contact verdict in step', () => {
for (const { label, entry } of everySnapshotEntry()) {
expect(
isRuntimeHostContactRevokedVerdict(
runtimeHostContactFromSnapshot(entry.snapshot!, entry.status)
),
label
).toBe(isRuntimeHostContactRevoked(entry))
}
})
})
describe('the contact separates what the host said from what it is worth', () => {
it('retains the host answer through every non-live verdict', () => {
const answered = makeStatus()
for (const [verification, transport, retired] of [
['unavailable', 'ready', false],
['checking', 'connecting', false],
['unavailable', 'disconnected', false],
['blocked', 'ready', false],
['verified', 'ready', true]
] as const) {
const contact = runtimeHostContactFromSnapshot(
makeSnapshot(verification, transport, retired, answered),
null
)
expect(contact.verdict, `${verification}/${transport}`).not.toBe('live')
// The fact the host gave us survives; only its currency is in question.
expect(lastRuntimeHostAnswer(contact)).toBe(answered)
expect(liveRuntimeHostStatus(contact)).toBeNull()
}
})
it('reports a verified probe as live and nothing else', () => {
const answered = makeStatus()
const contact = runtimeHostContactFromSnapshot(
makeSnapshot('verified', 'ready', false, answered),
answered
)
expect(contact.verdict).toBe('live')
expect(liveRuntimeHostStatus(contact)).toBe(answered)
expect(lastRuntimeHostAnswer(contact)).toBe(answered)
})
it('tells a host that was never reached apart from a handshake in flight', () => {
// Previously collapsed nulls need opposite Connect affordances.
expect(
runtimeHostContactFromSnapshot(makeSnapshot('unavailable', 'unknown', false, null), null)
).toEqual({ verdict: 'unverifiable', reason: 'never-asked', lastAnswer: null })
expect(
runtimeHostContactFromSnapshot(makeSnapshot('unavailable', 'connecting', false, null), null)
).toEqual({ verdict: 'unverifiable', reason: 'transport-connecting', lastAnswer: null })
})
it('tells a refused host apart from a retired pairing', () => {
const answered = makeStatus()
expect(
runtimeHostContactFromSnapshot(makeSnapshot('blocked', 'ready', false, answered), null)
.verdict
).toBe('refused')
expect(
runtimeHostContactFromSnapshot(makeSnapshot('verified', 'ready', true, answered), null)
.verdict
).toBe('retired')
})
})
@@ -52,26 +52,3 @@ it.each([
expect(call.mock.calls.filter(([args]) => args.method === 'jira.listIssues')).toHaveLength(1)
}
)
it('forwards both filters to a host that supports the combined board query', async () => {
call.mockImplementation(async (args: { method: string }) =>
args.method === 'status.get'
? createCompatibleRuntimeStatusResponse()
: { id: 'board-filter', ok: true, result: [] }
)
const filters = { statuses: ['Blocked'], currentSprint: true }
await jiraListIssues(
{ kind: 'environment', environmentId: 'board-current' },
'all',
50,
'site-a',
filters
)
expect(call).toHaveBeenCalledWith(
expect.objectContaining({
selector: 'board-current',
method: 'jira.listIssues',
params: { filter: 'all', limit: 50, siteId: 'site-a', filters }
})
)
})
@@ -2,32 +2,6 @@ import { describe, expect, it } from 'vitest'
import { parseJiraConnectionStatus } from './runtime-jira-connection-status'
describe('parseJiraConnectionStatus', () => {
it('accepts an upgraded host without changing the Cloud/Server values older readers know', () => {
const site = {
id: 'site-scoped',
siteUrl: 'https://example.atlassian.net',
email: '',
displayName: 'Ada',
accountId: 'account-alpha',
authType: 'cloud',
apiBaseUrl: 'https://api.atlassian.com/ex/jira/cloud-abc'
}
const status = parseJiraConnectionStatus({
connected: true,
viewer: null,
sites: [site],
supportsScopedTokens: true
})
expect(status.sites).toEqual([site])
expect(status.supportsScopedTokens).toBe(true)
expect(
parseJiraConnectionStatus({ connected: true, viewer: null }).supportsScopedTokens
).toBeUndefined()
expect(
parseJiraConnectionStatus({ connected: true, supportsScopedTokens: 'yes' })
.supportsScopedTokens
).toBeUndefined()
})
it.each([
['undefined', undefined],
['null', null],
@@ -37,73 +11,6 @@ describe('parseJiraConnectionStatus', () => {
expect(parseJiraConnectionStatus(value)).toEqual({ connected: false, viewer: null })
})
it('keeps a well-formed status', () => {
const status = {
connected: true,
viewer: { accountId: 'a', email: 'a@example.com', displayName: 'A' },
sites: [],
activeSiteId: 'site-1',
credentialProtection: 'plaintext'
}
expect(parseJiraConnectionStatus(status)).toEqual(status)
})
it('round-trips a populated multi-site status unchanged', () => {
const status = {
connected: true,
viewer: {
accountId: 'account-cloud',
displayName: 'Ada Lovelace',
email: 'ada@example.com',
avatarUrl: 'https://avatar.example/ada.png'
},
sites: [
{
id: 'site-server',
siteUrl: 'https://jira.internal.example',
email: '',
displayName: 'Ada (PAT)',
accountId: '',
authType: 'server'
},
{
id: 'site-cloud',
siteUrl: 'https://example.atlassian.net',
email: 'ada@example.com',
displayName: 'Ada Lovelace',
accountId: 'account-cloud',
authType: 'cloud'
},
{
id: 'site-legacy',
siteUrl: 'https://legacy.atlassian.net',
email: 'ada@legacy.example',
displayName: 'Ada (legacy)',
accountId: 'account-legacy'
}
],
activeSiteId: 'site-cloud',
selectedSiteId: 'all',
credentialError: 'Could not decrypt the stored Jira token.',
credentialProtection: 'plaintext'
}
expect(parseJiraConnectionStatus(status)).toEqual(status)
})
it.each([
['a non-object viewer', { connected: true, viewer: 'me' }],
['a non-array sites value', { connected: true, viewer: null, sites: {} }]
])('keeps a connected status with %s', (_label, value) => {
expect(parseJiraConnectionStatus(value)).toEqual({ connected: true, viewer: null })
})
it('fills a missing viewer with null', () => {
expect(parseJiraConnectionStatus({ connected: false })).toEqual({
connected: false,
viewer: null
})
})
it('keeps a connected status while dropping malformed nested values', () => {
expect(
parseJiraConnectionStatus({
@@ -139,48 +46,4 @@ describe('parseJiraConnectionStatus', () => {
selectedSiteId: 'site-1'
})
})
it('keeps a site with an unknown auth type connected', () => {
expect(
parseJiraConnectionStatus({
connected: true,
viewer: null,
sites: [
{
id: 'site-1',
siteUrl: 'https://example.atlassian.net',
email: 'a@example.com',
displayName: 'Example',
accountId: 'account-1',
authType: 'datacenter'
}
]
})
).toEqual({
connected: true,
viewer: null,
sites: [
{
id: 'site-1',
siteUrl: 'https://example.atlassian.net',
email: 'a@example.com',
displayName: 'Example',
accountId: 'account-1'
}
]
})
})
it('ignores the Keychain fields an older host still sends', () => {
const status = parseJiraConnectionStatus({
connected: true,
viewer: null,
credentialError: 'Could not decrypt saved Jira credential.',
credentialErrorReason: 'keychain_locked',
canMoveCredentialKeyToFile: true
})
expect(status.credentialError).toBe('Could not decrypt saved Jira credential.')
expect(status).not.toHaveProperty('credentialErrorReason')
expect(status).not.toHaveProperty('canMoveCredentialKeyToFile')
})
})
@@ -1,68 +0,0 @@
// @vitest-environment happy-dom
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { readJiraSavedFilterState, mutateJiraSavedFilters } from './runtime-jira-saved-filter-state'
import { JIRA_SAVED_FILTER_RUNTIME_CAPABILITY } from '../../../shared/jira/jira-saved-filter-capability'
const { assertCapability, rpc } = vi.hoisted(() => ({ assertCapability: vi.fn(), rpc: vi.fn() }))
vi.mock('./runtime-rpc-client', () => ({
assertRuntimeEnvironmentCapability: assertCapability,
callRuntimeRpc: rpc
}))
const state = {
filters: [{ id: 'mine', name: 'My work', jql: 'project = APP' }],
activeFilterId: 'mine'
}
beforeEach(() => {
vi.resetAllMocks()
})
afterEach(() => {
vi.unstubAllGlobals()
})
it('uses local UI state for local execution', async () => {
const read = vi.fn(async () => state)
const mutate = vi.fn(async () => state)
vi.stubGlobal('window', {
api: { ui: { getJiraSavedFilters: read, mutateJiraSavedFilters: mutate } }
})
expect(await readJiraSavedFilterState({ kind: 'local' })).toEqual(state)
await mutateJiraSavedFilters({ kind: 'local' }, { kind: 'select', id: 'mine' })
expect(mutate).toHaveBeenCalledWith({ kind: 'select', id: 'mine' })
expect(rpc).not.toHaveBeenCalled()
})
it('routes paired/SSH persistence to the selected Jira host rather than this device', async () => {
rpc.mockResolvedValue(state)
const target = { kind: 'environment', environmentId: 'ssh-host-b' } as const
expect(await readJiraSavedFilterState(target)).toEqual(state)
await mutateJiraSavedFilters(target, { kind: 'select', id: 'mine' })
expect(assertCapability).toHaveBeenCalledWith(
'ssh-host-b',
JIRA_SAVED_FILTER_RUNTIME_CAPABILITY,
expect.any(String),
15_000
)
expect(rpc).toHaveBeenCalledWith(
target,
'ui.mutateJiraSavedFilters',
{ kind: 'select', id: 'mine' },
{ timeoutMs: 15_000 }
)
expect(rpc.mock.calls.some(([, method]) => method === 'ui.set')).toBe(false)
})
it('never sends new fields to an older host or falls back to local persistence', async () => {
assertCapability.mockRejectedValue(new Error('Update the Jira host'))
await expect(
mutateJiraSavedFilters(
{ kind: 'environment', environmentId: 'old-host' },
{ kind: 'select', id: 'mine' }
)
).rejects.toThrow('Update')
expect(rpc).not.toHaveBeenCalled()
})
it('propagates loss of contact instead of pretending the write was saved', async () => {
rpc.mockRejectedValue(new Error('Connection lost'))
await expect(
mutateJiraSavedFilters(
{ kind: 'environment', environmentId: 'host-a' },
{ kind: 'select', id: null }
)
).rejects.toThrow('Connection lost')
})
@@ -1,84 +0,0 @@
// @vitest-environment happy-dom
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { jiraListIssues, jiraListIssuesForTarget } from './runtime-jira-client'
import {
readJiraQuickFilterState,
writeJiraQuickFilterState
} from './runtime-jira-quick-filter-state'
import { JIRA_STATUS_FILTER_RUNTIME_CAPABILITY } from '../../../shared/jira/jira-quick-filters'
const { assertCapability, rpc } = vi.hoisted(() => ({ assertCapability: vi.fn(), rpc: vi.fn() }))
vi.mock('./runtime-rpc-client', () => ({
assertRuntimeEnvironmentCapability: assertCapability,
callRuntimeRpc: rpc
}))
beforeEach(() => {
vi.resetAllMocks()
})
afterEach(() => {
vi.unstubAllGlobals()
})
const target = { kind: 'environment', environmentId: 'jira-owner' } as const
it('keeps the old request shape when no statuses are selected', async () => {
rpc.mockResolvedValue([])
await jiraListIssues(target, 'all', 50, 'site-a')
expect(assertCapability).not.toHaveBeenCalled()
expect(rpc).toHaveBeenCalledWith(
target,
'jira.listIssues',
{ filter: 'all', limit: 50, siteId: 'site-a' },
{ timeoutMs: 30_000 }
)
})
it('gates status list filters on the called execution host', async () => {
rpc.mockResolvedValue([])
await jiraListIssuesForTarget(target, 'all', 50, 'site-a', { statuses: ['In Progress'] })
expect(assertCapability).toHaveBeenCalledWith(
'jira-owner',
JIRA_STATUS_FILTER_RUNTIME_CAPABILITY,
expect.any(String),
15_000
)
expect(rpc).toHaveBeenCalledWith(
target,
'jira.listIssues',
{ filter: 'all', limit: 50, siteId: 'site-a', filters: { statuses: ['In Progress'] } },
{ timeoutMs: 30_000 }
)
})
it('refuses an older host without silently dropping selection or writing strict resume fields', async () => {
assertCapability.mockRejectedValue(new Error('Update the Jira host'))
await expect(
jiraListIssues(target, 'all', 50, 'site-a', { statuses: ['Blocked'] })
).rejects.toThrow('Update')
await expect(writeJiraQuickFilterState(target, { statuses: ['Blocked'] })).rejects.toThrow(
'Update'
)
expect(rpc).not.toHaveBeenCalled()
})
it('routes persisted state through host UI methods and acknowledges the write', async () => {
rpc.mockResolvedValue({ statuses: ['Blocked'] })
expect(await readJiraQuickFilterState(target)).toEqual({ statuses: ['Blocked'] })
expect(await writeJiraQuickFilterState(target, { statuses: ['Blocked'] })).toEqual({
statuses: ['Blocked']
})
expect(rpc).toHaveBeenLastCalledWith(
target,
'ui.setJiraQuickFilters',
{ statuses: ['Blocked'] },
{ timeoutMs: 15_000 }
)
})
it('uses local IPC and reports a lost write instead of pretending to save', async () => {
const read = vi.fn(async () => ({ statuses: ['Open'] }))
const write = vi.fn(async () => {
throw new Error('Lost host')
})
vi.stubGlobal('window', {
api: { ui: { getJiraQuickFilters: read, setJiraQuickFilters: write } }
})
expect(await readJiraQuickFilterState({ kind: 'local' })).toEqual({ statuses: ['Open'] })
await expect(writeJiraQuickFilterState({ kind: 'local' }, { statuses: [] })).rejects.toThrow(
'Lost host'
)
expect(rpc).not.toHaveBeenCalled()
})
@@ -1,66 +0,0 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { browseRuntimeServerDirectory } from './runtime-server-directory-browser'
import { clearRuntimeCompatibilityCacheForTests } from './runtime-rpc-client'
import {
MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION,
RUNTIME_PROTOCOL_VERSION
} from '../../../shared/protocol-version'
import { stubRuntimeEnvironmentBridge } from './runtime-environment-bridge-fixture'
const runtimeEnvironmentCall = vi.fn()
beforeEach(() => {
clearRuntimeCompatibilityCacheForTests()
runtimeEnvironmentCall.mockReset()
runtimeEnvironmentCall.mockImplementation((args: { method: string }) => {
if (args.method === 'status.get') {
return Promise.resolve({
id: 'status',
ok: true,
result: {
runtimeProtocolVersion: RUNTIME_PROTOCOL_VERSION,
minCompatibleRuntimeClientVersion: MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION
},
_meta: { runtimeId: 'remote-runtime' }
})
}
return Promise.resolve({
id: 'browse',
ok: true,
result: {
resolvedPath: '/home/me',
pathFlavor: 'posix',
entries: [
{ name: '100 - file.txt', isDirectory: false, isSymlink: false },
{ name: '9 - file.txt', isDirectory: false, isSymlink: false },
{ name: '10 - repo', isDirectory: true, isSymlink: false },
{ name: '99 - file.txt', isDirectory: false, isSymlink: false }
]
},
_meta: { runtimeId: 'remote-runtime' }
})
})
stubRuntimeEnvironmentBridge({ call: runtimeEnvironmentCall })
})
describe('runtime server directory browser', () => {
it('routes browse requests through the selected runtime environment', async () => {
await expect(browseRuntimeServerDirectory('env-1', '~')).resolves.toEqual({
resolvedPath: '/home/me',
pathFlavor: 'posix',
entries: [
{ name: '10 - repo', isDirectory: true, isSymlink: false },
{ name: '9 - file.txt', isDirectory: false, isSymlink: false },
{ name: '99 - file.txt', isDirectory: false, isSymlink: false },
{ name: '100 - file.txt', isDirectory: false, isSymlink: false }
]
})
expect(runtimeEnvironmentCall).toHaveBeenLastCalledWith({
selector: 'env-1',
method: 'files.browseServerDir',
params: { path: '~' },
timeoutMs: 15_000
})
})
})
@@ -1,86 +0,0 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { SSH_TARGET_MANAGEMENT_RUNTIME_CAPABILITY } from '../../../shared/ssh-target-management'
const mocks = vi.hoisted(() => ({
callRuntimeRpc: vi.fn(),
runtimeEnvironmentSupportsCapability: vi.fn()
}))
vi.mock('./runtime-rpc-client', () => ({
callRuntimeRpc: mocks.callRuntimeRpc,
runtimeEnvironmentSupportsCapability: mocks.runtimeEnvironmentSupportsCapability
}))
const {
addRuntimeSshRepo,
addRuntimeSshTarget,
browseRuntimeSshDirectory,
listRuntimeEditableSshTargets,
removeRuntimeSshTarget,
RuntimeSshTargetManagementUnsupportedError,
updateRuntimeSshTarget
} = await import('./runtime-ssh-target-management')
const input = { label: 'Build', host: 'build.internal', port: 22, username: 'ci' }
const CALLS: [string, () => Promise<unknown>][] = [
['list', () => listRuntimeEditableSshTargets('env-1')],
['add', () => addRuntimeSshTarget('env-1', input)],
['update', () => updateRuntimeSshTarget('env-1', 'ssh-1', input)],
['remove', () => removeRuntimeSshTarget('env-1', 'ssh-1')],
['browse', () => browseRuntimeSshDirectory('env-1', 'ssh-1', '~')],
['add project', () => addRuntimeSshRepo('env-1', { connectionId: 'ssh-1', remotePath: '~/app' })]
]
describe('managing a paired server SSH targets across versions', () => {
const sshApi = { addTarget: vi.fn(), listTargets: vi.fn(), browseDir: vi.fn() }
beforeEach(() => {
vi.clearAllMocks()
vi.stubGlobal('window', { api: { ssh: sshApi, repos: { addRemote: vi.fn() } } })
})
it.each(CALLS)(
'an old server without the capability refuses %s and nothing falls back to this client',
async (_name, call) => {
mocks.runtimeEnvironmentSupportsCapability.mockResolvedValue(false)
await expect(call()).rejects.toBeInstanceOf(RuntimeSshTargetManagementUnsupportedError)
expect(mocks.runtimeEnvironmentSupportsCapability).toHaveBeenCalledWith(
'env-1',
SSH_TARGET_MANAGEMENT_RUNTIME_CAPABILITY
)
expect(mocks.callRuntimeRpc).not.toHaveBeenCalled()
expect(sshApi.addTarget).not.toHaveBeenCalled()
expect(sshApi.listTargets).not.toHaveBeenCalled()
expect(sshApi.browseDir).not.toHaveBeenCalled()
}
)
it.each(CALLS)('a current server is called for %s', async (_name, call) => {
mocks.runtimeEnvironmentSupportsCapability.mockResolvedValue(true)
mocks.callRuntimeRpc.mockResolvedValue({ targets: [], target: {}, repo: {} })
await call()
expect(mocks.callRuntimeRpc.mock.calls[0]?.[0]).toEqual({
kind: 'environment',
environmentId: 'env-1'
})
})
it('sends a whole target so the server can clear omitted fields', async () => {
mocks.runtimeEnvironmentSupportsCapability.mockResolvedValue(true)
mocks.callRuntimeRpc.mockResolvedValue({ target: { id: 'ssh-1', ...input } })
await updateRuntimeSshTarget('env-1', 'ssh-1', input)
expect(mocks.callRuntimeRpc).toHaveBeenCalledWith(
{ kind: 'environment', environmentId: 'env-1' },
'ssh.updateTarget',
{ targetId: 'ssh-1', target: input },
{}
)
})
})