diff --git a/ui/src/components/monitoring/auth-monitor/index.tsx b/ui/src/components/monitoring/auth-monitor/index.tsx
index 04f05f5a..615410dd 100644
--- a/ui/src/components/monitoring/auth-monitor/index.tsx
+++ b/ui/src/components/monitoring/auth-monitor/index.tsx
@@ -22,6 +22,7 @@ import { useAuthMonitorData } from './hooks';
import { LivePulse } from './components/live-pulse';
import { ProviderCard } from './components/provider-card';
import { SummaryCard } from './components/summary-card';
+import { getSuccessRate } from './utils';
const STORAGE_KEY = 'auth-monitor-selected-provider';
@@ -78,6 +79,13 @@ export function AuthMonitor() {
const selectedProviderData = effectiveProvider
? providerStats.find((ps) => ps.provider === effectiveProvider)
: null;
+ const displayedAccountCount = selectedProviderData?.accountCount ?? accounts.length;
+ const displayedSuccess = selectedProviderData?.successCount ?? totalSuccess;
+ const displayedFailure = selectedProviderData?.failureCount ?? totalFailure;
+ const displayedTotalRequests = selectedProviderData?.totalRequests ?? totalRequests;
+ const displayedSuccessRate = selectedProviderData
+ ? getSuccessRate(selectedProviderData.successCount, selectedProviderData.failureCount)
+ : overallSuccessRate;
const handlePauseToggle = (accountIds: string[], paused: boolean) => {
if (
@@ -147,8 +155,8 @@ export function AuthMonitor() {
Updated {timeSinceUpdate || 'now'}
|
- {t('authMonitor.accountsCount', { count: accounts.length })}
- {totalRequests.toLocaleString()} req
+ {t('authMonitor.accountsCount', { count: displayedAccountCount })}
+ {displayedTotalRequests.toLocaleString()} req
@@ -157,29 +165,29 @@ export function AuthMonitor() {
}
label={t('authMonitor.accounts')}
- value={accounts.length}
+ value={displayedAccountCount}
color="var(--accent)"
/>
}
label={t('authMonitor.success')}
- value={totalSuccess.toLocaleString()}
+ value={displayedSuccess.toLocaleString()}
color={STATUS_COLORS.success}
/>
}
label={t('authMonitor.failed')}
- value={totalFailure.toLocaleString()}
- color={totalFailure > 0 ? STATUS_COLORS.failed : undefined}
+ value={displayedFailure.toLocaleString()}
+ color={displayedFailure > 0 ? STATUS_COLORS.failed : undefined}
/>
}
label={t('authMonitor.successRate')}
- value={`${overallSuccessRate}%`}
+ value={`${displayedSuccessRate}%`}
color={
- overallSuccessRate === 100
+ displayedSuccessRate === 100
? STATUS_COLORS.success
- : overallSuccessRate >= 95
+ : displayedSuccessRate >= 95
? STATUS_COLORS.degraded
: STATUS_COLORS.failed
}
diff --git a/ui/tests/unit/ui/components/monitoring/auth-monitor/auth-monitor.test.tsx b/ui/tests/unit/ui/components/monitoring/auth-monitor/auth-monitor.test.tsx
new file mode 100644
index 00000000..c808338d
--- /dev/null
+++ b/ui/tests/unit/ui/components/monitoring/auth-monitor/auth-monitor.test.tsx
@@ -0,0 +1,183 @@
+import { render, screen, userEvent, within } from '@tests/setup/test-utils';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { AuthMonitor } from '@/components/monitoring/auth-monitor';
+import type { AuthMonitorData } from '@/components/monitoring/auth-monitor/hooks';
+
+vi.mock('@/components/account-flow-viz', () => ({
+ AccountFlowViz: ({
+ providerData,
+ onBack,
+ }: {
+ providerData: { displayName: string };
+ onBack: () => void;
+ }) => (
+
+
+
{providerData.displayName}
+
+ ),
+}));
+
+vi.mock(import('react-i18next'), async (importOriginal) => {
+ const actual = await importOriginal();
+
+ return {
+ ...actual,
+ useTranslation: () => ({
+ t: (key: string, options?: { count?: number }) => {
+ const translations: Record = {
+ 'authMonitor.accounts': 'Accounts',
+ 'authMonitor.success': 'Success',
+ 'authMonitor.failed': 'Failed',
+ 'authMonitor.successRate': 'Success Rate',
+ };
+
+ if (key === 'authMonitor.accountsCount') {
+ return `${options?.count ?? 0} accounts`;
+ }
+
+ return translations[key] ?? key;
+ },
+ }),
+ };
+});
+
+const { useAuthMonitorDataMock } = vi.hoisted(() => ({
+ useAuthMonitorDataMock: vi.fn<() => AuthMonitorData>(),
+}));
+
+vi.mock('@/components/monitoring/auth-monitor/hooks', () => ({
+ useAuthMonitorData: useAuthMonitorDataMock,
+}));
+
+function getSummaryRow() {
+ const accountsLabel = screen.getByText('Accounts');
+ const summaryRow = accountsLabel.parentElement?.parentElement?.parentElement;
+
+ if (!summaryRow) {
+ throw new Error('Unable to locate the auth monitor summary row.');
+ }
+
+ return summaryRow;
+}
+
+function getSummaryCard(label: string) {
+ const labelNode = within(getSummaryRow()).getByText(label);
+ const card = labelNode.closest('div')?.parentElement;
+
+ if (!card) {
+ throw new Error(`Unable to locate summary card for label "${label}".`);
+ }
+
+ return card;
+}
+
+const providerStats = [
+ {
+ provider: 'gemini',
+ displayName: 'Google Gemini',
+ totalRequests: 15,
+ successCount: 12,
+ failureCount: 3,
+ accountCount: 2,
+ accounts: [
+ {
+ id: 'gemini-primary',
+ email: 'gemini-primary@example.com',
+ tokenFile: '/tmp/gemini-primary.json',
+ provider: 'gemini',
+ displayName: 'Google Gemini',
+ isDefault: true,
+ successCount: 10,
+ failureCount: 2,
+ color: '#4285F4',
+ },
+ {
+ id: 'gemini-secondary',
+ email: 'gemini-secondary@example.com',
+ tokenFile: '/tmp/gemini-secondary.json',
+ provider: 'gemini',
+ displayName: 'Google Gemini',
+ isDefault: false,
+ successCount: 2,
+ failureCount: 1,
+ color: '#34A853',
+ },
+ ],
+ },
+ {
+ provider: 'codex',
+ displayName: 'OpenAI Codex',
+ totalRequests: 27,
+ successCount: 23,
+ failureCount: 4,
+ accountCount: 2,
+ accounts: [
+ {
+ id: 'codex-primary',
+ email: 'codex-primary@example.com',
+ tokenFile: '/tmp/codex-primary.json',
+ provider: 'codex',
+ displayName: 'OpenAI Codex',
+ isDefault: true,
+ successCount: 15,
+ failureCount: 2,
+ color: '#10a37f',
+ },
+ {
+ id: 'codex-secondary',
+ email: 'codex-secondary@example.com',
+ tokenFile: '/tmp/codex-secondary.json',
+ provider: 'codex',
+ displayName: 'OpenAI Codex',
+ isDefault: false,
+ successCount: 8,
+ failureCount: 2,
+ color: '#0f766e',
+ },
+ ],
+ },
+] satisfies AuthMonitorData['providerStats'];
+
+const authMonitorData: AuthMonitorData = {
+ accounts: providerStats.flatMap((provider) => provider.accounts),
+ totalSuccess: 35,
+ totalFailure: 7,
+ totalRequests: 42,
+ providerStats,
+ overallSuccessRate: 83,
+ isLoading: false,
+ error: null,
+ timeSinceUpdate: '2s ago',
+};
+
+describe('AuthMonitor', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ vi.mocked(window.localStorage.getItem).mockReturnValue(null);
+ useAuthMonitorDataMock.mockReturnValue(authMonitorData);
+ });
+
+ it('scopes header and summary metrics to the selected provider detail view', async () => {
+ render();
+
+ expect(screen.getByText('4 accounts')).toBeInTheDocument();
+ expect(screen.getByText('42 req')).toBeInTheDocument();
+ expect(within(getSummaryCard('Accounts')).getByText('4')).toBeInTheDocument();
+ expect(within(getSummaryCard('Success')).getByText('35')).toBeInTheDocument();
+ expect(within(getSummaryCard('Failed')).getByText('7')).toBeInTheDocument();
+ expect(within(getSummaryCard('Success Rate')).getByText('83%')).toBeInTheDocument();
+
+ await userEvent.click(screen.getByRole('button', { name: /Google Gemini/i }));
+
+ expect(screen.getByTestId('provider-detail')).toHaveTextContent('Google Gemini');
+ expect(screen.getByText('2 accounts')).toBeInTheDocument();
+ expect(screen.getByText('15 req')).toBeInTheDocument();
+ expect(within(getSummaryCard('Accounts')).getByText('2')).toBeInTheDocument();
+ expect(within(getSummaryCard('Success')).getByText('12')).toBeInTheDocument();
+ expect(within(getSummaryCard('Failed')).getByText('3')).toBeInTheDocument();
+ expect(within(getSummaryCard('Success Rate')).getByText('80%')).toBeInTheDocument();
+ });
+});