diff --git a/mobile/src/notifications/use-remote-push-capable-hosts.test.tsx b/mobile/src/notifications/use-remote-push-capable-hosts.test.tsx
index 9b25ca3dcf9..b038b499ea2 100644
--- a/mobile/src/notifications/use-remote-push-capable-hosts.test.tsx
+++ b/mobile/src/notifications/use-remote-push-capable-hosts.test.tsx
@@ -180,17 +180,4 @@ describe('useRemotePushCapableHosts', () => {
await answer('host-1', [CAPABILITY])
expect(latest).toEqual({ supported: true, resolved: true })
})
-
- it('ignores an answer from a host the catalog no longer lists', async () => {
- await mount()
- await setClients([
- { hostId: 'host-ghost', client: clientFor('host-ghost'), state: 'connected' }
- ])
-
- await answer('host-ghost', [CAPABILITY])
-
- // An unpaired desktop cannot push to this phone, so its vote must not offer
- // the switch — nor count as the answer that resolves the section.
- expect(latest).toEqual({ supported: false, resolved: false })
- })
})
diff --git a/mobile/src/onboarding/MobileOnboardingPage.test.ts b/mobile/src/onboarding/MobileOnboardingPage.test.ts
index be539ea9208..fec0ef53169 100644
--- a/mobile/src/onboarding/MobileOnboardingPage.test.ts
+++ b/mobile/src/onboarding/MobileOnboardingPage.test.ts
@@ -97,7 +97,7 @@ describe('MobileOnboardingPage', () => {
const callbacks = await renderPage('session-view')
act(() => button('Open sessions in Chat UI').props.onPress())
- expect(callbacks.onSessionChoice).toHaveBeenCalledWith('chat')
+ expect(callbacks.onSessionChoice).toHaveBeenCalledExactlyOnceWith('chat')
expect(callbacks.onNotificationChoice).not.toHaveBeenCalled()
})
diff --git a/mobile/src/onboarding/NotificationOnboardingPreview.test.ts b/mobile/src/onboarding/NotificationOnboardingPreview.test.ts
index c279ec60a2c..5016ba38bd6 100644
--- a/mobile/src/onboarding/NotificationOnboardingPreview.test.ts
+++ b/mobile/src/onboarding/NotificationOnboardingPreview.test.ts
@@ -87,6 +87,7 @@ describe('NotificationOnboardingPreview', () => {
})
it('does not animate the banners when the page is off-screen', async () => {
+ mocks.reducedMotion = false
await renderPreview(false)
expect(mocks.loop).not.toHaveBeenCalled()
})
diff --git a/mobile/src/settings/app-update-settings-rows.test.tsx b/mobile/src/settings/app-update-settings-rows.test.tsx
index 77177bf7d63..b566cbc0508 100644
--- a/mobile/src/settings/app-update-settings-rows.test.tsx
+++ b/mobile/src/settings/app-update-settings-rows.test.tsx
@@ -65,7 +65,7 @@ describe('AppUpdateSettingsRows', () => {
'Last checked 2h ago'
])
act(() => pressables[0].props.onPress())
- expect(onUpdate).toHaveBeenCalledTimes(1)
+ expect(onUpdate).toHaveBeenCalledExactlyOnceWith('https://example.test')
})
it('shows a plain, untappable version row when current, and Never before a first success', () => {
diff --git a/mobile/src/settings/settings-screen-state.test.tsx b/mobile/src/settings/settings-screen-state.test.tsx
index ba790d50abc..a0ec8801f13 100644
--- a/mobile/src/settings/settings-screen-state.test.tsx
+++ b/mobile/src/settings/settings-screen-state.test.tsx
@@ -153,7 +153,7 @@ describe('shared settings screen state', () => {
// Without the request-epoch fence the stale read would flip the switch back on.
expect(switchProps().value).toBe(false)
})
- it('does not enable notifications after denied OS permission', async () => {
+ it('does not enable notifications when permission is not granted', async () => {
const denied = {
granted: false,
status: 'undetermined',
diff --git a/mobile/src/settings/voice-settings-poller-refresh.test.tsx b/mobile/src/settings/voice-settings-poller-refresh.test.tsx
index ec3b4370e19..6a44f4f4415 100644
--- a/mobile/src/settings/voice-settings-poller-refresh.test.tsx
+++ b/mobile/src/settings/voice-settings-poller-refresh.test.tsx
@@ -6,7 +6,7 @@ import type { VoiceSettingsOperations } from './voice-settings-operations'
// Why: the sibling state test stubs the poller, so it can only prove the screen's local
// machine. This one runs the real useDictationSetupPoller, whose refreshNow is gated on
-// visible && foreground, to prove the rejected-save recovery actually reaches the wire.
+// visible && foreground, to prove rejected-save recovery reaches the load operation.
vi.mock('react-native', () => ({
View: 'View',
Text: 'Text',
diff --git a/src/main/persistence/applying-settings/persistence-native-chat-tab-view-mode.test.ts b/src/main/persistence/applying-settings/persistence-native-chat-tab-view-mode.test.ts
index 5de84f4dac3..4c05c32eb82 100644
--- a/src/main/persistence/applying-settings/persistence-native-chat-tab-view-mode.test.ts
+++ b/src/main/persistence/applying-settings/persistence-native-chat-tab-view-mode.test.ts
@@ -60,7 +60,7 @@ describe('Store native-chat tab viewMode persistence', () => {
})
// Preserve absent viewMode for legacy tabs; renderer hydration supplies terminal mode.
- it('round-trips viewMode for unified tabs and defaults legacy tabs to terminal', async () => {
+ it('loads chat viewMode and preserves missing legacy viewMode', async () => {
const WORKTREE = 'repo1::/worktree'
writeDataFile({
schemaVersion: 1,
diff --git a/src/main/persistence/applying-settings/persistence-right-sidebar-tab.test.ts b/src/main/persistence/applying-settings/persistence-right-sidebar-tab.test.ts
index 5b04ff67e3e..4cb794b84d6 100644
--- a/src/main/persistence/applying-settings/persistence-right-sidebar-tab.test.ts
+++ b/src/main/persistence/applying-settings/persistence-right-sidebar-tab.test.ts
@@ -22,7 +22,7 @@ describe('normalizeRightSidebarTab', () => {
}
)
- it('preserves the folder-only pr-checks tab across restarts', () => {
+ it('preserves the folder-only pr-checks tab', () => {
expect(normalizeRightSidebarTab('pr-checks')).toBe('pr-checks')
})
diff --git a/src/main/persistence/applying-settings/persistence-settings-update.test.ts b/src/main/persistence/applying-settings/persistence-settings-update.test.ts
index 8800870d033..618095236b3 100644
--- a/src/main/persistence/applying-settings/persistence-settings-update.test.ts
+++ b/src/main/persistence/applying-settings/persistence-settings-update.test.ts
@@ -98,7 +98,7 @@ describe('Store', () => {
expect(updated.branchPrefix).toBe('git-username')
})
- it('persists the agent skill sharing capability as an exact boolean', async () => {
+ it('normalizes the agent skill sharing capability to an exact boolean', async () => {
const store = await createStore()
expect(store.updateSettings({ agentSkillSharingEnabled: true }).agentSkillSharingEnabled).toBe(
diff --git a/src/main/persistence/loading-store/legacy-opencode-go-api-key-migration.test.ts b/src/main/persistence/loading-store/legacy-opencode-go-api-key-migration.test.ts
index a5e94937b51..019330f25a1 100644
--- a/src/main/persistence/loading-store/legacy-opencode-go-api-key-migration.test.ts
+++ b/src/main/persistence/loading-store/legacy-opencode-go-api-key-migration.test.ts
@@ -119,6 +119,7 @@ describe('migrateLegacyOpenCodeGoApiKey', () => {
expect(migrateLegacyOpenCodeGoApiKey(secrets, store)).toBe(true)
expect(store.save).not.toHaveBeenCalled()
expect(store.value()).toBe('fake-current-key')
+ expect(secrets.sealedBlob(LEGACY_OPENCODE_GO_API_KEY_SLOT)).toBeNull()
expect(secretStore.decryptString).not.toHaveBeenCalled()
expect(console.warn).toHaveBeenCalledWith(
'[opencode-go] Kept the existing saved API key and dropped the one from settings.'
diff --git a/src/main/persistence/loading-store/normalize-loaded-project-catalog.test.ts b/src/main/persistence/loading-store/normalize-loaded-project-catalog.test.ts
index 8a535b41919..597a1bf6242 100644
--- a/src/main/persistence/loading-store/normalize-loaded-project-catalog.test.ts
+++ b/src/main/persistence/loading-store/normalize-loaded-project-catalog.test.ts
@@ -63,5 +63,13 @@ describe('normalizeLoadedProjectCatalog', () => {
const result = normalizeLoadedProjectCatalog({}, vi.fn())
expect(result.projects).toEqual([])
expect(result.projectHostSetups).toEqual([])
+ const malformed = corrupt(makeParsed([], []), {
+ projects: 'not-an-array',
+ projectHostSetups: {}
+ })
+ expect(normalizeLoadedProjectCatalog(malformed, vi.fn())).toEqual({
+ projects: [],
+ projectHostSetups: []
+ })
})
})
diff --git a/src/renderer/src/components/tab-bar/TabBarCreateEntry.keyboard.test.tsx b/src/renderer/src/components/tab-bar/TabBarCreateEntry.keyboard.test.tsx
index 035cba0c0c1..547462c9ca8 100644
--- a/src/renderer/src/components/tab-bar/TabBarCreateEntry.keyboard.test.tsx
+++ b/src/renderer/src/components/tab-bar/TabBarCreateEntry.keyboard.test.tsx
@@ -8,9 +8,6 @@ import type { TerminalTab } from '../../../../shared/terminal-tab-types'
import type { Worktree } from '../../../../shared/worktree/types'
import type { TabEntryOption } from './tab-create-entry-action'
import type { TabAgentLaunchOption } from './tab-agent-launch-options'
-// Unmocked on purpose: the empty-query message must stay in step with the
-// placeholder rendered below.
-import { getTabEntryOptions as classifyTabEntryOptions } from './tab-create-entry-classifier'
import { TooltipProvider } from '@/components/ui/tooltip'
import { useAppStore } from '@/store'
import type { AppState } from '@/store/types'
@@ -310,20 +307,6 @@ describe('TabBarCreateEntry keyboard navigation', () => {
expect(input.getAttribute('aria-label')).toBe(placeholder)
})
- it('states the same thing in the empty-query message as in the placeholder', () => {
- mount()
-
- const [emptyOption] = classifyTabEntryOptions('', {
- files: [],
- loading: false,
- loadError: null
- })
- expect(emptyOption.classification).toMatchObject({ kind: 'empty' })
- expect(
- emptyOption.classification.kind === 'empty' ? emptyOption.classification.message : null
- ).toBe(container.querySelector('input')!.getAttribute('placeholder'))
- })
-
it('offers no switch rows when the menu opens with tabs open and no query', () => {
seedOpenTabs()
mount(
diff --git a/src/renderer/src/components/tab-bar/TabStripScrollIndicator.test.tsx b/src/renderer/src/components/tab-bar/TabStripScrollIndicator.test.tsx
index d7c64f2f518..8ac01b3eb5b 100644
--- a/src/renderer/src/components/tab-bar/TabStripScrollIndicator.test.tsx
+++ b/src/renderer/src/components/tab-bar/TabStripScrollIndicator.test.tsx
@@ -31,13 +31,6 @@ describe('TabStripScrollIndicator', () => {
expect(indicator.className).toContain('opacity-0')
})
- it('applies pointer-events-none when disabled', () => {
- const { getByTestId } = render()
- const indicator = getByTestId('tab-strip-scroll-indicator')
- expect(indicator.className).toContain('pointer-events-none')
- expect(indicator.className).not.toContain('group-hover/tab-strip:pointer-events-auto')
- })
-
it('stays hidden and unexpanded on hover when disabled', () => {
const { getByTestId } = render()
const indicator = getByTestId('tab-strip-scroll-indicator')
@@ -113,6 +106,7 @@ describe('TabStripScrollIndicator', () => {
expect(scrollToMock).toHaveBeenCalledTimes(1)
expect(scrollToMock).toHaveBeenCalledWith(
expect.objectContaining({
+ left: 300,
behavior: 'smooth'
})
)
diff --git a/src/shared/feedback-image-limits.test.ts b/src/shared/feedback-image-limits.test.ts
index 171364886de..3d0f80093a0 100644
--- a/src/shared/feedback-image-limits.test.ts
+++ b/src/shared/feedback-image-limits.test.ts
@@ -1,9 +1,5 @@
import { describe, expect, it } from 'vitest'
-import {
- MAX_FEEDBACK_IMAGE_BYTES,
- MAX_FEEDBACK_IMAGE_COUNT,
- MAX_FEEDBACK_IMAGE_TOTAL_BYTES
-} from './feedback-image-limits'
+import { MAX_FEEDBACK_IMAGE_BYTES, MAX_FEEDBACK_IMAGE_TOTAL_BYTES } from './feedback-image-limits'
// Why: the exact value is a judgement call, staying under the host's limit is
// not. https://www.onorca.dev/v1/feedback is a Vercel Function and rejects
@@ -19,8 +15,4 @@ describe('feedback image limits', () => {
it('cannot let one image exceed the whole budget', () => {
expect(MAX_FEEDBACK_IMAGE_BYTES).toBeLessThanOrEqual(MAX_FEEDBACK_IMAGE_TOTAL_BYTES)
})
-
- it('leaves room for more than one attachment', () => {
- expect(MAX_FEEDBACK_IMAGE_COUNT).toBeGreaterThan(1)
- })
})