import { render, screen } from '@testing-library/react' import { describe, it, expect } from 'vitest' import { axe } from 'vitest-axe' import { Progress, ProgressLabel, ProgressValue } from './progress' describe('Progress', () => { it('renders bar variant by default with role and value', () => { render() const el = screen.getByRole('progressbar') expect(el).toHaveAttribute('data-slot', 'progress') expect(el).toHaveAttribute('data-variant', 'bar') expect(el).toHaveAttribute('aria-valuenow', '40') expect(el).toHaveAttribute('aria-valuemin', '0') expect(el).toHaveAttribute('aria-valuemax', '100') }) it('renders bar Track and Indicator with width applied by Base UI', () => { const { container } = render() const track = container.querySelector('[data-slot=progress-track]') as HTMLElement const indicator = container.querySelector('[data-slot=progress-indicator]') as HTMLElement expect(track).toBeInTheDocument() expect(indicator).toBeInTheDocument() expect(indicator.style.width).toBe('50%') }) it('applies thickness to bar track height', () => { const { container } = render() const track = container.querySelector('[data-slot=progress-track]') as HTMLElement expect(track.style.height).toBe('10px') }) it('renders circular variant with an SVG', () => { const { container } = render() const root = screen.getByRole('progressbar') expect(root).toHaveAttribute('data-variant', 'circular') const svg = container.querySelector('svg[data-slot=progress-circular]') as SVGElement expect(svg).toBeInTheDocument() expect(svg.getAttribute('width')).toBe('56') expect(svg.getAttribute('height')).toBe('56') }) it('respects size and thickness on circular variant', () => { const { container } = render() const svg = container.querySelector('svg[data-slot=progress-circular]') as SVGElement expect(svg.getAttribute('width')).toBe('80') const indicator = container.querySelector('svg [data-slot=progress-indicator]') as SVGCircleElement expect(indicator.getAttribute('stroke-width')).toBe('6') }) it('passes indicatorColor through via the --progress-color CSS variable', () => { render() const root = screen.getByRole('progressbar') expect(root.style.getPropertyValue('--progress-color')).toBe('oklch(0.7 0.2 30)') }) it('links ProgressLabel to the root via aria-labelledby', () => { render( Uploading , ) const root = screen.getByRole('progressbar') const labelId = root.getAttribute('aria-labelledby') expect(labelId).toBeTruthy() expect(document.getElementById(labelId!)?.textContent).toBe('Uploading') }) it('renders the formatted value via ProgressValue', () => { render( , ) expect(screen.getByText('42%')).toBeInTheDocument() }) it('marks complete state on parts when value reaches max', () => { const { container } = render() const indicator = container.querySelector('[data-slot=progress-indicator]') as HTMLElement expect(indicator).toHaveAttribute('data-complete') }) it('forwards className alongside the layout classes', () => { render() const root = screen.getByRole('progressbar') expect(root.className).toContain('custom-class') expect(root.className).toContain('grid') }) it('has no accessibility violations (bar)', async () => { const { container } = render( Loading , ) expect(await axe(container)).toHaveNoViolations() }) it('has no accessibility violations (circular)', async () => { const { container } = render( Loading , ) expect(await axe(container)).toHaveNoViolations() }) })