diff --git a/.github/workflows/performance-contracts.yml b/.github/workflows/performance-contracts.yml index db271e8ab42..4d0a51b3ad8 100644 --- a/.github/workflows/performance-contracts.yml +++ b/.github/workflows/performance-contracts.yml @@ -20,7 +20,6 @@ on: - 'src/main/ipc/pty/runtime/spawn-preflight-saved-resume.test.ts' - 'src/main/native-chat/agent-session-wire/structured-agent-session-terminal-writer-acquire.test.ts' - 'src/main/runtime/hook-status-resume-sleep-ordering.test.ts' - - 'src/renderer/src/hooks/ipc-events/agent-status-refused-resume.performance.test.ts' - 'src/renderer/src/components/terminal-pane/pty-connection/saved-resume-cancellation.test.ts' - 'src/main/sqlite/sync-database.test.ts' - 'src/main/runtime/orchestration/db/row-column-lists.test.ts' diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index f8d15f14b11..4e91c79455c 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -10353,13 +10353,11 @@ "src/renderer/src/hooks/installed-agent-skill-discovery-cache.test.ts": 53, "src/renderer/src/hooks/installed-agent-skill-discovery.test.ts": 74, "src/renderer/src/hooks/installed-agent-skill-runtime-eviction.test.ts": 54, - "src/renderer/src/hooks/installed-agent-skill-verdict.test.ts": 195, "src/renderer/src/hooks/ipc-events/agent-status-pane-routing-index-retention.test.ts": 4878, "src/renderer/src/hooks/ipc-events/agent-status-pane-routing-index.test.ts": 1892, "src/renderer/src/hooks/ipc-events/agent-status-pending-retry-gate.test.ts": 466, "src/renderer/src/hooks/ipc-events/agent-status-program-status-only.test.ts": 398, "src/renderer/src/hooks/ipc-events/agent-status-reconnect-replay-notification.test.ts": 352, - "src/renderer/src/hooks/ipc-events/agent-status-refused-resume.performance.test.ts": 1851, "src/renderer/src/hooks/ipc-events/agent-status-terminal-title-tab-write.test.ts": 2247, "src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.fallback.test.ts": 776, "src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.owner.test.ts": 623, diff --git a/config/vitest.performance.config.ts b/config/vitest.performance.config.ts index d8fecb02f77..d2ef47fbbee 100644 --- a/config/vitest.performance.config.ts +++ b/config/vitest.performance.config.ts @@ -10,7 +10,6 @@ const contracts = [ 'src/main/ipc/pty/runtime/spawn-preflight-saved-resume.test.ts', 'src/main/native-chat/agent-session-wire/structured-agent-session-terminal-writer-acquire.test.ts', 'src/main/runtime/hook-status-resume-sleep-ordering.test.ts', - 'src/renderer/src/hooks/ipc-events/agent-status-refused-resume.performance.test.ts', 'src/shared/tui-agent-permission-choice.test.ts', 'src/renderer/src/components/settings/agent-permission-conversion-persistence.test.tsx', 'src/main/runtime/rpc/methods/repo.test.ts', diff --git a/src/renderer/src/hooks/editor-external-watch-selected-host.test.ts b/src/renderer/src/hooks/editor-external-watch-selected-host.test.ts index dda4a06a3bb..9bdfe547579 100644 --- a/src/renderer/src/hooks/editor-external-watch-selected-host.test.ts +++ b/src/renderer/src/hooks/editor-external-watch-selected-host.test.ts @@ -163,15 +163,6 @@ it.each(['worktree', 'folder'] as const)( } ) -it.each(['worktree', 'folder'] as const)( - 'preserves the %s watcher snapshot when selection and watched roots stay unchanged', - (workspace) => { - const state = makeState(workspace) - const first = selectEditorExternalWatchTargets(state) - expect(selectEditorExternalWatchTargets({ ...state })).toBe(first) - } -) - it.each(['worktree', 'folder'] as const)( "watches the selected host's %s root when hosts publish the same id at different roots", (workspace) => { diff --git a/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts b/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts index eef4c04e3b7..bf587ff3389 100644 --- a/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts +++ b/src/renderer/src/hooks/installed-agent-skill-discovery.test.ts @@ -16,7 +16,6 @@ vi.mock('@/runtime/runtime-skills-client', () => ({ discoverSkillsForRuntimeTarg const { discoverInstalledAgentSkills, getRuntimeScopedSkillDiscoveryKey, - getSkillDiscoveryTargetKey, invalidateInstalledAgentSkillDiscovery, resetSkillDiscoveryCacheForTests } = await import('./installed-agent-skill-discovery') @@ -217,39 +216,6 @@ describe('installed agent skill discovery lifecycle', () => { expect(discoverSkillsForRuntimeTarget).toHaveBeenCalledTimes(targets.length) }) - it('keys targets by runtime and project identity', () => { - expect(getSkillDiscoveryTargetKey(undefined)).toBe('host') - expect(getSkillDiscoveryTargetKey({ runtime: 'wsl', wslDistro: 'Ubuntu' })).toBe('wsl:Ubuntu') - expect(getSkillDiscoveryTargetKey({ projectRuntime: resolvedHostProjectRuntime })).toBe( - 'repo-1:windows-host' - ) - expect(getSkillDiscoveryTargetKey({ projectRuntime: repairProjectRuntime })).toBe( - 'repo-1:repair:wsl-distro-required:default' - ) - }) - - it('normalizes effective filters into local, project, and environment keys', () => { - const target = { - projectRuntime: resolvedWslProjectRuntime, - names: [' Computer-Use ', 'orchestration', 'computer-use'], - sourceKinds: ['home' as const] - } - const normalizedFilters = [['computer-use', 'orchestration'], ['home']] - - expect(getSkillDiscoveryTargetKey(target)).toBe( - JSON.stringify(['repo-1:wsl:Ubuntu', ...normalizedFilters]) - ) - expect(getRuntimeScopedSkillDiscoveryKey(remote('env-a'), target)).toBe( - JSON.stringify(['runtime:env-a', ...normalizedFilters]) - ) - expect(getSkillDiscoveryTargetKey(target, [], [])).toBe( - JSON.stringify(['repo-1:wsl:Ubuntu', ...normalizedFilters]) - ) - expect(getSkillDiscoveryTargetKey(target, ['ORCHESTRATION'], [])).toBe( - JSON.stringify(['repo-1:wsl:Ubuntu', ['orchestration'], ['home']]) - ) - }) - it('keys the bounded cache by runtime scope, not by the client target', async () => { // Keep runtime-scoped remote keys through cache bounding; host-only target keys collapse environments (#6887). expect(getRuntimeScopedSkillDiscoveryKey(remote('env-a'), undefined)).toBe('runtime:env-a') diff --git a/src/renderer/src/hooks/installed-agent-skill-verdict.test.ts b/src/renderer/src/hooks/installed-agent-skill-verdict.test.ts deleted file mode 100644 index 0bd964458a3..00000000000 --- a/src/renderer/src/hooks/installed-agent-skill-verdict.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { SkillDiscoverySource, SkillSourceKind } from '../../../shared/skills' - -import { - getInstalledAgentSkillVerdict, - type InstalledAgentSkillScan -} from './installed-agent-skill-verdict' - -function source( - sourceKind: SkillSourceKind, - skippedReason?: SkillDiscoverySource['skippedReason'] -): SkillDiscoverySource { - return { - id: `${sourceKind}-root`, - label: sourceKind, - path: `/roots/${sourceKind}`, - sourceKind, - providers: ['claude'], - owner: null, - // An unread root reports `exists`: the host could not prove otherwise. - exists: true, - ...(skippedReason ? { skippedReason } : {}) - } -} - -function scan(overrides: Partial = {}): InstalledAgentSkillScan { - return { - enabled: true, - installed: false, - settled: true, - error: null, - sources: [], - sourceKinds: ['home'], - ...overrides - } -} - -const unverifiable = (overrides: Partial): boolean => - getInstalledAgentSkillVerdict(scan(overrides)).installedUnverifiable - -describe('getInstalledAgentSkillVerdict', () => { - it('ignores an unreadable root outside the queried source kinds', () => { - expect(unverifiable({ sources: [source('repo', 'unavailable')] })).toBe(false) - }) - - // Pre-answer failure leaves sources empty, so missing results need a separate unknown check. - it('cannot vouch for a negative when the scan errored before ever answering', () => { - expect(unverifiable({ settled: false, error: 'scan failed' })).toBe(true) - }) - - it('keeps an answer it already holds when a later refresh fails', () => { - expect(unverifiable({ settled: true, error: 'scan failed' })).toBe(false) - }) - - it('stays silent while a first scan is still pending with no error', () => { - expect(unverifiable({ settled: false })).toBe(false) - }) - - it('takes finding the skill as proof, whatever else failed', () => { - expect(unverifiable({ installed: true, settled: false, error: 'scan failed' })).toBe(false) - }) - - it('says nothing about a query that is switched off', () => { - expect(unverifiable({ enabled: false, sources: [source('home', 'unavailable')] })).toBe(false) - }) -}) - -describe('installed-skill verdict while a WSL distro is stopped (E9)', () => { - // What main answers for a blocked WSL target or a blocked repo root: never read, never "missing". - const stoppedDistroSource = (sourceKind: SkillSourceKind): SkillDiscoverySource => ({ - id: `wsl-unavailable-${sourceKind}-ubuntu`, - label: 'WSL Ubuntu', - path: '', - sourceKind, - providers: [], - owner: null, - exists: false, - skippedReason: 'unavailable' - }) - - it('doubts a negative answer instead of confirming the skill is not installed', () => { - const verdict = getInstalledAgentSkillVerdict( - scan({ sources: [stoppedDistroSource('home'), stoppedDistroSource('repo')] }) - ) - expect(verdict.installedUnverifiable).toBe(true) - expect(verdict.error).toBe('A skill folder did not respond, so this status may be incomplete.') - }) -}) diff --git a/src/renderer/src/hooks/ipc-events/agent-status-reconnect-replay-notification.test.ts b/src/renderer/src/hooks/ipc-events/agent-status-reconnect-replay-notification.test.ts index 9e51628c867..0a659e95c82 100644 --- a/src/renderer/src/hooks/ipc-events/agent-status-reconnect-replay-notification.test.ts +++ b/src/renderer/src/hooks/ipc-events/agent-status-reconnect-replay-notification.test.ts @@ -46,13 +46,10 @@ function createApplicator(): (data: AgentStatusIpcPayload) => unknown { // A relay reconnect re-sends every cached row; each replayed `done` used to notify again. describe('live agent-status replay notifications', () => { - let setAgentStatus: ReturnType - beforeEach(() => { mocks.observe.mockReset() - setAgentStatus = vi.fn() mocks.state.current = buildStoreState({ - setAgentStatus, + setAgentStatus: vi.fn(), workspaceSessionReady: true, tabsByWorktree: { 'wt-1': [{ id: 'tab-1', ptyId: 'pty-1', worktreeId: 'wt-1', title: 'Claude' }] @@ -63,15 +60,6 @@ describe('live agent-status replay notifications', () => { }) }) - it('updates status from a replayed done without observing it as a completion', () => { - const apply = createApplicator() - - expect(apply(status({ isReplay: true }))).toBe('applied') - - expect(setAgentStatus).toHaveBeenCalledTimes(1) - expect(mocks.observe).not.toHaveBeenCalled() - }) - function seedRow(row: { state: string; stateStartedAt: number }): void { const current = mocks.state.current if (current) { diff --git a/src/renderer/src/hooks/ipc-events/agent-status-refused-resume.performance.test.ts b/src/renderer/src/hooks/ipc-events/agent-status-refused-resume.performance.test.ts deleted file mode 100644 index ce4bd11b672..00000000000 --- a/src/renderer/src/hooks/ipc-events/agent-status-refused-resume.performance.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { afterEach, expect, it, vi } from 'vitest' -import type { - AgentStatusIpcPayload, - RefusedPaneResume -} from '../../../../shared/agent-status-types' -import { createTestStore } from '@/store/slices/store-test-helpers' -import { createStoreSessionMockApi } from '@/store/slices/store-session-test-harness' -import { registerAgentStatusListeners } from './agent-status-listeners' - -const bridge = vi.hoisted(() => ({ getState: vi.fn(), setState: vi.fn() })) -vi.mock('@/store', () => ({ useAppStore: bridge })) - -afterEach(() => vi.unstubAllGlobals()) - -it.each([10, 100])( - 'counts refused-clear queue moves and real store notifications at %i entries', - (size) => { - vi.stubGlobal('window', undefined) - createStoreSessionMockApi() - const store = createTestStore() - bridge.getState.mockImplementation(store.getState) - bridge.setState.mockImplementation(store.setState) - const refused: RefusedPaneResume = { - agent: 'codex', - providerSession: { key: 'session_id', id: 'conversation' }, - expectedStatus: { paneKey: 'tab:leaf', receivedAt: 10, stateStartedAt: 1 }, - expectedSavedRecord: { paneKey: 'tab:leaf', capturedAt: 1, updatedAt: 1 } - } - const event = (index: number): AgentStatusIpcPayload => ({ - paneKey: index % 2 ? `other-${index}` : 'tab:leaf', - connectionId: null, - agentType: 'codex', - providerSession: refused.providerSession, - state: 'done', - prompt: '', - receivedAt: 10, - stateStartedAt: 1 - }) - let reads = 0 - let writes = 0 - const countQueue = (entries: T[]): T[] => { - entries.forEach((entry, index) => - Object.defineProperty(entries, index, { - configurable: true, - enumerable: true, - get: () => { - reads += 1 - return entry - }, - set: (next: T) => { - writes += 1 - entry = next - } - }) - ) - return entries - } - let copied = 0 - const countMap = (entries: T): T => - new Proxy(entries, { - ownKeys(target) { - const keys = Reflect.ownKeys(target) - copied += keys.length - return keys - } - }) - store.setState({ - agentStatusByPaneKey: countMap( - Object.fromEntries( - Array.from({ length: size }, (_, index) => { - const row = event(index) - return [ - index === 0 ? 'tab:leaf' : `other-${index}`, - { ...row, updatedAt: 10, stateHistory: [] } - ] - }) - ) - ), - sleepingAgentSessionsByPaneKey: countMap( - Object.fromEntries( - Array.from({ length: size }, (_, index) => [ - index === 0 ? 'tab:leaf' : `other-${index}`, - { - paneKey: index === 0 ? 'tab:leaf' : `other-${index}`, - worktreeId: 'wt', - agent: 'codex', - providerSession: refused.providerSession, - prompt: '', - state: 'done' as const, - capturedAt: 1, - updatedAt: 1 - } - ]) - ) - ) - }) - const accepted = vi.fn() - const disposeAccepted = store.getState().subscribeAgentStatusChanges(accepted) - const previous = store.getState().agentStatusByPaneKey['tab:leaf'] - const notifications = vi.fn() - const unsubscribe = store.subscribe(notifications) - const pending = countQueue( - Array.from({ length: size }, (_, index) => ({ - data: event(index), - firstSeenAt: 0, - replay: false - })) - ) - const burst = countQueue(Array.from({ length: size }, (_, index) => event(index))) - // Newer same-conversation work must survive the old refusal too. - burst[size - 1] = { ...event(0), receivedAt: 11 } - const onClear = vi.fn>(() => () => {}) - vi.stubGlobal('window', { - ...window, - api: { - ...window.api, - agentStatus: { - onSet: vi.fn(() => () => {}), - onClear - } - } - }) - const unsubs: (() => void)[] = [] - registerAgentStatusListeners({ - unsubs, - pendingAgentStatusEvents: pending, - liveAgentStatusBurstQueue: burst, - transientClearWatermarkByConnectionId: new Map(), - enqueueLiveAgentStatus: vi.fn(), - drainQueuedLiveAgentStatusesForPane: vi.fn() - }) - const clear = onClear.mock.calls[0]![0] - reads = 0 - writes = 0 - copied = 0 - try { - clear({ paneKey: 'tab:leaf', refusedResume: refused }) - expect(accepted).toHaveBeenCalledExactlyOnceWith([ - { paneKey: 'tab:leaf', previous, current: undefined } - ]) - const removed = size / 2 - // Reverse splice shifts 1+…+m surviving entries in EACH queue, besides one predicate read per row. - expect([reads, writes]).toEqual([3 * size + removed * (removed + 1), removed * (removed + 1)]) - expect(copied).toBe(2 * size) - expect(notifications).toHaveBeenCalledTimes(2) - expect([pending.length, burst.length]).toEqual([removed, removed]) - expect(burst.at(-1)?.receivedAt).toBe(11) - expect(store.getState().agentStatusByPaneKey['tab:leaf']).toBeUndefined() - expect(Object.keys(store.getState().sleepingAgentSessionsByPaneKey)).toHaveLength(size - 1) - notifications.mockClear() - copied = 0 - clear({ paneKey: 'tab:leaf', refusedResume: refused }) - expect(notifications).not.toHaveBeenCalled() - expect(copied).toBe(0) - } finally { - unsubs.forEach((dispose) => dispose()) - disposeAccepted() - unsubscribe() - onClear.mockRestore() - } - } -) diff --git a/src/renderer/src/hooks/ipc-events/agent-status-terminal-title-tab-write.test.ts b/src/renderer/src/hooks/ipc-events/agent-status-terminal-title-tab-write.test.ts index 0e769af5f14..33004fbf0ca 100644 --- a/src/renderer/src/hooks/ipc-events/agent-status-terminal-title-tab-write.test.ts +++ b/src/renderer/src/hooks/ipc-events/agent-status-terminal-title-tab-write.test.ts @@ -1,13 +1,11 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import type { useAppStore } from '@/store' import { createTestStore } from '@/store/slices/store-test-helpers' -import { resolveAgentStatusTerminalTitle } from '@/lib/agent-status-terminal-title' import type { AgentStatusIpcPayload } from '../../../../shared/agent-status-types' import { makePaneKey } from '../../../../shared/stable-pane-id' import type { TerminalTab } from '../../../../shared/terminal-tab-types' import { buildWindowApi } from '../ipc-events-agent-status-window-test-fixtures' import type { AgentStatusSetData } from '../ipc-events-agent-status-store-test-fixtures' -import { resolvePaneKey, shouldApplyResolvedAgentTerminalTitleToTab } from './agent-status-routing' vi.mock('../agent-hook-completion-notifications', () => ({ observeAgentHookCompletionForNotification: vi.fn(), @@ -50,53 +48,6 @@ function storeWithDivergedTitleSlots(args: { } as unknown as ReturnType } -describe('hook-driven tab title writes', () => { - it('exposes the tab record title separately from the pane slot title', () => { - const store = storeWithDivergedTitleSlots({ - tabTitle: 'Codex - action required', - paneSlotTitle: 'Codex ready' - }) - - const resolved = resolvePaneKey(store, PANE_KEY) - - expect(resolved.title).toBe('Codex ready') - expect(resolved.tabTitle).toBe('Codex - action required') - }) - - // Unmounted panes kept old titles, causing the former pane-slot guard to skip clearing Orca’s stale action-required tab title. - it('rewrites a stale action-required tab title once the agent reports done', () => { - const store = storeWithDivergedTitleSlots({ - tabTitle: 'Codex - action required', - paneSlotTitle: 'Codex ready' - }) - const resolved = resolvePaneKey(store, PANE_KEY) - const nextTitle = resolveAgentStatusTerminalTitle( - { agentType: 'codex', state: 'done' }, - resolved.title - ) - - expect(nextTitle).toBe('Codex ready') - expect( - shouldApplyResolvedAgentTerminalTitleToTab(store, PANE_KEY, resolved.title, nextTitle) - ).toBe(false) - expect( - shouldApplyResolvedAgentTerminalTitleToTab(store, PANE_KEY, resolved.tabTitle, nextTitle) - ).toBe(true) - }) - - it('still skips the write when the tab record already holds the resolved title', () => { - const store = storeWithDivergedTitleSlots({ - tabTitle: 'Codex ready', - paneSlotTitle: 'Codex ready' - }) - const resolved = resolvePaneKey(store, PANE_KEY) - - expect( - shouldApplyResolvedAgentTerminalTitleToTab(store, PANE_KEY, resolved.tabTitle, 'Codex ready') - ).toBe(false) - }) -}) - describe('hook-driven tab title IPC integration', () => { afterEach(() => { vi.doUnmock('../../store') diff --git a/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.fallback.test.ts b/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.fallback.test.ts index 222f0d2be0b..6b06ae23e27 100644 --- a/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.fallback.test.ts +++ b/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.fallback.test.ts @@ -15,10 +15,8 @@ const mocks = vi.hoisted(() => { return { ...listeners, getState: vi.fn(), - subscribe: vi.fn(), replyTabCreate: vi.fn(), - createBrowserTab: vi.fn(), - browserTabRequestsReady: vi.fn() + createBrowserTab: vi.fn() } }) @@ -26,16 +24,13 @@ vi.mock('@/components/browser-pane/host-guest/webview-registry', () => ({ destroyPersistentWebview: vi.fn() })) vi.mock('../../store', () => ({ - useAppStore: { getState: mocks.getState, subscribe: mocks.subscribe } + useAppStore: { getState: mocks.getState } })) vi.mock('./browser-automation-bootstrap-lease', () => ({ acquireBrowserAutomationBootstrapLease: vi.fn() })) -import { - registerBrowserRequestIpcBridge, - signalBrowserTabRequestsReadyAfterRestore -} from './browser-request-ipc-bridge' +import { registerBrowserRequestIpcBridge } from './browser-request-ipc-bridge' const ACTIVE_WT = 'repo-local::/Users/me/app' const RECENT_WT = 'repo-local::/Users/me/app-2' @@ -89,7 +84,6 @@ describe('an extension tab with no active workspace', () => { return () => {} }, replyTabCreate: mocks.replyTabCreate, - browserTabRequestsReady: mocks.browserTabRequestsReady, onRequestRemoteCliBrowserScope: () => () => {}, onRequestTabSetProfile: () => () => {}, onRequestTabClose: () => () => {} @@ -100,24 +94,6 @@ describe('an extension tab with no active workspace', () => { registerBrowserRequestIpcBridge([]) }) - it('tells main it can take tab requests once workspaces are restored', () => { - signalBrowserTabRequestsReadyAfterRestore([]) - expect(mocks.browserTabRequestsReady).toHaveBeenCalledTimes(1) - vi.clearAllMocks() - const listeners: ((state: { workspaceSessionReady: boolean }) => void)[] = [] - mocks.subscribe.mockImplementation( - (listener: (state: { workspaceSessionReady: boolean }) => void) => { - listeners.push(listener) - return () => {} - } - ) - mocks.getState.mockReturnValue({ ...storeState(null), workspaceSessionReady: false }) - signalBrowserTabRequestsReadyAfterRestore([]) - expect(mocks.browserTabRequestsReady).not.toHaveBeenCalled() - listeners.forEach((listener) => listener({ workspaceSessionReady: true })) - expect(mocks.browserTabRequestsReady).toHaveBeenCalledTimes(1) - }) - it("opens in the workspace the profile's tabs were last used in", () => { mocks.getState.mockReturnValue(storeState(null)) mocks.createListener?.({ diff --git a/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.owner.test.ts b/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.owner.test.ts index e3bbae2941f..81afb73345c 100644 --- a/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.owner.test.ts +++ b/src/renderer/src/hooks/ipc-events/browser-request-ipc-bridge.owner.test.ts @@ -231,17 +231,4 @@ describe('a managed SSH host reaches only its own workspaces on this desktop (#2 { requestId: 'p4', workspaceId: null } ]) }) - - it('answers no when the store cannot resolve the owner', () => { - mocks.getState.mockImplementation(() => { - throw new Error('store unavailable') - }) - - mocks.scopeListener?.({ requestId: 's5', environmentId: 'env-remote', workspaceId: REMOTE_WT }) - - expect(mocks.replyRemoteCliBrowserScope).toHaveBeenCalledWith({ - requestId: 's5', - workspaceId: null - }) - }) }) diff --git a/src/renderer/src/hooks/ipc-events/browser-state-open-link-profile.test.ts b/src/renderer/src/hooks/ipc-events/browser-state-open-link-profile.test.ts index 011202889fc..97726f98aab 100644 --- a/src/renderer/src/hooks/ipc-events/browser-state-open-link-profile.test.ts +++ b/src/renderer/src/hooks/ipc-events/browser-state-open-link-profile.test.ts @@ -105,43 +105,6 @@ describe('link-opened Orca tabs', () => { ) }) - // Baseline defect: remove .fails when the captured-claim handoff rejects this event. - it.fails('rejects a missing source tab without default-profile fallback', () => { - storeState.value = { - browserPagesByWorkspace: { - 'workspace-1': [{ id: 'page-1', workspaceId: 'missing', worktreeId: 'worktree-1' }] - }, - browserTabsByWorktree: {}, - createBrowserTab: createBrowserTabMock - } - - captureOpenLinkHandler()({ browserPageId: 'page-1', url: 'https://docs.example.com/guide' }) - - expect(createBrowserTabMock).not.toHaveBeenCalled() - }) - - it('creates modifier-click links in the background', () => { - storeState.value = { - browserPagesByWorkspace: { - 'workspace-1': [{ id: 'page-1', workspaceId: 'workspace-1', worktreeId: 'worktree-1' }] - }, - browserTabsByWorktree: {}, - createBrowserTab: createBrowserTabMock - } - - captureOpenLinkHandler()({ - browserPageId: 'page-1', - url: 'https://docs.example.com/background', - activate: false - }) - - expect(createBrowserTabMock).toHaveBeenCalledWith( - 'worktree-1', - 'https://docs.example.com/background', - expect.objectContaining({ activate: false }) - ) - }) - // Move focus to the opened tab or Cmd/Ctrl+W closes its opener (#18832). it('moves keyboard focus into a foreground link tab but not a background one', () => { storeState.value = { diff --git a/src/renderer/src/hooks/ipc-events/direct-ssh-connect-reply-routing.test.ts b/src/renderer/src/hooks/ipc-events/direct-ssh-connect-reply-routing.test.ts index 5027ccbe87a..cef5f3c6152 100644 --- a/src/renderer/src/hooks/ipc-events/direct-ssh-connect-reply-routing.test.ts +++ b/src/renderer/src/hooks/ipc-events/direct-ssh-connect-reply-routing.test.ts @@ -5,7 +5,6 @@ import type { SshConnectionState, SshProviderEpoch } from '../../../../shared/ssh-types' -import { makeTab, makeWorktree } from '@/store/slices/store-test-helpers' import { registerDirectSshStateIpcBridge } from './direct-ssh-state-ipc-bridge' function connectedState( @@ -40,46 +39,6 @@ async function settle(): Promise { const originalStore = useAppStore.getState() const cleanups: (() => void)[] = [] -const WORKTREE_ID = 'repo-ssh::/work/demo' -const TAB_ID = 'tab-ssh' -const PTY_ID = 'ssh:target-a@@pty-1' - -function seedSshTab(): void { - useAppStore.setState({ - repos: [ - { - id: 'repo-ssh', - path: '/work/demo', - displayName: 'demo', - badgeColor: '#000', - addedAt: 1, - connectionId: 'target-a', - executionHostId: 'ssh:target-a' - } - ], - worktreesByRepo: { - 'repo-ssh': [ - makeWorktree({ - id: WORKTREE_ID, - repoId: 'repo-ssh', - path: '/work/demo', - hostId: 'ssh:target-a' - }) - ] - }, - tabsByWorktree: { - [WORKTREE_ID]: [makeTab({ id: TAB_ID, worktreeId: WORKTREE_ID, ptyId: PTY_ID })] - }, - ptyIdsByTabId: { [TAB_ID]: [PTY_ID] } - }) -} - -function expectSshTabBound(): void { - const state = useAppStore.getState() - expect(state.tabsByWorktree[WORKTREE_ID][0].ptyId).toBe(PTY_ID) - expect(state.ptyIdsByTabId[TAB_ID]).toEqual([PTY_ID]) -} - async function createHarness( initialStates: readonly SshConnectionState[] = [], reconciledStates: readonly SshConnectionState[] = [] @@ -159,42 +118,6 @@ afterEach(async () => { }) describe('direct SSH connected-state routing', () => { - it.each(['reply-first', 'push-first'] as const)( - 'keeps the target bindings on connected pushes when ordering is %s', - async (ordering) => { - seedSshTab() - const harness = await createHarness() - const state = connectedState() - if (ordering === 'reply-first') { - harness.applyConnectReply(state) - } - harness.emit(state) - if (ordering === 'push-first') { - harness.applyConnectReply(state) - } - await settle() - harness.emit({ ...state }) - - expectSshTabBound() - } - ) - - it.each(['disconnected', 'error'] as const)( - 'keeps bindings on %s and on the next connected push', - async (status) => { - seedSshTab() - const state = connectedState() - const harness = await createHarness([state]) - harness.emit({ ...state, status }) - // Loss of contact is not evidence the remote PTY exited. - expectSshTabBound() - - harness.applyConnectReply(state) - harness.emit(state) - expectSshTabBound() - } - ) - it.each(['providerEpoch', 'connectionGeneration'] as const)( 'reconciles a partial %s on initial hydration', async (missingField) => { diff --git a/src/renderer/src/hooks/ipc-events/floating-workspace-reveal-routing.test.ts b/src/renderer/src/hooks/ipc-events/floating-workspace-reveal-routing.test.ts index eadab771476..09f10c8e4b6 100644 --- a/src/renderer/src/hooks/ipc-events/floating-workspace-reveal-routing.test.ts +++ b/src/renderer/src/hooks/ipc-events/floating-workspace-reveal-routing.test.ts @@ -51,7 +51,6 @@ vi.mock('@/lib/focus-terminal-tab-surface', () => ({ import { registerTerminalUiRoutingIpcBridge } from './terminal-ui-routing-ipc-bridge' import { registerTerminalPresentationIpcBridge } from './terminal-presentation-ipc-bridge' -import { registerTerminalRequestIpcBridge } from './terminal-request-ipc-bridge' import { registerMobileAndTerminalCloseIpcBridge } from './mobile-terminal-close-ipc-bridge' const MAIN = 'repo1::/repo1/main' @@ -101,7 +100,6 @@ function setup(): { const unsubs: (() => void)[] = [] registerTerminalUiRoutingIpcBridge(unsubs) registerTerminalPresentationIpcBridge(unsubs) - registerTerminalRequestIpcBridge(unsubs) registerMobileAndTerminalCloseIpcBridge(unsubs, vi.fn()) dispatchEvent.mockClear() return { @@ -173,21 +171,6 @@ describe('taking the user to a floating workspace terminal', () => { expect(testStore().getState().activeTabIdByWorktree[FLOATING]).toBe(tabs.at(-1)?.id) }) - it('a background create into the floating workspace does not open the panel', () => { - const { emit, dispatchEvent } = setup() - const before = mainWindow() - - emit('onCreateTerminal', { worktreeId: FLOATING, presentation: 'background' }) - emit('onRequestTerminalCreate', { - requestId: 'req-2', - worktreeId: FLOATING, - presentation: 'background' - }) - - expect(mainWindow()).toEqual(before) - expect(panelToggles(dispatchEvent)).toBe(0) - }) - it('focusing a floating editor tab opens the panel on it', async () => { const { emit, dispatchEvent } = setup() const main = await drawTabsFromMain(testStore()) diff --git a/src/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.test.ts b/src/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.test.ts index c53ddbd5060..0c225cd54b5 100644 --- a/src/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.test.ts +++ b/src/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.test.ts @@ -393,19 +393,6 @@ describe('runtime file opens on the host desktop', () => { ).toBe(true) }) - it.each(['caller', 'clients'] as const)( - 'keeps the desktop still when navigation %s does not target the host', - async (navigation) => { - const { openFile, store } = await setup('terminal') - const before = screenState(store) - - await openFile({ worktreeId: VIEWED, ...VIEWED_APP_TS, navigation }) - await openFile({ worktreeId: BACKGROUND, ...APP_TS, navigation }) - - expect(screenState(store)).toEqual(before) - } - ) - it.each(['all', 'host'] as const)( 'brings the user to the file with navigation %s', async (navigation) => { diff --git a/src/renderer/src/hooks/ipc-events/orca-profile-auth-ipc-bridge.test.ts b/src/renderer/src/hooks/ipc-events/orca-profile-auth-ipc-bridge.test.ts index 5dc7258cd38..7333fc368be 100644 --- a/src/renderer/src/hooks/ipc-events/orca-profile-auth-ipc-bridge.test.ts +++ b/src/renderer/src/hooks/ipc-events/orca-profile-auth-ipc-bridge.test.ts @@ -79,15 +79,6 @@ describe('orca profile auth IPC bridge', () => { unsubs.forEach((dispose) => dispose()) expect(unsubscribe).toHaveBeenCalledTimes(1) }) - - it('skips registration when the preload bridge does not expose the event', () => { - vi.stubGlobal('window', { api: { orcaProfiles: { authStatus } } }) - const unsubs: (() => void)[] = [] - - registerOrcaProfileAuthIpcBridge(unsubs) - - expect(unsubs).toHaveLength(0) - }) }) describe('orca profile sign-in progress IPC bridge', () => { diff --git a/src/renderer/src/hooks/ipc-events/os-markdown-file-open-bridge.test.ts b/src/renderer/src/hooks/ipc-events/os-markdown-file-open-bridge.test.ts index 3223d077789..6168ba0b8d5 100644 --- a/src/renderer/src/hooks/ipc-events/os-markdown-file-open-bridge.test.ts +++ b/src/renderer/src/hooks/ipc-events/os-markdown-file-open-bridge.test.ts @@ -313,16 +313,4 @@ describe('registerOsMarkdownFileOpenBridge', () => { expect(mocks.toastError).not.toHaveBeenCalled() expect(unhandledRejections).toEqual([]) }) - - it('tolerates a preload without the markdown open channel', async () => { - stubPreload({}) - - const unsubs: (() => void)[] = [] - expect(() => registerOsMarkdownFileOpenBridge(unsubs)).not.toThrow() - await settle() - - expect(unsubs).toEqual([]) - expect(mocks.openFile).not.toHaveBeenCalled() - expect(mocks.toastError).not.toHaveBeenCalled() - }) }) diff --git a/src/renderer/src/hooks/ipc-events/ssh-managed-server-converted-catalogs.test.ts b/src/renderer/src/hooks/ipc-events/ssh-managed-server-converted-catalogs.test.ts index ab98b548bb4..600b2f43a63 100644 --- a/src/renderer/src/hooks/ipc-events/ssh-managed-server-converted-catalogs.test.ts +++ b/src/renderer/src/hooks/ipc-events/ssh-managed-server-converted-catalogs.test.ts @@ -125,24 +125,6 @@ describe('a host that just moved to its managed server', () => { ).toBeNull() }) - it('shows the server copies only, under the server name', async () => { - applySshManagedServerTransition('ssh-1', undefined, { - kind: 'managed', - environmentId: 'env-1' - }) - - await vi.waitFor(() => - expect(store.getState().repos.map((entry) => entry.executionHostId)).toEqual([ - 'runtime:env-1' - ]) - ) - const state = store.getState() - expect(state.worktreesByRepo['repo-1']).toEqual([]) - expect(state.runtimeEnvironments.map((entry) => entry.name)).toEqual(['Box server']) - expect(state.projectGroups.map((entry) => entry.executionHostId)).toEqual(['runtime:env-1']) - expect(state.folderWorkspaces.map((entry) => entry.executionHostId)).toEqual(['runtime:env-1']) - }) - it('carries the host’s visit recency to the server instead of leaving it for the next prune', async () => { store.setState({ lastVisitedAtByWorktreeId: { [`ssh:ssh-1|${worktreeId}`]: 500, [`local|${worktreeId}`]: 7 } diff --git a/src/renderer/src/hooks/ipc-events/ssh-managed-server-state-effects.test.ts b/src/renderer/src/hooks/ipc-events/ssh-managed-server-state-effects.test.ts index 4afe3842539..40b3d012224 100644 --- a/src/renderer/src/hooks/ipc-events/ssh-managed-server-state-effects.test.ts +++ b/src/renderer/src/hooks/ipc-events/ssh-managed-server-state-effects.test.ts @@ -39,11 +39,9 @@ const offer: Status = { reason: 'relay_terminals_live', terminals: 3 } -const moveToManagedServer = vi.fn() beforeEach(() => { vi.clearAllMocks() - Object.assign(window, { api: { ssh: { moveToManagedServer } } }) }) afterEach(() => { Reflect.deleteProperty(window, 'api') @@ -88,21 +86,3 @@ describe('a host kept connected for the relay bridge', () => { expect(listPanes).not.toHaveBeenCalled() }) }) - -describe('a host the managed server does not serve', () => { - it('shows only for a newly marked offer, never for a plain live-terminals status', () => { - applySshManagedServerTransition('ssh-1', offer, offer) - applySshManagedServerTransition('ssh-1', undefined, { - kind: 'relay', - reason: 'relay_terminals_live', - terminals: 3 - }) - expect(mocks.toast).not.toHaveBeenCalled() - }) - - it('stays silent where the move is not available', () => { - Object.assign(window, { api: { ssh: {} } }) - applySshManagedServerTransition('ssh-1', undefined, offer) - expect(mocks.toast).not.toHaveBeenCalled() - }) -}) diff --git a/src/renderer/src/hooks/ipc-events/terminal-pane-reveal-ipc-bridge.test.ts b/src/renderer/src/hooks/ipc-events/terminal-pane-reveal-ipc-bridge.test.ts index 050df7f2154..947b9b1874e 100644 --- a/src/renderer/src/hooks/ipc-events/terminal-pane-reveal-ipc-bridge.test.ts +++ b/src/renderer/src/hooks/ipc-events/terminal-pane-reveal-ipc-bridge.test.ts @@ -74,17 +74,6 @@ describe('registerTerminalPaneRevealIpcBridge', () => { expect(cleanup).toHaveBeenCalledOnce() }) - it('finds the owning server from the workspace when the caller names no host', () => { - const { deliver } = installBridge() - mocks.ownerEnvironmentIdForWorkspace.mockReturnValue('env-1') - - deliver({ ...request, executionHostId: null }) - - expect(mocks.revealTerminalPane).toHaveBeenCalledWith( - expect.objectContaining({ tabId: toWebTerminalSurfaceTabId('host-tab-1') }) - ) - }) - it.each<[string, Partial]>([ ['a local workspace', { executionHostId: null }], ['an SSH workspace this app runs', { executionHostId: 'ssh:box' }], diff --git a/src/renderer/src/hooks/ipc-events/terminal-pane-title-ipc-bridge.test.ts b/src/renderer/src/hooks/ipc-events/terminal-pane-title-ipc-bridge.test.ts index dd29efb4e9a..724efb32c09 100644 --- a/src/renderer/src/hooks/ipc-events/terminal-pane-title-ipc-bridge.test.ts +++ b/src/renderer/src/hooks/ipc-events/terminal-pane-title-ipc-bridge.test.ts @@ -76,11 +76,6 @@ describe('a pane title from main', () => { expect(layout()).toEqual({ ...rootless, titlesByLeafId: { [LEAF_ID]: 'REVIEWER' } }) }) - it('drops the field once the last title is cleared', () => { - applyRuntimePaneTitle({ tabId: 'tab-1', leafId: SIBLING_ID, title: '' }) - expect(layout()).not.toHaveProperty('titlesByLeafId') - }) - it('ignores unknown tabs, leaves outside the layout, and non-leaf ids', () => { applyRuntimePaneTitle({ tabId: 'other-tab', leafId: LEAF_ID, title: 'WRONG' }) applyRuntimePaneTitle({ diff --git a/src/renderer/src/hooks/ipc-events/terminal-presentation-pane-title.test.ts b/src/renderer/src/hooks/ipc-events/terminal-presentation-pane-title.test.ts index 2dce478d7f6..5289d2f19b2 100644 --- a/src/renderer/src/hooks/ipc-events/terminal-presentation-pane-title.test.ts +++ b/src/renderer/src/hooks/ipc-events/terminal-presentation-pane-title.test.ts @@ -147,13 +147,6 @@ describe('a revealed terminal’s title, in a layout-owner build', () => { expect(state.terminalLayoutsByTabId[TAB]?.ptyIdsByLeafId).toEqual({ [LEAF]: 'pty-1' }) expect(state.terminalLayoutsByTabId[TAB]?.titlesByLeafId).toBeUndefined() }) - - it('writes no pane title into a tab the window already holds', async () => { - const state = await setup(true) - - expect(state.terminalLayoutsByTabId[TAB]?.ptyIdsByLeafId).toEqual({ [LEAF]: 'pty-1' }) - expect(state.terminalLayoutsByTabId[TAB]?.titlesByLeafId).toBeUndefined() - }) }) describe('a revealed terminal’s title, while the window owns the layout', () => { diff --git a/src/renderer/src/hooks/ipc-events/wsl-host-ipc-bridge.test.ts b/src/renderer/src/hooks/ipc-events/wsl-host-ipc-bridge.test.ts index 6ad34001316..9528e3b89b1 100644 --- a/src/renderer/src/hooks/ipc-events/wsl-host-ipc-bridge.test.ts +++ b/src/renderer/src/hooks/ipc-events/wsl-host-ipc-bridge.test.ts @@ -44,10 +44,6 @@ function storeWith(state: Parameters[1]) { } describe('selectWslHostsWithVisibleWork', () => { - it('is empty when no project or terminal on a WSL host is open', () => { - expect(selectWslHostsWithVisibleWork(storeWith({}).getState())).toEqual([]) - }) - it('names the WSL host of the active workspace, routed by the workspace’s own repo', () => { const store = storeWith({ activeWorktreeId: 'wsl-repo::/home/me/app' }) expect(selectWslHostsWithVisibleWork(store.getState())).toEqual([WSL_ENV]) diff --git a/src/renderer/src/hooks/ipc-tab-switch-owner-selection.test.ts b/src/renderer/src/hooks/ipc-tab-switch-owner-selection.test.ts index 0bb77cd391a..3b86e1944df 100644 --- a/src/renderer/src/hooks/ipc-tab-switch-owner-selection.test.ts +++ b/src/renderer/src/hooks/ipc-tab-switch-owner-selection.test.ts @@ -101,13 +101,6 @@ describe('keyboard tab switches in a server workspace', () => { ) }) - it('stays local for a workspace no server owns', () => { - mocks.ownerEnvironmentId.mockReturnValue(null) - mocks.getState.mockReturnValue(serverWorkspaceStore()) - expect(handleSwitchTabAcrossAllTypes(-1)).toBe(true) - expect(mocks.activateOnOwner).not.toHaveBeenCalled() - }) - it('tells the server about a browser tab it hosts, cancelable by later navigation', () => { mocks.getState.mockReturnValue(serverWorkspaceStore()) mocks.navOrder.mockReturnValue([ @@ -141,14 +134,4 @@ describe('keyboard tab switches in a server workspace', () => { }) ) }) - - it('keeps a switch to a chat this machine hosts local', () => { - mocks.getState.mockReturnValue(serverWorkspaceStore([agentTab('local')])) - mocks.navOrder.mockReturnValue([ - { type: 'agent-session', id: 'session-1', tabId: 'agent-tab' }, - { type: 'terminal', id: 'web-terminal-b', tabId: 'web-terminal-b' } - ]) - expect(handleSwitchTabAcrossAllTypes(-1)).toBe(true) - expect(mocks.runtimeRpc).not.toHaveBeenCalled() - }) }) diff --git a/src/renderer/src/hooks/ipc-tab-switch.test.ts b/src/renderer/src/hooks/ipc-tab-switch.test.ts index 680cd4d6563..3f2c6cf72d1 100644 --- a/src/renderer/src/hooks/ipc-tab-switch.test.ts +++ b/src/renderer/src/hooks/ipc-tab-switch.test.ts @@ -138,16 +138,6 @@ describe('handleSwitchTerminalTab', () => { expect(store.setActiveTabType).not.toHaveBeenCalled() }) - it('returns false when only one terminal tab exists', () => { - const store = makeStore('terminal') - getStateMock.mockReturnValue(store) - getActiveTabNavOrderMock.mockReturnValue([{ type: 'terminal', id: 'term-1' }]) - - expect(handleSwitchTerminalTab(1)).toBe(false) - expect(store.setActiveTab).not.toHaveBeenCalled() - expect(store.setActiveTabType).not.toHaveBeenCalled() - }) - it('jumps to the first terminal when an editor tab is active', () => { const store = makeStore('editor') store.activeFileId = 'editor-2' @@ -420,16 +410,6 @@ describe('handleSwitchTabAcrossAllTypes', () => { expect(store.setActiveTab).toHaveBeenCalledWith('term-1') expect(store.setActiveTabType).toHaveBeenCalledWith('terminal', 'wt-1') }) - - it('returns false when only one tab exists total', () => { - const store = makeStore('terminal') - getStateMock.mockReturnValue(store) - getActiveTabNavOrderMock.mockReturnValue([{ type: 'terminal', id: 'term-1' }]) - - expect(handleSwitchTabAcrossAllTypes(1)).toBe(false) - expect(store.setActiveTab).not.toHaveBeenCalled() - expect(store.setActiveTabType).not.toHaveBeenCalled() - }) }) describe('handleSwitchRecentTab', () => { @@ -462,26 +442,4 @@ describe('handleSwitchRecentTab', () => { expect(store.activateTab).toHaveBeenCalledWith('tab-b') expect(store.setActiveTabType).toHaveBeenCalledWith('browser', 'wt-1') }) - - it('returns false when the MRU stack has no previous visible tab', () => { - const store = makeStore('terminal') - store.groupsByWorktree = { - 'wt-1': [ - { - id: 'group-1', - activeTabId: 'tab-term-1', - tabOrder: ['tab-term-1'], - recentTabIds: ['tab-term-1'] - } - ] - } - getStateMock.mockReturnValue(store) - getActiveTabNavOrderMock.mockReturnValue([ - { type: 'terminal', id: 'term-1', tabId: 'tab-term-1' } - ]) - - expect(handleSwitchRecentTab()).toBe(false) - expect(store.setActiveTab).not.toHaveBeenCalled() - expect(store.setActiveTabType).not.toHaveBeenCalled() - }) })