diff --git a/src/components/providers/forms/CodexOAuthSection.tsx b/src/components/providers/forms/CodexOAuthSection.tsx index df8b3ce67..d94d90247 100644 --- a/src/components/providers/forms/CodexOAuthSection.tsx +++ b/src/components/providers/forms/CodexOAuthSection.tsx @@ -28,6 +28,8 @@ import CodexOauthAccountQuota from "@/components/CodexOauthAccountQuota"; interface CodexOAuthSectionProps { className?: string; + /** 是否展示每个账号的订阅额度 */ + showAccountQuota?: boolean; /** 当前选中的 ChatGPT 账号 ID */ selectedAccountId?: string | null; /** 账号选择回调 */ @@ -46,6 +48,7 @@ interface CodexOAuthSectionProps { */ export const CodexOAuthSection: React.FC = ({ className, + showAccountQuota = false, selectedAccountId, onAccountSelect, fastModeEnabled = false, @@ -222,7 +225,9 @@ export const CodexOAuthSection: React.FC = ({ - + {showAccountQuota && ( + + )} ))} diff --git a/src/components/settings/AuthCenterPanel.tsx b/src/components/settings/AuthCenterPanel.tsx index 04dd51359..d949e3160 100644 --- a/src/components/settings/AuthCenterPanel.tsx +++ b/src/components/settings/AuthCenterPanel.tsx @@ -67,7 +67,7 @@ export function AuthCenterPanel() { - + ); diff --git a/tests/components/CodexOAuthSection.test.tsx b/tests/components/CodexOAuthSection.test.tsx new file mode 100644 index 000000000..679504bae --- /dev/null +++ b/tests/components/CodexOAuthSection.test.tsx @@ -0,0 +1,70 @@ +import { render, screen } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { CodexOAuthSection } from "@/components/providers/forms/CodexOAuthSection"; +import { AuthCenterPanel } from "@/components/settings/AuthCenterPanel"; + +const mocks = vi.hoisted(() => ({ + useCodexOauth: vi.fn(), + renderAccountQuota: vi.fn(), +})); + +vi.mock("@/components/providers/forms/hooks/useCodexOauth", () => ({ + useCodexOauth: mocks.useCodexOauth, +})); + +vi.mock("@/components/CodexOauthAccountQuota", () => ({ + default: ({ accountId }: { accountId: string }) => { + mocks.renderAccountQuota(accountId); + return
{accountId}
; + }, +})); + +vi.mock("@/components/providers/forms/CopilotAuthSection", () => ({ + CopilotAuthSection: () =>
, +})); + +describe("CodexOAuthSection", () => { + beforeEach(() => { + mocks.useCodexOauth.mockReturnValue({ + accounts: [ + { + id: "account-1", + provider: "codex_oauth", + login: "user@example.com", + avatar_url: null, + authenticated_at: 0, + is_default: true, + github_domain: "", + }, + ], + defaultAccountId: "account-1", + hasAnyAccount: true, + pollingState: "idle", + deviceCode: null, + error: null, + isPolling: false, + isAddingAccount: false, + isRemovingAccount: false, + isSettingDefaultAccount: false, + addAccount: vi.fn(), + removeAccount: vi.fn(), + setDefaultAccount: vi.fn(), + cancelAuth: vi.fn(), + logout: vi.fn(), + }); + }); + + it("does not render account quota by default", () => { + render(); + + expect(mocks.renderAccountQuota).not.toHaveBeenCalled(); + expect(screen.queryByTestId("account-quota")).not.toBeInTheDocument(); + }); + + it("renders account quota in Auth Center", () => { + render(); + + expect(mocks.renderAccountQuota).toHaveBeenCalledWith("account-1"); + expect(screen.getByTestId("account-quota")).toHaveTextContent("account-1"); + }); +});