import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { BrowserRouter } from 'react-router-dom'; import { AgentDashboardPage } from '../AgentDashboard'; // Helper to create a mock mutation result const mockMutation = (overrides = {}) => ({ mutateAsync: vi.fn().mockResolvedValue({}), isPending: false, isError: false, error: null, data: undefined, ...overrides, }); // Mock the API hooks vi.mock('@/api/automation', () => ({ useAgents: vi.fn(), useCreateAgent: vi.fn(() => mockMutation()), useUpdateAgent: vi.fn(() => mockMutation()), useDeleteAgent: vi.fn(() => mockMutation()), useExecuteAgent: vi.fn(() => mockMutation()), useTestRunAgent: vi.fn(() => mockMutation()), useAgentRuns: vi.fn(), useAgentVersions: vi.fn(), useRestoreAgentVersion: vi.fn(() => mockMutation()), useAgentTools: vi.fn(() => ({ data: [] })), useSendAgentMessage: vi.fn(() => mockMutation()), })); // Mock i18next vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key, i18n: { language: 'en' }, }), })); // Mock toast vi.mock('@/components/ui/Toast', () => ({ useToast: () => ({ toast: { success: vi.fn(), error: vi.fn() }, }), })); // Mock lucide-react icons vi.mock('lucide-react', () => ({ Activity: () =>
, AlertCircle: () =>
, Bot: () =>
, Brain: () =>
, Clock: () =>
, DollarSign: () =>
, GitBranch: () =>
, History: () =>
, Loader2: () =>
, MessageCircle: () =>
, Play: () =>
, Plus: () =>
, RefreshCw: () =>
, Send: () =>
, Settings2: () =>
, TestTube: () =>
, Trash2: () =>
, Zap: () =>
, })); // Mock Modal component vi.mock('@/components/ui/Modal', () => ({ Modal: ({ open, title, children }: any) => open ?

{title}

{children}
: null, })); // Mock AgentForm vi.mock('@/components/automation/AgentForm', () => ({ AgentForm: () =>
, })); // Mock Skeleton vi.mock('@/components/ui/Skeleton', () => ({ Skeleton: ({ className }: any) =>
, })); // Mock Card vi.mock('@/components/ui/Card', () => ({ Card: ({ children, className }: any) =>
{children}
, })); // Mock EmptyState vi.mock('@/components/ui/EmptyState', () => ({ EmptyState: ({ title, description, icon, action }: any) => (

{title}

{description}

{icon} {action}
), })); // Mock Badge vi.mock('@/components/ui/Badge', () => ({ Badge: ({ children, variant }: any) => {children}, })); const mockAgents = [ { id: '1', name: 'Test Agent', description: 'A test agent', llm_model: 'gpt-4', mode: 'reactive', is_active: true, created_at: '2024-01-01T00:00:00Z', updated_at: '2024-01-01T00:00:00Z', }, { id: '2', name: 'Inactive Agent', description: 'An inactive agent', llm_model: 'gpt-3.5', mode: 'scheduled', is_active: false, created_at: '2024-01-02T00:00:00Z', updated_at: '2024-01-02T00:00:00Z', }, ]; function renderWithProviders(ui: React.ReactElement) { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, }, }); return render( {ui} ); } describe('AgentDashboard', () => { beforeEach(() => { vi.clearAllMocks(); }); it('renders the agent list', async () => { const { useAgents } = await import('@/api/automation'); (useAgents as any).mockReturnValue({ data: mockAgents, isLoading: false, error: null, }); renderWithProviders(); await waitFor(() => { expect(screen.getByText('Test Agent')).toBeDefined(); expect(screen.getByText('Inactive Agent')).toBeDefined(); }); }); it('shows loading state', async () => { const { useAgents } = await import('@/api/automation'); (useAgents as any).mockReturnValue({ data: undefined, isLoading: true, error: null, }); renderWithProviders(); expect(screen.getAllByTestId('skeleton').length).toBe(3); }); it('shows empty state when no agents', async () => { const { useAgents } = await import('@/api/automation'); (useAgents as any).mockReturnValue({ data: [], isLoading: false, error: null, }); renderWithProviders(); await waitFor(() => { expect(screen.getByText('agent.noAgents')).toBeDefined(); }); }); it('opens create form when create button is clicked', async () => { const { useAgents } = await import('@/api/automation'); (useAgents as any).mockReturnValue({ data: mockAgents, isLoading: false, error: null, }); renderWithProviders(); const createButton = screen.getByText('agent.create'); fireEvent.click(createButton); await waitFor(() => { expect(screen.getByTestId('modal')).toBeDefined(); }); }); it('calls execute API when execute button is clicked', async () => { const { useAgents, useExecuteAgent } = await import('@/api/automation'); const mockExecute = vi.fn().mockResolvedValue({}); (useAgents as any).mockReturnValue({ data: mockAgents, isLoading: false, error: null, }); (useExecuteAgent as any).mockReturnValue({ mutateAsync: mockExecute, isPending: false, }); renderWithProviders(); // Execute buttons have title="agent.execute" - find by title attribute const executeButtons = screen.getAllByTitle('agent.execute'); expect(executeButtons.length).toBeGreaterThan(0); fireEvent.click(executeButtons[0]); await waitFor(() => { expect(mockExecute).toHaveBeenCalledWith('1'); }); }); });