import React from 'react'; import { describe, it, expect } from 'vitest'; import { render, screen } from '@testing-library/react'; import { PixelProgress } from '../../feedback/PixelProgress'; describe('PixelProgress — ARIA contract', () => { it('exposes role="progressbar" with valuenow/min/max', () => { render(); const bar = screen.getByRole('progressbar'); expect(bar.getAttribute('aria-valuenow')).toBe('42'); expect(bar.getAttribute('aria-valuemin')).toBe('0'); expect(bar.getAttribute('aria-valuemax')).toBe('100'); }); it('defaults the accessible name to "Progress" when no label is given', () => { render(); expect(screen.getByRole('progressbar', { name: 'Progress' })).toBeInTheDocument(); }); it('uses the label as the accessible name when provided', () => { render(); expect(screen.getByRole('progressbar', { name: 'HP' })).toBeInTheDocument(); }); it('clamps value into the 0-100 range', () => { const { rerender } = render(); expect(screen.getByRole('progressbar').getAttribute('aria-valuenow')).toBe('100'); rerender(); expect(screen.getByRole('progressbar').getAttribute('aria-valuenow')).toBe('0'); }); it('indeterminate drops aria-valuenow and sets aria-busy', () => { render(); const bar = screen.getByRole('progressbar'); expect(bar.getAttribute('aria-valuenow')).toBeNull(); expect(bar.getAttribute('aria-busy')).toBe('true'); }); }); describe('PixelProgress — label row + showValue', () => { it('shows label text and the numeric percentage by default', () => { render(); expect(screen.getByText('XP')).toBeInTheDocument(); expect(screen.getByText('75%')).toBeInTheDocument(); }); it('hides the percentage when showValue={false}', () => { render(); expect(screen.queryByText('75%')).toBeNull(); }); it('hides the percentage while indeterminate', () => { render(); expect(screen.queryByText('75%')).toBeNull(); }); }); describe('PixelProgress — pixel surface (segmented HP bar)', () => { it('renders 10 segment blocks inside the progressbar', () => { render(); const bar = screen.getByRole('progressbar'); expect(bar.children.length).toBe(10); }); it('fills segments proportionally to the value with the tone fill', () => { render(); const segments = Array.from(screen.getByRole('progressbar').children) as HTMLElement[]; const filled = segments.filter((s) => s.className.includes('bg-retro-green') && !s.className.includes('opacity-50')); expect(filled.length).toBe(5); }); }); describe('PixelProgress — linear surface (smooth bar)', () => { it('renders an inner fill div whose width tracks the value', () => { render(); const bar = screen.getByRole('progressbar'); const fill = bar.firstElementChild as HTMLElement; expect(fill.style.width).toBe('60%'); }); it('indeterminate stretches the fill to 100% with pulse animation', () => { render(); const fill = screen.getByRole('progressbar').firstElementChild as HTMLElement; expect(fill.style.width).toBe('100%'); expect(fill.className).toContain('animate-pulse'); }); });