diff --git a/src/renderer/src/components/diff-comments/diff-comment-drag-auto-scroll.test.ts b/src/renderer/src/components/diff-comments/diff-comment-drag-auto-scroll.test.ts index 777eb9b59f9..101dbaab34e 100644 --- a/src/renderer/src/components/diff-comments/diff-comment-drag-auto-scroll.test.ts +++ b/src/renderer/src/components/diff-comments/diff-comment-drag-auto-scroll.test.ts @@ -9,25 +9,6 @@ function stepAt(clientY: number, frameDeltaMs = ONE_FRAME_MS): number { } describe('getDragAutoScrollStepPx', () => { - it('stays still while the pointer is away from both edges', () => { - expect(stepAt(300)).toBe(0) - expect(stepAt(130)).toBe(0) - expect(stepAt(470)).toBe(0) - }) - - it('pulls down past the bottom edge and up past the top edge', () => { - expect(stepAt(490)).toBeGreaterThan(0) - expect(stepAt(110)).toBeLessThan(0) - }) - - it('pulls harder the further past the edge the pointer is', () => { - expect(stepAt(600)).toBeGreaterThan(stepAt(490)) - }) - - it('caps the pull however far past the edge the pointer goes', () => { - expect(stepAt(5000)).toBe(stepAt(100_000)) - }) - it('covers the same distance per millisecond at any refresh rate', () => { expect(stepAt(600, ONE_FRAME_MS / 2) * 2).toBeCloseTo(stepAt(600, ONE_FRAME_MS), 8) }) diff --git a/src/renderer/src/components/editor/editor-saved-event-view.test.ts b/src/renderer/src/components/editor/editor-saved-event-view.test.ts index ce2a2de5d86..49e32df3ac9 100644 --- a/src/renderer/src/components/editor/editor-saved-event-view.test.ts +++ b/src/renderer/src/components/editor/editor-saved-event-view.test.ts @@ -15,13 +15,6 @@ function tab(id: string): OpenFile { } describe('editorSavedEventView', () => { - it('is the saving view while it is open', () => { - const files = [tab('other'), tab('saver')] - expect( - editorSavedEventView(files, { fileId: 'saver', recordViewIds: ['other', 'saver'] })?.id - ).toBe('saver') - }) - it("falls back to the record's other views when the saving view closed mid-write", () => { const files = [tab('unrelated'), tab('other')] expect( @@ -29,9 +22,4 @@ describe('editorSavedEventView', () => { ).toBe('other') expect(editorSavedEventView(files, { fileId: 'closed' })).toBeUndefined() }) - - it('ignores malformed details', () => { - expect(editorSavedEventView([tab('a')], null)).toBeUndefined() - expect(editorSavedEventView([tab('a')], { content: 'x' })).toBeUndefined() - }) }) diff --git a/src/renderer/src/components/editor/monaco-reveal-range.test.ts b/src/renderer/src/components/editor/monaco-reveal-range.test.ts deleted file mode 100644 index d97ef6a74fe..00000000000 --- a/src/renderer/src/components/editor/monaco-reveal-range.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { computeMonacoRevealRange } from './monaco-reveal-range' - -describe('computeMonacoRevealRange', () => { - it('returns the requested single-line match range when it is already valid', () => { - expect( - computeMonacoRevealRange({ - line: 4, - column: 7, - matchLength: 5, - maxLine: 20, - lineMaxColumn: 80 - }) - ).toEqual({ - startLineNumber: 4, - startColumn: 7, - endLineNumber: 4, - endColumn: 12 - }) - }) - - it('clamps the line and columns to the model bounds', () => { - expect( - computeMonacoRevealRange({ - line: 999, - column: 200, - matchLength: 10, - maxLine: 6, - lineMaxColumn: 14 - }) - ).toEqual({ - startLineNumber: 6, - startColumn: 14, - endLineNumber: 6, - endColumn: 15 - }) - }) - - it('falls back to a one-column range when match length is zero', () => { - expect( - computeMonacoRevealRange({ - line: 2, - column: 3, - matchLength: 0, - maxLine: 10, - lineMaxColumn: 9 - }) - ).toEqual({ - startLineNumber: 2, - startColumn: 3, - endLineNumber: 2, - endColumn: 4 - }) - }) -}) diff --git a/src/renderer/src/components/linear-issue-text-save-plan.test.ts b/src/renderer/src/components/linear-issue-text-save-plan.test.ts index 74049f74368..184b06df5aa 100644 --- a/src/renderer/src/components/linear-issue-text-save-plan.test.ts +++ b/src/renderer/src/components/linear-issue-text-save-plan.test.ts @@ -23,15 +23,4 @@ describe('getLinearIssueTextSavePlan', () => { expect(plan).toEqual({ kind: 'changed', patch: { description: 'Updated details' } }) }) - - it('preserves the required-title guard', () => { - const plan = getLinearIssueTextSavePlan({ - descriptionDraft: 'Details', - field: 'title', - issue: { title: 'Issue title', description: 'Details' }, - titleDraft: ' ' - }) - - expect(plan).toEqual({ kind: 'empty-title' }) - }) }) diff --git a/src/renderer/src/components/native-chat/native-chat-image-paste.test.ts b/src/renderer/src/components/native-chat/native-chat-image-paste.test.ts deleted file mode 100644 index a331f2c0bea..00000000000 --- a/src/renderer/src/components/native-chat/native-chat-image-paste.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { getAgentImageHandling, isNativeChatPastedImagePath } from './native-chat-image-paste' - -describe('image paste agent map', () => { - it('vision-capable TUIs take image attachments', () => { - expect(getAgentImageHandling('claude')).toBe('attachment') - expect(getAgentImageHandling('codex')).toBe('attachment') - expect(getAgentImageHandling('grok')).toBe('attachment') - }) - - it('unknown/custom agent is unsupported', () => { - expect(getAgentImageHandling('some-custom-agent')).toBe('unsupported') - }) -}) - -describe('isNativeChatPastedImagePath', () => { - it('detects clipboard-paste temp files (so the chip shows a friendly label)', () => { - expect( - isNativeChatPastedImagePath( - '/var/folders/x/orca-paste-1782775228480-c9a3c86b-1234-5678-9abc-def012345678.png' - ) - ).toBe(true) - // Windows-style separators resolve to the same basename. - expect(isNativeChatPastedImagePath('C:\\Temp\\orca-paste-1-2.png')).toBe(true) - }) - - it('leaves picked/dropped files showing their real name', () => { - expect(isNativeChatPastedImagePath('/Users/me/Pictures/hero-image-2.png')).toBe(false) - expect(isNativeChatPastedImagePath('/tmp/screenshot.png')).toBe(false) - }) -}) diff --git a/src/renderer/src/components/native-chat/native-chat-send-eligibility.test.ts b/src/renderer/src/components/native-chat/native-chat-send-eligibility.test.ts deleted file mode 100644 index d33daf1b5f4..00000000000 --- a/src/renderer/src/components/native-chat/native-chat-send-eligibility.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - deriveNativeChatCanSend, - shouldChatTakeOverMobileSurface -} from './native-chat-send-eligibility' - -describe('deriveNativeChatCanSend', () => { - it('blocks sends when a mobile client holds the pty (presence-lock active)', () => { - expect(deriveNativeChatCanSend({ kind: 'mobile', clientId: 'phone-1' })).toBe(false) - }) - - it('allows sends when the desktop drives the pty', () => { - expect(deriveNativeChatCanSend({ kind: 'desktop' })).toBe(true) - }) - - it('allows sends when the pty is idle', () => { - expect(deriveNativeChatCanSend({ kind: 'idle' })).toBe(true) - }) - - it('treats an unresolved driver (null/undefined) as unlocked', () => { - expect(deriveNativeChatCanSend(null)).toBe(true) - expect(deriveNativeChatCanSend(undefined)).toBe(true) - }) -}) - -describe('shouldChatTakeOverMobileSurface', () => { - it('takes over the mobile surface when the tab is in chat view', () => { - expect(shouldChatTakeOverMobileSurface('chat')).toBe(true) - }) - - it('leaves the terminal mobile overlay in place in terminal view', () => { - expect(shouldChatTakeOverMobileSurface('terminal')).toBe(false) - }) -}) diff --git a/src/renderer/src/components/right-sidebar/ai-vault-scope-state.test.ts b/src/renderer/src/components/right-sidebar/ai-vault-scope-state.test.ts deleted file mode 100644 index a58c4975b68..00000000000 --- a/src/renderer/src/components/right-sidebar/ai-vault-scope-state.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { normalizeAiVaultScopeForContext } from './ai-vault-scope-state' - -describe('normalizeAiVaultScopeForContext', () => { - it('falls back from project to all when no active project is available', () => { - expect( - normalizeAiVaultScopeForContext({ - scope: 'project', - activeProjectKey: null, - activeWorktreePath: '/repo' - }) - ).toBe('all') - }) - - it('falls back from workspace to all when no active workspace path is available', () => { - expect( - normalizeAiVaultScopeForContext({ - scope: 'workspace', - activeProjectKey: 'project:orca', - activeWorktreePath: null - }) - ).toBe('all') - }) - - it('keeps available project and workspace scopes selected', () => { - expect( - normalizeAiVaultScopeForContext({ - scope: 'project', - activeProjectKey: 'project:orca', - activeWorktreePath: '/repo' - }) - ).toBe('project') - - expect( - normalizeAiVaultScopeForContext({ - scope: 'workspace', - activeProjectKey: null, - activeWorktreePath: '/repo' - }) - ).toBe('workspace') - }) -}) diff --git a/src/renderer/src/components/right-sidebar/commit-failure-dialog-state.test.ts b/src/renderer/src/components/right-sidebar/commit-failure-dialog-state.test.ts deleted file mode 100644 index 0fe830147b8..00000000000 --- a/src/renderer/src/components/right-sidebar/commit-failure-dialog-state.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - shouldShowCommitFailureDialog, - syncCommitFailureDialogState, - type CommitFailureDialogState -} from './commit-failure-dialog-state' - -describe('commit failure dialog state', () => { - it('keeps an open dialog visible when a new detailed error arrives for the same worktree', () => { - const state: CommitFailureDialogState = { worktreeKey: 'wt-1', open: true } - - expect(syncCommitFailureDialogState(state, 'wt-1', true)).toBe(state) - expect(shouldShowCommitFailureDialog(state, 'wt-1', true)).toBe(true) - }) - - it('closes the dialog when the failure moves to another worktree', () => { - expect(syncCommitFailureDialogState({ worktreeKey: 'wt-1', open: true }, 'wt-2', true)).toEqual( - { - worktreeKey: 'wt-2', - open: false - } - ) - }) - - it('closes the dialog when the latest failure no longer has expanded details', () => { - const next = syncCommitFailureDialogState({ worktreeKey: 'wt-1', open: true }, 'wt-1', false) - - expect(next).toEqual({ worktreeKey: 'wt-1', open: false }) - expect(shouldShowCommitFailureDialog(next, 'wt-1', false)).toBe(false) - }) -}) diff --git a/src/renderer/src/components/right-sidebar/local-workspace-port-sections.test.ts b/src/renderer/src/components/right-sidebar/local-workspace-port-sections.test.ts deleted file mode 100644 index a43c99c81d1..00000000000 --- a/src/renderer/src/components/right-sidebar/local-workspace-port-sections.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { shouldShowLocalWorkspacePortSections } from './local-workspace-port-sections' - -const empty = { activePorts: [], otherWorkspacePorts: [], externalPorts: [] } - -describe('shouldShowLocalWorkspacePortSections', () => { - it('shows the sections whenever the scan succeeded', () => { - expect(shouldShowLocalWorkspacePortSections(null, empty)).toBe(true) - expect(shouldShowLocalWorkspacePortSections({}, empty)).toBe(true) - }) - - // Failed scans retain last-good ports; preserve their actions alongside the status bar's count/list. - it.each([ - ['activePorts', { ...empty, activePorts: [{}] }], - ['otherWorkspacePorts', { ...empty, otherWorkspacePorts: [{}] }], - ['externalPorts', { ...empty, externalPorts: [{}] }] - ])('keeps the sections when a failed scan retained %s', (_section, sections) => { - expect(shouldShowLocalWorkspacePortSections({ unavailableReason: 'dropped' }, sections)).toBe( - true - ) - }) - - it('lets the notice stand alone when a failed scan has nothing left to list', () => { - expect(shouldShowLocalWorkspacePortSections({ unavailableReason: 'dropped' }, empty)).toBe( - false - ) - }) -}) diff --git a/src/renderer/src/components/right-sidebar/source-control-primary-action-tooltip.test.ts b/src/renderer/src/components/right-sidebar/source-control-primary-action-tooltip.test.ts deleted file mode 100644 index fa3812c5f7d..00000000000 --- a/src/renderer/src/components/right-sidebar/source-control-primary-action-tooltip.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { shouldShowPrimaryTooltip } from './source-control-primary-action-tooltip' -import type { PrimaryActionKind } from './source-control-primary-action' - -function action(kind: PrimaryActionKind, disabled: boolean) { - return { kind, disabled, label: kind, title: kind } -} - -describe('shouldShowPrimaryTooltip', () => { - it('shows the tooltip when disabled β€” the title carries the blocking reason', () => { - for (const kind of ['stage', 'create_pr', 'create_pr_intent', 'commit'] as const) { - expect(shouldShowPrimaryTooltip(action(kind, true))).toBe(true) - } - }) - - it('hides pure repeats on enabled Stage All and Create PR', () => { - expect(shouldShowPrimaryTooltip(action('stage', false))).toBe(false) - expect(shouldShowPrimaryTooltip(action('create_pr', false))).toBe(false) - }) - - it('keeps the Create PR intent tooltip β€” it explains the prepare step the label omits', () => { - expect(shouldShowPrimaryTooltip(action('create_pr_intent', false))).toBe(true) - }) - - it('shows informative tooltips for commit and remote counts', () => { - for (const kind of ['commit', 'push', 'pull', 'sync', 'publish'] as const) { - expect(shouldShowPrimaryTooltip(action(kind, false))).toBe(true) - } - }) -}) diff --git a/src/renderer/src/components/sparse/sparse-directory-browse.test.ts b/src/renderer/src/components/sparse/sparse-directory-browse.test.ts deleted file mode 100644 index 84f21f8b9aa..00000000000 --- a/src/renderer/src/components/sparse/sparse-directory-browse.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { DirEntry } from '../../../../shared/filesystem-entry-types' -import { - getSparseBrowseTrail, - joinSparseBrowsePath, - listBrowsableDirectories -} from './sparse-directory-browse' - -const entry = (name: string, isDirectory: boolean): DirEntry => ({ - name, - isDirectory, - isSymlink: false -}) - -describe('listBrowsableDirectories', () => { - it('keeps only sorted, non-hidden directories', () => { - expect( - listBrowsableDirectories([ - entry('packages', true), - entry('README.md', false), - entry('.git', true), - entry('.vscode', true), - entry('node_modules', true), - entry('apps', true) - ]) - ).toEqual(['apps', 'packages']) - }) -}) - -describe('joinSparseBrowsePath', () => { - it('omits the separator at the repository root', () => { - expect(joinSparseBrowsePath('', 'apps')).toBe('apps') - expect(joinSparseBrowsePath('apps', 'web')).toBe('apps/web') - }) -}) - -describe('getSparseBrowseTrail', () => { - it('builds cumulative segments', () => { - expect(getSparseBrowseTrail('')).toEqual([]) - expect(getSparseBrowseTrail('apps/web')).toEqual([ - { name: 'apps', path: 'apps' }, - { name: 'web', path: 'apps/web' } - ]) - }) -}) diff --git a/src/renderer/src/components/sparse/sparse-directory-entry-input.test.ts b/src/renderer/src/components/sparse/sparse-directory-entry-input.test.ts index db261c184e2..4236a08d200 100644 --- a/src/renderer/src/components/sparse/sparse-directory-entry-input.test.ts +++ b/src/renderer/src/components/sparse/sparse-directory-entry-input.test.ts @@ -1,8 +1,5 @@ import { describe, expect, it } from 'vitest' -import { - addSparseDirectoryEntries, - parseSparseDirectoryEntryInput -} from './sparse-directory-entry-input' +import { parseSparseDirectoryEntryInput } from './sparse-directory-entry-input' describe('parseSparseDirectoryEntryInput', () => { it('normalizes a single typed path', () => { @@ -26,12 +23,3 @@ describe('parseSparseDirectoryEntryInput', () => { expect(parseSparseDirectoryEntryInput('.').error).toBeTruthy() }) }) - -describe('addSparseDirectoryEntries', () => { - it('appends only new entries and preserves order', () => { - expect(addSparseDirectoryEntries(['apps/web'], ['apps/web', 'packages/ui'])).toEqual([ - 'apps/web', - 'packages/ui' - ]) - }) -}) diff --git a/src/renderer/src/components/status-bar/workspace-space-format.test.ts b/src/renderer/src/components/status-bar/workspace-space-format.test.ts deleted file mode 100644 index 57b089bc2ac..00000000000 --- a/src/renderer/src/components/status-bar/workspace-space-format.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - formatBytes, - formatCompactCount, - getWorkspaceSpaceScanTimeLabel, - getWorkspaceSpaceStatusLabel -} from './workspace-space-format' - -describe('workspace space format helpers', () => { - it('formats byte values with stable units', () => { - expect(formatBytes(0)).toBe('0 B') - expect(formatBytes(512)).toBe('512 B') - expect(formatBytes(1536)).toBe('1.50 KB') - expect(formatBytes(5 * 1024 * 1024)).toBe('5.00 MB') - }) - - it('formats counts and statuses for dense table UI', () => { - expect(formatCompactCount(1530)).toBe('1.5k') - expect(formatCompactCount(25_000)).toBe('25k') - expect(getWorkspaceSpaceStatusLabel('permission-denied')).toBe('No access') - }) - - it('formats scan times as relative age labels', () => { - const now = new Date('2026-05-14T22:15:00Z').getTime() - // Pinned to 'en' so the expectation matches the UI language, not the machine's OS locale. - const formatter = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }) - - expect(getWorkspaceSpaceScanTimeLabel(now - 2 * 60_000, now)).toBe( - formatter.format(-2, 'minute') - ) - expect(getWorkspaceSpaceScanTimeLabel(now - 3 * 60 * 60_000, now)).toBe( - formatter.format(-3, 'hour') - ) - }) -}) diff --git a/src/renderer/src/components/task-page-checks-pill.test.ts b/src/renderer/src/components/task-page-checks-pill.test.ts deleted file mode 100644 index 5e4a3aaace1..00000000000 --- a/src/renderer/src/components/task-page-checks-pill.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { getChecksLabel, getChecksPillTone } from './task-page-checks-pill' - -describe('task page checks pill', () => { - it('labels a green summary carrying one neutral check as passing', () => { - const item = { - checksSummary: { - state: 'success' as const, - total: 2, - passed: 1, - failed: 0, - pending: 0, - neutral: 1 - } - } - - expect(getChecksLabel(item)).toBe('1/2 passed') - expect(getChecksPillTone(item)).toContain('emerald') - }) - - it('only says unresolved when nothing passed, failed or is running', () => { - const item = { - checksSummary: { - state: 'neutral' as const, - total: 1, - passed: 0, - failed: 0, - pending: 0, - neutral: 1 - } - } - - expect(getChecksLabel(item)).toBe('Unresolved checks') - expect(getChecksPillTone(item)).toContain('text-muted-foreground') - }) - - it('falls back while the summary is unknown or empty', () => { - expect(getChecksLabel({})).toBe('Checks') - expect( - getChecksLabel({ - checksSummary: { - state: 'none', - total: 0, - passed: 0, - failed: 0, - pending: 0, - neutral: 0 - } - }) - ).toBe('No checks') - }) -}) diff --git a/src/renderer/src/components/task-page-empty-state.test.ts b/src/renderer/src/components/task-page-empty-state.test.ts deleted file mode 100644 index 25cd9bd6223..00000000000 --- a/src/renderer/src/components/task-page-empty-state.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { getRepoBackedTaskEmptyState } from './task-page-empty-state' - -describe('getRepoBackedTaskEmptyState', () => { - it('explains when no repo-backed task source is selected', () => { - expect( - getRepoBackedTaskEmptyState({ - provider: 'github', - selectedRepoCount: 0 - }) - ).toEqual({ - title: 'No project sources selected', - description: - 'Select at least one project source so Orca knows which host/account to fetch tasks from.' - }) - }) - - it('keeps GitHub no-match copy when sources are selected', () => { - expect( - getRepoBackedTaskEmptyState({ - provider: 'github', - selectedRepoCount: 2 - }) - ).toEqual({ - title: 'No matching GitHub work', - description: 'Change the query or clear it.' - }) - }) - - it('uses GitLab view-specific no-match copy when sources are selected', () => { - expect( - getRepoBackedTaskEmptyState({ - provider: 'gitlab', - selectedRepoCount: 1, - gitlabView: 'mrs' - }) - ).toEqual({ - title: 'No GitLab merge requests', - description: 'No GitLab MRs match this filter.' - }) - }) -}) diff --git a/src/renderer/src/components/task-page/task-page-pagination-page-numbers.test.ts b/src/renderer/src/components/task-page/task-page-pagination-page-numbers.test.ts deleted file mode 100644 index 00cdce4581c..00000000000 --- a/src/renderer/src/components/task-page/task-page-pagination-page-numbers.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import { getPageNumbers } from './task-page-pagination-page-numbers' - -describe('getPageNumbers', () => { - it('lists every zero-based page when the total fits the no-ellipsis threshold', () => { - expect(getPageNumbers(0, 1)).toEqual([0]) - expect(getPageNumbers(4, 9)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8]) - }) - - it('returns an empty list when there are no pages', () => { - expect(getPageNumbers(0, 0)).toEqual([]) - }) - - it('collapses the tail when the current page is near the start', () => { - expect(getPageNumbers(0, 20)).toEqual([0, 1, 2, 'ellipsis', 19]) - }) - - it('collapses the head when the current page is near the end', () => { - expect(getPageNumbers(19, 20)).toEqual([0, 'ellipsis', 17, 18, 19]) - }) - - it('collapses both sides around a middle page', () => { - expect(getPageNumbers(10, 20)).toEqual([0, 'ellipsis', 8, 9, 10, 11, 12, 'ellipsis', 19]) - }) - - it('omits the ellipsis when the window is exactly adjacent to an edge', () => { - expect(getPageNumbers(3, 10)).toEqual([0, 1, 2, 3, 4, 5, 'ellipsis', 9]) - }) - - it('drops the window entirely when the current page is out of range', () => { - expect(getPageNumbers(-5, 12)).toEqual([0, 'ellipsis', 11]) - expect(getPageNumbers(100, 12)).toEqual([0, 'ellipsis', 11]) - }) -}) diff --git a/src/renderer/src/components/terminal-pane/terminal-drop-write-failure.test.ts b/src/renderer/src/components/terminal-pane/terminal-drop-write-failure.test.ts deleted file mode 100644 index 4df8127f196..00000000000 --- a/src/renderer/src/components/terminal-pane/terminal-drop-write-failure.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest' - -const toastError = vi.hoisted(() => vi.fn()) - -vi.mock('sonner', () => ({ - toast: { - error: toastError - } -})) - -vi.mock('@/i18n/i18n', () => ({ - translate: (_key: string, fallback: string) => fallback -})) - -import { showTerminalDropWriteFailure } from './terminal-drop-write-failure' - -afterEach(() => { - toastError.mockClear() -}) - -describe('terminal drop write failure notification', () => { - it('does not show an error for stale targets', () => { - showTerminalDropWriteFailure('target-stale') - showTerminalDropWriteFailure(undefined) - - expect(toastError).not.toHaveBeenCalled() - }) - - it('shows a timeout error without dropped path content', () => { - showTerminalDropWriteFailure('operation-timeout') - - expect(toastError).toHaveBeenCalledWith( - 'File drop cancelled: terminal did not accept the path before the safety timeout.' - ) - }) - - it('shows a rejected-write error without dropped path content', () => { - showTerminalDropWriteFailure('write-rejected') - - expect(toastError).toHaveBeenCalledWith( - 'File drop cancelled: terminal could not accept the path.' - ) - }) -}) diff --git a/src/renderer/src/components/terminal-pane/terminal-pane-close-identity.test.ts b/src/renderer/src/components/terminal-pane/terminal-pane-close-identity.test.ts deleted file mode 100644 index 1fb24a000dd..00000000000 --- a/src/renderer/src/components/terminal-pane/terminal-pane-close-identity.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - resolveTabTitleAfterPaneClose, - shouldClearLaunchAgentForClosedPane -} from './terminal-pane-close-identity' - -describe('shouldClearLaunchAgentForClosedPane', () => { - it('clears launch identity only when the launch-owning PTY closes', () => { - const tab = { launchAgent: 'codex' as const, ptyId: 'pty-agent' } - - expect(shouldClearLaunchAgentForClosedPane(tab, 'pty-agent')).toBe(true) - expect(shouldClearLaunchAgentForClosedPane(tab, 'pty-shell')).toBe(false) - }) - - it('does not mutate identity-free or not-yet-bound tabs', () => { - expect(shouldClearLaunchAgentForClosedPane({ ptyId: 'pty-1' }, 'pty-1')).toBe(false) - expect( - shouldClearLaunchAgentForClosedPane({ launchAgent: 'claude', ptyId: null }, 'pty-1') - ).toBe(false) - }) -}) - -describe('resolveTabTitleAfterPaneClose', () => { - it('uses the promoted sibling title when one is known', () => { - expect(resolveTabTitleAfterPaneClose({ 2: 'codex' }, 2)).toBe('codex') - }) - - it('resets to the tab fallback when the promoted shell has no title', () => { - expect(resolveTabTitleAfterPaneClose({ 1: 'closed agent' }, 2)).toBe('') - expect(resolveTabTitleAfterPaneClose({}, null)).toBe('') - }) -}) diff --git a/src/renderer/src/components/terminal-pane/terminal-render-desync-evidence-persistence.test.ts b/src/renderer/src/components/terminal-pane/terminal-render-desync-evidence-persistence.test.ts index 78723ef6c24..2b03ee0c5f3 100644 --- a/src/renderer/src/components/terminal-pane/terminal-render-desync-evidence-persistence.test.ts +++ b/src/renderer/src/components/terminal-pane/terminal-render-desync-evidence-persistence.test.ts @@ -11,16 +11,4 @@ describe('createCaptureId', () => { expect(createCaptureId(paneKey)).toMatch(TERMINAL_RENDER_DESYNC_CAPTURE_ID_PATTERN) }) - - it('keeps the leaf id so a capture is still traceable to its pane', () => { - const leafId = createBrowserUuid() - - expect(createCaptureId(makePaneKey(createBrowserUuid(), leafId))).toContain(leafId) - }) - - it('does not collide for repeated captures of the same pane', () => { - const paneKey = makePaneKey(createBrowserUuid(), createBrowserUuid()) - - expect(createCaptureId(paneKey)).not.toBe(createCaptureId(paneKey)) - }) }) diff --git a/src/renderer/src/hooks/fork-push-warning.test.ts b/src/renderer/src/hooks/fork-push-warning.test.ts deleted file mode 100644 index f4940c77c10..00000000000 --- a/src/renderer/src/hooks/fork-push-warning.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { FORK_PUSH_NO_MAINTAINER_EDIT_WARNING, getForkPushWarning } from './fork-push-warning' - -const forkTarget = { remoteName: 'pr-contributor-orca', branchName: 'contributor/fix' } -const originTarget = { remoteName: 'origin', branchName: 'feature/fix' } - -describe('getForkPushWarning', () => { - it('warns for a fork PR whose author disabled maintainer edits', () => { - expect(getForkPushWarning({ pushTarget: forkTarget, maintainerCanModify: false })).toBe( - FORK_PUSH_NO_MAINTAINER_EDIT_WARNING - ) - }) - - it('does not warn when maintainer edits are allowed', () => { - expect(getForkPushWarning({ pushTarget: forkTarget, maintainerCanModify: true })).toBeNull() - }) - - it('does not warn when the maintainer flag is unknown', () => { - expect(getForkPushWarning({ pushTarget: forkTarget })).toBeNull() - }) - - it('does not warn for a same-repo PR even if the flag is false (we own origin)', () => { - expect(getForkPushWarning({ pushTarget: originTarget, maintainerCanModify: false })).toBeNull() - }) - - it('does not warn when there is no resolved push target', () => { - expect(getForkPushWarning({ maintainerCanModify: false })).toBeNull() - }) -}) diff --git a/src/renderer/src/ssh/ssh-connect-verb.test.ts b/src/renderer/src/ssh/ssh-connect-verb.test.ts deleted file mode 100644 index fa930b336c5..00000000000 --- a/src/renderer/src/ssh/ssh-connect-verb.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import { sshConnectingLabel, sshConnectVerb } from './ssh-connect-verb' - -vi.mock('@/i18n/i18n', () => ({ - translate: (_key: string, fallback: string) => fallback -})) - -// One shared vocabulary keeps simultaneous sidebar/pane/header/status controls consistent. -describe('sshConnectVerb', () => { - it('names an authentication failure a reconnect', () => { - expect(sshConnectVerb('auth-failed')).toBe('Reconnect') - }) - - it.each(['error', 'reconnection-failed'] as const)('names %s a retry', (status) => { - expect(sshConnectVerb(status)).toBe('Retry') - }) - - it.each(['disconnected', 'connecting', 'deploying-relay', 'reconnecting', 'connected'] as const)( - 'falls back to Connect for %s', - (status) => { - expect(sshConnectVerb(status)).toBe('Connect') - } - ) - - it.each([null, undefined])('falls back to Connect for %s', (status) => { - expect(sshConnectVerb(status)).toBe('Connect') - }) -}) - -describe('sshConnectingLabel', () => { - it('uses the single-character ellipsis, matching the rest of the catalog', () => { - expect(sshConnectingLabel()).toBe('Connecting…') - }) -}) diff --git a/src/shared/sidebar-list/text-order.test.ts b/src/shared/sidebar-list/text-order.test.ts index fe2351566d3..00443191425 100644 --- a/src/shared/sidebar-list/text-order.test.ts +++ b/src/shared/sidebar-list/text-order.test.ts @@ -51,13 +51,6 @@ describe('compareSidebarText', () => { expect(compareSidebarText(`CAFE${COMBINING_ACUTE}`, nfc)).toBeLessThan(0) }) - it('returns 0 only for canonically equal text, leaving the tie to the caller', () => { - expect(compareSidebarText('same', 'same')).toBe(0) - expect(compareSidebarText('', '')).toBe(0) - expect(compareSidebarText('', 'a')).toBeLessThan(0) - expect(compareSidebarText('a', 'a ')).toBeLessThan(0) - }) - it('is antisymmetric across a mixed corpus', () => { const corpus = [ 'w2', @@ -85,11 +78,6 @@ describe('compareCodePoints', () => { expect('πŸŽ‰'.charCodeAt(0)).toBeLessThan(REPLACEMENT_CHAR.charCodeAt(0)) expect(compareCodePoints('πŸŽ‰', REPLACEMENT_CHAR)).toBeGreaterThan(0) }) - - it('orders a prefix first', () => { - expect(compareCodePoints('local|a', 'local|ab')).toBeLessThan(0) - expect(compareCodePoints('x', 'x')).toBe(0) - }) }) describe('createSidebarTextComparator', () => { diff --git a/src/shared/structural-value-equality.test.ts b/src/shared/structural-value-equality.test.ts index d368d4d8fe2..f2df7b15b9a 100644 --- a/src/shared/structural-value-equality.test.ts +++ b/src/shared/structural-value-equality.test.ts @@ -10,17 +10,6 @@ const comparators = [ ] as const describe.each(comparators)('%s', (_name, valuesEqual) => { - it('compares primitives and identical references', () => { - expect(valuesEqual('a', 'a')).toBe(true) - expect(valuesEqual('a', 'b')).toBe(false) - expect(valuesEqual(null, null)).toBe(true) - expect(valuesEqual(null, {})).toBe(false) - expect(valuesEqual(undefined, null)).toBe(false) - const fn = (): void => {} - expect(valuesEqual(fn, fn)).toBe(true) - expect(valuesEqual(fn, (): void => {})).toBe(false) - }) - it('walks arrays element-wise and never mixes them with records', () => { expect(valuesEqual([1, [2, { a: 'b' }]], [1, [2, { a: 'b' }]])).toBe(true) expect(valuesEqual([1, 2], [1, 2, 3])).toBe(false) @@ -56,11 +45,6 @@ describe.each(comparators)('%s', (_name, valuesEqual) => { expect(valuesEqual(new Row(), new Row())).toBe(false) expect(valuesEqual(new Row(), { x: 1 })).toBe(false) }) - - it('ignores symbol keys', () => { - const key = Symbol('marker') - expect(valuesEqual({ [key]: 1, a: 1 }, { [key]: 2, a: 1 })).toBe(true) - }) }) describe('structuralValuesEqual', () => { diff --git a/src/shared/structured-agent-session-first-prompt.spec.ts b/src/shared/structured-agent-session-first-prompt.spec.ts index 2bac3e6aae7..82502b77e46 100644 --- a/src/shared/structured-agent-session-first-prompt.spec.ts +++ b/src/shared/structured-agent-session-first-prompt.spec.ts @@ -122,9 +122,4 @@ describe('first structured chat prompt', () => { const url = 'https://example.test/issues/123' expect(firstStructuredAgentSessionPrompt([message(url), message('Later')])).toBe(url) }) - - it('returns empty when no user prose exists', () => { - expect(firstStructuredAgentSessionPrompt([])).toBe('') - expect(firstStructuredAgentSessionPrompt([message(' ')])).toBe('') - }) }) diff --git a/src/shared/terminal-selection-gutter.test.ts b/src/shared/terminal-selection-gutter.test.ts index 5f95fd85d59..a2345899229 100644 --- a/src/shared/terminal-selection-gutter.test.ts +++ b/src/shared/terminal-selection-gutter.test.ts @@ -21,12 +21,6 @@ describe('stripTerminalSelectionGutter', () => { ) }) - it('drops the gutter from a single wrapped line', () => { - expect(stripTerminalSelectionGutter(' one logical line, joined by xterm')).toBe( - 'one logical line, joined by xterm' - ) - }) - it('keeps relative indentation inside the gutter', () => { const nested = [' def run():', ' return 1', '', ' run()'].join('\n') expect(stripTerminalSelectionGutter(nested)).toBe( @@ -39,17 +33,6 @@ describe('stripTerminalSelectionGutter', () => { expect(stripTerminalSelectionGutter(midLine)).toBe(midLine) }) - it('leaves unindented output untouched', () => { - const shellOutput = ['$ git status', 'On branch main', 'nothing to commit'].join('\n') - expect(stripTerminalSelectionGutter(shellOutput)).toBe(shellOutput) - }) - - it('ignores blank lines when measuring the gutter', () => { - expect(stripTerminalSelectionGutter([' a', '', ' b'].join('\n'))).toBe( - ['a', '', 'b'].join('\n') - ) - }) - it('ignores whitespace-only lines when measuring the gutter', () => { expect(stripTerminalSelectionGutter([' a', ' ', ' b'].join('\n'))).toBe( ['a', '', 'b'].join('\n') @@ -71,21 +54,11 @@ describe('stripTerminalSelectionGutter', () => { ) }) - it('leaves wide characters and emoji in the content alone', () => { - expect( - stripTerminalSelectionGutter([' ε€‰ζ›΄γ‚’ι©η”¨γ—γΎγ—γŸ πŸŽ‰', ' γŠη–²γ‚Œγ•γΎ'].join('\n')) - ).toBe(['ε€‰ζ›΄γ‚’ι©η”¨γ—γΎγ—γŸ πŸŽ‰', 'γŠη–²γ‚Œγ•γΎ'].join('\n')) - }) - it('does not strip past a shorter line', () => { const uneven = [' deep', ' shallow'].join('\n') expect(stripTerminalSelectionGutter(uneven)).toBe([' deep', 'shallow'].join('\n')) }) - it('is a no-op on an empty selection', () => { - expect(stripTerminalSelectionGutter('')).toBe('') - }) - it('leaves tab-indented text alone (terminal cells never hold tabs)', () => { const tabbed = ['\tone', '\ttwo'].join('\n') expect(stripTerminalSelectionGutter(tabbed)).toBe(tabbed) diff --git a/src/shared/workspace-layout/workspace-layout-editor-open-file-id.test.ts b/src/shared/workspace-layout/workspace-layout-editor-open-file-id.test.ts index cff2a8f7859..8a198b1d8cf 100644 --- a/src/shared/workspace-layout/workspace-layout-editor-open-file-id.test.ts +++ b/src/shared/workspace-layout/workspace-layout-editor-open-file-id.test.ts @@ -1,5 +1,4 @@ import { describe, expect, it, vi } from 'vitest' -import { FLOATING_TERMINAL_WORKTREE_ID } from '../constants' import { ownedEditorFileId } from '../workspace-session-pane-ownership' import { build, emptyModel, testContext, WS } from './workspace-layout-command.test-fixture' import { applyLayoutCommand } from './workspace-layout-commands' @@ -40,12 +39,6 @@ function workspace( } describe('the file id main gives a file it opens', () => { - it('is the owned id of a file no tab shows, never the bare path another host may hold', () => { - expect(editorOpenFileId(workspace(WT, []), file('/repo/a.ts'))).toBe( - ownedEditorFileId('/repo/a.ts', WT, null) - ) - }) - it("is the id a tab already shows the same owner's file under, the bare path included", () => { expect( editorOpenFileId(workspace(WT, [file('/repo/a.ts')], ['/repo/a.ts']), file('/repo/a.ts')) @@ -58,12 +51,6 @@ describe('the file id main gives a file it opens', () => { ownedEditorFileId('/repo/a.ts', WT, null) ) }) - - it('is an owned id in the floating workspace', () => { - expect( - editorOpenFileId(workspace(FLOATING_TERMINAL_WORKTREE_ID, []), file('/tmp/notes.md')) - ).toBe(ownedEditorFileId('/tmp/notes.md', FLOATING_TERMINAL_WORKTREE_ID, null)) - }) }) describe('an open main makes itself, naming the file but not its id', () => { diff --git a/src/shared/workspace-session-schema-field-coverage.test.ts b/src/shared/workspace-session-schema-field-coverage.test.ts index 61a9cbc0816..2f843af8da8 100644 --- a/src/shared/workspace-session-schema-field-coverage.test.ts +++ b/src/shared/workspace-session-schema-field-coverage.test.ts @@ -1,48 +1,6 @@ import { describe, expect, it } from 'vitest' -import type { z } from 'zod' -import { parseWorkspaceSession, workspaceSessionStateSchema } from './workspace-session-schema' -import type { WorkspaceSessionState } from './workspace-session-state-types' - -/** Zod strips unlisted fields at local and SSH load boundaries although writes accept them. Pin schema coverage to WorkspaceSessionState so fields survive quit/relaunch, including close tombstones that otherwise resurrect tabs. */ -const PERSISTED_WORKSPACE_SESSION_FIELDS = { - activeRepoId: true, - activeWorkspaceKey: true, - activeWorkspaceExecutionHostId: true, - activeWorktreeId: true, - activeTabId: true, - tabsByWorktree: true, - terminalLayoutsByTabId: true, - localOnlyScrollbackByTabId: true, - activeWorktreeIdsOnShutdown: true, - openFilesByWorktree: true, - activeFileIdByWorktree: true, - markdownFrontmatterVisible: true, - browserTabsByWorktree: true, - browserPagesByWorkspace: true, - activeBrowserTabIdByWorktree: true, - clientHostedBrowserPagesByWorktree: true, - clientHostedBrowserCloseIntentsByEnvironment: true, - pairedTerminalTabCloseIntentsByEnvironment: true, - activeTabTypeByWorktree: true, - browserUrlHistory: true, - workspaceDocHistory: true, - activeTabIdByWorktree: true, - unifiedTabs: true, - tabGroups: true, - tabGroupLayouts: true, - activeGroupIdByWorktree: true, - activeConnectionIdsAtShutdown: true, - remoteSessionIdsByTabId: true, - lastVisitedAtByWorktreeId: true, - defaultTerminalTabsAppliedByWorktreeId: true, - sleepingAgentSessionsByPaneKey: true, - terminalPtyIncarnationsByPaneKey: true, - terminalTopologyRevisionByRepoId: true, - terminalSurfaceTombstonesByPaneKey: true, - closedTerminalTabTombstonesByTabId: true, - closedTerminalPanesByPaneKey: true -} satisfies Record +import { parseWorkspaceSession } from './workspace-session-schema' const MINIMAL_SESSION = { activeRepoId: null, @@ -53,21 +11,6 @@ const MINIMAL_SESSION = { } describe('workspaceSessionStateSchema field coverage', () => { - it('parses every field declared on WorkspaceSessionState', () => { - // The satisfies guard checks the field list; this runtime check catches schema omissions by name. - // The public ZodType annotation hides shape; inspect the underlying object without widening that API. - const schemaKeys = new Set( - Object.keys( - (workspaceSessionStateSchema as unknown as z.ZodObject>).shape - ) - ) - const missing = Object.keys(PERSISTED_WORKSPACE_SESSION_FIELDS).filter( - (field) => !schemaKeys.has(field) - ) - - expect(missing, `declared on WorkspaceSessionState but absent from the load schema`).toEqual([]) - }) - it('round-trips the closed-tab tombstone map through parseWorkspaceSession', () => { // A persisted close must survive relaunch or disconnected tabs reappear despite every single-process test passing. const parsed = parseWorkspaceSession({ diff --git a/src/shared/workspace-space-scan-budget.test.ts b/src/shared/workspace-space-scan-budget.test.ts index 2cd3ac61892..d8c88cfc656 100644 --- a/src/shared/workspace-space-scan-budget.test.ts +++ b/src/shared/workspace-space-scan-budget.test.ts @@ -99,16 +99,4 @@ describe('workspace space scan budget', () => { ).rejects.toBeInstanceOf(WorkspaceSpaceScanCapacityError) expect(closed).toBe(true) }) - - it('reports the configured cap rather than the default limits', async () => { - await expect( - collectWorkspaceSpaceDirectoryEntries( - [{ name: 'first' }, { name: 'second' }], - '/workspace', - (entry) => entry.name, - createWorkspaceSpaceScanBudget({ maxEntries: 1, maxRetainedBytes: 4 * 1024 * 1024 }), - () => undefined - ) - ).rejects.toThrow('limit: 1 entries or 4 MiB of live scan state') - }) }) diff --git a/src/shared/worktree/retired-name-cache.test.ts b/src/shared/worktree/retired-name-cache.test.ts index b58f9783e20..151ee229d53 100644 --- a/src/shared/worktree/retired-name-cache.test.ts +++ b/src/shared/worktree/retired-name-cache.test.ts @@ -61,15 +61,6 @@ describe('readRetiredNameRegistryForRepo', () => { }) describe('retiredNamesAfterRefresh', () => { - it('takes the new registry on success', () => { - expect( - retiredNamesAfterRefresh(loadOf('repo-1', ['nautilus']), 'repo-1', { - exhaustedTiers: 1, - names: ['nautilus-2'] - }) - ).toEqual(loadOf('repo-1', ['nautilus-2'], 1)) - }) - // A failed refresh must not un-retire names while the create form requests suggestions. it('holds the previous registry when the refresh fails', () => { expect(retiredNamesAfterRefresh(loadOf('repo-1', ['nautilus'], 2), 'repo-1', null)).toEqual( @@ -83,12 +74,6 @@ describe('retiredNamesAfterRefresh', () => { registry: EMPTY_RETIRED_NAME_REGISTRY }) }) - - it('answers empty when the first fetch for a repo fails', () => { - expect(retiredNamesAfterRefresh(null, 'repo-1', null).registry).toEqual( - EMPTY_RETIRED_NAME_REGISTRY - ) - }) }) describe('selectRetiredNameRegistry', () => { @@ -99,9 +84,4 @@ describe('selectRetiredNameRegistry', () => { expect(selectRetiredNameRegistry(loaded, null)).toEqual(EMPTY_RETIRED_NAME_REGISTRY) expect(selectRetiredNameRegistry(null, 'repo-1')).toEqual(EMPTY_RETIRED_NAME_REGISTRY) }) - - it('returns the stored registry itself so downstream memos do not rerun', () => { - const loaded = loadOf('repo-1', ['nautilus']) - expect(selectRetiredNameRegistry(loaded, 'repo-1')).toBe(loaded.registry) - }) })