diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index a7d570513a1..08bf17b13f1 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -7803,7 +7803,6 @@ "src/renderer/src/components/feature-wall/feature-wall-animation-visibility.test.tsx": 592, "src/renderer/src/components/feature-wall/feature-wall-setup-checklist-localized-copy.test.ts": 578, "src/renderer/src/components/feature-wall/feature-wall-setup-progress.test.ts": 62, - "src/renderer/src/components/feature-wall/feature-wall-usage-tracking.test.ts": 106, "src/renderer/src/components/feature-wall/use-feature-wall-completion.test.ts": 47, "src/renderer/src/components/feature-wall/use-feature-wall-tour-telemetry.test.ts": 31, "src/renderer/src/components/feature-wall/use-integration-connection-status.test.ts": 1429, @@ -8066,7 +8065,6 @@ "src/renderer/src/components/native-chat/native-chat-launch-default-adoption.test.ts": 197, "src/renderer/src/components/native-chat/native-chat-launch-draft-resolution.test.ts": 70, "src/renderer/src/components/native-chat/native-chat-launch-draft-send.test.ts": 39, - "src/renderer/src/components/native-chat/native-chat-layout-actions.test.ts": 2289, "src/renderer/src/components/native-chat/native-chat-leaf-routing.test.ts": 24, "src/renderer/src/components/native-chat/native-chat-live-message-preparation.test.ts": 152, "src/renderer/src/components/native-chat/native-chat-live-status.test.ts": 87, @@ -8289,7 +8287,6 @@ "src/renderer/src/components/new-workspace/SmartWorkspaceSourceResultList.linear-read-error.test.tsx": 717, "src/renderer/src/components/new-workspace/project-combobox-matching.test.ts": 73, "src/renderer/src/components/new-workspace/smart-workspace-command-value.test.ts": 48, - "src/renderer/src/components/new-workspace/smart-workspace-source-popover-focus.test.ts": 123, "src/renderer/src/components/new-workspace/smart-workspace-source-results.test.ts": 204, "src/renderer/src/components/new-workspace/use-jira-composer-project.test.tsx": 172, "src/renderer/src/components/new-workspace/use-jira-source-connection.test.tsx": 208, @@ -8720,7 +8717,6 @@ "src/renderer/src/components/settings/NotificationHostToggles.test.tsx": 427, "src/renderer/src/components/settings/NotificationsPane.hidden-workspaces.test.tsx": 1362, "src/renderer/src/components/settings/NotificationsPane.test.tsx": 1723, - "src/renderer/src/components/settings/OpenInMenuSetting.test.ts": 148, "src/renderer/src/components/settings/OrchestrationPane.test.tsx": 1824, "src/renderer/src/components/settings/OrchestrationSkillAgentCoverage.test.tsx": 247, "src/renderer/src/components/settings/PluginConsentDialog.test.tsx": 1638, @@ -8747,7 +8743,6 @@ "src/renderer/src/components/settings/RuntimeSshAccessControl.test.tsx": 441, "src/renderer/src/components/settings/SessionHistoryComputerRow.test.tsx": 642, "src/renderer/src/components/settings/SessionHistorySettingsPane.test.tsx": 903, - "src/renderer/src/components/settings/Settings.load-performance.test.ts": 38, "src/renderer/src/components/settings/SettingsConstants.test.ts": 97, "src/renderer/src/components/settings/SettingsFormControls.font-autocomplete.test.tsx": 789, "src/renderer/src/components/settings/SettingsFormControls.number-field.test.tsx": 753, @@ -8836,7 +8831,6 @@ "src/renderer/src/components/settings/repository/source-control/repository-source-control-ai-persist-queue.test.ts": 67, "src/renderer/src/components/settings/runtime-default-host-row.test.tsx": 1765, "src/renderer/src/components/settings/runtime-server-default-name.test.ts": 122, - "src/renderer/src/components/settings/runtime-server-row-meta.test.ts": 165, "src/renderer/src/components/settings/runtime-server-row-presentation.test.ts": 357, "src/renderer/src/components/settings/runtime-server-row-unverifiable-host.test.tsx": 2162, "src/renderer/src/components/settings/runtime-share-computer-button.test.tsx": 1304, @@ -9353,7 +9347,6 @@ "src/renderer/src/components/status-bar/usage-percentage-label.localization.test.ts": 185, "src/renderer/src/components/status-bar/usage-percentage-label.test.ts": 20, "src/renderer/src/components/status-bar/usage-pool-label.test.ts": 76, - "src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts": 34, "src/renderer/src/components/status-bar/usage-roster-row-state.test.ts": 71, "src/renderer/src/components/status-bar/usage-unit-label-parity.test.tsx": 335, "src/renderer/src/components/status-bar/use-owner-usage-rate-limits.test.tsx": 261, @@ -12593,7 +12586,6 @@ "src/shared/native-chat-agent-support.test.ts": 38, "src/shared/native-chat-appearance-settings.test.ts": 34, "src/shared/native-chat-approval-envelope.test.ts": 49, - "src/shared/native-chat/input/native-chat-ask-fifo.test.ts": 30, "src/shared/native-chat/input/native-chat-ask.test.ts": 95, "src/shared/native-chat/input/native-chat-background-task-row.test.ts": 67, "src/shared/native-chat-context-usage.test.ts": 28, diff --git a/src/renderer/src/components/editor/check-run-details-tab.test.ts b/src/renderer/src/components/editor/check-run-details-tab.test.ts index ca9d2878878..91278bb053d 100644 --- a/src/renderer/src/components/editor/check-run-details-tab.test.ts +++ b/src/renderer/src/components/editor/check-run-details-tab.test.ts @@ -1,23 +1,7 @@ import { describe, expect, it } from 'vitest' -import { - buildCheckRunDetailsTabId, - getCheckRunDetailsTabLabel, - getCheckRunTabIdentity -} from './check-run-details-tab' +import { buildCheckRunDetailsTabId, getCheckRunTabIdentity } from './check-run-details-tab' describe('check-run-details-tab', () => { - it('builds a stable tab id from worktree and check identity', () => { - expect( - buildCheckRunDetailsTabId('wt-1', { - name: 'verify', - status: 'completed', - conclusion: 'failure', - url: null, - checkRunId: 99 - }) - ).toBe('wt-1::check-details::check-run:99') - }) - it('falls back to workflow and url identities when check run id is missing', () => { expect( getCheckRunTabIdentity({ @@ -48,15 +32,4 @@ describe('check-run-details-tab', () => { buildCheckRunDetailsTabId('wt-1', { ...base, name: 'test: unit', gitlabJobId: 42 }) ).not.toBe(buildCheckRunDetailsTabId('wt-1', { ...base, name: 'test: unit', gitlabJobId: 43 })) }) - - it('uses the check name for the tab label', () => { - expect( - getCheckRunDetailsTabLabel({ - name: 'verify', - status: 'completed', - conclusion: 'failure', - url: null - }) - ).toBe('verify') - }) }) diff --git a/src/renderer/src/components/editor/rich-markdown-review-note-layout.test.ts b/src/renderer/src/components/editor/rich-markdown-review-note-layout.test.ts index 4327f65d007..f310c9053ca 100644 --- a/src/renderer/src/components/editor/rich-markdown-review-note-layout.test.ts +++ b/src/renderer/src/components/editor/rich-markdown-review-note-layout.test.ts @@ -1,9 +1,6 @@ import { describe, expect, it } from 'vitest' import type { DiffComment } from '../../../../shared/diff-comment-types' -import { - shouldExpandRichMarkdownReviewRail, - stackRichMarkdownReviewNotePositions -} from './rich-markdown-review-note-layout' +import { stackRichMarkdownReviewNotePositions } from './rich-markdown-review-note-layout' function makeComment(overrides: Partial): DiffComment { return { @@ -36,41 +33,4 @@ describe('stackRichMarkdownReviewNotePositions', () => { expect(stacked[0].top).toBe(100) expect(stacked[1].top).toBeGreaterThan(stacked[0].top) }) - - it('reserves quote height for fallback source-line excerpts', () => { - const stacked = stackRichMarkdownReviewNotePositions([ - { - comment: makeComment({ id: 'first', body: 'note' }), - top: 100 - }, - { - comment: makeComment({ id: 'second', body: 'note' }), - top: 100 - } - ]) - - expect(stacked[1].top).toBe(210) - }) -}) - -describe('shouldExpandRichMarkdownReviewRail', () => { - it('expands while a markdown note draft is open even before the note is saved', () => { - expect( - shouldExpandRichMarkdownReviewRail({ - hasReviewNotes: false, - reviewRailOpen: false, - hasDraftNote: true - }) - ).toBe(true) - }) - - it('keeps saved notes collapsed until the user opens the rail', () => { - expect( - shouldExpandRichMarkdownReviewRail({ - hasReviewNotes: true, - reviewRailOpen: false, - hasDraftNote: false - }) - ).toBe(false) - }) }) diff --git a/src/renderer/src/components/feature-wall/feature-wall-usage-tracking.test.ts b/src/renderer/src/components/feature-wall/feature-wall-usage-tracking.test.ts deleted file mode 100644 index fd07b2fe198..00000000000 --- a/src/renderer/src/components/feature-wall/feature-wall-usage-tracking.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { ProviderRateLimits } from '../../../../shared/rate-limit-types' -import { - getFeatureWallUsageProviderConnection, - hasFeatureWallUsageTracking -} from './feature-wall-usage-tracking' - -function rateLimits(overrides: Partial = {}): ProviderRateLimits { - return { - provider: 'codex', - session: null, - weekly: null, - updatedAt: 1, - error: null, - status: 'ok', - ...overrides - } -} - -describe('feature wall usage tracking state', () => { - it('treats system-default Codex rate limit data as connected', () => { - expect( - getFeatureWallUsageProviderConnection({ - managedAccountCount: 0, - provider: rateLimits({ - session: { - usedPercent: 10, - windowMinutes: 300, - resetsAt: null, - resetDescription: null - } - }) - }) - ).toEqual({ connected: true, label: 'Connected · System default' }) - }) - - it('keeps managed accounts connected even before live quota data arrives', () => { - expect( - getFeatureWallUsageProviderConnection({ - managedAccountCount: 2, - provider: null - }) - ).toEqual({ connected: true, label: 'Connected · 2' }) - }) - - it('returns not set up when there are no accounts or quota signals', () => { - expect( - getFeatureWallUsageProviderConnection({ - managedAccountCount: 0, - provider: null - }) - ).toEqual({ connected: false, label: 'Tracking not set up' }) - }) - - it('returns unknown when the account list has not loaded', () => { - expect( - getFeatureWallUsageProviderConnection({ - managedAccountCount: undefined, - provider: null - }) - ).toEqual({ connected: false, label: 'Account status unknown' }) - }) - - it('prefers observed provider usage over an unknown account list', () => { - expect( - getFeatureWallUsageProviderConnection({ - managedAccountCount: undefined, - provider: rateLimits() - }) - ).toEqual({ connected: true, label: 'Connected · System default' }) - }) - - it('marks the usage step complete from system-default provider data', () => { - expect( - hasFeatureWallUsageTracking({ - claudeManagedAccountCount: 0, - codexManagedAccountCount: 0, - claudeRateLimits: null, - codexRateLimits: rateLimits() - }) - ).toBe(true) - }) -}) diff --git a/src/renderer/src/components/github/PRFilterPickers.test.ts b/src/renderer/src/components/github/PRFilterPickers.test.ts index 1adfdce4274..50e2a231d9a 100644 --- a/src/renderer/src/components/github/PRFilterPickers.test.ts +++ b/src/renderer/src/components/github/PRFilterPickers.test.ts @@ -13,16 +13,6 @@ describe('filterPullRequestPickerOptions', () => { { key: 'docs', primary: 'documentation' } ] - it('returns all options for empty queries', () => { - expect(filterPullRequestPickerOptions(options, '')).toEqual(options) - expect(filterPullRequestPickerOptions(options, ' ')).toEqual(options) - }) - - it('matches primary and secondary text case-insensitively', () => { - expect(filterPullRequestPickerOptions(options, 'BUG')).toEqual([options[1]]) - expect(filterPullRequestPickerOptions(options, 'smith')).toEqual([options[0]]) - }) - it('rejects oversized pasted queries before reading picker option text', () => { const oversizedQuery = 'secret-pr-picker-filter'.repeat(PULL_REQUEST_PICKER_QUERY_MAX_BYTES) const throwingOptions = [ diff --git a/src/renderer/src/components/native-chat-resume-failure-guidance.test.ts b/src/renderer/src/components/native-chat-resume-failure-guidance.test.ts index aba8df5cb8e..6ddd6341357 100644 --- a/src/renderer/src/components/native-chat-resume-failure-guidance.test.ts +++ b/src/renderer/src/components/native-chat-resume-failure-guidance.test.ts @@ -32,16 +32,6 @@ describe('resumeFailureGuidance', () => { } ) - it.each([ - 'agent_session_conflict', - 'agent_session_ownership_unknown', - 'execution_owner_reconciling' - ])('words %s without Orca internals', (reason) => { - expect(resumeFailureGuidance({ outcome: 'refused', reason }).text).not.toMatch( - /owns|process|session/ - ) - }) - it('never offers a retry for a delivery nobody could confirm', () => { expect( resumeFailureGuidance({ outcome: 'unconfirmed', reason: 'agent_session_conflict' }) diff --git a/src/renderer/src/components/native-chat/native-chat-appearance-palette.test.ts b/src/renderer/src/components/native-chat/native-chat-appearance-palette.test.ts index d2a0c26e42e..3c01c56c756 100644 --- a/src/renderer/src/components/native-chat/native-chat-appearance-palette.test.ts +++ b/src/renderer/src/components/native-chat/native-chat-appearance-palette.test.ts @@ -1,7 +1,6 @@ // @vitest-environment happy-dom import { readFileSync } from 'node:fs' import { resolve } from 'node:path' -import { compile } from 'tailwindcss' import { afterEach, describe, expect, it, vi } from 'vitest' import { createGlobalSettingsFixture } from '../../../../shared/global-settings-test-fixture' import * as terminalThemeSelection from '../../../../shared/terminal-theme-selection' @@ -123,23 +122,3 @@ describe('matching chat surfaces with opposite app schemes', () => { expect(styles.getPropertyValue('--chat-source-foreground')).toBe('#fafafa') }) }) - -describe('chat scheme and inherited dark utilities', () => { - it('compiles the custom variant and excludes light chats and enables dark chats', async () => { - const declaration = css.match(/^@custom-variant dark \((.+)\);$/m) - expect(declaration).not.toBeNull() - if (!declaration) { - throw new Error('Missing dark variant') - } - const compiler = await compile( - `${declaration[0]}\n@theme { --color-input: #123456; }\n@tailwind utilities;` - ) - expect(compiler.build(['dark:bg-input/30'])).toContain('data-native-chat-scheme') - expect(declaration[1]).toContain( - ".dark *:not(:where([data-native-chat-scheme='light'], [data-native-chat-scheme='light'] *))" - ) - expect(declaration[1]).toContain( - ", [data-native-chat-scheme='dark'], [data-native-chat-scheme='dark'] *" - ) - }) -}) diff --git a/src/renderer/src/components/native-chat/native-chat-layout-actions.test.ts b/src/renderer/src/components/native-chat/native-chat-layout-actions.test.ts deleted file mode 100644 index fb860bec07a..00000000000 --- a/src/renderer/src/components/native-chat/native-chat-layout-actions.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { AppState } from '@/store/types' -import { - canRunNativeChatSplitTarget, - resolveActiveNativeChatSplitTarget -} from './native-chat-layout-actions' - -function stateWithActiveTab(tab: Record, tabOrder = ['chat']) { - return { - groupsByWorktree: { - workspace: [{ id: 'group', worktreeId: 'workspace', activeTabId: 'chat', tabOrder }] - }, - unifiedTabsByWorktree: { - workspace: [ - { - id: 'chat', - entityId: 'session', - groupId: 'group', - worktreeId: 'workspace', - ...tab - } - ] - } - } as unknown as Pick -} - -describe('native chat layout actions', () => { - it('can split a structured chat even when it is the only tab', () => { - const state = stateWithActiveTab({ contentType: 'agent-session', agentSessionAgent: 'codex' }) - const target = resolveActiveNativeChatSplitTarget(state, 'workspace', 'group') - - expect(target).toEqual({ kind: 'workspace-tab', unifiedTabId: 'chat', groupId: 'group' }) - expect(canRunNativeChatSplitTarget(state, target)).toBe(true) - }) - - it('resolves terminal-backed chat mode to the existing pane split path', () => { - const state = stateWithActiveTab({ contentType: 'terminal', viewMode: 'chat' }) - - expect(resolveActiveNativeChatSplitTarget(state, 'workspace', 'group')).toEqual({ - kind: 'terminal-pane', - terminalTabId: 'session' - }) - expect( - resolveActiveNativeChatSplitTarget( - stateWithActiveTab({ contentType: 'terminal', viewMode: 'terminal' }), - 'workspace', - 'group' - ) - ).toBeNull() - }) -}) diff --git a/src/renderer/src/components/new-workspace/ProjectComboboxRow.test.tsx b/src/renderer/src/components/new-workspace/ProjectComboboxRow.test.tsx index 1d98a5ae859..4abd8da599b 100644 --- a/src/renderer/src/components/new-workspace/ProjectComboboxRow.test.tsx +++ b/src/renderer/src/components/new-workspace/ProjectComboboxRow.test.tsx @@ -30,14 +30,6 @@ function markedText(): string { } describe('MatchedText', () => { - it('underlines the matched run', () => { - act(() => { - root.render() - }) - - expect(markedText()).toBe('orca') - }) - // UTF-16 hit offsets and code-point rendering differ for emoji; marks must stay on the matched glyphs. it('aligns marks with the query when the name starts with an emoji', () => { const option: NewWorkspaceProjectOption = { diff --git a/src/renderer/src/components/new-workspace/smart-workspace-source-popover-focus.test.ts b/src/renderer/src/components/new-workspace/smart-workspace-source-popover-focus.test.ts deleted file mode 100644 index 26dad28d3f5..00000000000 --- a/src/renderer/src/components/new-workspace/smart-workspace-source-popover-focus.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -// @vitest-environment happy-dom -import { describe, expect, it } from 'vitest' - -import { isComposerFieldToFieldFocus } from './smart-workspace-source-popover-focus' - -describe('isComposerFieldToFieldFocus', () => { - it('returns true when focus moves between fields inside the composer root', () => { - document.body.innerHTML = ` -
- - -
- ` - const nameInput = document.getElementById('name') as HTMLInputElement - const projectButton = document.getElementById('project') as HTMLButtonElement - - expect( - isComposerFieldToFieldFocus({ - currentTarget: nameInput, - relatedTarget: projectButton - }) - ).toBe(true) - }) - - it('returns false for dialog autofocus where focus comes from outside the composer', () => { - document.body.innerHTML = ` - -
- -
- ` - const nameInput = document.getElementById('name') as HTMLInputElement - const closeButton = document.getElementById('close') as HTMLButtonElement - - expect( - isComposerFieldToFieldFocus({ - currentTarget: nameInput, - relatedTarget: closeButton - }) - ).toBe(false) - }) - - it('returns false when relatedTarget is missing', () => { - document.body.innerHTML = ` -
- -
- ` - const nameInput = document.getElementById('name') as HTMLInputElement - - expect( - isComposerFieldToFieldFocus({ - currentTarget: nameInput, - relatedTarget: null - }) - ).toBe(false) - }) -}) diff --git a/src/renderer/src/components/settings/OpenInMenuSetting.test.ts b/src/renderer/src/components/settings/OpenInMenuSetting.test.ts deleted file mode 100644 index 84c65fcceb6..00000000000 --- a/src/renderer/src/components/settings/OpenInMenuSetting.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { - createPresetOpenInApplication, - shouldCommitOpenInApplicationsDraft -} from './OpenInMenuSetting' -import { - getOpenInAppPresets, - isOpenInAppPresetAdded, - OpenInApplicationIcon -} from '@/lib/open-in-app-catalog' -import type { OpenInAppPreset } from '@/lib/open-in-app-catalog' - -function requirePreset(id: string): OpenInAppPreset { - const preset = getOpenInAppPresets().find((entry) => entry.id === id) - if (!preset) { - throw new Error(`Preset not found: ${id}`) - } - return preset -} - -describe('OpenInMenuSetting presets', () => { - it('creates stable preset rows for known apps', () => { - const cursor = requirePreset('cursor') - - expect(createPresetOpenInApplication(cursor)).toEqual({ - id: 'cursor', - label: 'Cursor', - command: 'cursor' - }) - }) - - it('recognizes legacy preset rows by command', () => { - const cursor = requirePreset('cursor') - - expect(isOpenInAppPresetAdded([{ command: ' cursor ' }], cursor)).toBe(true) - }) - - it('keeps the Zed icon visible on dark menus', () => { - const icon = OpenInApplicationIcon({ application: { command: 'zed' } }) - - expect(icon.props.className).toContain('dark:invert') - }) -}) - -describe('OpenInMenuSetting application drafts', () => { - it('does not commit rows until both label and command are present', () => { - expect( - shouldCommitOpenInApplicationsDraft([{ id: 'draft', label: 'Cursor', command: '' }]) - ).toBe(false) - expect( - shouldCommitOpenInApplicationsDraft([{ id: 'draft', label: '', command: 'cursor' }]) - ).toBe(false) - expect( - shouldCommitOpenInApplicationsDraft([{ id: 'draft', label: ' ', command: 'cursor' }]) - ).toBe(false) - expect( - shouldCommitOpenInApplicationsDraft([{ id: 'draft', label: 'Cursor', command: ' ' }]) - ).toBe(false) - }) - - it('allows commit when every draft row has a label and command', () => { - expect(shouldCommitOpenInApplicationsDraft([])).toBe(true) - expect( - shouldCommitOpenInApplicationsDraft([{ id: 'cursor', label: 'Cursor', command: 'cursor' }]) - ).toBe(true) - expect( - shouldCommitOpenInApplicationsDraft([ - { id: 'cursor', label: 'Cursor', command: 'cursor' }, - { id: 'zed', label: 'Zed', command: 'zed' } - ]) - ).toBe(true) - }) -}) diff --git a/src/renderer/src/components/settings/Settings.load-performance.test.ts b/src/renderer/src/components/settings/Settings.load-performance.test.ts deleted file mode 100644 index 6edea688f1e..00000000000 --- a/src/renderer/src/components/settings/Settings.load-performance.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { deriveNeededSectionIds } from './settings-load-performance' - -describe('Settings load-performance helpers', () => { - it('keeps only eager and active sections mounted for empty search on first paint', () => { - const needed = deriveNeededSectionIds({ - navSectionIds: ['general', 'agents', 'appearance', 'terminal', 'stats', 'ssh', 'repo-a'], - mountedSectionIds: new Set(['general']), - activeSectionId: 'general', - pendingSectionId: null, - query: '', - visibleSectionIds: new Set([ - 'general', - 'agents', - 'appearance', - 'terminal', - 'stats', - 'ssh', - 'repo-a' - ]) - }) - - expect(Array.from(needed).sort()).toEqual(['general']) - }) - - it('keeps search mounting scoped to the active section', () => { - const needed = deriveNeededSectionIds({ - navSectionIds: ['general', 'agents', 'appearance', 'terminal', 'stats', 'repo-a'], - mountedSectionIds: new Set(['general']), - activeSectionId: 'general', - pendingSectionId: null, - query: 'stats', - visibleSectionIds: new Set(['stats']) - }) - - expect(needed.has('stats')).toBe(false) - expect(needed.has('general')).toBe(false) - }) - - it('mounts the active matched section during search', () => { - const needed = deriveNeededSectionIds({ - navSectionIds: ['general', 'agents', 'appearance', 'terminal', 'stats', 'repo-a'], - mountedSectionIds: new Set(['general']), - activeSectionId: 'stats', - pendingSectionId: null, - query: 'stats', - visibleSectionIds: new Set(['stats']) - }) - - expect(needed.has('stats')).toBe(true) - }) - - it('keeps a pending deep-link target mounted before jump work continues', () => { - const needed = deriveNeededSectionIds({ - navSectionIds: ['general', 'agents', 'appearance', 'terminal', 'repo-a'], - mountedSectionIds: new Set(['general']), - activeSectionId: 'general', - pendingSectionId: 'repo-a', - query: '', - visibleSectionIds: new Set(['general', 'agents', 'appearance', 'terminal', 'repo-a']) - }) - - expect(needed.has('repo-a')).toBe(true) - }) -}) diff --git a/src/renderer/src/components/settings/developer-permissions-search.test.ts b/src/renderer/src/components/settings/developer-permissions-search.test.ts index eb7a3194bf2..1936f84c5b6 100644 --- a/src/renderer/src/components/settings/developer-permissions-search.test.ts +++ b/src/renderer/src/components/settings/developer-permissions-search.test.ts @@ -54,9 +54,4 @@ describe('developer permissions LAN search', () => { expect(await searchInLocale('ko', 'LAN')).toBe(true) expect(await searchInLocale('es', 'LAN')).toBe(true) }) - - it('indexes both wordings as distinct Chinese keywords', async () => { - await i18n.changeLanguage('zh') - expect(getLanEntry().keywords).toEqual(expect.arrayContaining(['局域网', '本地网络'])) - }) }) diff --git a/src/renderer/src/components/settings/runtime-server-row-meta.test.ts b/src/renderer/src/components/settings/runtime-server-row-meta.test.ts deleted file mode 100644 index fca8dfb29fa..00000000000 --- a/src/renderer/src/components/settings/runtime-server-row-meta.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { describeNetworkAddress } from './network-address-label' -import { getRuntimeServerProblemLine } from './runtime-server-row-meta' - -const quietRow = { - accessRevoked: false, - problem: 'Timed out waiting for the remote Orca runtime.', - probeFailed: true, - compatibilityBlocked: false -} - -describe('runtime server problem line', () => { - it('says when an unreachable server was last seen instead of repeating the failure', () => { - const now = Date.UTC(2026, 9, 20) - expect( - getRuntimeServerProblemLine({ - environment: { lastUsedAt: now - 3 * 86_400_000 }, - row: quietRow, - remoteUpdate: undefined, - managedStatusError: null, - managedSummary: null, - address: '100.88.12.5:6768', - now - }) - ).toEqual({ text: 'Last seen 3 days ago · 100.88.12.5:6768', destructive: false }) - }) - - it('says a server was never connected rather than still waiting', () => { - expect( - getRuntimeServerProblemLine({ - environment: { lastUsedAt: null }, - row: quietRow, - remoteUpdate: undefined, - managedStatusError: null, - managedSummary: null, - address: '100.88.12.5:6768' - })?.text - ).toBe('Never connected · 100.88.12.5:6768') - }) -}) - -describe('a server paired twice', () => { - it('names the twin ahead of reachability, since one entry must go', () => { - expect( - getRuntimeServerProblemLine({ - environment: { lastUsedAt: null }, - row: quietRow, - remoteUpdate: undefined, - managedStatusError: null, - managedSummary: null, - address: '100.88.12.5:6768', - duplicateOfNames: ['Studio relay'] - }) - ).toEqual({ - text: 'Same server as Studio relay, paired twice. Remove one so its projects can be edited.', - destructive: true - }) - }) -}) - -describe('network address label', () => { - it('names Tailscale and LAN addresses instead of the interface', () => { - expect(describeNetworkAddress('utun6', '100.108.226.109')).toBe('Tailscale · 100.108.226.109') - expect(describeNetworkAddress('en0', '192.168.1.20')).toBe('Local network · 192.168.1.20') - expect(describeNetworkAddress('eth0', '203.0.113.5')).toBe('eth0 · 203.0.113.5') - }) -}) diff --git a/src/renderer/src/components/sidebar/worktree-unnest.test.ts b/src/renderer/src/components/sidebar/worktree-unnest.test.ts index 8869a35978f..5e531f99920 100644 --- a/src/renderer/src/components/sidebar/worktree-unnest.test.ts +++ b/src/renderer/src/components/sidebar/worktree-unnest.test.ts @@ -12,17 +12,6 @@ describe('unnestWorktrees', () => { vi.spyOn(console, 'error').mockImplementation(() => {}) }) - it('clears the parent link on every requested worktree', async () => { - const updateWorktreeLineage = vi.fn().mockResolvedValue(undefined) - - await unnestWorktrees(['repo1::/a', 'repo1::/b'], updateWorktreeLineage) - - expect(updateWorktreeLineage).toHaveBeenCalledTimes(2) - expect(updateWorktreeLineage).toHaveBeenCalledWith('repo1::/a', { noParent: true }) - expect(updateWorktreeLineage).toHaveBeenCalledWith('repo1::/b', { noParent: true }) - expect(toast.error).not.toHaveBeenCalled() - }) - it('toasts instead of rejecting when the lineage update fails', async () => { const updateWorktreeLineage = vi .fn() @@ -40,13 +29,4 @@ describe('unnestWorktrees', () => { expect(toast.error).toHaveBeenCalledTimes(1) }) - - it('does nothing for an empty selection', async () => { - const updateWorktreeLineage = vi.fn().mockResolvedValue(undefined) - - await unnestWorktrees([], updateWorktreeLineage) - - expect(updateWorktreeLineage).not.toHaveBeenCalled() - expect(toast.error).not.toHaveBeenCalled() - }) }) diff --git a/src/renderer/src/components/skills/skill-install-workspace-choices.test.ts b/src/renderer/src/components/skills/skill-install-workspace-choices.test.ts index 45bd7620f1e..9b27e192a76 100644 --- a/src/renderer/src/components/skills/skill-install-workspace-choices.test.ts +++ b/src/renderer/src/components/skills/skill-install-workspace-choices.test.ts @@ -1,5 +1,4 @@ import { describe, expect, it } from 'vitest' -import type { FolderWorkspace } from '../../../../shared/folder-workspace-types' import type { Repo } from '../../../../shared/repo-types' import type { Worktree } from '../../../../shared/worktree/types' import { skillInstallWorkspaceChoices } from './skill-install-workspace-choices' @@ -25,23 +24,4 @@ describe('skillInstallWorkspaceChoices', () => { }) ).toEqual([{ id: worktree.id, label: worktree.displayName, kind: 'worktree' }]) }) - - it('keeps local, paired-runtime, and SSH workspace catalogs isolated', () => { - const folders = [ - { id: 'local', name: 'Local', folderPath: '/local', executionHostId: 'local' }, - { - id: 'runtime', - name: 'Runtime', - folderPath: '/runtime', - executionHostId: 'runtime:environment_1' - }, - { id: 'ssh', name: 'SSH', folderPath: '/ssh', executionHostId: 'ssh:ssh_1' } - ] as FolderWorkspace[] - const input = { repos: [], worktreesByRepo: {}, folderWorkspaces: folders } - expect(skillInstallWorkspaceChoices({ ...input, environmentId: 'local' })).toHaveLength(1) - expect(skillInstallWorkspaceChoices({ ...input, environmentId: 'environment_1' })).toHaveLength( - 1 - ) - expect(skillInstallWorkspaceChoices({ ...input, environmentId: 'ssh:ssh_1' })).toHaveLength(1) - }) }) diff --git a/src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts b/src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts deleted file mode 100644 index 85e60279449..00000000000 --- a/src/renderer/src/components/status-bar/usage-provider-settings-target.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { describe, expect, it } from 'vitest' -import type { ClaudeManagedAccount } from '../../../../shared/managed-account-types' -import { - getUsageProviderAccountsSectionId, - usageRowSignInOpensSettings -} from './usage-provider-settings-target' - -describe('getUsageProviderAccountsSectionId', () => { - it('routes providers only to settings sections that exist', () => { - expect(getUsageProviderAccountsSectionId('claude')).toBe('accounts-claude') - expect(getUsageProviderAccountsSectionId('codex')).toBe('accounts-codex') - expect(getUsageProviderAccountsSectionId('gemini')).toBe('accounts-gemini') - expect(getUsageProviderAccountsSectionId('opencode-go')).toBe('accounts-opencode-go') - expect(getUsageProviderAccountsSectionId('minimax')).toBe('accounts-minimax') - expect(getUsageProviderAccountsSectionId('grok')).toBe('accounts-grok') - expect(getUsageProviderAccountsSectionId('cursor')).toBe('accounts-cursor') - expect(getUsageProviderAccountsSectionId('zcode')).toBe('accounts-zcode') - }) - - it('does not invent an Accounts section for CLI-owned credentials', () => { - expect(getUsageProviderAccountsSectionId('antigravity')).toBeNull() - expect(getUsageProviderAccountsSectionId('kimi')).toBeNull() - }) -}) - -describe('usageRowSignInOpensSettings', () => { - const account: ClaudeManagedAccount = { - id: 'a', - email: 'a@example.com', - authMethod: 'subscription-oauth', - managedAuthPath: '/unused', - createdAt: 1, - updatedAt: 1, - lastAuthenticatedAt: 1 - } - const saved = { claudeManagedAccounts: [account] } - - it('keeps the Claude menu, with its per-account Sign in, once accounts are saved', () => { - expect(usageRowSignInOpensSettings('claude', saved)).toBe(false) - expect(usageRowSignInOpensSettings('claude', { claudeManagedAccounts: [] })).toBe(true) - expect(usageRowSignInOpensSettings('claude', null)).toBe(true) - expect(usageRowSignInOpensSettings('codex', saved)).toBe(true) - expect(usageRowSignInOpensSettings('kimi', null)).toBe(false) - }) - - it("keeps the Settings shortcut on a remote server, whose accounts aren't local", () => { - expect( - usageRowSignInOpensSettings('claude', { - claudeManagedAccounts: [account], - activeRuntimeEnvironmentId: 'env-1' - }) - ).toBe(true) - }) -}) diff --git a/src/renderer/src/components/task-page/linear/task-page-linear-team-selection.test.ts b/src/renderer/src/components/task-page/linear/task-page-linear-team-selection.test.ts index 18fe6e36da9..6c431c610fc 100644 --- a/src/renderer/src/components/task-page/linear/task-page-linear-team-selection.test.ts +++ b/src/renderer/src/components/task-page/linear/task-page-linear-team-selection.test.ts @@ -14,17 +14,6 @@ function team(id: string): LinearTeam { } describe('reconcileLinearTeamSelection', () => { - it('selects every available team when the saved selection is sticky-all', () => { - expect(Array.from(reconcileLinearTeamSelection([team('a'), team('b')], null))).toEqual([ - 'a', - 'b' - ]) - }) - - it('preserves saved teams that still exist', () => { - expect(Array.from(reconcileLinearTeamSelection([team('a'), team('b')], ['b']))).toEqual(['b']) - }) - it('drops stale saved teams after switching workspaces', () => { expect(Array.from(reconcileLinearTeamSelection([team('c'), team('d')], ['a', 'd']))).toEqual([ 'd' @@ -52,21 +41,6 @@ describe('reconcileLinearTeamSelection', () => { }) describe('storedLinearTeamSelection', () => { - it('keeps a string array', () => { - expect(storedLinearTeamSelection(['a', 'b'])).toEqual(['a', 'b']) - }) - - it('reads null and undefined as sticky-all', () => { - expect(storedLinearTeamSelection(null)).toBeNull() - expect(storedLinearTeamSelection(undefined)).toBeNull() - }) - - it('reads a string, an object or a number as sticky-all instead of throwing', () => { - expect(storedLinearTeamSelection('a')).toBeNull() - expect(storedLinearTeamSelection({ 0: 'a' })).toBeNull() - expect(storedLinearTeamSelection(7)).toBeNull() - }) - it('drops non-string entries from a mixed array', () => { expect(storedLinearTeamSelection(['a', 1, null, 'b'])).toEqual(['a', 'b']) }) diff --git a/src/renderer/src/components/terminal-pane/terminal-keyboard-protocol-pane-agent.test.ts b/src/renderer/src/components/terminal-pane/terminal-keyboard-protocol-pane-agent.test.ts index d9278d6f0c5..4752757cb86 100644 --- a/src/renderer/src/components/terminal-pane/terminal-keyboard-protocol-pane-agent.test.ts +++ b/src/renderer/src/components/terminal-pane/terminal-keyboard-protocol-pane-agent.test.ts @@ -36,8 +36,4 @@ describe('pane-scoped terminal keyboard protocol agent', () => { expect(resolvedKittyKeyboard(null, 'grok')).toBe(false) }) - - it('keeps explicit pane startup identity ahead of a stale tab launch agent', () => { - expect(resolvePaneKeyboardProtocolAgent({ launchAgent: 'claude' }, 'grok')).toBe('claude') - }) }) diff --git a/src/renderer/src/components/terminal-pane/terminal-modify-other-keys-enter.test.ts b/src/renderer/src/components/terminal-pane/terminal-modify-other-keys-enter.test.ts index 7c767e022e1..da7b25fbd7f 100644 --- a/src/renderer/src/components/terminal-pane/terminal-modify-other-keys-enter.test.ts +++ b/src/renderer/src/components/terminal-pane/terminal-modify-other-keys-enter.test.ts @@ -1,6 +1,5 @@ import { readFileSync } from 'node:fs' import { join } from 'node:path' -import { Terminal } from '@xterm/headless' import { describe, expect, it } from 'vitest' import { TerminalKittyKeyboardModeTracker } from '../../../../shared/terminal-kitty-keyboard-mode-tracker' import { @@ -15,26 +14,6 @@ function readFixture(name: string): string { return readFileSync(join(FIXTURE_DIR, `${name}.txt`), 'utf8') } -/** pi's editor rows: the lines between the last two full-width rules above the footer. */ -async function renderEditorRows(transcript: string): Promise { - const terminal = new Terminal({ cols: 100, rows: 30, allowProposedApi: true }) - await new Promise((resolve) => terminal.write(transcript, resolve)) - const buffer = terminal.buffer.active - const rows: string[] = [] - for (let row = 0; row < terminal.rows; row++) { - rows.push( - buffer - .getLine(buffer.viewportY + row) - ?.translateToString(true) - .trim() ?? '' - ) - } - terminal.dispose() - const rules = rows.flatMap((text, index) => (/^─{50,}$/.test(text) ? [index] : [])) - const [open, close] = rules.slice(-2) - return rows.slice(open + 1, close).filter((text) => text.length > 0) -} - function enter(overrides: Partial): TerminalShortcutEvent { return { key: 'Enter', @@ -68,25 +47,6 @@ function resolveForPane(event: TerminalShortcutEvent, modes: TerminalKittyKeyboa } describe('modified Enter for an app that armed modifyOtherKeys (STA-7701)', () => { - it('reads pi editing semantics from the captured transcripts', async () => { - // ESC CR flips meaning with pi's private kitty state, which the pane cannot see. - expect(await renderEditorRows(readFixture('pi-0-74-modify-other-keys-esc-cr'))).toEqual(['def']) - expect(await renderEditorRows(readFixture('pi-0-74-late-kitty-esc-cr'))).toEqual(['abc', 'def']) - // CSI 27 ; mod ; 13 ~ means the same thing in both states. - for (const name of [ - 'pi-0-74-modify-other-keys-shift-enter-csi27', - 'pi-0-74-late-kitty-shift-enter-csi27' - ]) { - expect(await renderEditorRows(readFixture(name))).toEqual(['abc', 'def']) - } - for (const name of [ - 'pi-0-74-modify-other-keys-alt-enter-csi27', - 'pi-0-74-late-kitty-alt-enter-csi27' - ]) { - expect(await renderEditorRows(readFixture(name))).toEqual(['def']) - } - }) - it('sends xterm modifyOtherKeys Enter chords once pi has armed the mode', () => { const modes = new TerminalKittyKeyboardModeTracker() modes.scan(readFixture('pi-0-74-modify-other-keys-esc-cr')) diff --git a/src/renderer/src/runtime/layout-apply-paired-server-guard.test.ts b/src/renderer/src/runtime/layout-apply-paired-server-guard.test.ts index 5c6b887235e..1a70311cb75 100644 --- a/src/renderer/src/runtime/layout-apply-paired-server-guard.test.ts +++ b/src/renderer/src/runtime/layout-apply-paired-server-guard.test.ts @@ -1,6 +1,4 @@ // Paired-owned workspace layouts stay on their server; even layout-owner builds must never send them to local main. -import { readdirSync, readFileSync, statSync } from 'node:fs' -import path from 'node:path' import { beforeEach, describe, expect, it, vi } from 'vitest' import type { WorktreeOperationRouteState } from '@/lib/worktree-operation-route' import type { AppState } from '@/store/types' @@ -14,7 +12,6 @@ import { sendToServerMain, type WindowLayoutCommand } from './layout-apply-send' -import { runtimeEnvironmentIdUnlessTwin } from '@/lib/resolve-owner' import { createInitialTerminalThroughLayoutOwner } from '@/store/terminals/terminal-tab-create-through-layout-owner' const WORKTREE_ID = 'repo-1::/srv/w' @@ -80,10 +77,6 @@ describe.each(PAIRED_WORKSPACES)('$name', ({ workspaceId, rows }) => { mocks.callRuntimeRpc.mockReset() }) - it('resolves to its server, so every guard below reads it as paired', () => { - expect(runtimeEnvironmentIdUnlessTwin(rows, workspaceId)).toBe('env-b') - }) - it.each(COMMANDS)('sendLayoutApply sends no $type', (command) => { const handlers = { apply: vi.fn(), asToday: vi.fn(), refused: vi.fn() } @@ -117,39 +110,3 @@ describe.each(PAIRED_WORKSPACES)('$name', ({ workspaceId, rows }) => { expect(layoutApplyCalls()).toEqual([]) }) }) - -/** Every renderer source file that names the `layout.apply` method, with its count. */ -function layoutApplySenders(root: string): Record { - const found: Record = {} - const walk = (dir: string): void => { - for (const entry of readdirSync(dir)) { - const full = path.join(dir, entry) - if (statSync(full).isDirectory()) { - walk(full) - continue - } - if (!/\.tsx?$/.test(entry) || /\.(test|spec)\.tsx?$/.test(entry)) { - continue - } - const count = readFileSync(full, 'utf8').split(`'layout.apply'`).length - 1 - if (count > 0) { - found[path.relative(root, full).split(path.sep).join('/')] = count - } - } - } - walk(root) - return found -} - -describe('layout.apply senders', () => { - // A new sender must go through sendLayoutApply or carry the same guard, plus a case above. - it('are only the guarded paths pinned above', () => { - expect(layoutApplySenders(path.resolve(__dirname, '..'))).toEqual({ - // Only sendLayoutApply and sendToServerMain (layout-apply-send.ts) call it. - 'runtime/layout-apply-call.ts': 1, - // Tests' stand-in for main: it answers layout.apply, never sends it. - 'runtime/layout-apply-test-transport.test-fixture.ts': 1, - 'store/terminals/terminal-tab-create-through-layout-owner.ts': 1 - }) - }) -}) diff --git a/src/renderer/src/store/slices/editor-set-active-file-guard.test.ts b/src/renderer/src/store/slices/editor-set-active-file-guard.test.ts index de7f90c7c11..beb3f437908 100644 --- a/src/renderer/src/store/slices/editor-set-active-file-guard.test.ts +++ b/src/renderer/src/store/slices/editor-set-active-file-guard.test.ts @@ -41,11 +41,6 @@ afterEach(() => { }) describe('setActiveFile with an id that has no open file', () => { - it('premise: the open document is active', () => { - expect(store.getState().activeFileId).toBe(fileId) - expect(store.getState().activeFileIdByWorktree['wt-1']).toBe(fileId) - }) - it('leaves the in-memory and per-workspace active file unchanged', () => { store.getState().setActiveFile(GHOST_ID) expect(store.getState().activeFileId).toBe(fileId) diff --git a/src/shared/native-chat/input/native-chat-ask-fifo.test.ts b/src/shared/native-chat/input/native-chat-ask-fifo.test.ts deleted file mode 100644 index 6da8e414349..00000000000 --- a/src/shared/native-chat/input/native-chat-ask-fifo.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { expect, it } from 'vitest' -import { extractPendingAsk } from './native-chat-ask' -import type { NativeChatMessage } from '../../native-chat-types' - -type Block = NativeChatMessage['blocks'][number] - -function ask(text: string): Block { - return { type: 'tool-call', name: 'AskUserQuestion', input: { questions: [{ question: text }] } } -} -function toolResult(): Block { - return { type: 'tool-result', output: 'ok' } -} -function assistant(id: string, blocks: Block[]): NativeChatMessage { - return { id, role: 'assistant', timestamp: 1, source: 'transcript', blocks } -} - -it('keeps the newest ask pending when an older duplicate-content ask resolves first', () => { - const pending = extractPendingAsk([assistant('m', [ask('same'), ask('same'), toolResult()])]) - expect(pending?.questions[0]?.question).toBe('same') -})