import React from 'react' import { render, screen } from '@testing-library/react' import '@testing-library/jest-dom' import { Progress } from '../progress' describe('Progress Component', () => { describe('Basic Rendering', () => { it('renders correctly with default props', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toBeInTheDocument() expect(progress).toHaveClass('relative') expect(progress).toHaveClass('w-full') expect(progress).toHaveClass('overflow-hidden') expect(progress).toHaveClass('bg-muted') }) it('renders with custom value', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-valuenow', '50') expect(progress).toHaveAttribute('aria-valuemin', '0') expect(progress).toHaveAttribute('aria-valuemax', '100') }) it('applies custom className', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('custom-progress') }) it('forwards ref correctly', () => { const ref = React.createRef() render() expect(ref.current).toBeInstanceOf(HTMLDivElement) }) }) describe('Value Handling', () => { it('handles value normalization correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-valuenow', '100') }) it('handles negative values correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-valuenow', '0') }) it('handles custom max value', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-valuenow', '50') expect(progress).toHaveAttribute('aria-valuemax', '200') }) it('calculates percentage correctly with custom max', () => { render() const label = screen.getByText('25%') expect(label).toBeInTheDocument() }) }) describe('Variants', () => { it('renders default variant correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('bg-muted') }) it('renders primary variant correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('bg-primary/20') }) it('renders secondary variant correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('bg-secondary/20') }) it('renders success variant correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('bg-success/20') }) it('renders warning variant correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('bg-warning/20') }) it('renders error variant correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('bg-error/20') }) }) describe('Sizes', () => { it('renders xs size correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('h-1') }) it('renders sm size correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('h-1.5') }) it('renders default size correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('h-2') }) it('renders md size correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('h-2.5') }) it('renders lg size correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('h-3') }) it('renders xl size correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('h-4') }) }) describe('Radius', () => { it('renders none radius correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('rounded-none') }) it('renders sm radius correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('rounded-sm') }) it('renders default radius correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('rounded-md') }) it('renders lg radius correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('rounded-lg') }) it('renders full radius correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('rounded-full') }) }) describe('Animation', () => { it('renders default animation correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('[&>div]:transition-all') expect(progress).toHaveClass('[&>div]:duration-500') }) it('renders smooth animation correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('[&>div]:transition-all') expect(progress).toHaveClass('[&>div]:duration-700') }) it('renders fast animation correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('[&>div]:transition-all') expect(progress).toHaveClass('[&>div]:duration-300') }) it('renders none animation correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).not.toHaveClass('[&>div]:transition-all') }) }) describe('Indicator Variants', () => { it('renders default indicator variant correctly', () => { render() const progress = screen.getByRole('progressbar') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('bg-foreground') }) it('renders primary indicator variant correctly', () => { render() const progress = screen.getByRole('progressbar') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('bg-primary') }) it('renders secondary indicator variant correctly', () => { render() const progress = screen.getByRole('progressbar') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('bg-secondary') }) it('renders success indicator variant correctly', () => { render() const progress = screen.getByRole('progressbar') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('bg-success') }) it('renders warning indicator variant correctly', () => { render() const progress = screen.getByRole('progressbar') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('bg-warning') }) it('renders error indicator variant correctly', () => { render() const progress = screen.getByRole('progressbar') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('bg-error') }) }) describe('Value Label', () => { it('does not show value label by default', () => { render() expect(screen.queryByText('50%')).not.toBeInTheDocument() }) it('shows value label when enabled', () => { render() const label = screen.getByText('50%') expect(label).toBeInTheDocument() }) it('shows custom value label', () => { render() const label = screen.getByText('50/100') expect(label).toBeInTheDocument() }) it('applies custom label className', () => { render() const label = screen.getByText('50%') expect(label).toHaveClass('custom-label') }) it('shows correct percentage for custom max', () => { render() const label = screen.getByText('50%') expect(label).toBeInTheDocument() }) }) describe('Indeterminate State', () => { it('renders indeterminate progress correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).not.toHaveAttribute('aria-valuenow') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('animate-indeterminate-progress') }) it('does not show aria-valuenow when indeterminate', () => { render() const progress = screen.getByRole('progressbar') expect(progress).not.toHaveAttribute('aria-valuenow') }) }) describe('Accessibility', () => { it('has correct ARIA attributes', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('role', 'progressbar') expect(progress).toHaveAttribute('aria-valuemin', '0') expect(progress).toHaveAttribute('aria-valuemax', '100') expect(progress).toHaveAttribute('aria-valuenow', '50') }) it('supports custom ARIA attributes', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-label', 'Loading progress') }) }) describe('Complex Combinations', () => { it('renders with multiple props correctly', () => { render( ) const progress = screen.getByRole('progressbar') expect(progress).toHaveClass('bg-success/20') expect(progress).toHaveClass('h-3') expect(progress).toHaveClass('rounded-sm') expect(progress).toHaveClass('[&>div]:duration-300') const indicator = progress.querySelector('div') expect(indicator).toHaveClass('bg-primary') const label = screen.getByText('3/4 complete') expect(label).toHaveClass('font-bold') }) it('maintains displayName', () => { expect(Progress.displayName).toBe('Progress') }) }) describe('Edge Cases', () => { it('handles zero value correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-valuenow', '0') const label = screen.getByText('0%') expect(label).toBeInTheDocument() }) it('handles max value correctly', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-valuenow', '100') const label = screen.getByText('100%') expect(label).toBeInTheDocument() }) it('handles zero max value', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('aria-valuemax', '0') const label = screen.getByText('0%') expect(label).toBeInTheDocument() }) it('passes through HTML attributes', () => { render() const progress = screen.getByRole('progressbar') expect(progress).toHaveAttribute('data-testid', 'progress-test') expect(progress).toHaveAttribute('id', 'progress-1') }) }) })