import { render, screen, fireEvent } from '@testing-library/react'; import { describe, it, expect } from 'vitest'; import { ActionList } from './ActionList'; import { ActionItem } from '@/lib/queries/ActionsPageQuery'; describe('ActionList', () => { const mockActions: ActionItem[] = [ { id: 'action-1', timestamp: '2024-01-15T10:30:00Z', type: 'USER_UPDATE', initiator: 'John Doe', status: 'COMPLETED', details: 'Updated profile settings', }, { id: 'action-2', timestamp: '2024-01-15T11:45:00Z', type: 'ONBOARDING', initiator: 'Jane Smith', status: 'PENDING', details: 'Started onboarding process', }, { id: 'action-3', timestamp: '2024-01-15T12:00:00Z', type: 'USER_UPDATE', initiator: 'Bob Johnson', status: 'FAILED', details: 'Failed to update email', }, { id: 'action-4', timestamp: '2024-01-15T13:15:00Z', type: 'ONBOARDING', initiator: 'Alice Brown', status: 'IN_PROGRESS', details: 'Completing verification', }, ]; describe('Rendering states', () => { it('renders table headers', () => { render(); expect(screen.getByText('Timestamp')).toBeDefined(); expect(screen.getByText('Type')).toBeDefined(); expect(screen.getByText('Initiator')).toBeDefined(); expect(screen.getByText('Status')).toBeDefined(); expect(screen.getByText('Details')).toBeDefined(); }); it('renders all action rows', () => { render(); mockActions.forEach((action) => { expect(screen.getByText(action.timestamp)).toBeDefined(); expect(screen.getAllByText(action.type).length).toBeGreaterThan(0); expect(screen.getByText(action.initiator)).toBeDefined(); expect(screen.getByText(action.details)).toBeDefined(); }); }); it('renders action status badges', () => { render(); // Check that status badges are rendered for each action expect(screen.getByText('COMPLETED')).toBeDefined(); expect(screen.getByText('PENDING')).toBeDefined(); expect(screen.getByText('FAILED')).toBeDefined(); expect(screen.getByText('IN PROGRESS')).toBeDefined(); }); it('renders empty table when no actions provided', () => { render(); // Table headers should still be visible expect(screen.getByText('Timestamp')).toBeDefined(); expect(screen.getByText('Type')).toBeDefined(); expect(screen.getByText('Initiator')).toBeDefined(); expect(screen.getByText('Status')).toBeDefined(); expect(screen.getByText('Details')).toBeDefined(); }); }); describe('Interaction behavior', () => { it('renders clickable rows', () => { render(); // Check that rows have clickable attribute const rows = screen.getAllByRole('row'); // Skip the header row const dataRows = rows.slice(1); dataRows.forEach((row) => { expect(row).toBeDefined(); }); }); it('renders row with key based on action id', () => { const { container } = render(); // Verify that each row has a unique key const rows = container.querySelectorAll('tbody tr'); expect(rows.length).toBe(mockActions.length); mockActions.forEach((action, index) => { const row = rows[index]; expect(row).toBeDefined(); }); }); }); describe('Visual presentation', () => { it('renders table structure correctly', () => { const { container } = render(); // Verify table structure const table = container.querySelector('table'); expect(table).toBeDefined(); const thead = container.querySelector('thead'); expect(thead).toBeDefined(); const tbody = container.querySelector('tbody'); expect(tbody).toBeDefined(); }); it('renders timestamp in monospace font', () => { render(); // The timestamp should be rendered with monospace font const timestamp = screen.getByText('2024-01-15T10:30:00Z'); expect(timestamp).toBeDefined(); }); it('renders type with medium weight', () => { render(); // The type should be rendered with medium weight const types = screen.getAllByText('USER_UPDATE'); expect(types.length).toBeGreaterThan(0); }); it('renders initiator with low variant', () => { render(); // The initiator should be rendered with low variant const initiator = screen.getByText('John Doe'); expect(initiator).toBeDefined(); }); it('renders details with low variant', () => { render(); // The details should be rendered with low variant const details = screen.getByText('Updated profile settings'); expect(details).toBeDefined(); }); }); describe('Edge cases', () => { it('handles single action', () => { const singleAction = [mockActions[0]]; render(); expect(screen.getByText(singleAction[0].timestamp)).toBeDefined(); expect(screen.getByText(singleAction[0].type)).toBeDefined(); expect(screen.getByText(singleAction[0].initiator)).toBeDefined(); expect(screen.getByText(singleAction[0].details)).toBeDefined(); }); it('handles actions with long details', () => { const longDetailsAction: ActionItem = { id: 'action-long', timestamp: '2024-01-15T14:00:00Z', type: 'USER_UPDATE', initiator: 'Long Name User', status: 'COMPLETED', details: 'This is a very long details text that might wrap to multiple lines and should still be displayed correctly in the table', }; render(); expect(screen.getByText(longDetailsAction.details)).toBeDefined(); }); it('handles actions with special characters in details', () => { const specialDetailsAction: ActionItem = { id: 'action-special', timestamp: '2024-01-15T15:00:00Z', type: 'USER_UPDATE', initiator: 'Special User', status: 'COMPLETED', details: 'Updated settings & preferences (admin)', }; render(); expect(screen.getByText(specialDetailsAction.details)).toBeDefined(); }); it('handles actions with unicode characters', () => { const unicodeAction: ActionItem = { id: 'action-unicode', timestamp: '2024-01-15T16:00:00Z', type: 'USER_UPDATE', initiator: 'Über User', status: 'COMPLETED', details: 'Updated profile with emoji 🚀', }; render(); expect(screen.getByText(unicodeAction.details)).toBeDefined(); }); }); describe('Status badge integration', () => { it('renders ActionStatusBadge for each action', () => { render(); // Each action should have a status badge const completedBadge = screen.getByText('COMPLETED'); const pendingBadge = screen.getByText('PENDING'); const failedBadge = screen.getByText('FAILED'); const inProgressBadge = screen.getByText('IN PROGRESS'); expect(completedBadge).toBeDefined(); expect(pendingBadge).toBeDefined(); expect(failedBadge).toBeDefined(); expect(inProgressBadge).toBeDefined(); }); it('renders correct badge variant for each status', () => { render(); // Verify that badges are rendered with correct variants // This is verified by the ActionStatusBadge component tests expect(screen.getByText('COMPLETED')).toBeDefined(); expect(screen.getByText('PENDING')).toBeDefined(); expect(screen.getByText('FAILED')).toBeDefined(); expect(screen.getByText('IN PROGRESS')).toBeDefined(); }); }); });