/** * RecentProjects Component Tests */ import { render, screen } from '@testing-library/react'; import { RecentProjects } from '@/components/dashboard/RecentProjects'; import type { DashboardProject } from '@/lib/api/hooks/useDashboard'; // Mock next-intl navigation jest.mock('@/lib/i18n/routing', () => ({ Link: ({ children, href }: { children: React.ReactNode; href: string }) => ( {children} ), })); describe('RecentProjects', () => { const mockProjects: DashboardProject[] = [ { id: 'proj-1', name: 'Project One', description: 'First project description', status: 'active', autonomy_level: 'milestone', created_at: '2025-01-01T00:00:00Z', owner_id: 'user-1', progress: 75, openIssues: 5, activeAgents: 3, currentSprint: 'Sprint 2', lastActivity: '5 minutes ago', }, { id: 'proj-2', name: 'Project Two', description: 'Second project description', status: 'paused', autonomy_level: 'full_control', created_at: '2025-01-02T00:00:00Z', owner_id: 'user-1', progress: 30, openIssues: 8, activeAgents: 0, lastActivity: '2 days ago', }, ]; it('renders project cards', () => { render(); expect(screen.getByText('Project One')).toBeInTheDocument(); expect(screen.getByText('Project Two')).toBeInTheDocument(); }); it('displays section header with View all link', () => { render(); expect(screen.getByText('Recent Projects')).toBeInTheDocument(); const viewAllLink = screen.getByRole('link', { name: /View all/i }); expect(viewAllLink).toHaveAttribute('href', '/projects'); }); it('displays project descriptions', () => { render(); expect(screen.getByText('First project description')).toBeInTheDocument(); expect(screen.getByText('Second project description')).toBeInTheDocument(); }); it('displays project metrics', () => { render(); // Check agents count expect(screen.getByText('3 agents')).toBeInTheDocument(); expect(screen.getByText('0 agents')).toBeInTheDocument(); // Check issues count expect(screen.getByText('5 issues')).toBeInTheDocument(); expect(screen.getByText('8 issues')).toBeInTheDocument(); }); it('displays sprint info when available', () => { render(); expect(screen.getByText('Sprint 2')).toBeInTheDocument(); }); it('displays last activity time', () => { render(); expect(screen.getByText('5 minutes ago')).toBeInTheDocument(); expect(screen.getByText('2 days ago')).toBeInTheDocument(); }); it('shows loading skeletons when isLoading is true', () => { render(); // Should show skeleton cards expect(screen.getByText('Recent Projects')).toBeInTheDocument(); }); it('shows empty state when no projects', () => { render(); expect(screen.getByText('No projects yet')).toBeInTheDocument(); expect(screen.getByRole('link', { name: /Create your first project/i })).toBeInTheDocument(); }); it('links project cards to project detail page', () => { render(); const projectLink = screen.getByRole('link', { name: /Project One/i }); expect(projectLink).toHaveAttribute('href', '/projects/proj-1'); }); it('applies custom className', () => { const { container } = render(); expect(container.firstChild).toHaveClass('custom-class'); }); });