diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc
index f6a6f94c912..15a820f0dd4 100644
--- a/config/reliability-gates.jsonc
+++ b/config/reliability-gates.jsonc
@@ -1403,7 +1403,7 @@
"id": "settings.accounts-section-lifetime",
"title": "Accounts search preserves matching account section owners",
"maturity": "experimental",
- "protection": "partial",
+ "protection": "none",
"owner": "renderer-settings",
"layer": "renderer-unit",
"surfaces": [
@@ -1413,53 +1413,29 @@
],
"platforms": ["macos", "linux", "windows"],
"providers": ["local", "remote-runtime", "ssh", "wsl"],
- "coveredPlatforms": ["macos"],
+ "coveredPlatforms": [],
"coveredProviders": [],
- "coverageNotes": "Actual AccountsPane, Grok, Cursor and Codex login components; synthetic APIs/store with Windows account support enabled/disabled. No real account, keychain or provider action.",
+ "coverageNotes": "Audit1437 removes AccountsPane.section-lifetime.test.tsx: DOM identity, mock status/read/subscription counts and simulated platform variants are intentionally retired. No equivalent replacement coverage is claimed. Historical coverage account: Actual AccountsPane, Grok, Cursor and Codex login components; synthetic APIs/store with Windows account support enabled/disabled. No real account, keychain or provider action.",
"motivatingLinks": [
"https://github.com/stablyai/orca/blob/main/src/renderer/src/components/settings/accounts/AccountsPane.tsx"
],
"invariant": "Matching sections retain their owners as earlier search results disappear; genuine removal releases the Codex subscription and reopens fresh status reads.",
- "oracle": "Across nine matching Grok, ten matching Cursor and eleven matching Codex queries each matched section keeps the same DOM node and its status-read, watcher and subscription counts do not grow, against four to six reads each before. Explicit refresh, store-published usage updates, pushed login URLs and genuine removal all still reach the retained section.",
- "commands": [
- "ORCA_BACKGROUND_LAUNCH=1 pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx"
- ],
- "testFiles": [
- "src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx"
- ],
- "assertionRefs": [
- {
- "file": "src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx",
- "assertions": [
- "preserves explicit Grok refresh and real hide/reopen status reads",
- "keeps the login subscription until Codex genuinely hides",
- "keeps Cursor refresh driven by usage updates and genuine reopen"
- ]
- }
- ],
- "evidenceRuns": [
- {
- "date": "2026-09-26",
- "runner": "local",
- "platform": "macos",
- "command": "ORCA_BACKGROUND_LAUNCH=1 pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/AccountsPane.section-lifetime.test.tsx",
- "currentCommand": "ORCA_BACKGROUND_LAUNCH=1 pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx",
- "result": "passed",
- "durationSeconds": 1.84,
- "summary": "10 tests/1 suite pass after the shared SettingsSectionStack adoption. Read-count oracles restated as node identity plus non-growing counts; original main fails the three retained-section cases and the retained Codex subscription, and passes the explicit-refresh, usage-driven and genuine-removal controls."
- }
- ],
+ "oracle": "No current automated oracle is claimed after Audit1437 removed this suite. Historical oracle account: Across nine matching Grok, ten matching Cursor and eleven matching Codex queries each matched section keeps the same DOM node and its status-read, watcher and subscription counts do not grow, against four to six reads each before. Explicit refresh, store-published usage updates, pushed login URLs and genuine removal all still reach the retained section.",
+ "commands": [],
+ "testFiles": [],
+ "assertionRefs": [],
+ "evidenceRuns": [],
"runtimeBudget": {
"p95Seconds": 10,
"scope": "Focused renderer-unit suites, p95 not established."
},
"flakeHistory": {
"status": "not-started",
- "evidence": "Author and independent local evidence only; no CI soak."
+ "evidence": "No current suite remains. Historical account: Author and independent local evidence only; no CI soak."
},
"redGreenEvidence": {
- "status": "complete",
- "evidence": "Candidate ten pass; current-main original seven fail and three controls pass."
+ "status": "missing",
+ "evidence": "Historical red/green only after suite removal. Candidate ten pass; current-main original seven fail and three controls pass."
},
"performanceBudget": {
"required": true,
@@ -1470,7 +1446,8 @@
"No native Linux/Windows or live SSH/WSL/paired provider behavior; platform flags are simulated.",
"Hidden Electron Grok proof uses the original audit baseline and synthetic status; current-main Cursor addition has unit evidence only.",
"Matching search no longer incidentally refreshes Grok/Cursor status or pending Codex URLs. Every one of those surfaces is store-subscribed or push-subscribed, so the retained section still tracks usage updates, pushed login URLs, explicit refresh and true hide/reopen; there is no bounded automatic freshness deadline and none of them relied on one before.",
- "Child drafts, errors, copied feedback and timers remain until their own transition or real removal."
+ "Child drafts, errors, copied feedback and timers remain until their own transition or real removal.",
+ "Audit1437 removes AccountsPane.section-lifetime.test.tsx: DOM identity, mock status/read/subscription counts and simulated platform variants are intentionally retired. No equivalent replacement coverage is claimed. Original complete gate record: {\"id\":\"settings.accounts-section-lifetime\",\"title\":\"Accounts search preserves matching account section owners\",\"maturity\":\"experimental\",\"protection\":\"partial\",\"owner\":\"renderer-settings\",\"layer\":\"renderer-unit\",\"surfaces\":[\"Accounts settings search\",\"Grok and Cursor account status\",\"Codex pending sign-in link\"],\"platforms\":[\"macos\",\"linux\",\"windows\"],\"providers\":[\"local\",\"remote-runtime\",\"ssh\",\"wsl\"],\"coveredPlatforms\":[\"macos\"],\"coveredProviders\":[],\"coverageNotes\":\"Actual AccountsPane, Grok, Cursor and Codex login components; synthetic APIs/store with Windows account support enabled/disabled. No real account, keychain or provider action.\",\"motivatingLinks\":[\"https://github.com/stablyai/orca/blob/main/src/renderer/src/components/settings/accounts/AccountsPane.tsx\"],\"invariant\":\"Matching sections retain their owners as earlier search results disappear; genuine removal releases the Codex subscription and reopens fresh status reads.\",\"oracle\":\"Across nine matching Grok, ten matching Cursor and eleven matching Codex queries each matched section keeps the same DOM node and its status-read, watcher and subscription counts do not grow, against four to six reads each before. Explicit refresh, store-published usage updates, pushed login URLs and genuine removal all still reach the retained section.\",\"commands\":[\"ORCA_BACKGROUND_LAUNCH=1 pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx\"],\"testFiles\":[\"src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx\"],\"assertionRefs\":[{\"file\":\"src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx\",\"assertions\":[\"preserves explicit Grok refresh and real hide/reopen status reads\",\"keeps the login subscription until Codex genuinely hides\",\"keeps Cursor refresh driven by usage updates and genuine reopen\"]}],\"evidenceRuns\":[{\"date\":\"2026-09-26\",\"runner\":\"local\",\"platform\":\"macos\",\"command\":\"ORCA_BACKGROUND_LAUNCH=1 pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/AccountsPane.section-lifetime.test.tsx\",\"currentCommand\":\"ORCA_BACKGROUND_LAUNCH=1 pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx\",\"result\":\"passed\",\"durationSeconds\":1.84,\"summary\":\"10 tests/1 suite pass after the shared SettingsSectionStack adoption. Read-count oracles restated as node identity plus non-growing counts; original main fails the three retained-section cases and the retained Codex subscription, and passes the explicit-refresh, usage-driven and genuine-removal controls.\"}],\"runtimeBudget\":{\"p95Seconds\":10,\"scope\":\"Focused renderer-unit suites, p95 not established.\"},\"flakeHistory\":{\"status\":\"not-started\",\"evidence\":\"Author and independent local evidence only; no CI soak.\"},\"redGreenEvidence\":{\"status\":\"complete\",\"evidence\":\"Candidate ten pass; current-main original seven fail and three controls pass.\"},\"performanceBudget\":{\"required\":true,\"evidence\":\"Actual renderer status-read/subscription admissions counted; the section map now lives in the shared SettingsSectionStack and no cache, poll, listener or process is added. No CPU, latency or heap claim. Matching sections retain local state and lose only the incidental search-driven refresh that duplicated an existing subscription.\"},\"knownGaps\":[\"CI soak pending.\",\"No native Linux/Windows or live SSH/WSL/paired provider behavior; platform flags are simulated.\",\"Hidden Electron Grok proof uses the original audit baseline and synthetic status; current-main Cursor addition has unit evidence only.\",\"Matching search no longer incidentally refreshes Grok/Cursor status or pending Codex URLs. Every one of those surfaces is store-subscribed or push-subscribed, so the retained section still tracks usage updates, pushed login URLs, explicit refresh and true hide/reopen; there is no bounded automatic freshness deadline and none of them relied on one before.\",\"Child drafts, errors, copied feedback and timers remain until their own transition or real removal.\"],\"promotionCriteria\":[\"Retain read/subscription counts and genuine-removal controls; collect CI soak and relevant full-app provider evidence.\"],\"demotionRule\":\"Keep experimental until soak; investigate owner and refresh regressions without weakening assertions or adding retries.\"}"
],
"promotionCriteria": [
"Retain read/subscription counts and genuine-removal controls; collect CI soak and relevant full-app provider evidence."
diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json
index 3ed7ee2d677..2ebbdfcb9f2 100644
--- a/config/scripts/ci-shard-timings.json
+++ b/config/scripts/ci-shard-timings.json
@@ -7839,9 +7839,6 @@
"src/renderer/src/components/right-sidebar/source-control/ai/useSourceControlAgentActionDialog.test.tsx": 6336,
"src/renderer/src/components/right-sidebar/source-control/listing/useSourceControlSubmoduleStatus.test.tsx": 2076,
"src/renderer/src/components/settings/accounts/AccountsPane.owner-scope.test.tsx": 4057,
- "src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx": 2893,
- "src/renderer/src/components/settings/accounts/AccountsPane.test.tsx": 2701,
- "src/renderer/src/components/settings/agents/surfaces/AgentDefaultSurfaceSection.test.tsx": 3070,
"src/renderer/src/components/skills/setup/AgentSkillSetupPanel.freshness.test.tsx": 15418,
"src/renderer/src/components/skills/setup/AgentSkillSetupPanel.plan-status.test.tsx": 23334,
"src/renderer/src/components/skills/setup/AgentSkillSetupPanel.remote-availability.test.tsx": 5937,
diff --git a/src/renderer/src/components/settings/accounts/AccountsPane.owner-scope.test.tsx b/src/renderer/src/components/settings/accounts/AccountsPane.owner-scope.test.tsx
index 93cccee97f3..5dfdb7325a5 100644
--- a/src/renderer/src/components/settings/accounts/AccountsPane.owner-scope.test.tsx
+++ b/src/renderer/src/components/settings/accounts/AccountsPane.owner-scope.test.tsx
@@ -1,28 +1,18 @@
// @vitest-environment happy-dom
import '@testing-library/jest-dom/vitest'
-import { useEffect, useLayoutEffect, useState } from 'react'
-import { act, cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react'
+import { act, cleanup, fireEvent, render, screen, within } from '@testing-library/react'
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { toast } from 'sonner'
import { i18n } from '@/i18n/i18n'
-import esCatalog from '@/i18n/locales/es.json'
-import { callAntigravityAccounts } from '@/runtime/runtime-antigravity-accounts-client'
-import type { AntigravityAccountState } from '../../../../../shared/antigravity-account-types'
import { getDefaultSettings } from '../../../../../shared/constants'
-import type { GlobalSettings } from '../../../../../shared/global-settings-types'
import type {
ClaudeManagedAccountSummary,
ClaudeRateLimitAccountsState
} from '../../../../../shared/managed-account-types'
import type { RuntimeClientTarget } from '../../../../../shared/runtime-client-target'
import { AccountsPane } from './AccountsPane'
-import { createTestStore } from '@/store/slices/store-test-helpers'
-import { useSettingsHostNavigation } from '../host-scope/use-settings-host-navigation'
-import { resolveSettingsHostScope, type SettingsHostScope } from '../host-scope/settings-host-scope'
+import type { SettingsHostScope } from '../host-scope/settings-host-scope'
import type { SettingsNavigationTarget } from '@/lib/settings-navigation-types'
-import { ProviderAccountChatButton } from '../../status-bar/ProviderAccountChatButton'
-import { ClaudeSwitcherMenu } from '../../status-bar/ClaudeSwitcherMenu'
-import { TooltipProvider } from '../../ui/tooltip'
// Why: focus deliberately points at another server; the pane must follow hostScope only.
const focusedElsewhere = {
@@ -190,46 +180,6 @@ afterEach(() => {
Reflect.deleteProperty(window, 'api')
})
-it('lists the accounts of the host chosen in the page, not the focused server', async () => {
- render(renderPane(scopeFor(null)))
- await act(async () => {})
- expect(screen.getByText('local@desktop.test')).toBeTruthy()
- expect(fake.watchedTargets).toEqual([{ kind: 'local' }])
-})
-
-it('shows Windows account guidance for the page owner rather than the focused server', async () => {
- fake.query = 'antigravity'
- const empty: AntigravityAccountState = {
- accounts: [],
- activeAccountId: null,
- selectedAccountId: null,
- currentAccount: null
- }
- vi.mocked(callAntigravityAccounts).mockResolvedValue(empty)
- render(
-
- )
-
- expect(await screen.findByText('No native agy account is signed in.')).toBeTruthy()
- expect(callAntigravityAccounts).toHaveBeenCalledWith(
- { kind: 'environment', environmentId: 'server-a' },
- { runtime: 'host', wslDistro: null },
- 'List'
- )
- expect(
- screen.getByText(
- 'Select applies and verifies the host default agy credential. Command choices and later account changes are handled by agy. Existing sessions may keep their previous account.'
- )
- ).toBeTruthy()
- expect(screen.queryByText(/Selection applies to new agy sessions on this host/)).toBeNull()
-})
-
it("drops a server's late account result after the page moves to another server", async () => {
const view = render(renderPane(scopeFor('server-a')))
await act(async () => {})
@@ -263,237 +213,3 @@ it('keeps a late account result once the pane is back on the server it was sent
expect(within(alphaRow()).getByText('Active')).toBeTruthy()
})
-
-it("shows a WSL host's distro accounts from this desktop and selects for that distro", async () => {
- const roster = claudeRoster('acct-w', 'wsl@ubuntu.test', false)
- roster.accounts = roster.accounts.map((account) => ({
- ...account,
- managedAuthRuntime: 'wsl',
- wslDistro: 'Ubuntu'
- }))
- fake.rosters.set('local', roster)
- render(
-
- )
- await act(async () => {})
- expect(fake.watchedTargets).toEqual([{ kind: 'local' }])
- fireEvent.click(screen.getByText('wsl@ubuntu.test'))
- expect(fake.selects).toEqual([
- [{ kind: 'local' }, { accountId: 'acct-w', runtime: 'wsl', wslDistro: 'Ubuntu' }]
- ])
-})
-
-it.each(['add', 'manage'] as const)(
- '%s navigation keeps native Windows accounts through consumption until explicit navigation releases them',
- async (entry) => {
- vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Windows')
- const roster = claudeRoster('native', 'native@windows.test', true)
- roster.accounts.push(
- { ...roster.accounts[0], id: 'native2', email: 'second@windows.test' },
- {
- ...roster.accounts[0],
- id: 'wsl',
- email: 'wsl@ubuntu.test',
- managedAuthRuntime: 'wsl',
- wslDistro: 'Ubuntu'
- }
- )
- fake.rosters.set('local', roster)
- const settingsStore = createTestStore()
- settingsStore.setState({
- settings: {
- ...focusedElsewhere,
- localAccountRuntime: 'wsl',
- localAccountWslDistro: 'Ubuntu'
- }
- })
- const writeSettings = vi.fn(async (updates: Partial) => ({
- ...settingsStore.getState().settings,
- ...updates
- }))
- Object.assign(window.api, { settings: { set: writeSettings } })
- function Visit({
- target,
- clear
- }: {
- target: SettingsNavigationTarget | null
- clear: () => void
- }) {
- const navigation = useSettingsHostNavigation(target)
- const { consumeSettingsNavigation } = navigation
- const settings = settingsStore((state) => state.settings) ?? focusedElsewhere
- const scope = resolveSettingsHostScope({
- choice: navigation.settingsHostChoice,
- defaultEnvironmentId: 'focused-server',
- savedEnvironmentIds: ['focused-server'],
- catalogHydrated: true
- })
- useEffect(() => {
- if (target) {
- consumeSettingsNavigation(target)
- clear()
- }
- }, [target, clear, consumeSettingsNavigation])
- useLayoutEffect(() => {
- // The first possible action precedes consumption effects, even with another default host.
- document.querySelector('#accounts-claude button')?.click()
- }, [])
- return (
- <>
-
-
-
- >
- )
- }
- function Flow() {
- const [target, setTarget] = useState(null)
- const [opened, setOpened] = useState(false)
- fake.navigate = (next) => {
- setTarget(next)
- setOpened(true)
- }
- return (
-
- {opened ? (
- <>
-
- setTarget(null)} />
- >
- ) : entry === 'add' ? (
-
- ) : (
- true }}
- />
- )}
-
- )
- }
- const view = render()
- const enter = async () => {
- const trigger = await screen.findByRole('button', {
- name: entry === 'add' ? 'Add Account…' : 'Switch Account'
- })
- await waitFor(() => expect(trigger).toBeEnabled())
- if (entry === 'add') {
- fireEvent.click(trigger)
- } else {
- fireEvent.pointerDown(trigger, { button: 0, ctrlKey: false, pointerType: 'mouse' })
- fireEvent.click(await screen.findByRole('menuitem', { name: /Add another account…/ }))
- }
- }
- const add = async () => {
- const section = document.getElementById('accounts-claude')
- if (!section) {
- throw new Error('Missing Claude section')
- }
- const button = within(section).getByRole('button', { name: 'Add Account' })
- await waitFor(() => expect(button).toBeEnabled())
- fireEvent.click(button)
- await act(async () => {})
- }
- await enter()
- await waitFor(() => expect(fake.add).toHaveBeenCalled())
- expect(fake.add.mock.calls[0]).toEqual([
- { runtime: 'host', wslDistro: undefined, copyLink: false }
- ])
- expect(fake.watchedTargets).not.toContainEqual({
- kind: 'environment',
- environmentId: 'focused-server'
- })
- expect(screen.getByText('native@windows.test')).toBeTruthy()
- expect(screen.queryByText('wsl@ubuntu.test')).toBeNull()
- expect(writeSettings).not.toHaveBeenCalled()
- await add()
- expect(fake.add.mock.lastCall?.[0].runtime).toBe('host')
- // The actual picker remains available; only an explicit selection writes the preference.
- fake.query = 'Account Location'
- view.rerender()
- vi.spyOn(console, 'error').mockImplementation(() => {})
- i18n.addResourceBundle('es', 'translation', esCatalog)
- await i18n.changeLanguage(entry === 'manage' ? 'es' : 'en')
- writeSettings.mockRejectedValueOnce(new Error('settings write failed'))
- await act(async () => fireEvent.click(screen.getByRole('radio', { name: 'Windows' })))
- expect(toast.error).toHaveBeenCalledExactlyOnceWith(
- entry === 'manage'
- ? 'No se pudo guardar la ubicación de las cuentas. Inténtalo de nuevo.'
- : 'Account location could not be saved. Try again.'
- )
- expect(console.error).not.toHaveBeenCalled()
- await i18n.changeLanguage('en')
- expect(settingsStore.getState().settings?.localAccountRuntime).toBe('wsl')
- expect(screen.getByRole('radio', { name: 'Windows' })).toHaveAttribute('aria-checked', 'true')
- fake.query = 'claude'
- view.rerender()
- expect(screen.getByText('native@windows.test')).toBeTruthy()
- expect(screen.queryByText('wsl@ubuntu.test')).toBeNull()
- fake.query = 'Account Location'
- view.rerender()
- writeSettings.mockClear()
- const write = Promise.withResolvers()
- writeSettings.mockReturnValueOnce(write.promise)
- fireEvent.click(screen.getByRole('radio', { name: 'Windows' }))
- expect(screen.getByRole('radio', { name: 'Windows' })).toHaveAttribute('aria-checked', 'true')
- expect(writeSettings).toHaveBeenCalledExactlyOnceWith({ localAccountRuntime: 'host' })
- await act(async () =>
- write.resolve({
- ...focusedElsewhere,
- localAccountRuntime: 'host',
- localAccountWslDistro: 'Ubuntu'
- })
- )
- await act(async () => fireEvent.click(screen.getByRole('radio', { name: 'WSL' })))
- expect(writeSettings.mock.lastCall).toEqual([{ localAccountRuntime: 'wsl' }])
- fake.query = 'claude'
- view.rerender()
- await add()
- expect(fake.add.mock.lastCall?.[0]).toMatchObject({ runtime: 'wsl', wslDistro: 'Ubuntu' })
- expect(screen.getByText('wsl@ubuntu.test')).toBeTruthy()
- fireEvent.click(screen.getByText('Close Settings'))
- await enter()
- await add()
- expect(fake.add.mock.lastCall?.[0].runtime).toBe('host')
- fireEvent.click(screen.getByText('Choose local host'))
- await add()
- expect(fake.add.mock.lastCall?.[0].runtime).toBe('wsl')
- fireEvent.click(screen.getByText('Close Settings'))
- await enter()
- fireEvent.click(screen.getByText('Ordinary accounts'))
- await add()
- expect(fake.add.mock.lastCall?.[0].runtime).toBe('wsl')
- }
-)
diff --git a/src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx b/src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx
deleted file mode 100644
index 475aa8c2286..00000000000
--- a/src/renderer/src/components/settings/accounts/AccountsPane.section-lifetime.test.tsx
+++ /dev/null
@@ -1,295 +0,0 @@
-// @vitest-environment happy-dom
-import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
-import { afterEach, beforeEach, expect, it, vi } from 'vitest'
-import { getDefaultSettings } from '../../../../../shared/constants'
-import { AccountsPane } from './AccountsPane'
-import { LOCAL_SETTINGS_HOST_SCOPE } from '../host-scope/settings-host-scope'
-
-const fake = vi.hoisted(() => ({
- query: '',
- cursorStatus: vi.fn(async () => ({
- signedIn: false,
- email: null,
- displayName: null,
- credentialSource: null,
- planType: null,
- tokenFresh: false,
- error: null
- })),
- cursorRefresh: vi.fn(async () => {}),
- cursorUsage: { updatedAt: 0 },
- status: vi.fn(async () => ({
- signedIn: false,
- email: null,
- teamId: null,
- tokenFresh: false,
- error: null
- })),
- pending: vi.fn(async () => null),
- subscribe: vi.fn(() => vi.fn()),
- refresh: vi.fn(async () => {}),
- write: vi.fn(),
- watcher: vi.fn(() => ({ close: vi.fn() })),
- grokUsage: { updatedAt: 0 }
-}))
-vi.mock('@/i18n/i18n', () => ({
- i18n: { language: 'en' },
- translate: (_key: string, fallback: string, values?: Record) =>
- Object.entries(values ?? {}).reduce(
- (text, [key, value]) => text.replaceAll(`{{${key}}}`, String(value)),
- fallback
- )
-}))
-vi.mock('@/store/index', () => ({
- useAppStore: (selector: (state: Record) => unknown) =>
- selector({
- settingsSearchQuery: fake.query,
- rateLimits: {
- codex: null,
- codexTarget: { runtime: 'host', wslDistro: null },
- minimax: null,
- cursor: fake.cursorUsage,
- grok: fake.grokUsage
- },
- runtimeEnvironments: [],
- refreshRateLimits: fake.cursorRefresh,
- refreshGrokRateLimits: fake.refresh,
- recordFeatureInteraction: fake.write,
- fetchSettings: fake.write
- })
-}))
-vi.mock('@/runtime/runtime-provider-accounts-client', () => ({
- emptyClaudeAccountsState: () => ({
- accounts: [],
- activeAccountId: null,
- activeAccountIdsByRuntime: { host: null, wsl: {} }
- }),
- emptyCodexAccountsState: () => ({
- accounts: [],
- activeAccountId: null,
- activeAccountIdsByRuntime: { host: null, wsl: {} }
- }),
- getProviderAccountsOwnerKey: (target: { kind: string; environmentId?: string }) =>
- target.environmentId ?? 'local',
- watchProviderAccounts: fake.watcher,
- selectClaudeProviderAccount: fake.write,
- selectCodexProviderAccount: fake.write,
- removeClaudeProviderAccount: fake.write,
- removeCodexProviderAccount: fake.write
-}))
-beforeEach(() => {
- vi.clearAllMocks()
- fake.query = ''
- fake.grokUsage = { updatedAt: 0 }
- fake.cursorUsage = { updatedAt: 0 }
- Object.assign(window, {
- api: {
- opencodeGoCredentials: {
- getStatus: vi.fn(async () => ({ apiKeyConfigured: false })),
- saveApiKey: vi.fn(async () => ({ apiKeyConfigured: true })),
- clearApiKey: vi.fn(async () => ({ apiKeyConfigured: false }))
- },
- minimaxCredentials: {
- getStatus: vi.fn(async () => ({ cookieConfigured: false, apiKeyConfigured: false }))
- },
- zcodePlanCredentials: {
- getStatus: vi.fn(async () => ({
- apiKeyConfigured: false,
- zcodeCliConfigured: false,
- apiKeyProtection: null
- }))
- },
- codexConfigSync: {
- status: vi.fn(async () => ({
- state: 'synced',
- reason: null,
- systemConfigPath: '/synthetic/config.toml'
- }))
- },
- codexAccounts: { getPendingLoginUrl: fake.pending, onPendingLoginUrlChanged: fake.subscribe },
- cursorAccounts: { getStatus: fake.cursorStatus },
- grokAccounts: { getStatus: fake.status }
- }
- })
-})
-afterEach(() => {
- cleanup()
- Reflect.deleteProperty(window, 'api')
-})
-
-it.each([false, true])(
- 'retains Grok status reads with Windows account support %s',
- async (wslSupportedPlatform) => {
- const props = {
- settings: getDefaultSettings('/synthetic'),
- updateSettings: fake.write,
- updateSettingsOrThrow: fake.write,
- hostScope: LOCAL_SETTINGS_HOST_SCOPE,
- wslSupportedPlatform
- }
- const view = render()
- await act(async () => {})
- // Assert DOM identity across query edits so search cannot remount sections and add reads/watchers.
- const mountedHeading = screen.getByText('Grok (xAI)', { exact: true })
- const watchersAfterMount = fake.watcher.mock.calls.length
- const statusReadsAfterMount = fake.status.mock.calls.length
- for (const query of ['g', 'gr', 'gro', 'grok', '', 'g', 'gr', 'gro', 'grok']) {
- fake.query = query
- await act(async () => view.rerender())
- expect(screen.getByText('Grok (xAI)', { exact: true })).toBe(mountedHeading)
- }
- expect(fake.watcher.mock.calls.length).toBe(watchersAfterMount)
- expect(fake.status.mock.calls.length).toBe(statusReadsAfterMount)
- }
-)
-it.each([false, true])(
- 'retains Codex login reads with Windows account support %s',
- async (wslSupportedPlatform) => {
- const props = {
- settings: getDefaultSettings('/synthetic'),
- updateSettings: fake.write,
- updateSettingsOrThrow: fake.write,
- hostScope: LOCAL_SETTINGS_HOST_SCOPE,
- wslSupportedPlatform
- }
- const view = render()
- await act(async () => {})
- const mountedHeading = screen.getByText('Codex', { exact: true })
- const pendingReadsAfterMount = fake.pending.mock.calls.length
- const subscriptionsAfterMount = fake.subscribe.mock.calls.length
- for (const query of [
- 'c',
- 'co',
- 'cod',
- 'code',
- 'codex',
- '',
- 'c',
- 'co',
- 'cod',
- 'code',
- 'codex'
- ]) {
- fake.query = query
- await act(async () => view.rerender())
- expect(screen.getByText('Codex', { exact: true })).toBe(mountedHeading)
- }
- expect(fake.pending.mock.calls.length).toBe(pendingReadsAfterMount)
- expect(fake.subscribe.mock.calls.length).toBe(subscriptionsAfterMount)
- }
-)
-it('preserves explicit Grok refresh and real hide/reopen status reads', async () => {
- fake.query = 'grok'
- const props = {
- settings: getDefaultSettings('/synthetic'),
- updateSettings: fake.write,
- updateSettingsOrThrow: fake.write,
- hostScope: LOCAL_SETTINGS_HOST_SCOPE
- }
- const view = render()
- await act(async () => {})
- fireEvent.click(screen.getByRole('button', { name: 'Refresh usage' }))
- await act(async () => {})
- expect(fake.refresh).toHaveBeenCalledTimes(1)
- expect(fake.status).toHaveBeenCalledTimes(2)
- fake.query = 'codex'
- await act(async () => view.rerender())
- expect(screen.queryByText('Grok (xAI)', { exact: true })).toBeNull()
- fake.query = 'grok'
- await act(async () => view.rerender())
- expect(fake.status).toHaveBeenCalledTimes(3)
- expect(fake.write).not.toHaveBeenCalled()
-})
-
-it('keeps usage-driven Grok status refreshes while the section stays mounted', async () => {
- fake.query = 'grok'
- const props = {
- settings: getDefaultSettings('/synthetic'),
- updateSettings: fake.write,
- updateSettingsOrThrow: fake.write,
- hostScope: LOCAL_SETTINGS_HOST_SCOPE
- }
- const view = render()
- await act(async () => {})
- fake.grokUsage = { updatedAt: 10 }
- await act(async () => view.rerender())
- expect(fake.status).toHaveBeenCalledTimes(2)
- fake.query = 'gro'
- await act(async () => view.rerender())
- expect(fake.status).toHaveBeenCalledTimes(2)
- fake.grokUsage = { updatedAt: 11 }
- await act(async () => view.rerender())
- expect(fake.status).toHaveBeenCalledTimes(3)
-})
-
-it('keeps the login subscription until Codex genuinely hides', async () => {
- const props = {
- settings: getDefaultSettings('/synthetic'),
- updateSettings: fake.write,
- updateSettingsOrThrow: fake.write,
- hostScope: LOCAL_SETTINGS_HOST_SCOPE
- }
- const view = render()
- await act(async () => {})
- const unsubscribe = fake.subscribe.mock.results[0].value
- fake.query = 'codex'
- await act(async () => view.rerender())
- expect(unsubscribe).not.toHaveBeenCalled()
- fake.query = 'grok'
- await act(async () => view.rerender())
- expect(unsubscribe).toHaveBeenCalledTimes(1)
- fake.query = 'codex'
- await act(async () => view.rerender())
- expect(fake.subscribe).toHaveBeenCalledTimes(2)
- view.unmount()
- expect(fake.subscribe.mock.results[1].value).toHaveBeenCalledTimes(1)
-})
-
-it.each([false, true])(
- 'retains Cursor status reads with Windows account support %s',
- async (wslSupportedPlatform) => {
- const props = {
- settings: getDefaultSettings('/synthetic'),
- updateSettings: fake.write,
- updateSettingsOrThrow: fake.write,
- hostScope: LOCAL_SETTINGS_HOST_SCOPE,
- wslSupportedPlatform
- }
- const view = render()
- await act(async () => {})
- const mountedHeading = screen.getByText('Cursor', { exact: true })
- const statusReadsAfterMount = fake.cursorStatus.mock.calls.length
- for (const query of ['c', 'cu', 'cur', 'curs', 'curso', 'cursor', '', 'c', 'cu', 'cursor']) {
- fake.query = query
- await act(async () => view.rerender())
- expect(screen.getByText('Cursor', { exact: true })).toBe(mountedHeading)
- }
- expect(fake.cursorStatus.mock.calls.length).toBe(statusReadsAfterMount)
- expect(fake.write).not.toHaveBeenCalled()
- }
-)
-
-it('keeps Cursor refresh driven by usage updates and genuine reopen', async () => {
- fake.query = 'cursor'
- const props = {
- settings: getDefaultSettings('/synthetic'),
- updateSettings: fake.write,
- updateSettingsOrThrow: fake.write,
- hostScope: LOCAL_SETTINGS_HOST_SCOPE
- }
- const view = render()
- await act(async () => {})
- fireEvent.click(screen.getByRole('button', { name: 'Refresh usage' }))
- await act(async () => {})
- expect(fake.cursorRefresh).toHaveBeenCalledTimes(1)
- expect(fake.cursorStatus).toHaveBeenCalledTimes(1)
- fake.cursorUsage = { updatedAt: 1 }
- await act(async () => view.rerender())
- expect(fake.cursorStatus).toHaveBeenCalledTimes(2)
- fake.query = 'codex'
- await act(async () => view.rerender())
- expect(screen.queryByText('Cursor', { exact: true })).toBeNull()
- fake.query = 'cursor'
- await act(async () => view.rerender())
- expect(fake.cursorStatus).toHaveBeenCalledTimes(3)
-})
diff --git a/src/renderer/src/components/settings/accounts/AccountsPane.test.tsx b/src/renderer/src/components/settings/accounts/AccountsPane.test.tsx
deleted file mode 100644
index 7090183dba3..00000000000
--- a/src/renderer/src/components/settings/accounts/AccountsPane.test.tsx
+++ /dev/null
@@ -1,319 +0,0 @@
-import React from 'react'
-import { renderToStaticMarkup } from 'react-dom/server'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { getDefaultSettings } from '../../../../../shared/constants'
-import type { GlobalSettings } from '../../../../../shared/global-settings-types'
-import type {
- ClaudeManagedAccountSummary,
- ClaudeRateLimitAccountsState
-} from '../../../../../shared/managed-account-types'
-import { i18n } from '../../../i18n/i18n'
-import { useAppStore } from '../../../store/index'
-import { AccountsPane } from './AccountsPane'
-import { resolveSettingsHostScope } from '../host-scope/settings-host-scope'
-import { renderClaudeAccountsSection } from './claude/accounts-pane-claude-section'
-import type { AccountsPaneSectionModel } from './accounts-pane-types'
-
-function renderPane(
- settings: GlobalSettings,
- props: Partial> = {}
-): string {
- return renderToStaticMarkup(
- React.createElement(AccountsPane, {
- settings,
- updateSettings: vi.fn(),
- updateSettingsOrThrow: vi.fn(),
- hostScope: resolveSettingsHostScope({
- choice: null,
- defaultEnvironmentId: settings.activeRuntimeEnvironmentId,
- savedEnvironmentIds: [],
- catalogHydrated: false
- }),
- ...props
- })
- )
-}
-
-describe('AccountsPane', () => {
- beforeEach(async () => {
- await i18n.changeLanguage('en')
- useAppStore.setState({ settingsSearchQuery: '', runtimeEnvironments: [] })
- })
-
- it('hides the WSL account location controls on platforms without WSL support', () => {
- const markup = renderPane({
- ...getDefaultSettings('/tmp'),
- localAccountRuntime: 'wsl'
- })
-
- expect(markup).not.toContain('Account location')
- expect(markup).not.toContain('aria-label="Account location"')
- expect(markup).not.toContain('WSL is not available on this machine.')
- })
-
- it('keeps the WSL account location controls on Windows-class hosts', () => {
- const markup = renderPane(
- {
- ...getDefaultSettings('/tmp'),
- localAccountRuntime: 'wsl'
- },
- { wslSupportedPlatform: true, wslCapabilitiesLoading: true }
- )
-
- expect(markup).toContain('Account location')
- expect(markup).toContain('aria-label="Account location"')
- expect(markup).toContain('role="radio" aria-checked="true" aria-disabled="true"')
- })
-
- it('selects the WSL account location under auto when the global project runtime is WSL', () => {
- // Shadow the read-only userAgent prototype getter, then remove the own property to restore it.
- const originalOwnUserAgent = Object.getOwnPropertyDescriptor(globalThis.navigator, 'userAgent')
- Object.defineProperty(globalThis.navigator, 'userAgent', {
- value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
- configurable: true
- })
- try {
- const markup = renderPane(
- {
- ...getDefaultSettings('/tmp'),
- localAccountRuntime: 'auto',
- localWindowsRuntimeDefault: { kind: 'wsl', distro: 'Ubuntu' }
- },
- { wslSupportedPlatform: true, wslCapabilitiesLoading: true }
- )
-
- expect(markup).toContain('aria-label="Account location"')
- expect(markup).toContain('role="radio" aria-checked="true" aria-disabled="true"')
- } finally {
- if (originalOwnUserAgent) {
- Object.defineProperty(globalThis.navigator, 'userAgent', originalOwnUserAgent)
- } else {
- delete (globalThis.navigator as { userAgent?: string }).userAgent
- }
- }
- })
-
- it('keeps the runtime label inside the localized account copy', () => {
- const markup = renderPane(getDefaultSettings('/tmp'))
-
- expect(markup).toContain('Showing accounts for this device. New accounts are added there.')
- expect(markup).toContain('authenticate with Google for this device. This uses credentials')
- expect(markup).not.toContain('ShowingThis device')
- expect(markup).not.toContain('forThis device')
- })
-
- it('localizes the runtime label before interpolating account copy', async () => {
- await i18n.changeLanguage('es')
-
- const markup = renderPane(getDefaultSettings('/tmp'))
-
- expect(markup).toMatch(
- /Mostrando cuentas para [Ee]ste dispositivo\. Las nuevas cuentas se agregan allí\./
- )
- expect(markup).not.toContain('This device')
- })
-
- it('scopes account copy to the active remote server and offers sign-in on that server', () => {
- // SSR reads Zustand’s initial state; this covers unnamed pre-hydration scope, while provider-account-scope.test covers named servers.
- const markup = renderPane(
- {
- ...getDefaultSettings('/tmp'),
- activeRuntimeEnvironmentId: 'env-1'
- },
- { wslSupportedPlatform: true }
- )
-
- expect(
- markup.split(
- 'Showing accounts managed by the remote server. New accounts sign in there; you finish in this device’s browser.'
- ).length - 1
- ).toBe(2)
- // Both sections must reassure desktop users and link runtime selection so remote scope cannot look like lost accounts.
- expect(markup.split('Accounts managed on this desktop are unchanged').length - 1).toBe(2)
- expect(markup.split('Open Remote Servers').length - 1).toBe(2)
- // Unloaded server names must not interpolate prose fallbacks into scope labels.
- expect(markup).toContain('Account scope: Remote server<')
- expect(markup).not.toContain('Remote server: the remote server')
- expect(markup).not.toContain('aria-label="Account location"')
- const addButtons = [...markup.matchAll(/Add Account/g)].map(({ index }) =>
- markup.slice(markup.lastIndexOf('