import { render, screen } from '@testing-library/react'; import { describe, it, expect } from 'vitest'; import { Progress } from './Progress'; describe('Progress Component', () => { describe('Linear variant', () => { it('renders linear progress bar', () => { render(); const progressBar = screen.getByRole('progressbar'); expect(progressBar).toBeInTheDocument(); }); it('renders with correct percentage', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ width: '50%' }); }); it('clamps value to max', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ width: '100%' }); }); it('clamps value to 0 minimum', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ width: '0%' }); }); it('shows label when provided', () => { render(); expect(screen.getByText('Upload progress')).toBeInTheDocument(); }); it('shows percentage when showLabel is true', () => { render(); expect(screen.getByText('75%')).toBeInTheDocument(); }); it('shows both label and percentage', () => { render(); expect(screen.getByText('Download')).toBeInTheDocument(); expect(screen.getByText('60%')).toBeInTheDocument(); }); it('applies custom color', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ backgroundColor: '#ff0000' }); }); it('has correct aria attributes', () => { render(); const progressBar = screen.getByRole('progressbar'); expect(progressBar).toHaveAttribute('aria-valuenow', '50'); expect(progressBar).toHaveAttribute('aria-valuemin', '0'); expect(progressBar).toHaveAttribute('aria-valuemax', '100'); expect(progressBar).toHaveAttribute('aria-label'); const ariaLabel = progressBar.getAttribute('aria-label'); expect(ariaLabel).toContain('50%'); }); it('applies custom className', () => { const { container } = render( , ); const wrapper = container.firstChild; expect(wrapper).toHaveClass('custom-progress'); }); }); describe('Circular variant', () => { it('renders circular progress', () => { render(); const progressBar = screen.getByRole('progressbar'); expect(progressBar).toBeInTheDocument(); expect(progressBar.tagName).toBe('svg'); }); it('renders with correct percentage', () => { const { container } = render(); const svg = container.querySelector('svg'); expect(svg).toBeInTheDocument(); }); it('shows percentage when showLabel is true', () => { render(); expect(screen.getByText('75%')).toBeInTheDocument(); }); it('does not show percentage when showLabel is false', () => { render(); expect(screen.queryByText('75%')).not.toBeInTheDocument(); }); it('applies custom color', () => { const { container } = render( , ); const circle = container.querySelector('circle[stroke-dasharray]'); expect(circle).toHaveStyle({ stroke: '#00ff00' }); }); it('has correct aria attributes', () => { render(); const progressBar = screen.getByRole('progressbar'); expect(progressBar).toHaveAttribute('aria-valuenow', '50'); expect(progressBar).toHaveAttribute('aria-valuemin', '0'); expect(progressBar).toHaveAttribute('aria-valuemax', '100'); }); it('applies custom className', () => { const { container } = render( , ); const wrapper = container.firstChild; expect(wrapper).toHaveClass('custom-circular'); }); it('clamps value to max in circular variant', () => { const { container } = render( , ); const svg = container.querySelector('svg'); expect(svg).toBeInTheDocument(); }); }); describe('Edge cases', () => { it('handles zero value', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ width: '0%' }); }); it('handles max value', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ width: '100%' }); }); it('handles custom max value', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ width: '25%' }); }); it('handles decimal values', () => { const { container } = render(); const progressFill = container.querySelector('.h-full'); expect(progressFill).toHaveStyle({ width: '33%' }); }); }); });