import { render, screen } from '@testing-library/react'; import { describe, it, expect, beforeEach } from 'vitest'; import { MilestoneItem } from './MilestoneItem'; describe('MilestoneItem', () => { const mockProps = { label: 'Total Races', value: '150', icon: '🏁', }; beforeEach(() => { // Clear any previous renders document.body.innerHTML = ''; }); describe('Rendering', () => { it('renders all milestone information correctly', () => { render(); expect(screen.getByText('🏁')).toBeDefined(); expect(screen.getByText('Total Races')).toBeDefined(); expect(screen.getByText('150')).toBeDefined(); }); it('renders with different icons', () => { const icons = ['🏁', '🏆', '⭐', '💎', '🎯', '⏱️']; icons.forEach((icon) => { render(); expect(screen.getByText(icon)).toBeDefined(); }); }); it('renders with different labels', () => { const labels = [ 'Total Races', 'Wins', 'Podiums', 'Laps Completed', 'Distance Traveled', 'Time Spent', ]; labels.forEach((label) => { render(); expect(screen.getByText(label)).toBeDefined(); }); }); it('renders with different values', () => { const values = ['0', '1', '10', '100', '1000', '10000', '999999']; values.forEach((value) => { render(); expect(screen.getByText(value)).toBeDefined(); }); }); it('renders with long label', () => { const longLabel = 'Total Distance Traveled in All Races Combined'; render( ); expect(screen.getByText(longLabel)).toBeDefined(); }); it('renders with long value', () => { const longValue = '12,345,678'; render( ); expect(screen.getByText(longValue)).toBeDefined(); }); it('renders with special characters in label', () => { const specialLabel = 'Races Won (2024)'; render( ); expect(screen.getByText(specialLabel)).toBeDefined(); }); it('renders with special characters in value', () => { const specialValue = '1,234.56'; render( ); expect(screen.getByText(specialValue)).toBeDefined(); }); }); describe('Empty states', () => { it('renders with empty label', () => { render( ); expect(screen.getByText('🏁')).toBeDefined(); expect(screen.getByText('150')).toBeDefined(); }); it('renders with empty value', () => { render( ); expect(screen.getByText('🏁')).toBeDefined(); expect(screen.getByText('Total Races')).toBeDefined(); }); it('renders with empty icon', () => { render( ); expect(screen.getByText('Total Races')).toBeDefined(); expect(screen.getByText('150')).toBeDefined(); }); it('renders with all empty values', () => { render( ); // Should still render the card structure expect(document.body.textContent).toBeDefined(); }); }); describe('Icon variations', () => { it('renders with emoji icons', () => { const emojiIcons = ['🏁', '🏆', '⭐', '💎', '🎯', '⏱️', '🎮', '⚡']; emojiIcons.forEach((icon) => { render(); expect(screen.getByText(icon)).toBeDefined(); }); }); it('renders with unicode characters', () => { const unicodeIcons = ['★', '☆', '♦', '♥', '♠', '♣']; unicodeIcons.forEach((icon) => { render(); expect(screen.getByText(icon)).toBeDefined(); }); }); it('renders with text icons', () => { const textIcons = ['A', 'B', 'C', '1', '2', '3', '!', '@', '#']; textIcons.forEach((icon) => { render(); expect(screen.getByText(icon)).toBeDefined(); }); }); }); describe('Value formatting', () => { it('renders numeric values', () => { const numericValues = ['0', '1', '10', '100', '1000', '10000']; numericValues.forEach((value) => { render(); expect(screen.getByText(value)).toBeDefined(); }); }); it('renders formatted numbers', () => { const formattedValues = ['1,000', '10,000', '100,000', '1,000,000']; formattedValues.forEach((value) => { render(); expect(screen.getByText(value)).toBeDefined(); }); }); it('renders decimal values', () => { const decimalValues = ['0.0', '1.5', '10.25', '100.99']; decimalValues.forEach((value) => { render(); expect(screen.getByText(value)).toBeDefined(); }); }); it('renders percentage values', () => { const percentageValues = ['0%', '50%', '100%', '150%']; percentageValues.forEach((value) => { render(); expect(screen.getByText(value)).toBeDefined(); }); }); it('renders time values', () => { const timeValues = ['0:00', '1:30', '10:45', '1:23:45']; timeValues.forEach((value) => { render(); expect(screen.getByText(value)).toBeDefined(); }); }); }); describe('Label variations', () => { it('renders single word labels', () => { const singleWordLabels = ['Races', 'Wins', 'Losses', 'Time', 'Distance']; singleWordLabels.forEach((label) => { render(); expect(screen.getByText(label)).toBeDefined(); }); }); it('renders multi-word labels', () => { const multiWordLabels = [ 'Total Races', 'Race Wins', 'Podium Finishes', 'Laps Completed', 'Distance Traveled', ]; multiWordLabels.forEach((label) => { render(); expect(screen.getByText(label)).toBeDefined(); }); }); it('renders labels with parentheses', () => { const parentheticalLabels = [ 'Races (All)', 'Wins (Ranked)', 'Time (Active)', 'Distance (Total)', ]; parentheticalLabels.forEach((label) => { render(); expect(screen.getByText(label)).toBeDefined(); }); }); it('renders labels with numbers', () => { const numberedLabels = [ 'Races 2024', 'Wins 2023', 'Season 1', 'Group A', ]; numberedLabels.forEach((label) => { render(); expect(screen.getByText(label)).toBeDefined(); }); }); }); describe('Edge cases', () => { it('handles very long label and value', () => { const longLabel = 'This is an extremely long milestone label that should still be displayed correctly without breaking the layout'; const longValue = '999,999,999,999,999,999,999,999,999'; render( ); expect(screen.getByText(longLabel)).toBeDefined(); expect(screen.getByText(longValue)).toBeDefined(); }); it('handles special characters in all fields', () => { const specialProps = { label: 'Races Won (2024) #1!', value: '1,234.56', icon: '🏆', }; render(); expect(screen.getByText(specialProps.label)).toBeDefined(); expect(screen.getByText(specialProps.value)).toBeDefined(); expect(screen.getByText(specialProps.icon)).toBeDefined(); }); it('handles unicode in all fields', () => { const unicodeProps = { label: '★ Star Races ★', value: '★ 100 ★', icon: '★', }; render(); expect(screen.getByText(unicodeProps.label)).toBeDefined(); expect(screen.getByText(unicodeProps.value)).toBeDefined(); expect(screen.getByText(unicodeProps.icon)).toBeDefined(); }); it('handles zero value', () => { render( ); expect(screen.getByText('0')).toBeDefined(); }); it('handles negative value', () => { render( ); expect(screen.getByText('-5')).toBeDefined(); }); it('handles scientific notation', () => { render( ); expect(screen.getByText('1.5e6')).toBeDefined(); }); }); describe('Layout structure', () => { it('renders with correct visual hierarchy', () => { const { container } = render(); // Check that the component renders with the expected structure // The component should have a Card with a Group containing icon, label, and value expect(container.firstChild).toBeDefined(); // Verify all text elements are present expect(screen.getByText('🏁')).toBeDefined(); expect(screen.getByText('Total Races')).toBeDefined(); expect(screen.getByText('150')).toBeDefined(); }); it('maintains consistent structure across different props', () => { const testCases = [ { label: 'A', value: '1', icon: 'X' }, { label: 'Long Label', value: '1000', icon: '🏆' }, { label: 'Special!@#', value: '1.23', icon: '★' }, ]; testCases.forEach((props) => { const { container } = render(); // Each should render successfully expect(container.firstChild).toBeDefined(); expect(screen.getByText(props.label)).toBeDefined(); expect(screen.getByText(props.value)).toBeDefined(); expect(screen.getByText(props.icon)).toBeDefined(); }); }); }); });