Surface ChatGPT Official OAuth status in settings

Settings now mounts the ChatGPT OAuth status controls only after providers have loaded and ChatGPT Official is confirmed active. This keeps token-refreshing status reads scoped to the selected built-in provider.

Constraint: OAuth status reads can refresh tokens as a side effect

Rejected: Mount ChatGPT OAuth status unconditionally | it repeats the old official OAuth status misfire pattern

Confidence: high

Scope-risk: narrow

Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx --testNamePattern "ChatGPT|official OAuth|Providers tab"

Tested: git diff --check
This commit is contained in:
程序员阿江(Relakkes) 2026-05-18 23:54:03 +08:00
parent 83ee4c09ec
commit 7a818ac728
2 changed files with 22 additions and 0 deletions

View File

@ -69,6 +69,10 @@ vi.mock('../components/settings/ClaudeOfficialLogin', () => ({
ClaudeOfficialLogin: () => <div data-testid="claude-official-login" />,
}))
vi.mock('../components/settings/ChatGPTOfficialLogin', () => ({
ChatGPTOfficialLogin: () => <div data-testid="chatgpt-official-login" />,
}))
vi.mock('../pages/AdapterSettings', () => ({
AdapterSettings: () => <div>Adapter Settings Mock</div>,
}))
@ -700,6 +704,16 @@ describe('Settings > Providers tab', () => {
expect(screen.queryByTestId('claude-official-login')).not.toBeInTheDocument()
})
it('does not query ChatGPT OAuth status before providers finish loading', () => {
providerStoreState.providers = []
providerStoreState.activeId = 'openai-official'
providerStoreState.hasLoadedProviders = false
render(<Settings />)
expect(screen.queryByTestId('chatgpt-official-login')).not.toBeInTheDocument()
})
it('shows official OAuth status only after official provider is confirmed active', () => {
providerStoreState.providers = []
providerStoreState.activeId = null
@ -720,6 +734,7 @@ describe('Settings > Providers tab', () => {
const openAIProvider = screen.getByTestId('openai-official-provider')
expect(within(openAIProvider).getByText('ChatGPT Official')).toBeInTheDocument()
expect(within(openAIProvider).getByText('Default')).toBeInTheDocument()
expect(screen.getByTestId('chatgpt-official-login')).toBeInTheDocument()
expect(screen.queryByTestId('claude-official-login')).not.toBeInTheDocument()
})

View File

@ -32,6 +32,7 @@ import { ActivitySettings } from './ActivitySettings'
import { MemorySettings } from './MemorySettings'
import { useUIStore, type SettingsTab } from '../stores/uiStore'
import { ClaudeOfficialLogin } from '../components/settings/ClaudeOfficialLogin'
import { ChatGPTOfficialLogin } from '../components/settings/ChatGPTOfficialLogin'
import { OPENAI_OFFICIAL_PROVIDER_ID } from '../constants/openaiOfficialProvider'
import { useUpdateStore } from '../stores/updateStore'
import { formatBytes } from '../lib/formatBytes'
@ -288,6 +289,12 @@ function ProviderSettings() {
<div className="text-xs text-[var(--color-text-tertiary)] mt-0.5">{t('settings.providers.openaiOfficialDesc')}</div>
</div>
</div>
{isOpenAIOfficialActive && (
<div className="px-4 pb-4 pt-3 border-t border-[var(--color-border-separator)]">
<ChatGPTOfficialLogin />
</div>
)}
</div>
{/* Saved providers */}