test: remove 47 low-value cases and 13 suites (#34136)

* test: remove 37 low-value cases and 3 suites

* test: delete ten more renderer wiring and copy suites

* test: drop deleted suite from its contract entry point

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-10-26 17:30:36 -07:00
committed by GitHub
co-authored by OrcaWin
parent acf1a8c6e0
commit 77130982fa
27 changed files with 6 additions and 1251 deletions
-10
View File
@@ -7371,7 +7371,6 @@
"src/renderer/src/components/dashboard-popout/use-agent-dashboard-telemetry.test.ts": 1675,
"src/renderer/src/components/dashboard-popout/useDashboardSnapshot.test.tsx": 432,
"src/renderer/src/components/dashboard/AgentDashboardDrawer.test.tsx": 1745,
"src/renderer/src/components/dashboard/AgentDashboardSettingsMenu.test.tsx": 479,
"src/renderer/src/components/dashboard/DashboardAgentChildDisclosure.test.tsx": 1607,
"src/renderer/src/components/dashboard/DashboardAgentRow.test.tsx": 1601,
"src/renderer/src/components/dashboard/agent-dashboard-open-mode.test.ts": 43,
@@ -8755,7 +8754,6 @@
"src/renderer/src/components/settings/FloatingWorkspacePane.test.tsx": 1311,
"src/renderer/src/components/settings/GeneralPane.section-lifetime.test.tsx": 1192,
"src/renderer/src/components/settings/GeneralPane.test.ts": 1066,
"src/renderer/src/components/settings/GeneralRemoteServerUpdates.test.tsx": 283,
"src/renderer/src/components/settings/GeneralUpdateSettingsSection.test.tsx": 1749,
"src/renderer/src/components/settings/GeneralWorkspaceSettingsSection.test.tsx": 2551,
"src/renderer/src/components/settings/GhosttyImportModal.test.ts": 162,
@@ -8844,7 +8842,6 @@
"src/renderer/src/components/settings/TerminalSettingsPreview.lifecycle.test.tsx": 318,
"src/renderer/src/components/settings/TerminalTccAttributionNotice.test.tsx": 282,
"src/renderer/src/components/settings/TerminalThemeSections.lifecycle.test.ts": 1337,
"src/renderer/src/components/settings/VoiceDictationSettingsSection.test.tsx": 491,
"src/renderer/src/components/settings/VoiceMicrophoneSetting.test.tsx": 577,
"src/renderer/src/components/settings/VoicePane.test.tsx": 770,
"src/renderer/src/components/settings/VoiceSpeechModelSection.test.tsx": 647,
@@ -8898,7 +8895,6 @@
"src/renderer/src/components/settings/repository/execution/RepositoryHostSetupsSection.test.tsx": 1674,
"src/renderer/src/components/settings/repository/execution/RepositoryHostSetupsSection.workspace-window.test.tsx": 1584,
"src/renderer/src/components/settings/repository/execution/RepositoryWorktreeDefaultsSection.test.tsx": 577,
"src/renderer/src/components/settings/repository/execution/repository-description-templates.test.tsx": 592,
"src/renderer/src/components/settings/repository/execution/repository-hook-settings-draft.test.ts": 368,
"src/renderer/src/components/settings/repository/execution/repository-host-setup-options.test.ts": 151,
"src/renderer/src/components/settings/repository/identity/RepositoryForkSyncSection.test.tsx": 530,
@@ -9180,7 +9176,6 @@
"src/renderer/src/components/sidebar/use-workspace-reveal-body-redirect.test.tsx": 142,
"src/renderer/src/components/sidebar/use-workspace-status-drop.test.ts": 158,
"src/renderer/src/components/sidebar/use-worktree-activity-status.test.tsx": 133,
"src/renderer/src/components/sidebar/use-worktree-activity-statuses.test.ts": 123,
"src/renderer/src/components/sidebar/use-worktree-agent-rows-subscriptions.test.tsx": 1600,
"src/renderer/src/components/sidebar/use-worktree-card-secondary-details.store-subscriptions.test.tsx": 1528,
"src/renderer/src/components/sidebar/use-worktree-sleep-state.test.tsx": 285,
@@ -9458,7 +9453,6 @@
"src/renderer/src/components/status-bar/workspace-space-layout.test.ts": 21,
"src/renderer/src/components/status-bar/workspace-space-open-change.test.ts": 123,
"src/renderer/src/components/status-bar/workspace-space-presentation.test.ts": 522,
"src/renderer/src/components/status-bar/workspace-space-treemap.test.tsx": 389,
"src/renderer/src/components/status-bar/workspace-space-visit-activity.test.ts": 86,
"src/renderer/src/components/status-bar/workspace-space-worktree-row.test.tsx": 2100,
"src/renderer/src/components/tab-bar/BrowserTab.test.tsx": 1689,
@@ -9958,7 +9952,6 @@
"src/renderer/src/components/terminal-pane/terminal-copy-shortcut.test.ts": 1636,
"src/renderer/src/components/terminal-pane/terminal-ctrl-enter.test.ts": 115,
"src/renderer/src/components/terminal-pane/terminal-cursor-appearance-precedence.test.ts": 303,
"src/renderer/src/components/terminal-pane/terminal-cursor-inactive-style.test.ts": 388,
"src/renderer/src/components/terminal-pane/terminal-dead-session-reconcile.test.ts": 34,
"src/renderer/src/components/terminal-pane/terminal-delivery-watchdog.test.ts": 140,
"src/renderer/src/components/terminal-pane/terminal-drop-handler.test.ts": 519,
@@ -10185,7 +10178,6 @@
"src/renderer/src/components/terminal-pane/use-mobile-overlay-ticks-desktop-fit.test.tsx": 229,
"src/renderer/src/components/terminal-pane/use-mobile-overlay-ticks.perf.test.tsx": 237,
"src/renderer/src/components/terminal-pane/use-notification-dispatch-hidden-workspace.test.ts": 453,
"src/renderer/src/components/terminal-pane/use-notification-dispatch-verdict.test.ts": 424,
"src/renderer/src/components/terminal-pane/use-notification-dispatch.test.ts": 432,
"src/renderer/src/components/terminal-pane/use-parked-terminal-watcher-synchronization.react185.test.tsx": 298,
"src/renderer/src/components/terminal-pane/use-system-prefers-dark.test.ts": 33,
@@ -10311,7 +10303,6 @@
"src/renderer/src/components/workspace-cleanup/workspace-cleanup-removal-settlement.test.ts": 106,
"src/renderer/src/components/workspace-cleanup/workspace-cleanup-removal-timeout-recovery.test.ts": 1279,
"src/renderer/src/components/workspace-cleanup/workspace-cleanup-sort-header.test.tsx": 598,
"src/renderer/src/components/workspace-emoji/WorkspaceEmojiSuggestionPopover.test.tsx": 332,
"src/renderer/src/components/workspace-emoji/useWorkspaceEmojiShortcodeInput.test.tsx": 236,
"src/renderer/src/components/workspace-space/SpaceWindowStatePublisher.test.tsx": 618,
"src/renderer/src/components/workspace-space/space-window-state.test.ts": 162,
@@ -10529,7 +10520,6 @@
"src/renderer/src/hooks/worktree-head-identity-apply.test.ts": 50,
"src/renderer/src/hooks/zoom-routing.test.ts": 594,
"src/renderer/src/i18n/I18nProvider.test.tsx": 1691,
"src/renderer/src/i18n/catalog-nested-settings.test.ts": 777,
"src/renderer/src/i18n/intl-locale.test.ts": 135,
"src/renderer/src/i18n/language-catalog-timeout.test.tsx": 1932,
"src/renderer/src/i18n/language-detection-reconciliation.test.tsx": 1619,
-73
View File
@@ -1,73 +0,0 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { HandlerContext } from '../dispatch'
import { RuntimeClientError, type RuntimeClient } from '../runtime-client'
import { CONNECTOR_REPLY_UNAVAILABLE } from '../../shared/rpc-contract/connector-params'
import { CONNECTOR_HANDLERS, formatReply } from './connector'
const call = vi.fn()
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the reply handler calls only client.call.
const client = { call } as unknown as RuntimeClient
function context(): HandlerContext {
return { client, cwd: process.cwd(), flags: new Map([['text', 'done']]), json: true, rawArgs: [] }
}
beforeEach(() => {
vi.stubEnv('ORCA_PANE_KEY', 'tab:1')
vi.spyOn(console, 'log').mockImplementation(() => {})
call.mockReset()
})
afterEach(() => {
vi.unstubAllEnvs()
vi.restoreAllMocks()
})
describe('orca connector reply', () => {
it('sends the calling pane and the text, and says where it went', async () => {
call.mockResolvedValue({ result: { status: 'posted', messageId: '1793.1' } })
await CONNECTOR_HANDLERS['connector reply'](context())
expect(call).toHaveBeenCalledWith(
'connector.reply',
{ paneKey: 'tab:1', replyId: expect.any(String), text: 'done' },
{ timeoutMs: 180_000 }
)
expect(formatReply({ status: 'posted' })).toBe('Posted to the thread.')
expect(formatReply({ status: 'queued' })).toBe('Sent; Orca Cloud will post it to the thread.')
})
it('takes the pane from the scrub-safe alias when Claude scrubbed ORCA_PANE_KEY', async () => {
vi.stubEnv('ORCA_PANE_KEY', '')
vi.stubEnv('ORCA_AGENT_PANE', 'tab:2')
call.mockResolvedValue({ result: { status: 'queued' } })
await CONNECTOR_HANDLERS['connector reply'](context())
expect(call.mock.calls[0]?.[1]).toMatchObject({ paneKey: 'tab:2' })
})
it.each([
'not_a_cloud_conversation',
'connector_not_connected',
'connectors_disabled',
'method_not_found'
])('says replies are not available from this host when the host answers %s', async (code) => {
call.mockRejectedValue(new RuntimeClientError(code, code))
await expect(CONNECTOR_HANDLERS['connector reply'](context())).rejects.toMatchObject({
code: 'not_a_cloud_conversation',
message: CONNECTOR_REPLY_UNAVAILABLE
})
})
it('passes a refusal through, and refuses outside an agent pane', async () => {
call.mockRejectedValue(new RuntimeClientError('no_current_turn', 'no_current_turn'))
await expect(CONNECTOR_HANDLERS['connector reply'](context())).rejects.toMatchObject({
code: 'no_current_turn'
})
expect(call).toHaveBeenCalledTimes(1)
vi.stubEnv('ORCA_PANE_KEY', '')
vi.stubEnv('ORCA_AGENT_PANE', '')
await expect(CONNECTOR_HANDLERS['connector reply'](context())).rejects.toMatchObject({
code: 'invalid_argument'
})
})
})
@@ -2,7 +2,7 @@ import { mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { findAppAgentBrowserDriver, stageAppAgentBrowserDriver } from './serve-agent-browser-driver'
import { stageAppAgentBrowserDriver } from './serve-agent-browser-driver'
const roots: string[] = []
afterEach(() => {
@@ -12,23 +12,6 @@ afterEach(() => {
})
describe("finding the app's agent-browser driver (#33846)", () => {
it.each([
['linux', 'x64', 'agent-browser-linux-x64'],
['darwin', 'arm64', 'agent-browser-darwin-arm64'],
['win32', 'x64', 'agent-browser-win32-x64.exe']
] as const)('finds the copy a packaged %s app ships in resources', (platform, arch, name) => {
const resources = mkdtempSync(join(tmpdir(), 'orca-serve-agent-browser-'))
roots.push(resources)
mkdirSync(join(resources, 'app.asar.unpacked'))
writeFileSync(join(resources, name), '')
expect(findAppAgentBrowserDriver(join(resources, 'app.asar.unpacked'), platform, arch)).toBe(
join(resources, name)
)
expect(findAppAgentBrowserDriver(join(resources, 'app.asar.unpacked'), platform, 'ia32')).toBe(
undefined
)
})
// A running daemon locks its image on Windows; lending the installed copy would block app updates.
it('hands Windows orcad a profile copy outside the app install', async () => {
const resources = mkdtempSync(join(tmpdir(), 'orca-serve-agent-browser-'))
@@ -1,71 +0,0 @@
// @vitest-environment happy-dom
import { act, type ReactNode } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, describe, expect, it, vi } from 'vitest'
const updateSettings = vi.fn()
vi.mock('@/store', () => ({
useAppStore: (
selector: (state: {
settings: {
experimentalAgentDashboardMode: 'in-window'
experimentalAgentDashboardShowIdle: boolean
}
updateSettings: typeof updateSettings
}) => unknown
) =>
selector({
settings: {
experimentalAgentDashboardMode: 'in-window',
experimentalAgentDashboardShowIdle: false
},
updateSettings
})
}))
vi.mock('@/components/ui/dropdown-menu', () => ({
DropdownMenu: ({ children }: { children: ReactNode }) => <>{children}</>,
DropdownMenuContent: ({ children }: { children: ReactNode }) => <div>{children}</div>,
DropdownMenuSeparator: () => <hr />,
DropdownMenuTrigger: ({ children }: { children: ReactNode }) => <>{children}</>
}))
vi.mock('@/components/ui/tooltip', () => ({
Tooltip: ({ children }: { children: ReactNode }) => <>{children}</>,
TooltipContent: ({ children }: { children: ReactNode }) => <span>{children}</span>,
TooltipTrigger: ({ children }: { children: ReactNode }) => <>{children}</>
}))
import { AgentDashboardSettingsMenu } from './AgentDashboardSettingsMenu'
let root: Root | null = null
let container: HTMLDivElement | null = null
afterEach(() => {
act(() => root?.unmount())
root = null
container?.remove()
container = null
updateSettings.mockReset()
})
describe('AgentDashboardSettingsMenu', () => {
it('owns the idle-agent visibility setting', () => {
container = document.createElement('div')
document.body.appendChild(container)
root = createRoot(container)
act(() => {
root?.render(<AgentDashboardSettingsMenu onSwitchToPopout={vi.fn()} onOpenChange={vi.fn()} />)
})
const toggle = container.querySelector<HTMLButtonElement>(
'button[role="switch"][aria-label="Show idle agents"]'
)
expect(toggle).not.toBeNull()
act(() => toggle?.click())
expect(updateSettings).toHaveBeenCalledWith({ experimentalAgentDashboardShowIdle: true })
})
})
@@ -1,61 +0,0 @@
// @vitest-environment happy-dom
import { act } from 'react'
import { createRoot } from 'react-dom/client'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { GeneralRemoteServerUpdates } from './GeneralRemoteServerUpdates'
const storeMock = vi.hoisted(() => ({
state: {
settingsSearchQuery: '',
remoteServerUpdates: new Map([
[
'server-a',
{
environmentId: 'server-a',
name: 'Test server A',
phase: 'current'
}
]
]),
remoteServerUpdatesChecking: false,
remoteServerUpdatesRunning: false,
refreshRemoteServerUpdates: vi.fn(),
setRemoteServerUpdateDialogOpen: vi.fn()
}
}))
vi.mock('@/store', () => ({
useAppStore: (selector: (state: typeof storeMock.state) => unknown) => selector(storeMock.state)
}))
describe('GeneralRemoteServerUpdates', () => {
beforeEach(() => {
storeMock.state.refreshRemoteServerUpdates.mockReset()
storeMock.state.setRemoteServerUpdateDialogOpen.mockReset()
})
it('matches the local update check action and forwards modifier options', async () => {
const container = document.createElement('div')
const root = createRoot(container)
await act(async () => root.render(<GeneralRemoteServerUpdates />))
storeMock.state.refreshRemoteServerUpdates.mockClear()
const button = container.querySelector('button')
expect(button?.textContent).toContain('Check for Server Updates')
expect(button?.querySelector('svg.lucide-refresh-cw')).not.toBeNull()
expect(button?.querySelector('svg.lucide-download')).toBeNull()
expect(container.textContent).toContain('1 paired server · 1 up to date')
await act(async () => {
button?.dispatchEvent(new MouseEvent('click', { bubbles: true, shiftKey: true }))
})
expect(storeMock.state.setRemoteServerUpdateDialogOpen).toHaveBeenCalledWith(true)
expect(storeMock.state.refreshRemoteServerUpdates).toHaveBeenCalledWith({
includePrerelease: true,
includePerfPrerelease: false
})
await act(async () => root.unmount())
})
})
@@ -1,56 +0,0 @@
// @vitest-environment happy-dom
import { act } from 'react'
import { createRoot } from 'react-dom/client'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { getDefaultVoiceSettings } from '../../../../shared/constants'
import { i18n } from '@/i18n/i18n'
import { VoiceDictationSettingsSection } from './VoiceDictationSettingsSection'
const { shortcutLabel } = vi.hoisted(() => ({ shortcutLabel: vi.fn() }))
vi.mock('@/hooks/useShortcutLabel', () => ({ useShortcutLabel: shortcutLabel }))
vi.mock('./VoiceMicrophoneSetting', () => ({ VoiceMicrophoneSetting: () => null }))
afterEach(async () => {
await i18n.changeLanguage('en')
})
describe('dictation shortcut explanations', () => {
it.each([
['en', '⌘E'],
['en', 'Ctrl+E'],
['ko', '⌘E'],
['ko', 'Ctrl+E']
])('renders complete %s sentences with the platform shortcut %s', async (language, shortcut) => {
await i18n.changeLanguage(language)
shortcutLabel.mockReturnValue(shortcut)
const container = document.createElement('div')
const root = createRoot(container)
await act(async () => {
root.render(
<VoiceDictationSettingsSection
voiceSettings={getDefaultVoiceSettings()}
permissionPending={false}
onToggleVoiceDictation={vi.fn()}
onUpdateVoiceSettings={vi.fn()}
/>
)
})
try {
const descriptions = Array.from(container.querySelectorAll('p'), (p) => p.textContent)
if (language === 'ko') {
expect(descriptions).toEqual([
`${shortcut} 단축키를 눌러 포커스된 패널에 텍스트를 받아쓰세요.`,
`토글: ${shortcut} 단축키를 한 번 누르면 받아쓰기를 시작하고, 다시 누르면 중지합니다. 길게 누르기: ${shortcut} 단축키를 누르고 있는 동안 받아쓰기합니다.`
])
} else {
expect(descriptions).toEqual([
`Press ${shortcut} to dictate text into any focused pane.`,
`Toggle: press ${shortcut} once to start, again to stop. Hold: dictate while ${shortcut} is held.`
])
}
} finally {
await act(async () => root.unmount())
}
})
})
@@ -1,70 +0,0 @@
// @vitest-environment happy-dom
import { cleanup, render } from '@testing-library/react'
import { afterEach, describe, expect, it } from 'vitest'
import { setRendererUiLanguage } from '@/i18n/i18n'
import { RepositoryIssueCommandSetting } from './RepositoryIssueCommandSetting'
import { RepositoryHookCommandSourceSetting } from './RepositoryHookPolicySettings'
function renderSettings(hasSharedIssueCommand: boolean): ReturnType<typeof render> {
return render(
<>
<RepositoryIssueCommandSetting
issueCommandDraft=""
setIssueCommandDraft={() => {}}
hasSharedIssueCommand={hasSharedIssueCommand}
issueCommandSaveError={null}
commitIssueCommand={async () => {}}
/>
<RepositoryHookCommandSourceSetting
searchQuery=""
selectedPolicy="shared-only"
yamlState="missing"
yamlHooks={null}
copiedTemplate={false}
isAdvancedOpen
onSelectPolicy={() => {}}
onCopyTemplate={() => {}}
onAdvancedOpenChange={() => {}}
/>
</>
)
}
afterEach(async () => {
cleanup()
await setRendererUiLanguage('en')
})
describe('Repository settings complete translation templates', () => {
for (const language of ['en', 'ko'] as const) {
it.each([false, true])(
`preserves tokens and conditional defaults in ${language} (shared=%s)`,
async (shared) => {
await setRendererUiLanguage(language)
const view = renderSettings(shared)
const paragraphs = Array.from(view.container.querySelectorAll('p'))
const issue = paragraphs.find(
(p) => p.querySelector('code')?.textContent === '{{artifact_url}}'
)
expect(issue?.textContent).toContain('{{artifact_url}}')
expect(issue?.textContent).not.toContain('<artifactUrl>')
const defaultHelp = paragraphs.find(
(p) => p.querySelector('code')?.textContent === 'orca.yaml'
)
if (language === 'ko') {
expect(issue?.textContent).toContain('변수를 사용하세요.')
expect(defaultHelp?.textContent?.includes('있는 경우')).toBe(!shared)
} else {
expect(defaultHelp?.textContent?.includes('when one exists')).toBe(!shared)
}
const sourceHelp = paragraphs.find((p) =>
p.textContent?.includes(
language === 'ko' ? '로컬 명령이 모두' : 'and local commands exist'
)
)
expect(sourceHelp?.querySelector('code')?.textContent).toBe('orca.yaml')
}
)
}
})
@@ -1,67 +0,0 @@
import { describe, expect, it, afterEach, vi } from 'vitest'
import { shallow } from 'zustand/shallow'
import { selectWorktreeActivityStatuses } from './use-worktree-activity-statuses'
type StatusState = Parameters<typeof selectWorktreeActivityStatuses>[0]
function makeStatusState(): StatusState {
return {
tabsByWorktree: {},
browserTabsByWorktree: {},
unifiedTabsByWorktree: {},
structuredChatSleptAtByPaneKey: {},
runtimePaneTitlesByTabId: {},
ptyIdsByTabId: {},
terminalLayoutsByTabId: {},
agentStatusEpoch: 0,
agentStatusByPaneKey: {},
migrationUnsupportedByPtyId: {},
retainedAgentsByPaneKey: {},
runtimeAgentOrchestrationByPaneKey: {}
}
}
describe('selectWorktreeActivityStatuses', () => {
it('stays shallow-equal when an unrelated worktree receives activity updates', () => {
const state = makeStatusState()
const unrelatedUpdate: StatusState = {
...state,
agentStatusEpoch: 1,
browserTabsByWorktree: {
other: []
},
runtimePaneTitlesByTabId: {
'other-tab': { 0: 'codex [working]' }
},
ptyIdsByTabId: {
'other-tab': ['other-pty']
}
}
expect(
shallow(
selectWorktreeActivityStatuses(state, ['visible']),
selectWorktreeActivityStatuses(unrelatedUpdate, ['visible'])
)
).toBe(true)
})
})
const { rejectAppStoreAccess } = vi.hoisted(() => ({
rejectAppStoreAccess: vi.fn(() => {
throw new Error('Pure helper tests must not access the app store')
})
}))
vi.mock('@/store', () => ({
useAppStore: Object.assign(rejectAppStoreAccess, {
getState: rejectAppStoreAccess,
getInitialState: rejectAppStoreAccess,
setState: rejectAppStoreAccess,
subscribe: rejectAppStoreAccess
})
}))
afterEach(() => {
expect(rejectAppStoreAccess).not.toHaveBeenCalled()
})
@@ -1,65 +0,0 @@
// @vitest-environment happy-dom
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import { useState } from 'react'
import { afterEach, describe, expect, it } from 'vitest'
import type { WorkspaceSpaceWorktree } from '../../../../shared/workspace-space-types'
import { getWorkspaceSpaceWorktreeIdentity } from './workspace-space-delete-selection'
import { WorkspaceSpaceTreemap } from './workspace-space-treemap'
const worktree: WorkspaceSpaceWorktree = {
worktreeId: 'repo::/workspace',
repoId: 'repo',
executionHostId: 'local',
repoDisplayName: 'repo',
repoPath: '/repo',
displayName: 'workspace',
path: '/workspace',
branch: 'main',
isMainWorktree: false,
isRemote: false,
isSparse: false,
canDelete: true,
lastActivityAt: 0,
status: 'ok',
error: null,
scannedAt: 0,
sizeBytes: 4096,
reclaimableBytes: 4096,
skippedEntryCount: 0,
topLevelItems: [
{ name: 'node_modules', path: '/workspace/node_modules', kind: 'directory', sizeBytes: 3072 }
],
omittedTopLevelItemCount: 0,
omittedTopLevelSizeBytes: 0
}
function TreemapHarness(): React.JSX.Element {
const [selectedWorktreeId, setSelectedWorktreeId] = useState<string | null>(null)
const [zoomId, setZoomId] = useState<string | null>(null)
return (
<WorkspaceSpaceTreemap
rows={[worktree]}
isScanning={false}
selectedWorktreeId={selectedWorktreeId}
zoomedWorktree={zoomId === getWorkspaceSpaceWorktreeIdentity(worktree) ? worktree : null}
onSelect={setSelectedWorktreeId}
onZoomChange={setZoomId}
/>
)
}
afterEach(cleanup)
describe('WorkspaceSpaceTreemap', () => {
it('opens a workspace from its tile and returns to the overview', () => {
render(<TreemapHarness />)
fireEvent.click(screen.getByRole('button', { name: /workspace, 4/ }))
expect(screen.getByText('Folder sizes')).toBeTruthy()
expect(screen.getByText('node_modules')).toBeTruthy()
fireEvent.click(screen.getByRole('button', { name: 'All' }))
expect(screen.getByText('Click a workspace to zoom')).toBeTruthy()
})
})
@@ -1,45 +0,0 @@
import { describe, expect, it, vi } from 'vitest'
import type { PaneManager, ManagedPane } from '@/lib/pane-manager/pane-manager'
import { getDefaultSettings } from '../../../../shared/constants'
import { applyTerminalAppearance } from './terminal-appearance'
describe('terminal inactive cursor style', () => {
it('keeps blurred non-block cursors from rendering as an outline box', () => {
const options = {
cursorStyle: 'block' as const,
cursorInactiveStyle: 'outline' as const
}
const terminal = {
options,
cols: 80,
rows: 24
} as unknown as ManagedPane['terminal']
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: this fixture supplies the pane members used by appearance logic.
const pane = { id: 1, terminal } as ManagedPane
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: this fixture supplies the manager members used by appearance logic.
const manager = {
getPanes: () => [pane],
setPaneLigaturesEnabled: vi.fn(),
setPaneInlineImagesEnabled: vi.fn(),
setPaneStyleOptions: vi.fn()
} as unknown as PaneManager
const settings = {
...getDefaultSettings('/tmp'),
terminalCursorStyle: 'bar' as const
}
applyTerminalAppearance(
manager,
settings,
false,
new Map(),
new Map(),
'false',
new Map(),
new Map()
)
expect(options.cursorStyle).toBe('bar')
expect(options.cursorInactiveStyle).toBe('bar')
})
})
@@ -1,52 +0,0 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { dispatchTerminalNotification } from './use-notification-dispatch'
import {
PANE_KEY,
getLastNotificationDispatchArg,
makeAgentStatus,
resetNotificationDispatchMockState,
type NotificationDispatchMockState
} from './notification-dispatch-test-harness'
vi.mock('@/store', async () => {
const harness = await import('./notification-dispatch-test-harness')
return harness.createNotificationDispatchStoreModuleMock()
})
vi.mock('@/lib/desktop-notification-sound', async () => {
const harness = await import('./notification-dispatch-test-harness')
return harness.createDesktopNotificationSoundModuleMock()
})
let mockState: NotificationDispatchMockState
// Use the event row’s shared verdict so StopFailure says failed instead of finished.
describe('dispatchTerminalNotification verdict', () => {
beforeEach(() => {
mockState = resetNotificationDispatchMockState()
})
afterEach(() => {
vi.unstubAllGlobals()
})
it.each([
[{ mainAgent: { state: 'done', outcome: 'failure', stateStartedAt: 1 } }, 'failure'],
[{ mainAgent: { state: 'done', outcome: 'cancellation', stateStartedAt: 1 } }, 'cancellation'],
[{ interrupted: true }, 'cancellation'],
[{}, undefined]
] as const)('passes %j as the turn outcome %s', (overrides, outcome) => {
mockState.agentStatusByPaneKey[PANE_KEY] = makeAgentStatus(PANE_KEY, overrides)
dispatchTerminalNotification('wt-primary', {
source: 'agent-task-complete',
terminalTitle: 'codex',
paneKey: PANE_KEY
})
expect(getLastNotificationDispatchArg()).toMatchObject({
agentState: 'done',
agentTurnOutcome: outcome
})
})
})
@@ -1,59 +0,0 @@
// @vitest-environment happy-dom
import { useRef } from 'react'
import { cleanup, render, screen } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { WorkspaceEmojiSuggestionPopover } from './WorkspaceEmojiSuggestionPopover'
import type { WorkspaceEmojiSuggestion } from '@/lib/workspace-emoji-shortcodes'
Element.prototype.scrollIntoView ??= () => {}
const SUGGESTIONS: WorkspaceEmojiSuggestion[] = [
{ shortcode: 'smile', emoji: '😄' },
{ shortcode: 'smiley', emoji: '😃' },
{ shortcode: 'smirk', emoji: '😏' }
]
function PopoverHarness({ commandValue }: { commandValue: string }): React.JSX.Element {
const anchorRef = useRef<HTMLInputElement>(null)
return (
<div>
<input ref={anchorRef} aria-label="Workspace name" readOnly value=":smi" />
<WorkspaceEmojiSuggestionPopover
anchorRef={anchorRef}
commandValue={commandValue}
heading="Emoji"
onCommandValueChange={() => {}}
onOpenChange={() => {}}
onSelect={() => {}}
open
suggestions={SUGGESTIONS}
/>
</div>
)
}
describe('WorkspaceEmojiSuggestionPopover', () => {
let scrollIntoView: ReturnType<typeof vi.spyOn>
beforeEach(() => {
scrollIntoView = vi.spyOn(Element.prototype, 'scrollIntoView').mockImplementation(() => {})
})
afterEach(() => {
scrollIntoView.mockRestore()
cleanup()
})
it('scrolls the externally selected suggestion into view', async () => {
const { rerender } = render(<PopoverHarness commandValue="emoji:smile" />)
await screen.findByText(':smirk:')
scrollIntoView.mockClear()
rerender(<PopoverHarness commandValue="emoji:smirk" />)
const scrolled = scrollIntoView.mock.instances as unknown as Element[]
expect(scrolled.some((node) => node.getAttribute('data-value') === 'emoji:smirk')).toBe(true)
})
})
@@ -1,58 +0,0 @@
import i18next from 'i18next'
import { expect, it } from 'vitest'
import { parsePluginLanguagePackArtifact } from '../../../shared/plugins/plugin-language-pack-artifact'
import en from './locales/en.json'
import es from './locales/es.json'
import fr from './locales/fr.json'
import ja from './locales/ja.json'
import ko from './locales/ko.json'
import pt from './locales/pt.json'
import zh from './locales/zh.json'
const AGENT_SETTINGS_KEYS = [
'environmentName',
'environmentValue',
'savedEnvironment',
'newEnvironment',
'removeEnvironment',
'loadingHost',
'updateHost',
'readFailed',
'saveFailed',
'hostDefaults',
'save'
] as const
it.each([
['en', en],
['es', es],
['fr', fr],
['ja', ja],
['ko', ko],
['pt', pt],
['zh', zh]
] as const)(
'keeps %s agent settings usable as nested language-pack translations',
async (locale, catalog) => {
// Bundled security copy is intentionally unavailable to plugin language packs.
expect(
parsePluginLanguagePackArtifact(JSON.stringify({ settings: catalog.settings }))
).toMatchObject({ ok: true })
const instance = i18next.createInstance()
await instance.init({
lng: locale,
fallbackLng: false,
resources: { [locale]: { translation: catalog } },
ignoreJSONStructure: false
})
for (const key of AGENT_SETTINGS_KEYS) {
expect(instance.t(`settings.agents.${key}`, { name: 'PATH' })).toBe(
catalog.settings.agents[key].replace('{{name}}', 'PATH')
)
}
expect(instance.t('settings.appearance.chat.title')).toBe(
catalog.settings.appearance.chat.title
)
}
)
@@ -1,38 +0,0 @@
import { describe, expect, it } from 'vitest'
import { codexStructuredPermissionPolicy } from './codex-permission-policy'
const FULL_ACCESS = {
approvalPolicy: 'never',
sandbox: 'danger-full-access',
approvalsReviewer: 'user'
}
const ASK = { approvalPolicy: 'on-request', sandbox: 'read-only', approvalsReviewer: 'user' }
describe('codexStructuredPermissionPolicy', () => {
it('maps Full access to no prompts and no sandbox', () => {
expect(codexStructuredPermissionPolicy('full-access')).toEqual(FULL_ACCESS)
})
it('states every Ask field, the human reviewer too', () => {
expect(codexStructuredPermissionPolicy('ask')).toEqual(ASK)
})
it('keeps Approve for me in the configured workspace sandbox', () => {
expect(codexStructuredPermissionPolicy('auto')).toEqual({
approvalPolicy: 'on-request',
sandbox: 'workspace-write',
approvalsReviewer: 'auto_review'
})
})
it('names a sandbox mode for every mode', () => {
for (const mode of ['ask', 'auto', 'full-access'] as const) {
expect(codexStructuredPermissionPolicy(mode)).not.toHaveProperty('sandboxPolicy')
expect(typeof codexStructuredPermissionPolicy(mode).sandbox).toBe('string')
}
})
it('asks for a mode Codex does not have', () => {
expect(codexStructuredPermissionPolicy('accept-edits')).toEqual(ASK)
})
})
-67
View File
@@ -4,17 +4,14 @@ import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import {
__getSecureFileHardeningCacheStateForTests,
__resetSecureFileHardenedPathsForTests,
hardenExistingSecureFile,
isUnreadableError,
writeSecureFile
} from './secure-file'
import {
setWindowsSecurityForTests,
resetWindowsSecurityLoadForTests
} from './windows-security-addon'
import { createFakeWindowsSecurity } from './windows-security-addon.test-fixture'
const chmodFailure = vi.hoisted((): { code: string | null } => ({ code: null }))
@@ -61,18 +58,6 @@ describe('POSIX secure files', () => {
return dir
}
it('never touches the Windows ACL addon off win32', () => {
Object.defineProperty(process, 'platform', { configurable: true, value: 'linux' })
const fake = createFakeWindowsSecurity()
setWindowsSecurityForTests(fake)
const targetPath = join(tempDir(), 'secret.json')
writeSecureFile(targetPath, 'contents')
hardenExistingSecureFile(targetPath)
expect(fake.calls).toEqual([])
})
posixModeIt('restricts the published file and its directory by mode', () => {
Object.defineProperty(process, 'platform', { configurable: true, value: 'linux' })
const userDataPath = tempDir()
@@ -114,60 +99,8 @@ describe('POSIX secure files', () => {
expect(() => hardenExistingSecureFile(targetPath)).toThrow('EIO')
}
)
posixModeIt('LRU-bounds POSIX hardening entries while keeping recent paths cached', () => {
Object.defineProperty(process, 'platform', { configurable: true, value: 'linux' })
__resetSecureFileHardenedPathsForTests({
maxEntries: 2,
maxKeyBytes: 4096,
maxTotalKeyBytes: 8192
})
const userDataPath = tempDir()
const firstPath = join(userDataPath, 'first.json')
const secondPath = join(userDataPath, 'second.json')
writeFileSync(firstPath, '{}')
writeFileSync(secondPath, '{}')
hardenExistingSecureFile(firstPath)
hardenExistingSecureFile(secondPath)
expect(__getSecureFileHardeningCacheStateForTests().paths.paths).toEqual([
userDataPath,
secondPath
])
hardenExistingSecureFile(firstPath)
expect(__getSecureFileHardeningCacheStateForTests().paths.paths).toEqual([
userDataPath,
firstPath
])
})
})
function statMode(path: string): number {
return statSync(path).mode & 0o777
}
describe('isUnreadableError', () => {
const withCode = (code: string): NodeJS.ErrnoException => Object.assign(new Error(code), { code })
it('reports a denied read', () => {
expect(isUnreadableError(withCode('EPERM'))).toBe(true)
expect(isUnreadableError(withCode('EACCES'))).toBe(true)
})
/** AV locks (EBUSY) or fd exhaustion (EMFILE) reveal no contents and must never authorize regenerate-and-overwrite. */
it('reports a read that never reached the contents for any other reason', () => {
expect(isUnreadableError(withCode('EBUSY'))).toBe(true)
expect(isUnreadableError(withCode('EMFILE'))).toBe(true)
expect(isUnreadableError(withCode('ENFILE'))).toBe(true)
expect(isUnreadableError(withCode('EIO'))).toBe(true)
})
/** Missing files permit creation; parsed garbage permits repair. Neither is an unreadable-content failure. */
it('does not report a missing file or a parse failure', () => {
expect(isUnreadableError(withCode('ENOENT'))).toBe(false)
expect(isUnreadableError(new SyntaxError('Unexpected end of JSON input'))).toBe(false)
expect(isUnreadableError(withCode('EISDIR'))).toBe(false)
expect(isUnreadableError(undefined)).toBe(false)
})
})
@@ -5,10 +5,7 @@ import { tmpdir } from 'node:os'
import { afterEach, describe, expect, it } from 'vitest'
import {
createSequencedSetupAgentCommands,
SETUP_AGENT_SEQUENCE_STARTUP_COMMAND_ENV
} from './setup-agent-sequencing'
import { createSequencedSetupAgentCommands } from './setup-agent-sequencing'
import { quotePowerShellLiteral } from './powershell-native-argument'
const TEMP_DIRS: string[] = []
@@ -86,20 +83,6 @@ describe.skipIf(process.platform !== 'win32')('Windows setup-agent sequencing',
WINDOWS_PROCESS_TEST_TIMEOUT_MS
)
it('keeps the startup command out of generated cmd.exe source', () => {
const startupCommand = 'agent --prompt "& | ^ % ! 한글 trailing\\"'
const commands = createSequencedSetupAgentCommands({
runnerScriptPath: 'C:\\repo\\setup-runner.cmd',
startupCommand,
platform: 'windows',
nonce: 'windows-sequence'
})
expect(commands.setupCommand).not.toContain(startupCommand)
expect(commands.startupCommand).not.toContain(startupCommand)
expect(commands.startupEnv?.[SETUP_AGENT_SEQUENCE_STARTUP_COMMAND_ENV]).toBe(startupCommand)
})
it(
'propagates setup failure without launching the agent',
async () => {
@@ -6,7 +6,7 @@ import { indexSidebarFeed } from '../sidebar-list/sidebar-feed-index'
import { composeWorktreeHostIdentity } from '../worktree/host-qualified-identity'
import { WorkspaceRowsSnapshotSchema, type WorkspaceRow } from '../sidebar-list/workspace-rows'
import { SidebarFeedReader, type SidebarFeedReaderRead } from './sidebar-feed-reader'
import { installSidebarFeedSnapshot, type SidebarFeedSnapshot } from './sidebar-feed-snapshot'
import type { SidebarFeedSnapshot } from './sidebar-feed-snapshot'
const WORKSPACES = 1000
@@ -115,10 +115,4 @@ describe('sidebar feed snapshot', () => {
// A domain the change did not touch keeps its map.
expect(after.domains.review).toBe(before.domains.review)
})
it('keeps the snapshot itself when the install is the same', async () => {
const host = await readHost()
const snapshot = host.snapshot()
expect(installSidebarFeedSnapshot(snapshot.installed, snapshot)).toBe(snapshot)
})
})
@@ -1,150 +0,0 @@
import { describe, expect, it } from 'vitest'
import { getDefaultSettings } from './constants'
import type { GlobalSettings } from './global-settings-types'
import type { Repo } from './repo-types'
import type { TuiAgent } from './tui-agent'
import {
resolveSourceControlLaunchAgentScope,
summarizeReposOverridingActionRecipe
} from './source-control-launch-agent-selection'
function settingsWithGlobalResolveAgent(agentId: TuiAgent): GlobalSettings {
const base = getDefaultSettings('/tmp')
return {
...base,
defaultTuiAgent: agentId,
sourceControlAi: {
...base.sourceControlAi!,
enabled: true,
actions: {
...base.sourceControlAi!.actions,
resolveConflicts: { agentId, commandInputTemplate: '{basePrompt}', agentArgs: '' }
}
}
}
}
function repoWithResolveAgent(agentId: TuiAgent): Pick<Repo, 'sourceControlAi'> {
return {
sourceControlAi: {
actionOverrides: {
resolveConflicts: { agentId, commandInputTemplate: '{basePrompt}', agentArgs: '' }
}
}
}
}
describe('resolveSourceControlLaunchAgentScope', () => {
it('flags a repo override that pins a different agent than the global default', () => {
const scope = resolveSourceControlLaunchAgentScope({
settings: settingsWithGlobalResolveAgent('claude'),
repo: repoWithResolveAgent('codex'),
actionId: 'resolveConflicts'
})
expect(scope).toEqual({
effectiveAgentId: 'codex',
globalAgentId: 'claude',
overridesGlobalAgent: true
})
})
it('does not flag a repo override that matches the global agent', () => {
const scope = resolveSourceControlLaunchAgentScope({
settings: settingsWithGlobalResolveAgent('claude'),
repo: repoWithResolveAgent('claude'),
actionId: 'resolveConflicts'
})
expect(scope.overridesGlobalAgent).toBe(false)
})
it('does not flag when there is no repo override', () => {
const scope = resolveSourceControlLaunchAgentScope({
settings: settingsWithGlobalResolveAgent('claude'),
repo: null,
actionId: 'resolveConflicts'
})
expect(scope).toEqual({
effectiveAgentId: 'claude',
globalAgentId: 'claude',
overridesGlobalAgent: false
})
})
it('falls back to the default agent when no global recipe agent is set', () => {
const base = getDefaultSettings('/tmp')
const settings: GlobalSettings = {
...base,
defaultTuiAgent: 'claude',
sourceControlAi: { ...base.sourceControlAi!, enabled: true }
}
const scope = resolveSourceControlLaunchAgentScope({
settings,
repo: repoWithResolveAgent('codex'),
actionId: 'resolveConflicts'
})
expect(scope.globalAgentId).toBe('claude')
expect(scope.overridesGlobalAgent).toBe(true)
})
})
function repoOverriding(
id: string,
displayName: string,
agentId: TuiAgent
): Pick<Repo, 'id' | 'displayName' | 'sourceControlAi'> {
return { id, displayName, ...repoWithResolveAgent(agentId) }
}
describe('summarizeReposOverridingActionRecipe', () => {
it('lists repos with any action recipe override', () => {
const summary = summarizeReposOverridingActionRecipe({
repos: [
repoOverriding('repo-1', 'App', 'claude'),
{
id: 'repo-2',
displayName: 'Web',
sourceControlAi: {
actionOverrides: {
resolveConflicts: {
commandInputTemplate: '{basePrompt}\n\nUse project conflict rules.',
agentArgs: '--model gpt-5.4-mini'
}
}
}
},
{ id: 'repo-3', displayName: 'Docs' }
],
actionId: 'resolveConflicts'
})
expect(summary).toEqual({
count: 2,
overrides: [
{ repoId: 'repo-1', repoName: 'App', fields: ['agent', 'commandTemplate', 'agentArgs'] },
{ repoId: 'repo-2', repoName: 'Web', fields: ['commandTemplate', 'agentArgs'] }
]
})
})
it('includes legacy repo instructions as command template overrides', () => {
const summary = summarizeReposOverridingActionRecipe({
repos: [
{
id: 'repo-1',
displayName: 'App',
sourceControlAi: {
instructionsByOperation: {
commitMessage: 'Use project style.'
}
}
}
],
actionId: 'commitMessage'
})
expect(summary).toEqual({
count: 1,
overrides: [{ repoId: 'repo-1', repoName: 'App', fields: ['commandTemplate'] }]
})
})
})
@@ -1,4 +1,3 @@
import './source-control-launch-agent-selection.spec'
import './omp-source-control-discovery.spec'
import './source-control-ai-policy-regression.spec'
import './commit-message-omp.spec'
@@ -73,22 +73,6 @@ describe('the first frame of every agent’s picker', () => {
}
)
it.each(AGENTS)(
'%s: a warm host catalog lists its models before the session reports',
(agent) => {
const { state, snapshot } = firstFrame(agent, {
...HOST_CATALOG,
listingNamesConfiguredModel: false
})
expect(state.catalogSource).toBe('host')
const model = snapshot.find((descriptor) => descriptor.id === 'model')
expect(
model?.kind.type === 'select' && model.kind.choices.map((choice) => choice.value)
).toEqual(['model-listed'])
expect(state.record.values.model).toBeUndefined()
}
)
it.each(AGENTS)(
'%s: a new chat names the listed model and its effort when the host says it runs them',
(agent) => {
@@ -13,50 +13,6 @@ const oracle = (pending: string, chunk: string): string => {
return tail.length > MAX_PARTIAL_ESCAPE_TAIL_LENGTH ? '' : tail
}
// Every byte class the scanner branches on, plus code units the gate's `includes` must not confuse.
const ALPHABET = [
'\x1b',
'\x18',
'\x1a',
'\x07',
'\x00',
'\\',
'[',
']',
'P',
'X',
'^',
'_',
'(',
' ',
'0',
';',
'm',
'\n',
'\x7f',
'\x9c',
'é',
'中',
'\u{1f600}',
'\ud83d',
'\udc00'
]
// One representative of every state the scanner can be left in.
const PENDINGS = [
'',
'\x1b',
'\x1b[',
'\x1b[3',
'\x1b]0;ti',
'\x1b]0;ti\x1b',
'\x1bP dcs',
'\x1bPx\x1b',
'\x1b(',
'\x1b ',
'\x1b[1;2;3'
]
const SEQUENCES = [
'\x1b[1;31m',
'\x1b]0;my title\x07',
@@ -79,27 +35,7 @@ const SEQUENCES = [
'\x1bX sos \x1b\x1bP'
]
// Count corpus depth separately: astral symbols occupy two UTF-16 units, so text.length would drop valid depth-N strings.
function* stringsUpTo(maxDepth: number): Generator<{ depth: number; text: string }> {
yield { depth: 0, text: '' }
for (let depth = 1; depth <= maxDepth; depth++) {
const digits = Array.from({ length: depth }, () => 0)
for (;;) {
yield { depth, text: digits.map((digit) => ALPHABET[digit]).join('') }
let place = depth - 1
while (place >= 0 && ++digits[place] === ALPHABET.length) {
digits[place--] = 0
}
if (place < 0) {
break
}
}
}
}
describe('advancePartialEscapeTail differential fuzz', () => {
let checked = 0
let foldSplits = 0
// Re-split the whole stream to exercise oscEsc/stringEsc boundaries; pre-normalized tails make the fold assertion tautological.
const checkFolds = (text: string): void => {
if (text.length > 32) {
@@ -107,7 +43,6 @@ describe('advancePartialEscapeTail differential fuzz', () => {
}
const whole = extractPartialEscapeTail(text)
for (let cut = 0; cut <= text.length; cut++) {
foldSplits++
const folded = extractPartialEscapeTail(
extractPartialEscapeTail(text.slice(0, cut)) + text.slice(cut)
)
@@ -117,7 +52,6 @@ describe('advancePartialEscapeTail differential fuzz', () => {
}
}
const check = (pending: string, chunk: string): void => {
checked++
const actual = advancePartialEscapeTail(pending, chunk)
if (actual !== oracle(pending, chunk)) {
expect.fail(`gate diverged: ${JSON.stringify({ pending, chunk, actual })}`)
@@ -132,20 +66,6 @@ describe('advancePartialEscapeTail differential fuzz', () => {
checkFolds(pending + chunk)
}
it('matches the unguarded oracle on every chunk up to length 4', () => {
for (const { text: chunk } of stringsUpTo(3)) {
for (const pending of PENDINGS) {
check(pending, chunk)
}
}
for (const { depth, text: chunk } of stringsUpTo(4)) {
if (depth === 4) {
check('', chunk)
check('\x1b[', chunk)
}
}
})
it('matches at every split point of known sequences', () => {
for (const sequence of SEQUENCES) {
for (let cut = 0; cut <= sequence.length; cut++) {
@@ -161,22 +81,4 @@ describe('advancePartialEscapeTail differential fuzz', () => {
}
}
})
it('matches across the tail-length cap', () => {
const max = MAX_PARTIAL_ESCAPE_TAIL_LENGTH
for (const length of [max - 1, max, max + 1, max + 100]) {
const osc = `\x1b]0;${'x'.repeat(length - 4)}`
for (const chunk of ['', 'y', '\x07', '\x1b\\', '\x1b', 'plain\n', 'x'.repeat(5000)]) {
check(osc, chunk)
check('', osc + chunk)
check('\x1b]0;', osc.slice(4) + chunk)
}
}
})
it('ran the whole corpus', () => {
expect(checked).toBe(963_819)
// Completed strings retain only ESC, so the same corpus has fewer tail splits.
expect(foldSplits).toBe(6_234_666)
})
})
@@ -1,4 +1,4 @@
import { describe, expect, it, vi } from 'vitest'
import { describe, expect, it } from 'vitest'
import {
createRendererParityTerminal,
cursorPosition,
@@ -18,43 +18,6 @@ type AsyncOscParser = {
}
describe('terminal parity fixture writes', () => {
it('queues every original chunk and resolves only after the last callback', async () => {
const { terminal } = createRendererParityTerminal({ cols: 8, rows: 2 })
const writes: { data: string | Uint8Array; callback?: () => void }[] = []
try {
vi.spyOn(terminal, 'write').mockImplementation((data, callback) => {
writes.push({ data, callback })
})
const chunks = ['A\x1b[', '', '31mB', '\x1b[0mC']
let completed = false
const pending = writeChunksToTerminal(terminal, chunks).then(() => {
completed = true
})
expect(writes.map(({ data }) => data)).toEqual(chunks)
expect(writes.slice(0, -1).every(({ callback }) => callback === undefined)).toBe(true)
await Promise.resolve()
expect(completed).toBe(false)
writes.at(-1)?.callback?.()
await pending
expect(completed).toBe(true)
} finally {
terminal.dispose()
vi.restoreAllMocks()
}
})
it('completes an empty batch without writing or scheduling work', async () => {
const { terminal } = createRendererParityTerminal({ cols: 8, rows: 2 })
try {
const write = vi.spyOn(terminal, 'write')
await writeChunksToTerminal(terminal, [])
expect(write).not.toHaveBeenCalled()
} finally {
terminal.dispose()
vi.restoreAllMocks()
}
})
it('waits for an asynchronous parser barrier before exposing later chunks', async () => {
const { terminal } = createRendererParityTerminal({ cols: 8, rows: 2 })
let signalEntered = (): void => {}
@@ -2,7 +2,6 @@ import { describe, expect, it } from 'vitest'
import { isGeminiTerminalTitle } from './agent-title-core'
import { getAgentLabel, isClaudeAgent } from './agent-title-identity'
import { detectAgentStatusFromTitle } from './agent-title-status'
import { TERMINAL_TITLE_CLASSIFICATION_CORPUS } from './terminal-title-classification-corpus'
import {
getAgentLabel as getExplicitAgentLabel,
isClaudeAgent as isExplicitClaudeAgent,
@@ -244,12 +243,6 @@ const PINNED_CLASSIFICATIONS: readonly PinnedRow[] = [
]
describe('terminal title classification', () => {
it('covers every corpus title exactly once', () => {
expect(PINNED_CLASSIFICATIONS.map(([title]) => title)).toEqual([
...TERMINAL_TITLE_CLASSIFICATION_CORPUS
])
})
it.each(PINNED_CLASSIFICATIONS)(
'classifies %j identically',
(
+1 -23
View File
@@ -5,10 +5,7 @@ import {
projectOrchestrationFleet,
type FleetDurableWorker
} from './orchestration-fleet-projection'
import {
parseWorkerTerminalHostScope,
readWorkerTerminalHostScope
} from './worker-terminal-host-scope'
import { readWorkerTerminalHostScope } from './worker-terminal-host-scope'
/** One host_scope read must drive host labels and connection fences; divergent WSL-local parsing previously made live local workers unverifiable. */
const PANE_KEY = 'tab-host:leaf-host'
@@ -174,23 +171,4 @@ describe('worker terminal host scope', () => {
}
})
}
it('keeps the strict scope contract the process-liveness path depends on', () => {
expect(parseWorkerTerminalHostScope('{"kind":"ssh","targetId":"host-1"}')).toEqual({
kind: 'ssh',
targetId: 'host-1'
})
expect(
parseWorkerTerminalHostScope('{"kind":"wsl","hostId":"local","distro":"Ubuntu"}')
).toEqual({ kind: 'wsl', hostId: 'local', distro: 'Ubuntu' })
expect(parseWorkerTerminalHostScope('{"kind":"local","hostId":"local"}')).toEqual({
kind: 'local',
hostId: 'local'
})
// A scope missing the facts its kind requires is not a scope.
expect(parseWorkerTerminalHostScope('{"kind":"wsl","hostId":"local"}')).toBeNull()
expect(parseWorkerTerminalHostScope('{"kind":"ssh"}')).toBeNull()
expect(parseWorkerTerminalHostScope('local:workspace-1')).toBeNull()
expect(parseWorkerTerminalHostScope(null)).toBeNull()
})
})
@@ -5,8 +5,7 @@ import { LOCAL_EXECUTION_HOST_ID } from '../execution-host'
import {
DISK_TABLES,
type DiskFieldWritten,
type LayoutSource,
type UnwrittenLayoutSource
type LayoutSource
} from './workspace-layout-disk-fields'
import { EDITOR_FILE_KEY_FIELDS } from './workspace-layout-editor-tab-file'
import { loadWorkspaceLayout } from './workspace-layout-load'
@@ -18,37 +17,6 @@ import { saveWorkspaceLayout } from './workspace-layout-save'
import { addWorkspace, GIT_KEY, leaf } from './workspace-layout-session.test-fixture'
import type { WorkspaceSessionState } from '../workspace-session-state-types'
// A model or side-data field no disk field is written from fails here.
const everySourceIsWritten: [UnwrittenLayoutSource] extends [never] ? true : UnwrittenLayoutSource =
true
/** On-disk fields that hold one fact; each group must be written from the same source. */
const COPIES = [
['row.ptyId', 'layout.ptyIdsByLeafId'],
['row.id', 'terminalEntry.entityId'],
['row.title', 'terminalEntry.label'],
['row.customTitle', 'terminalEntry.customLabel'],
['row.generatedTitle', 'terminalEntry.generatedLabel'],
...['createdAt', 'color', 'aiVaultTitle', 'quickCommandLabel', 'isPinned', 'viewMode'].map(
(field) => [`row.${field}`, `terminalEntry.${field}`]
),
['row.sortOrder', 'terminalEntry.sortOrder', 'entry.sortOrder', 'group.tabOrder'],
[
'row.worktreeId',
'terminalEntry.worktreeId',
'entry.worktreeId',
'group.worktreeId',
'file.worktreeId',
'browser.worktreeId',
'sleeping.worktreeId',
'closedTab.worktreeId'
],
['sleeping.paneKey', 'sleeping.tabId'],
['terminalEntry.executionHostId', 'entry.executionHostId'],
['entry.isPreview', 'file.isPreview'],
['terminalEntry.groupId', 'entry.groupId', 'group.id']
]
/** Do not mutate identity fields: broken references would test integrity rather than fact ownership. */
const IDENTITY_SOURCES = new Set<LayoutSource>([
'tab.id',
@@ -290,32 +258,6 @@ function diskValues(session: WorkspaceSessionState): Map<string, string> {
const ALL_SOURCES = [...new Set([...WRITTEN_BY_FIELD.values(), TAB_LIST_ORDER].flatMap(sourcesOf))]
describe('each on-disk field has one source', () => {
it('is typed over every disk, model and side-data field', () => {
expect(everySourceIsWritten).toBe(true)
})
it('writes every copy of one fact from the same source', () => {
for (const group of COPIES) {
const sources = group.map((field) => {
const written = writtenOf(field)
return typeof written === 'string' ? written : written.from
})
expect(new Set(sources).size, group.join(' = ')).toBe(1)
}
})
it('has every source populated, so a mutation can show what it writes', () => {
const loaded = richLoaded()
const empty = ALL_SOURCES.filter((source) => {
const [prefix, field] = splitSource(source)
return (
!IDENTITY_SOURCES.has(source) &&
!holdersOf(loaded, prefix).some((holder) => holder[field] != null)
)
})
expect(empty).toEqual([])
})
it('holds each placed pane record in exactly one of its two holders', () => {
const loaded = richLoaded()
const leaves = Object.values(loaded.layout.workspaces).flatMap((workspace) =>
@@ -85,15 +85,6 @@ describe("main's load of a browser record with no tab", () => {
expect(resolveSessionTabRow(workspace, 'browser-1')?.tab.id).toBe(tab.id)
})
it('saves the tab, so the next load mints nothing new', () => {
const saved = saveWorkspaceLayout(load(savedSession()))
expect(
saved.unifiedTabs?.[KEY]?.find((entry) => entry.contentType === 'browser')
).toMatchObject({ entityId: 'browser-1', groupId: 'g2', label: 'Example' })
expect(load(saved).changes).toEqual([])
})
it('mints the same id on every load, and a restart after a save keeps one tab', () => {
const ids = (session: WorkspaceSessionState) =>
load(session)
@@ -415,7 +415,6 @@ const CORPUS: [string, unknown][] = [
describe('salvage equivalence with the pre-optimization implementation', () => {
let legacyParse: LegacyParse
let legacyUnionsBuilt = 0
beforeAll(async () => {
// Build the legacy schema from both legacy salvage combinators and plain unions to cover both optimizations.
@@ -427,7 +426,6 @@ describe('salvage equivalence with the pre-optimization implementation', () => {
z: {
...actual.z,
discriminatedUnion: (_key: string, options: z.ZodType[]) => {
legacyUnionsBuilt += 1
return actual.z.union(options)
}
}
@@ -443,11 +441,6 @@ describe('salvage equivalence with the pre-optimization implementation', () => {
vi.resetModules()
})
it('builds a legacy parser from the legacy combinators and plain unions', () => {
expect(legacyParse).not.toBe(parseWorkspaceSessionSalvaging)
expect(legacyUnionsBuilt).toBeGreaterThanOrEqual(2)
})
it.each(CORPUS)('matches the legacy result for %s', (_name, payload) => {
const legacy = legacyParse(payload)
const current = parseWorkspaceSessionSalvaging(payload)
@@ -461,14 +454,6 @@ describe('salvage equivalence with the pre-optimization implementation', () => {
expect(current.droppedPaths.toSorted()).toEqual(legacy.droppedPaths.toSorted())
})
it('rejects the same payloads the legacy parser rejects', () => {
const rejected = CORPUS.filter(([, payload]) => !legacyParse(payload).ok)
expect(rejected.length).toBeGreaterThan(0)
for (const [, payload] of rejected) {
expect(parseWorkspaceSessionSalvaging(payload).ok).toBe(false)
}
})
it('rejects a record carrying an enumerable symbol key, as zod.record did', () => {
const withSymbol: Record<string, unknown> = { 'tab-1:leaf-1': 'inc-1' }
withSymbol[Symbol('extra') as unknown as string] = 'x'