/** * ActivityTimeline Component Tests */ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ActivityTimeline } from '@/features/issues/components/ActivityTimeline'; import type { IssueActivity } from '@/features/issues/types'; const mockActivities: IssueActivity[] = [ { id: 'act-1', type: 'status_change', actor: { id: 'user-1', name: 'Test User', type: 'human' }, message: 'moved issue from "Open" to "In Progress"', timestamp: '2 hours ago', }, { id: 'act-2', type: 'comment', actor: { id: 'agent-1', name: 'Backend Agent', type: 'agent' }, message: 'Started working on this issue', timestamp: '3 hours ago', }, { id: 'act-3', type: 'created', actor: { id: 'user-2', name: 'Product Owner', type: 'human' }, message: 'created this issue', timestamp: '1 day ago', }, ]; describe('ActivityTimeline', () => { it('renders all activities', () => { render(); expect(screen.getByText('Test User')).toBeInTheDocument(); expect(screen.getByText('Backend Agent')).toBeInTheDocument(); expect(screen.getByText('Product Owner')).toBeInTheDocument(); }); it('renders activity messages', () => { render(); expect(screen.getByText(/moved issue from "Open" to "In Progress"/)).toBeInTheDocument(); expect(screen.getByText(/Started working on this issue/)).toBeInTheDocument(); expect(screen.getByText(/created this issue/)).toBeInTheDocument(); }); it('renders timestamps', () => { render(); expect(screen.getByText('2 hours ago')).toBeInTheDocument(); expect(screen.getByText('3 hours ago')).toBeInTheDocument(); expect(screen.getByText('1 day ago')).toBeInTheDocument(); }); it('shows add comment button when callback provided', () => { const mockOnAddComment = jest.fn(); render(); expect(screen.getByRole('button', { name: /add comment/i })).toBeInTheDocument(); }); it('calls onAddComment when button is clicked', async () => { const user = userEvent.setup(); const mockOnAddComment = jest.fn(); render(); await user.click(screen.getByRole('button', { name: /add comment/i })); expect(mockOnAddComment).toHaveBeenCalled(); }); it('shows empty state when no activities', () => { render(); expect(screen.getByText('No activity yet')).toBeInTheDocument(); }); it('applies custom className', () => { const { container } = render( ); expect(container.firstChild).toHaveClass('custom-class'); }); it('has proper list role for accessibility', () => { render(); expect(screen.getByRole('list', { name: /issue activity/i })).toBeInTheDocument(); }); });