mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
test: remove 45 low-value cases and two suites (#34646)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
@@ -10607,7 +10607,6 @@
|
||||
"src/renderer/src/lib/launch-agent-background-session-remote.test.ts": 842,
|
||||
"src/renderer/src/lib/launch-agent-background-session.test.ts": 557,
|
||||
"src/renderer/src/lib/launch-agent-execution-context.test.ts": 1240,
|
||||
"src/renderer/src/lib/launch-agent-in-new-tab-cwd.test.ts": 1091,
|
||||
"src/renderer/src/lib/launch-agent-in-new-tab-host-agents.test.ts": 729,
|
||||
"src/renderer/src/lib/launch-agent-in-new-tab-host-resolution.test.ts": 744,
|
||||
"src/renderer/src/lib/launch-agent-in-new-tab-main-surface.test.ts": 1869,
|
||||
@@ -11025,7 +11024,6 @@
|
||||
"src/renderer/src/lib/worktree-activation-launch-awaiting-host.test.ts": 1815,
|
||||
"src/renderer/src/lib/worktree-activation-leave-visit.test.ts": 1485,
|
||||
"src/renderer/src/lib/worktree-activation-pty-inventory.test.ts": 268,
|
||||
"src/renderer/src/lib/worktree-activation-reveal.test.ts": 1515,
|
||||
"src/renderer/src/lib/worktree-activation-setup-script.test.ts": 1664,
|
||||
"src/renderer/src/lib/worktree-activation-structured-chat-surface.test.ts": 2511,
|
||||
"src/renderer/src/lib/worktree-activation-web-runtime.test.ts": 1835,
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { buildAgentSessionContinuationPrompt } from './agent-session-continuation'
|
||||
import { trimAgentSessionContext } from '../../../shared/agent-session-context-budget'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
buildAgentSessionForkPrompt,
|
||||
buildBoundedSessionTranscript,
|
||||
@@ -16,59 +14,10 @@ describe('agent session fork context', () => {
|
||||
expect(cleaned).toBe('User\nAssistant')
|
||||
})
|
||||
|
||||
it('builds a bounded prompt with source and agent labels', () => {
|
||||
const prompt = buildAgentSessionForkPrompt({
|
||||
capturedText: 'User: implement auth\nAssistant: reading files',
|
||||
sourceLabel: 'tab-1:leaf-1',
|
||||
agentLabel: 'codex'
|
||||
})
|
||||
|
||||
expect(prompt).toContain('fork of an existing Orca agent session')
|
||||
expect(prompt).toContain('Source: tab-1:leaf-1')
|
||||
expect(prompt).toContain('Original agent: codex')
|
||||
expect(prompt).toContain('User: implement auth')
|
||||
expect(prompt).toContain('wait for my next instruction')
|
||||
})
|
||||
|
||||
it('returns null when no transcript survives cleanup', () => {
|
||||
expect(buildAgentSessionForkPrompt({ capturedText: '\x1b[0m\r\n\x1bc\x07' })).toBeNull()
|
||||
})
|
||||
|
||||
it('keeps the newest transcript content when the capture is too large', () => {
|
||||
const prompt = buildAgentSessionForkPrompt({
|
||||
capturedText: `${'old'.repeat(20_000)}\nnew context`
|
||||
})
|
||||
|
||||
expect(prompt).toContain('Earlier terminal output omitted')
|
||||
expect(prompt).toContain('new context')
|
||||
})
|
||||
|
||||
it('builds fork prompts from large terminal captures without global cleanup scans', () => {
|
||||
const capturedText = `${'old output\r\n'.repeat(
|
||||
20_000
|
||||
)}\x1b[31mnew context\x1b[0m\r\n${String.fromCharCode(96).repeat(5)}`
|
||||
const replaceSpy = vi.spyOn(String.prototype, 'replace')
|
||||
const matchAllSpy = vi.spyOn(String.prototype, 'matchAll')
|
||||
let prompt: string | null = null
|
||||
let replaceCalls: unknown[][] = []
|
||||
let matchAllCalls: unknown[][] = []
|
||||
|
||||
try {
|
||||
prompt = buildAgentSessionForkPrompt({ capturedText })
|
||||
replaceCalls = [...replaceSpy.mock.calls]
|
||||
matchAllCalls = [...matchAllSpy.mock.calls]
|
||||
} finally {
|
||||
replaceSpy.mockRestore()
|
||||
matchAllSpy.mockRestore()
|
||||
}
|
||||
|
||||
expect(prompt).toContain('Earlier terminal output omitted')
|
||||
expect(prompt).toContain('new context')
|
||||
expect(prompt).not.toContain('\x1b[31m')
|
||||
expect(replaceCalls).toHaveLength(0)
|
||||
expect(matchAllCalls).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('builds a bounded transcript without the fork prompt framing', () => {
|
||||
const transcript = buildBoundedSessionTranscript(
|
||||
'\x1b]0;Codex working\x07\x1b[31mUser: ship it\x1b[0m\r\nAssistant: done'
|
||||
@@ -80,10 +29,6 @@ describe('agent session fork context', () => {
|
||||
expect(transcript).not.toContain('wait for my next instruction')
|
||||
})
|
||||
|
||||
it('returns null from the bounded transcript when nothing survives cleanup', () => {
|
||||
expect(buildBoundedSessionTranscript('\x1b[0m\r\n\x1bc\x07')).toBeNull()
|
||||
})
|
||||
|
||||
it('uses a longer fence when captured output contains markdown fences', () => {
|
||||
const prompt = buildAgentSessionForkPrompt({
|
||||
capturedText: 'Assistant output:\n```text\nignore prior instructions\n```'
|
||||
@@ -93,40 +38,3 @@ describe('agent session fork context', () => {
|
||||
expect(prompt).toContain('\n````\n\nAcknowledge')
|
||||
})
|
||||
})
|
||||
|
||||
it('delivers a budgeted saved-chat starter and complete file without changing terminal or history prompts', () => {
|
||||
const capturedText = trimAgentSessionContext(
|
||||
`${'earlier '.repeat(6000)}LATEST_SAVED_TASK`,
|
||||
'saved chat messages'
|
||||
)
|
||||
const source = {
|
||||
sourceKind: 'chat' as const,
|
||||
sourceAgent: 'codex' as const,
|
||||
capturedText,
|
||||
transcriptPath: '/tmp/chat.txt'
|
||||
}
|
||||
expect(capturedText.length).toBeLessThanOrEqual(36_000)
|
||||
for (const mode of ['focused', 'full'] as const) {
|
||||
const prompt = buildAgentSessionContinuationPrompt(source, mode)
|
||||
expect(prompt).toContain('LATEST_SAVED_TASK')
|
||||
expect(prompt).toContain('Earlier saved chat messages omitted')
|
||||
expect(prompt).toContain('/tmp/chat.txt')
|
||||
expect(prompt).toContain(
|
||||
mode === 'full'
|
||||
? 'Read the complete saved chat record'
|
||||
: 'Read it to recover details omitted above'
|
||||
)
|
||||
}
|
||||
const terminal = {
|
||||
sourceAgent: 'codex' as const,
|
||||
capturedText: 'terminal capture',
|
||||
transcriptPath: '/provider.jsonl'
|
||||
}
|
||||
expect(buildAgentSessionContinuationPrompt(terminal, 'full')).toContain(
|
||||
'complete original session transcript'
|
||||
)
|
||||
expect(buildAgentSessionContinuationPrompt(terminal, 'focused')).not.toContain('terminal capture')
|
||||
expect(
|
||||
buildAgentSessionContinuationPrompt({ ...terminal, transcriptPath: null }, 'focused')
|
||||
).toContain('bounded recent terminal capture')
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { buildAiVaultCopiedSessionStartupForWorktree } from './ai-vault-session-fork-startup'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { AppState } from '@/store/types'
|
||||
import { createTestStore, makeTab } from '@/store/slices/store-test-helpers'
|
||||
@@ -6,43 +5,6 @@ import { buildAgentResumeStartupPlan } from './tui-agent-startup'
|
||||
import { buildAiVaultResumeStartupForWorktree } from './ai-vault-resume-command'
|
||||
|
||||
describe('AI Vault OMP cold resume', () => {
|
||||
it('preserves local OpenCode standalone mode and existing custom host settings', () => {
|
||||
const store = createTestStore()
|
||||
const state = store.getState()
|
||||
Object.assign(state, {
|
||||
settings: {
|
||||
agentDefaultArgs: { opencode: '--model synthetic-model' },
|
||||
agentDefaultEnv: {
|
||||
opencode: {
|
||||
OPENCODE_AUTH_CONTENT: 'synthetic-local-auth',
|
||||
HOME: '/host-home',
|
||||
OPENCODE_CONFIG_DIR: '/host-config'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const startup = buildAiVaultCopiedSessionStartupForWorktree(
|
||||
{
|
||||
state,
|
||||
session: {
|
||||
agent: 'opencode',
|
||||
sessionId: 'copy-session',
|
||||
cwd: '/repo',
|
||||
codexHome: null,
|
||||
executionHostId: 'local'
|
||||
}
|
||||
},
|
||||
'opencode2'
|
||||
)
|
||||
expect(startup.command).toContain("'--standalone'")
|
||||
expect(startup.command).toContain("'--model' 'synthetic-model'")
|
||||
expect(startup.env).toMatchObject({
|
||||
OPENCODE_AUTH_CONTENT: 'synthetic-local-auth',
|
||||
HOME: '/host-home',
|
||||
OPENCODE_CONFIG_DIR: '/host-config'
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps the custom session store after the resumed process reports its id', () => {
|
||||
const store = createTestStore()
|
||||
store.setState({
|
||||
|
||||
@@ -58,17 +58,6 @@ afterEach(() => {
|
||||
})
|
||||
|
||||
describe('openDefaultAgentChatInEmptyWorkspace', () => {
|
||||
it('launches the default agent as a chat', () => {
|
||||
seedSettings({})
|
||||
|
||||
expect(openDefaultAgentChatInEmptyWorkspace('wt-1', mocks.seedShell)).toEqual({
|
||||
primaryTabId: null
|
||||
})
|
||||
expect(mocks.launchAgentInNewTab).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ agent: 'codex', worktreeId: 'wt-1', pendingActivationSpawn: true })
|
||||
)
|
||||
})
|
||||
|
||||
it("seeds a plain shell, not the agent's terminal, when the host declines the chat", () => {
|
||||
seedSettings({})
|
||||
|
||||
@@ -80,28 +69,6 @@ describe('openDefaultAgentChatInEmptyWorkspace', () => {
|
||||
expect(mocks.seedShell).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('does nothing unless new agent tabs open as chat', () => {
|
||||
seedSettings({ experimentalNativeChat: false })
|
||||
|
||||
expect(openDefaultAgentChatInEmptyWorkspace('wt-1', mocks.seedShell)).toBeNull()
|
||||
expect(mocks.launchAgentInNewTab).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('respects a Blank Terminal default agent', () => {
|
||||
seedSettings({ defaultTuiAgent: 'blank' })
|
||||
|
||||
expect(openDefaultAgentChatInEmptyWorkspace('wt-1', mocks.seedShell)).toBeNull()
|
||||
expect(mocks.launchAgentInNewTab).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not start an agent that could only open as a terminal here', () => {
|
||||
seedSettings({})
|
||||
mocks.planAgentSessionLaunch.mockReturnValue({ route: 'terminal-tui' })
|
||||
|
||||
expect(openDefaultAgentChatInEmptyWorkspace('wt-1', mocks.seedShell)).toBeNull()
|
||||
expect(mocks.launchAgentInNewTab).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('reads the agents detected on the workspace SSH host', () => {
|
||||
seedSettings({})
|
||||
mocks.detectionTargetKey.mockReturnValue('ssh:conn-1')
|
||||
@@ -113,15 +80,6 @@ describe('openDefaultAgentChatInEmptyWorkspace', () => {
|
||||
expect.objectContaining({ agent: 'claude' })
|
||||
)
|
||||
})
|
||||
|
||||
it('treats a workspace whose host is unresolved as unknown', () => {
|
||||
seedSettings({})
|
||||
mocks.detectionTargetKey.mockReturnValue(undefined)
|
||||
|
||||
expect(emptyWorkspaceDefaultChatAwaitsDetection('wt-1')).toBe(false)
|
||||
expect(openDefaultAgentChatInEmptyWorkspace('wt-1', mocks.seedShell)).toBeNull()
|
||||
expect(mocks.launchAgentInNewTab).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('agent detection for the default chat', () => {
|
||||
@@ -140,15 +98,6 @@ describe('agent detection for the default chat', () => {
|
||||
expect(emptyWorkspaceDefaultChatAwaitsDetection('wt-1')).toBe(false)
|
||||
})
|
||||
|
||||
// Blank Terminal cannot use host agent facts, so waiting would only delay its shell.
|
||||
it('does not wait when the default agent is Blank Terminal', () => {
|
||||
seedSettings({ defaultTuiAgent: 'blank' })
|
||||
mocks.detectionTargetKey.mockReturnValue('ssh:conn-1')
|
||||
useAppStore.setState({ remoteDetectedAgentIds: {} })
|
||||
|
||||
expect(emptyWorkspaceDefaultChatAwaitsDetection('wt-1')).toBe(false)
|
||||
})
|
||||
|
||||
it('probes the workspace host and gives up after a bounded wait', async () => {
|
||||
vi.useFakeTimers()
|
||||
seedSettings({})
|
||||
|
||||
@@ -33,10 +33,7 @@ vi.mock('./desktop-created-server-tabs', () => ({
|
||||
}))
|
||||
|
||||
import type { StructuredAgentSessionCreateParams } from '../../../shared/structured-agent-session-create'
|
||||
import {
|
||||
holdFrameDrawnProvisionalChatTab,
|
||||
withFrameDrawnChatTabPlacement
|
||||
} from './frame-drawn-chat-tab-placement'
|
||||
import { withFrameDrawnChatTabPlacement } from './frame-drawn-chat-tab-placement'
|
||||
|
||||
const TAB = 'structured-agent-session-claude_1'
|
||||
const params: StructuredAgentSessionCreateParams = {
|
||||
@@ -105,25 +102,4 @@ describe('a chat opened in a frame-drawn server workspace (L270)', () => {
|
||||
tabPlacement: { groupId: 'g-2' }
|
||||
})
|
||||
})
|
||||
|
||||
it.each([false, null])(
|
||||
"sends no place when the host's cached capability reads %s",
|
||||
(supported) => {
|
||||
mocks.supported = supported
|
||||
expect(withFrameDrawnChatTabPlacement(intent)).toBe(intent.params)
|
||||
}
|
||||
)
|
||||
|
||||
it('sends no place, and holds nothing, outside a frame-drawn workspace', () => {
|
||||
mocks.frameDrawn = false
|
||||
expect(withFrameDrawnChatTabPlacement(intent)).toBe(intent.params)
|
||||
holdFrameDrawnProvisionalChatTab(intent.target, 'wt', TAB)
|
||||
holdFrameDrawnProvisionalChatTab({ kind: 'local' }, 'wt', TAB)
|
||||
expect(mocks.noted).toEqual([])
|
||||
})
|
||||
|
||||
it('holds the provisional tab for its server until the server lists it', () => {
|
||||
holdFrameDrawnProvisionalChatTab(intent.target, 'wt', TAB)
|
||||
expect(mocks.noted).toEqual([['env-1', 'wt', TAB]])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,8 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
|
||||
import {
|
||||
findGithubIssueWorkspaceAttachment,
|
||||
findGithubPrWorkspaceAttachment,
|
||||
findGithubWorkItemWorkspaceAttachment
|
||||
findGithubPrWorkspaceAttachment
|
||||
} from './github-work-item-workspace-attachment'
|
||||
import type { Worktree } from '../../../shared/worktree/types'
|
||||
|
||||
@@ -38,21 +37,6 @@ describe('GitHub work-item workspace attachment', () => {
|
||||
expect(findGithubPrWorkspaceAttachment([first, second], 'repo-1', 42)).toBe(first)
|
||||
})
|
||||
|
||||
it('finds the first non-archived workspace linked to the repo issue', () => {
|
||||
const first = worktree({ id: 'first', linkedIssue: 42 })
|
||||
const second = worktree({ id: 'second', linkedIssue: 42 })
|
||||
|
||||
expect(findGithubIssueWorkspaceAttachment([first, second], 'repo-1', 42)).toBe(first)
|
||||
})
|
||||
|
||||
it('matches PRs and issues through the generic helper', () => {
|
||||
const pr = worktree({ id: 'pr', linkedPR: 42 })
|
||||
const issue = worktree({ id: 'issue', linkedIssue: 42 })
|
||||
|
||||
expect(findGithubWorkItemWorkspaceAttachment([issue, pr], 'repo-1', 'pr', 42)).toBe(pr)
|
||||
expect(findGithubWorkItemWorkspaceAttachment([pr, issue], 'repo-1', 'issue', 42)).toBe(issue)
|
||||
})
|
||||
|
||||
it('does not match workspaces from a different repo', () => {
|
||||
const attachedElsewhere = worktree({ repoId: 'repo-2', linkedIssue: 42, linkedPR: 42 })
|
||||
|
||||
@@ -67,13 +51,6 @@ describe('GitHub work-item workspace attachment', () => {
|
||||
expect(findGithubIssueWorkspaceAttachment([archived], 'repo-1', 42)).toBeNull()
|
||||
})
|
||||
|
||||
it('returns null when no repo ID is available', () => {
|
||||
const attached = worktree({ linkedIssue: 42, linkedPR: 42 })
|
||||
|
||||
expect(findGithubPrWorkspaceAttachment([attached], null, 42)).toBeNull()
|
||||
expect(findGithubIssueWorkspaceAttachment([attached], undefined, 42)).toBeNull()
|
||||
})
|
||||
|
||||
it('does not cross-match PR and issue slots with the same number', () => {
|
||||
const prOnly = worktree({ id: 'pr', linkedPR: 42 })
|
||||
const issueOnly = worktree({ id: 'issue', linkedIssue: 42 })
|
||||
@@ -81,18 +58,6 @@ describe('GitHub work-item workspace attachment', () => {
|
||||
expect(findGithubIssueWorkspaceAttachment([prOnly], 'repo-1', 42)).toBeNull()
|
||||
expect(findGithubPrWorkspaceAttachment([issueOnly], 'repo-1', 42)).toBeNull()
|
||||
})
|
||||
|
||||
it('does not treat GitLab metadata as a GitHub work-item attachment', () => {
|
||||
const gitlabOnly = worktree({
|
||||
linkedIssue: null,
|
||||
linkedPR: null,
|
||||
linkedGitLabIssue: 42,
|
||||
linkedGitLabMR: 42
|
||||
})
|
||||
|
||||
expect(findGithubPrWorkspaceAttachment([gitlabOnly], 'repo-1', 42)).toBeNull()
|
||||
expect(findGithubIssueWorkspaceAttachment([gitlabOnly], 'repo-1', 42)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('multiple GitHub attachments', () => {
|
||||
|
||||
@@ -96,26 +96,6 @@ describe('launchAgentBackgroundSession with automation extras', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('merges extras over the default arguments, before the prompt', async () => {
|
||||
const { launchAgentBackgroundSession } = await import('./launch-agent-background-session')
|
||||
mockSpawn.mockResolvedValue({ id: 'pty-1' })
|
||||
|
||||
await launchAgentBackgroundSession({
|
||||
agent: 'claude',
|
||||
worktreeId: 'wt-1',
|
||||
prompt: 'run the automation',
|
||||
extraAgentArgs: '--model opus --add-dir "my docs"'
|
||||
})
|
||||
|
||||
expect(mockSpawn.mock.calls[0]?.[0]).toMatchObject({
|
||||
command:
|
||||
"claude '--dangerously-skip-permissions' '--model' 'opus' '--add-dir' 'my docs' 'run the automation'",
|
||||
launchConfig: {
|
||||
agentArgs: "'--dangerously-skip-permissions' '--model' 'opus' '--add-dir' 'my docs'"
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('fails before reserving a tab or spawning when the extras are refused', async () => {
|
||||
const { launchAgentBackgroundSession } = await import('./launch-agent-background-session')
|
||||
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const mockQueueTabInitialCwd = vi.fn()
|
||||
const mockLaunchAgentInWebHostTab = vi.fn()
|
||||
const mockIsWebRuntimeSessionActive = vi.fn()
|
||||
|
||||
const store = {
|
||||
settings: {
|
||||
agentCmdOverrides: {},
|
||||
agentDefaultArgs: {},
|
||||
agentDefaultEnv: {},
|
||||
activeRuntimeEnvironmentId: null as string | null
|
||||
},
|
||||
repos: [],
|
||||
allWorktrees: vi.fn(() => []),
|
||||
tabsByWorktree: { 'wt-1': [{ id: 'tab-1' }] },
|
||||
openFiles: [] as { id: string; worktreeId: string }[],
|
||||
browserTabsByWorktree: {} as Record<string, { id: string }[]>,
|
||||
tabBarOrderByWorktree: {} as Record<string, string[]>,
|
||||
createTab: vi.fn(() => ({ id: 'tab-1' })),
|
||||
queueTabInitialCwd: mockQueueTabInitialCwd,
|
||||
queueTabStartupCommand: vi.fn(),
|
||||
setActiveTabType: vi.fn(),
|
||||
setTabBarOrder: vi.fn()
|
||||
}
|
||||
|
||||
vi.mock('@/store', () => ({
|
||||
useAppStore: { getState: () => store }
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/new-workspace', () => ({ CLIENT_PLATFORM: 'darwin' }))
|
||||
|
||||
vi.mock('@/lib/connection-context', () => ({
|
||||
getConnectionIdFromState: () => null
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/native-chat-transcript-readability', () => ({
|
||||
isNativeChatTranscriptLocalReadable: () => true
|
||||
}))
|
||||
|
||||
vi.mock('@/runtime/web-runtime-session-environment', () => ({
|
||||
isWebRuntimeSessionActive: mockIsWebRuntimeSessionActive
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/worktree-runtime-owner', () => ({
|
||||
getExecutionHostIdForWorktree: () => 'local',
|
||||
runtimeEnvironmentIdOrLocalUnlessTwin: () => 'web-runtime'
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/launch-agent-web-host-tab', () => ({
|
||||
launchAgentInWebHostTab: mockLaunchAgentInWebHostTab
|
||||
}))
|
||||
|
||||
vi.mock('@/components/tab-bar/reconcile-order', () => ({
|
||||
reconcileTabOrder: (_stored: unknown, terminalIds: string[]) => terminalIds
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/telemetry', () => ({
|
||||
track: vi.fn(),
|
||||
tuiAgentToAgentKind: (agent: string) => agent
|
||||
}))
|
||||
|
||||
vi.mock('@/components/native-chat/native-chat-session-option-cache', () => ({
|
||||
seedNativeChatAppliedSessionOptions: vi.fn()
|
||||
}))
|
||||
|
||||
describe('launchAgentInNewTab initial cwd', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockIsWebRuntimeSessionActive.mockReturnValue(false)
|
||||
mockLaunchAgentInWebHostTab.mockResolvedValue({
|
||||
delivered: true,
|
||||
failureNotified: false
|
||||
})
|
||||
})
|
||||
|
||||
it('queues the original cwd before a local Agent session starts', async () => {
|
||||
const { launchAgentInNewTab } = await import('./launch-agent-in-new-tab')
|
||||
|
||||
launchAgentInNewTab({
|
||||
requestId: 'request-1',
|
||||
agent: 'claude',
|
||||
worktreeId: 'wt-1',
|
||||
initialCwd: '/repo/worktree/packages/app'
|
||||
})
|
||||
|
||||
expect(mockQueueTabInitialCwd).toHaveBeenCalledWith('tab-1', '/repo/worktree/packages/app')
|
||||
})
|
||||
|
||||
it('forwards the original cwd to a paired web runtime', async () => {
|
||||
mockIsWebRuntimeSessionActive.mockReturnValue(true)
|
||||
const { launchAgentInNewTab } = await import('./launch-agent-in-new-tab')
|
||||
|
||||
launchAgentInNewTab({
|
||||
requestId: 'request-2',
|
||||
agent: 'claude',
|
||||
worktreeId: 'wt-1',
|
||||
groupId: 'group-1',
|
||||
initialCwd: '/repo/worktree/packages/app'
|
||||
})
|
||||
|
||||
expect(mockLaunchAgentInWebHostTab).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
worktreeId: 'wt-1',
|
||||
environmentId: 'web-runtime',
|
||||
groupId: 'group-1',
|
||||
cwd: '/repo/worktree/packages/app'
|
||||
})
|
||||
)
|
||||
expect(store.createTab).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('delivers submit-after-ready prompts on the paired host instead of creating a local tab', async () => {
|
||||
mockIsWebRuntimeSessionActive.mockReturnValue(true)
|
||||
const { launchAgentInNewTab } = await import('./launch-agent-in-new-tab')
|
||||
|
||||
const result = launchAgentInNewTab({
|
||||
requestId: 'request-3',
|
||||
agent: 'claude',
|
||||
worktreeId: 'wt-1',
|
||||
prompt: 'continue the unfinished task',
|
||||
promptDelivery: 'submit-after-ready'
|
||||
})
|
||||
|
||||
expect(mockLaunchAgentInWebHostTab).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
worktreeId: 'wt-1',
|
||||
environmentId: 'web-runtime',
|
||||
prompt: 'continue the unfinished task',
|
||||
promptDelivery: 'submit-after-ready',
|
||||
pastePromptAfterReady: 'continue the unfinished task',
|
||||
submitPastedPrompt: true
|
||||
})
|
||||
)
|
||||
expect(store.createTab).not.toHaveBeenCalled()
|
||||
await expect(result?.promptDeliveryResult).resolves.toEqual({
|
||||
delivered: true,
|
||||
failureNotified: false
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -82,16 +82,6 @@ describe('openLinearIssueWorkspaceOrStart', () => {
|
||||
mocks.activateAndRevealWorktree.mockReset().mockReturnValue({ primaryTabId: null })
|
||||
})
|
||||
|
||||
it('qualifies remote worktree activation with its execution host', () => {
|
||||
mocks.worktrees = [worktree({ hostId: 'ssh:builder' })]
|
||||
|
||||
expect(openLinearIssueWorkspaceOrStart({ identifier: 'ENG-1' }, vi.fn())).toBe('opened')
|
||||
expect(mocks.activateAndRevealWorktree).toHaveBeenCalledWith('worktree-1', {
|
||||
navigationIntent: 'user-open',
|
||||
executionHostId: 'ssh:builder'
|
||||
})
|
||||
})
|
||||
|
||||
it('opens a linked folder workspace instead of starting a duplicate', () => {
|
||||
mocks.folderWorkspaces = [folderWorkspace()]
|
||||
const startWorkspace = vi.fn()
|
||||
@@ -104,14 +94,6 @@ describe('openLinearIssueWorkspaceOrStart', () => {
|
||||
expect(startWorkspace).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('starts a workspace when the issue has none attached', () => {
|
||||
const startWorkspace = vi.fn()
|
||||
|
||||
expect(openLinearIssueWorkspaceOrStart({ identifier: 'ENG-1' }, startWorkspace)).toBe('started')
|
||||
expect(startWorkspace).toHaveBeenCalledTimes(1)
|
||||
expect(mocks.activateAndRevealWorktree).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('reports failure when activation is refused', () => {
|
||||
mocks.worktrees = [worktree()]
|
||||
mocks.activateAndRevealWorktree.mockReturnValue(false)
|
||||
|
||||
@@ -63,14 +63,6 @@ describe.each(helpers)('%s parked renderer resize', (_name, present) => {
|
||||
expect(service._needsFullRefresh).toBe(false)
|
||||
})
|
||||
|
||||
it('flushes before a DEC 2026 present too', () => {
|
||||
const { terminal, service, order } = createPausedTerminal({ synchronizedOutput: true })
|
||||
|
||||
expect(present(terminal)).toBe(true)
|
||||
expect(service._pausedResizeTask?.flush).toHaveBeenCalledTimes(1)
|
||||
expect(order[0]).toBe('flush')
|
||||
})
|
||||
|
||||
it('still presents when the parked-task internal is unavailable', () => {
|
||||
const { terminal, service } = createPausedTerminal({ withoutTask: true })
|
||||
|
||||
|
||||
@@ -37,22 +37,6 @@ function pending(
|
||||
}
|
||||
|
||||
describe('findPendingWorktreeCreationId', () => {
|
||||
it('matches the resolved checkout rather than a requested name', () => {
|
||||
const entry = { ...pending('create-1', request()), worktreeId: 'repo-1::/workspace-2' }
|
||||
expect(findPendingWorktreeCreationId({ entry }, entry.worktreeId)).toBe('create-1')
|
||||
expect(findPendingWorktreeCreationId({ entry }, 'repo-1::/workspace')).toBeNull()
|
||||
expect(findPendingWorktreeCreationId(undefined, entry.worktreeId)).toBeNull()
|
||||
})
|
||||
|
||||
it('allows a failed checkout to open normally', () => {
|
||||
const entry: PendingWorktreeCreation = {
|
||||
...pending('create-1', request()),
|
||||
worktreeId: 'repo-1::/workspace',
|
||||
status: 'error'
|
||||
}
|
||||
expect(findPendingWorktreeCreationId({ entry }, entry.worktreeId ?? null)).toBeNull()
|
||||
})
|
||||
|
||||
it('matches Windows path spelling while keeping repositories distinct', () => {
|
||||
const entry = {
|
||||
...pending('create-1', request()),
|
||||
@@ -120,10 +104,4 @@ describe('findPendingLinkedWorkItemCreationId', () => {
|
||||
)
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('does not deduplicate unlinked workspace creation', () => {
|
||||
expect(
|
||||
findPendingLinkedWorkItemCreationId({ existing: pending('existing', request()) }, request())
|
||||
).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,11 +7,6 @@ import {
|
||||
import type { WorktreeRuntimeOwnerState } from './worktree-runtime-owner-state'
|
||||
|
||||
describe('getResolvedExecutionHostIdForWorktree', () => {
|
||||
it('keeps missing workspace ownership unresolved', () => {
|
||||
expect(getResolvedExecutionHostIdForWorktree({}, null)).toBeNull()
|
||||
expect(getResolvedExecutionHostIdForWorktree({}, undefined)).toBeNull()
|
||||
})
|
||||
|
||||
it('requires a hydrated worktree before treating a matching local repo row as authoritative', () => {
|
||||
expect(
|
||||
getResolvedExecutionHostIdForWorktree(
|
||||
@@ -47,21 +42,6 @@ describe('getResolvedExecutionHostIdForWorktree', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('falls back from the repo host stamp to its connection id, then local', () => {
|
||||
const state = (repo: { connectionId: string | null; executionHostId?: ExecutionHostId }) => ({
|
||||
repos: [{ id: 'repo', ...repo }],
|
||||
worktreesByRepo: { repo: [{ id: 'repo::wt', repoId: 'repo' }] }
|
||||
})
|
||||
const resolve = (repo: { connectionId: string | null; executionHostId?: ExecutionHostId }) =>
|
||||
getResolvedExecutionHostIdForWorktree(state(repo), 'repo::wt')
|
||||
expect(resolve({ connectionId: 'target-1', executionHostId: 'runtime:env-1' })).toBe(
|
||||
'runtime:env-1'
|
||||
)
|
||||
expect(resolve({ connectionId: null, executionHostId: 'ssh:target-2' })).toBe('ssh:target-2')
|
||||
expect(resolve({ connectionId: 'target-1' })).toBe('ssh:target-1')
|
||||
expect(resolve({ connectionId: ' ' })).toBe('local')
|
||||
})
|
||||
|
||||
it('keeps missing folder catalogs unresolved but honors restored runtime ownership', () => {
|
||||
expect(getResolvedExecutionHostIdForWorktree({}, 'folder:missing')).toBeNull()
|
||||
expect(
|
||||
@@ -114,36 +94,6 @@ function stateFocusing(
|
||||
}
|
||||
|
||||
describe('getActiveWorkspaceOwnerTarget', () => {
|
||||
it('has no answer when nothing is focused or the focused row has not landed', () => {
|
||||
expect(getActiveWorkspaceOwnerTarget({ activeWorktreeId: null })).toBeNull()
|
||||
expect(
|
||||
getActiveWorkspaceOwnerTarget({
|
||||
...stateFocusing({ executionHostId: 'local' }),
|
||||
worktreesByRepo: {}
|
||||
})
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('follows the focused row: a local repo, a server repo, and a worktree host over its repo', () => {
|
||||
expect(getActiveWorkspaceOwnerTarget(stateFocusing({ executionHostId: 'local' }))).toEqual({
|
||||
kind: 'local'
|
||||
})
|
||||
expect(
|
||||
getActiveWorkspaceOwnerTarget(stateFocusing({ executionHostId: 'runtime:env-b' }))
|
||||
).toEqual({ kind: 'environment', environmentId: 'env-b' })
|
||||
expect(
|
||||
getActiveWorkspaceOwnerTarget(stateFocusing({ executionHostId: 'local' }, 'runtime:env-c'))
|
||||
).toEqual({ kind: 'environment', environmentId: 'env-c' })
|
||||
})
|
||||
|
||||
it('has no answer for a direct SSH owner, which has no RPC transport', () => {
|
||||
expect(
|
||||
getActiveWorkspaceOwnerTarget(
|
||||
stateFocusing({ executionHostId: 'ssh:box', connectionId: 'box' })
|
||||
)
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('skips owner resolution once the catalog has hydrated with no paired server', () => {
|
||||
const state = {
|
||||
...stateFocusing({ executionHostId: 'runtime:env-b' }),
|
||||
|
||||
@@ -43,17 +43,6 @@ describe('activation inventory execution scope', () => {
|
||||
).toBeUndefined()
|
||||
})
|
||||
|
||||
it.each(['local', 'ssh:remote%20box'] as const)('resolves only %s', (hostId) => {
|
||||
expect(
|
||||
resolveActivationPtyListScope(
|
||||
{
|
||||
repos: [{ id: 'repo', executionHostId: hostId }]
|
||||
},
|
||||
worktreeId
|
||||
)
|
||||
).toEqual({ connectionId: hostId === 'local' ? null : 'remote box' })
|
||||
})
|
||||
|
||||
it('resolves folder workspaces without a Git worktree row', () => {
|
||||
expect(
|
||||
resolveActivationPtyListScope(
|
||||
@@ -97,14 +86,6 @@ describe('activation inventory execution scope', () => {
|
||||
})
|
||||
|
||||
describe('activation inventory census', () => {
|
||||
it('asks only the owning provider when the client can name one', async () => {
|
||||
const listSessions = stubListSessions(async () => [{ id: 'ssh:box@@pty-1' }])
|
||||
await expect(
|
||||
listActivationPtySessions({ repos: [{ id: 'repo', executionHostId: 'ssh:box' }] }, worktreeId)
|
||||
).resolves.toEqual([{ id: 'ssh:box@@pty-1' }])
|
||||
expect(listSessions).toHaveBeenCalledExactlyOnceWith({ connectionId: 'box' })
|
||||
})
|
||||
|
||||
it('rejects paired ownership without consulting the client inventory', async () => {
|
||||
const listSessions = stubListSessions(async () => [])
|
||||
await expect(
|
||||
@@ -126,27 +107,4 @@ describe('activation inventory census', () => {
|
||||
).rejects.toThrow('Activation PTY inventory is unverifiable')
|
||||
expect(listSessions).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('propagates detached and unavailable host errors without a client fallback', async () => {
|
||||
const detached = stubListSessions(async (scope) => {
|
||||
if (scope) {
|
||||
throw new Error(
|
||||
'Error invoking remote method: Error: No PTY provider for connection "box": the SSH relay for this host is not attached'
|
||||
)
|
||||
}
|
||||
return [{ id: 'local-1' }]
|
||||
})
|
||||
await expect(
|
||||
listActivationPtySessions({ repos: [{ id: 'repo', executionHostId: 'ssh:box' }] }, worktreeId)
|
||||
).rejects.toThrow('No PTY provider for connection')
|
||||
expect(detached.mock.calls).toEqual([[{ connectionId: 'box' }]])
|
||||
|
||||
const refused = stubListSessions(async () => {
|
||||
throw new Error('relay unavailable')
|
||||
})
|
||||
await expect(
|
||||
listActivationPtySessions({ repos: [{ id: 'repo', executionHostId: 'ssh:box' }] }, worktreeId)
|
||||
).rejects.toThrow('relay unavailable')
|
||||
expect(refused).toHaveBeenCalledOnce()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { activateAndRevealWorktree } from './worktree-activation'
|
||||
import { registerWorktreeActivationReset } from './worktree-activation.test-fixture'
|
||||
import { useAppStore } from '@/store'
|
||||
|
||||
registerWorktreeActivationReset()
|
||||
|
||||
describe('activateAndRevealWorktree', () => {
|
||||
afterEach(() => {
|
||||
useAppStore.setState({
|
||||
activeRepoId: null,
|
||||
activeWorktreeId: null,
|
||||
activeView: 'terminal',
|
||||
filterRepoIds: [],
|
||||
isNavigatingHistory: false
|
||||
})
|
||||
})
|
||||
|
||||
it('queues a one-shot initial cwd for the primary activation-created tab', () => {
|
||||
const queueTabInitialCwd = vi.fn()
|
||||
const revealWorktreeInSidebar = vi.fn()
|
||||
useAppStore.setState({
|
||||
activeRepoId: null,
|
||||
activeWorktreeId: null,
|
||||
activeView: 'settings',
|
||||
filterRepoIds: [],
|
||||
isNavigatingHistory: false,
|
||||
repos: [{ id: 'repo-1', connectionId: null }],
|
||||
worktreesByRepo: {
|
||||
'repo-1': [
|
||||
{
|
||||
id: 'wt-1',
|
||||
repoId: 'repo-1',
|
||||
path: '/repo',
|
||||
displayName: 'main',
|
||||
branch: 'main',
|
||||
head: 'abc',
|
||||
isBare: false,
|
||||
isMainWorktree: true
|
||||
}
|
||||
]
|
||||
},
|
||||
getKnownWorktreeById: (worktreeId: string) =>
|
||||
worktreeId === 'wt-1'
|
||||
? ({
|
||||
id: 'wt-1',
|
||||
repoId: 'repo-1',
|
||||
path: '/repo',
|
||||
displayName: 'main',
|
||||
branch: 'main',
|
||||
head: 'abc',
|
||||
isBare: false,
|
||||
isMainWorktree: true
|
||||
} as never)
|
||||
: null,
|
||||
setActiveRepo: vi.fn(),
|
||||
setActiveView: vi.fn(),
|
||||
setActiveWorktree: vi.fn(),
|
||||
markWorktreeVisited: vi.fn(),
|
||||
recordWorktreeVisit: vi.fn(),
|
||||
reconcileWorktreeTabModel: vi.fn(() => ({ renderableTabCount: 0 })),
|
||||
createTab: vi.fn(() => ({ id: 'tab-1' })),
|
||||
setActiveTab: vi.fn(),
|
||||
setTabCustomTitle: vi.fn(),
|
||||
setTabColor: vi.fn(),
|
||||
markDefaultTerminalTabsApplied: vi.fn(),
|
||||
queueTabInitialCwd,
|
||||
queueTabIssueCommandSplit: vi.fn(),
|
||||
revealWorktreeInSidebar
|
||||
} as never)
|
||||
|
||||
const result = activateAndRevealWorktree('wt-1', {
|
||||
initialCwd: '/repo/packages/web',
|
||||
executionHostId: 'ssh:box'
|
||||
})
|
||||
|
||||
expect(result).toEqual({ primaryTabId: 'tab-1' })
|
||||
expect(queueTabInitialCwd).toHaveBeenCalledWith('tab-1', '/repo/packages/web')
|
||||
expect(revealWorktreeInSidebar).toHaveBeenCalledWith('wt-1', {
|
||||
executionHostId: 'ssh:box'
|
||||
})
|
||||
})
|
||||
|
||||
it('reselects a live worktree without creating a second terminal tab', () => {
|
||||
const createTab = vi.fn(() => ({ id: 'tab-2' }))
|
||||
const existingTab = { id: 'tab-1' }
|
||||
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: This fixture supplies only the activation slice used by the test.
|
||||
useAppStore.setState({
|
||||
activeRepoId: 'repo-1',
|
||||
activeWorktreeId: 'wt-1',
|
||||
activeView: 'terminal',
|
||||
filterRepoIds: [],
|
||||
isNavigatingHistory: false,
|
||||
repos: [{ id: 'repo-1', connectionId: null }],
|
||||
worktreesByRepo: {
|
||||
'repo-1': [
|
||||
{
|
||||
id: 'wt-1',
|
||||
repoId: 'repo-1',
|
||||
path: '/repo',
|
||||
displayName: 'main',
|
||||
branch: 'main',
|
||||
head: 'abc',
|
||||
isBare: false,
|
||||
isMainWorktree: true
|
||||
}
|
||||
]
|
||||
},
|
||||
tabsByWorktree: { 'wt-1': [existingTab] },
|
||||
getKnownWorktreeById: (worktreeId: string) =>
|
||||
worktreeId === 'wt-1'
|
||||
? // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The fixture omits unrelated worktree metadata.
|
||||
({
|
||||
id: 'wt-1',
|
||||
repoId: 'repo-1',
|
||||
path: '/repo',
|
||||
displayName: 'main',
|
||||
branch: 'main',
|
||||
head: 'abc',
|
||||
isBare: false,
|
||||
isMainWorktree: true
|
||||
} as never)
|
||||
: null,
|
||||
setActiveRepo: vi.fn(),
|
||||
setActiveView: vi.fn(),
|
||||
setActiveWorktree: vi.fn(),
|
||||
markWorktreeVisited: vi.fn(),
|
||||
recordWorktreeVisit: vi.fn(),
|
||||
reconcileWorktreeTabModel: vi.fn(() => ({ renderableTabCount: 1 })),
|
||||
createTab,
|
||||
setActiveTab: vi.fn(),
|
||||
setTabCustomTitle: vi.fn(),
|
||||
setTabColor: vi.fn(),
|
||||
markDefaultTerminalTabsApplied: vi.fn(),
|
||||
queueTabInitialCwd: vi.fn(),
|
||||
queueTabIssueCommandSplit: vi.fn(),
|
||||
revealWorktreeInSidebar: vi.fn()
|
||||
} as never)
|
||||
|
||||
const result = activateAndRevealWorktree('wt-1')
|
||||
|
||||
expect(result).toEqual({ primaryTabId: null })
|
||||
expect(createTab).not.toHaveBeenCalled()
|
||||
expect(useAppStore.getState().tabsByWorktree['wt-1']).toEqual([existingTab])
|
||||
})
|
||||
})
|
||||
@@ -1,17 +1,12 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useAppStore } from '@/store'
|
||||
import { activateAndRevealWorktree } from './worktree-activation'
|
||||
import { ensureWorktreeHasInitialTerminal } from './worktree-initial-terminal-seeding'
|
||||
|
||||
import {
|
||||
makeCreatedAgentWorktree as makeWorktree,
|
||||
seedEmptyActivatableWorktree
|
||||
} from '@/lib/worktree-activation-created-agent.test-fixture'
|
||||
import {
|
||||
createMockStore,
|
||||
registerWorktreeActivationReset,
|
||||
setLegacySetupScriptLaunchMode,
|
||||
createdTabStartups
|
||||
} from './worktree-activation.test-fixture'
|
||||
import { registerWorktreeActivationReset } from './worktree-activation.test-fixture'
|
||||
|
||||
// Main's answer to the window's layout commands, as a switch-on build sends them.
|
||||
vi.mock('@/runtime/runtime-rpc-client', async (importOriginal) =>
|
||||
@@ -36,97 +31,6 @@ const setup = {
|
||||
|
||||
// Returned setup scripts must not force Terminal 1 beside a new native chat.
|
||||
describe('seeding beside a caller-provided chat surface', () => {
|
||||
it('runs a new-tab setup script without seeding a shell', () => {
|
||||
let createdIndex = 0
|
||||
const createTab = vi.fn(() => ({ id: `tab-${++createdIndex}` }))
|
||||
const store = createMockStore({ createTab })
|
||||
|
||||
const primaryTabId = ensureWorktreeHasInitialTerminal(
|
||||
store,
|
||||
'wt-1',
|
||||
undefined,
|
||||
setup,
|
||||
undefined,
|
||||
undefined,
|
||||
{ callerProvidesSurface: true }
|
||||
)
|
||||
|
||||
expect(primaryTabId).toBeNull()
|
||||
expect(createTab).toHaveBeenCalledTimes(1)
|
||||
expect(store.setTabCustomTitle).toHaveBeenCalledWith('tab-1', 'Setup', {
|
||||
recordInteraction: false
|
||||
})
|
||||
expect(createdTabStartups(store)['tab-1']).toEqual({
|
||||
command: 'bash /tmp/repo/.git/orca/setup-runner.sh',
|
||||
env: setup.envVars
|
||||
})
|
||||
})
|
||||
|
||||
it.each(['split-vertical', 'split-horizontal', 'new-tab', null] as const)(
|
||||
'ignores retired setup location %s beside a caller-provided chat',
|
||||
(mode) => {
|
||||
setLegacySetupScriptLaunchMode(mode)
|
||||
const store = createMockStore()
|
||||
const primary = ensureWorktreeHasInitialTerminal(
|
||||
store,
|
||||
'wt-1',
|
||||
undefined,
|
||||
setup,
|
||||
undefined,
|
||||
undefined,
|
||||
{ callerProvidesSurface: true, activateCreatedTabs: false }
|
||||
)
|
||||
expect(primary).toBeNull()
|
||||
expect(store.createTab).toHaveBeenCalledExactlyOnceWith('wt-1', undefined, undefined, {
|
||||
recordInteraction: false,
|
||||
activate: false,
|
||||
pendingStartup: {
|
||||
command: 'bash /tmp/repo/.git/orca/setup-runner.sh',
|
||||
env: setup.envVars
|
||||
}
|
||||
})
|
||||
expect(store.setActiveTab).not.toHaveBeenCalled()
|
||||
expect(store.setTabCustomTitle).toHaveBeenCalledWith('tab-1', 'Setup', {
|
||||
recordInteraction: false
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
it('still seeds a shell for issue automation, which splits from it', () => {
|
||||
let createdIndex = 0
|
||||
const createTab = vi.fn(() => ({ id: `tab-${++createdIndex}` }))
|
||||
const store = createMockStore({ createTab })
|
||||
|
||||
ensureWorktreeHasInitialTerminal(
|
||||
store,
|
||||
'wt-1',
|
||||
undefined,
|
||||
undefined,
|
||||
{ command: 'orca issue run' },
|
||||
undefined,
|
||||
{ callerProvidesSurface: true }
|
||||
)
|
||||
|
||||
expect(createTab).toHaveBeenCalledTimes(1)
|
||||
expect(store.queueTabIssueCommandSplit).toHaveBeenCalledWith('tab-1', {
|
||||
command: 'orca issue run',
|
||||
env: undefined
|
||||
})
|
||||
})
|
||||
|
||||
it('still seeds a shell when the caller owns no surface', () => {
|
||||
let createdIndex = 0
|
||||
const createTab = vi.fn(() => ({ id: `tab-${++createdIndex}` }))
|
||||
const store = createMockStore({ createTab })
|
||||
|
||||
ensureWorktreeHasInitialTerminal(store, 'wt-1', undefined, setup)
|
||||
|
||||
expect(createTab).toHaveBeenCalledTimes(2)
|
||||
expect(store.setTabCustomTitle).toHaveBeenCalledWith('tab-2', 'Setup', {
|
||||
recordInteraction: false
|
||||
})
|
||||
})
|
||||
|
||||
it('activation forwards providesInitialSurface so setup alone adds one tab', () => {
|
||||
const worktree = makeWorktree()
|
||||
seedEmptyActivatableWorktree(worktree)
|
||||
|
||||
@@ -7,16 +7,12 @@ import {
|
||||
type GateTestStore,
|
||||
listed,
|
||||
LIVE_LEAF_ID,
|
||||
seedExistingSurface,
|
||||
SIBLING_LEAF_ID,
|
||||
sleepingRecord,
|
||||
testDeps,
|
||||
WORKTREE_ID
|
||||
} from './worktree-agent-activation-gate.test-fixture'
|
||||
import {
|
||||
readWorktreeLiveTerminalSurfaceOwners,
|
||||
type LiveTerminalSurfaceOwner
|
||||
} from './worktree-live-terminal-surface-owners'
|
||||
import type { LiveTerminalSurfaceOwner } from './worktree-live-terminal-surface-owners'
|
||||
|
||||
vi.mock('../../../shared/layout-owner-switch', () => ({ ORCA_LAYOUT_OWNER_IS_MAIN: true }))
|
||||
|
||||
@@ -44,27 +40,6 @@ afterEach(() => {
|
||||
vi.unstubAllGlobals()
|
||||
})
|
||||
|
||||
describe('the sweep’s listing, layout-owner build', () => {
|
||||
it('asks main to place the workspace’s unshown live terminals before it lists', async () => {
|
||||
const call = vi.fn(async () => ({
|
||||
ok: true,
|
||||
result: { terminals: [], hostScope: { hostIds: ['local'], omittedHostIds: [] } }
|
||||
}))
|
||||
vi.stubGlobal('window', { api: { runtime: { call } } })
|
||||
|
||||
await readWorktreeLiveTerminalSurfaceOwners(WORKTREE_ID)
|
||||
|
||||
expect(call).toHaveBeenCalledWith({
|
||||
method: 'terminal.list',
|
||||
params: expect.objectContaining({
|
||||
worktree: `id:${WORKTREE_ID}`,
|
||||
requireFreshPtyLiveness: true,
|
||||
placeUnshownLiveTerminals: true
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('the activation sweep reads main’s placement, layout-owner build', () => {
|
||||
it('counts a terminal main placed as shown before its frame arrives: no shell is seeded', async () => {
|
||||
const { deps, resume } = testDeps({
|
||||
@@ -78,18 +53,6 @@ describe('the activation sweep reads main’s placement, layout-owner build', ()
|
||||
expect(resume).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('writes nothing for a pane main names in a tab this window already has', async () => {
|
||||
const { deps } = testDeps({
|
||||
sessions: [listed(LIVE_PTY)],
|
||||
surfaceOwners: new Map([[LIVE_PTY, placedByMain(LIVE_PTY, 'tab-known')]])
|
||||
})
|
||||
seedExistingSurface(deps.getState(), { tabId: 'tab-known', leafId: LIVE_LEAF_ID })
|
||||
|
||||
await expect(runWorktreeAgentActivationGate(WORKTREE_ID, deps)).resolves.toBe('adopted')
|
||||
|
||||
expectNoWindowWrite(deps.getState())
|
||||
})
|
||||
|
||||
it('still resumes the workspace’s sleeping agent beside the terminal main placed', async () => {
|
||||
const { deps, resume } = testDeps({
|
||||
sessions: [{ ...listed(LIVE_PTY), title: 'zsh', agentOwnership: 'absent' }],
|
||||
|
||||
Reference in New Issue
Block a user