mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 06:16:37 +00:00
test(ui): cover paused account flow viz filtering
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { render, screen, userEvent } from '@tests/setup/test-utils';
|
||||
import { AccountFlowViz } from '@/components/account-flow-viz';
|
||||
import type { ProviderData } from '@/components/account/flow-viz/types';
|
||||
|
||||
vi.mock(import('react-i18next'), async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
|
||||
return {
|
||||
...actual,
|
||||
useTranslation: () => ({
|
||||
t: (key: string, options?: { count?: number }) => {
|
||||
const translations: Record<string, string> = {
|
||||
'flowViz.showDetails': 'Show Details',
|
||||
'flowViz.hideDetails': 'Hide Details',
|
||||
'flowViz.backToProviders': 'Back to providers',
|
||||
'flowViz.resetLayout': 'Reset layout',
|
||||
};
|
||||
|
||||
if (key === 'flowViz.showPausedAccounts') {
|
||||
return `Show Paused (${options?.count ?? 0})`;
|
||||
}
|
||||
|
||||
if (key === 'flowViz.hidePausedAccounts') {
|
||||
return `Hide Paused (${options?.count ?? 0})`;
|
||||
}
|
||||
|
||||
return translations[key] ?? key;
|
||||
},
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('@/components/account/flow-viz/account-card', () => ({
|
||||
AccountCard: ({
|
||||
account,
|
||||
originalIndex,
|
||||
zone,
|
||||
}: {
|
||||
account: { email: string; paused?: boolean };
|
||||
originalIndex: number;
|
||||
zone: string;
|
||||
}) => (
|
||||
<div data-account-index={originalIndex} data-zone={zone}>
|
||||
{account.email}
|
||||
{account.paused ? ' (paused)' : ' (active)'}
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/account/flow-viz/provider-card', () => ({
|
||||
ProviderCard: ({ providerData }: { providerData: ProviderData }) => (
|
||||
<div data-provider-node>{providerData.accounts.length} visible accounts</div>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/account/flow-viz/connection-timeline', () => ({
|
||||
ConnectionTimeline: ({ events }: { events: Array<{ id: string }> }) => (
|
||||
<div>{events.length} timeline events</div>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/account/flow-viz/flow-paths', () => ({
|
||||
FlowPaths: ({ accounts }: { accounts: Array<{ id: string }> }) => (
|
||||
<div>paths:{accounts.map((account) => account.id).join(',')}</div>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/account/flow-viz/path-utils', () => ({
|
||||
calculateBezierPaths: () => [],
|
||||
}));
|
||||
|
||||
const providerData: ProviderData = {
|
||||
provider: 'codex',
|
||||
displayName: 'OpenAI Codex',
|
||||
totalRequests: 7,
|
||||
accounts: [
|
||||
{
|
||||
id: 'paused-account',
|
||||
email: 'paused@company.com',
|
||||
provider: 'codex',
|
||||
successCount: 4,
|
||||
failureCount: 0,
|
||||
color: '#f59e0b',
|
||||
paused: true,
|
||||
},
|
||||
{
|
||||
id: 'active-account',
|
||||
email: 'active@company.com',
|
||||
provider: 'codex',
|
||||
successCount: 2,
|
||||
failureCount: 1,
|
||||
color: '#10a37f',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe('AccountFlowViz paused account visibility', () => {
|
||||
beforeEach(() => {
|
||||
vi.mocked(window.localStorage.getItem).mockReturnValue(null);
|
||||
vi.stubGlobal(
|
||||
'requestAnimationFrame',
|
||||
vi.fn(() => 0)
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('hides and restores paused accounts from the provider detail visualization', async () => {
|
||||
render(<AccountFlowViz providerData={providerData} />);
|
||||
|
||||
expect(screen.getByRole('button', { name: 'Show Details' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Hide Paused (1)' })).toBeInTheDocument();
|
||||
expect(screen.getByText('active@company.com (active)')).toBeInTheDocument();
|
||||
expect(screen.getByText('paused@company.com (paused)')).toBeInTheDocument();
|
||||
expect(screen.getByText('2 visible accounts')).toBeInTheDocument();
|
||||
expect(screen.getByText('7 timeline events')).toBeInTheDocument();
|
||||
expect(screen.getByText('paths:paused-account,active-account')).toBeInTheDocument();
|
||||
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Hide Paused (1)' }));
|
||||
|
||||
expect(screen.getByRole('button', { name: 'Show Paused (1)' })).toHaveAttribute(
|
||||
'aria-pressed',
|
||||
'true'
|
||||
);
|
||||
expect(screen.getByText('active@company.com (active)')).toBeInTheDocument();
|
||||
expect(screen.queryByText('paused@company.com (paused)')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('1 visible accounts')).toBeInTheDocument();
|
||||
expect(screen.getByText('3 timeline events')).toBeInTheDocument();
|
||||
expect(screen.getByText('paths:active-account')).toBeInTheDocument();
|
||||
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Show Paused (1)' }));
|
||||
|
||||
expect(screen.getByRole('button', { name: 'Hide Paused (1)' })).toHaveAttribute(
|
||||
'aria-pressed',
|
||||
'false'
|
||||
);
|
||||
expect(screen.getByText('paused@company.com (paused)')).toBeInTheDocument();
|
||||
expect(screen.getByText('2 visible accounts')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('ignores hidden paused-account drag offsets when deciding whether reset layout should stay visible', async () => {
|
||||
vi.mocked(window.localStorage.getItem).mockImplementation((key: string) =>
|
||||
key === 'ccs-flow-positions-codex'
|
||||
? JSON.stringify({
|
||||
'paused-account': { x: 0, y: 160 },
|
||||
})
|
||||
: null
|
||||
);
|
||||
|
||||
render(<AccountFlowViz providerData={providerData} />);
|
||||
|
||||
expect(screen.getByRole('button', { name: 'Reset layout' })).toBeInTheDocument();
|
||||
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Hide Paused (1)' }));
|
||||
|
||||
expect(screen.queryByRole('button', { name: 'Reset layout' })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user