import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen } from '@testing-library/react'; import { ScoreBar, ScoreCard } from '../ScoreBar'; // Mock the @aiready/core/client module vi.mock('@aiready/core/client', async (importOriginal) => { const actual = (await importOriginal()) as any; return { ...actual, getRating: vi.fn((score: number) => { if (score >= 80) return 'Excellent'; if (score >= 60) return 'Good'; if (score >= 40) return 'Fair'; if (score >= 20) return 'Needs Work'; return 'Critical'; }), }; }); describe('ScoreBar', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('rendering', () => { it('should render with default props', () => { render(); expect(screen.getByText('Test Score')).toBeInTheDocument(); expect(screen.getByText('75/100')).toBeInTheDocument(); }); it('should render without score when showScore is false', () => { render(); expect(screen.getByText('Test Score')).toBeInTheDocument(); expect(screen.queryByText('75/100')).not.toBeInTheDocument(); }); it('should apply custom className', () => { const { container } = render( ); expect(container.firstChild).toHaveClass('custom-class'); }); it('should render with different sizes', () => { const { container, rerender } = render( ); // Small size should have h-1.5 for the bar expect(container.querySelector('.bg-slate-200')).toHaveClass('h-1.5'); rerender(); expect(container.querySelector('.bg-slate-200')).toHaveClass('h-3'); }); }); describe('score prop', () => { it('should handle score of 0', () => { const { container } = render(); expect(screen.getByText('0/100')).toBeInTheDocument(); // Should show critical rating (red) expect(container.querySelector('.bg-red-500')).toBeInTheDocument(); }); it('should handle perfect score of 100', () => { const { container } = render( ); expect(screen.getByText('100/100')).toBeInTheDocument(); // Should show excellent rating (green) expect(container.querySelector('.bg-green-500')).toBeInTheDocument(); }); it('should handle custom maxScore', () => { const { container } = render( ); expect(screen.getByText('150/200')).toBeInTheDocument(); // 150/200 = 75% which should be good (emerald) expect(container.querySelector('.bg-emerald-500')).toBeInTheDocument(); }); it('should clamp bar width to 0-100% range', () => { const { container, rerender } = render( ); // The bar width should be clamped to 0% const barElement = container.querySelector('[style*="width"]'); expect(barElement).toHaveStyle('width: 0%'); rerender(); // The bar width should be clamped to 100% expect(barElement).toHaveStyle('width: 100%'); }); }); describe('label display', () => { it('should render the provided label', () => { render(); expect(screen.getByText('Custom Label')).toBeInTheDocument(); }); it('should display label in correct size based on size prop', () => { const { rerender } = render( ); expect(screen.getByText('Test')).toHaveClass('text-xs'); rerender(); expect(screen.getByText('Test')).toHaveClass('text-base'); }); }); describe('color based on score', () => { it('should show green color for excellent scores (>=80)', () => { const { container } = render(); // Check for green-500 background class expect(container.querySelector('.bg-green-500')).toBeInTheDocument(); }); it('should show emerald color for good scores (>=60)', () => { const { container } = render(); // Check for emerald-500 background class expect(container.querySelector('.bg-emerald-500')).toBeInTheDocument(); }); it('should show amber color for fair scores (>=40)', () => { const { container } = render(); // Check for amber-500 background class expect(container.querySelector('.bg-amber-500')).toBeInTheDocument(); }); it('should show orange color for needs-work scores (>=20)', () => { const { container } = render(); // Check for orange-500 background class expect(container.querySelector('.bg-orange-500')).toBeInTheDocument(); }); it('should show red color for critical scores (<20)', () => { const { container } = render(); // Check for red-500 background class expect(container.querySelector('.bg-red-500')).toBeInTheDocument(); }); }); describe('accessibility', () => { it('should have proper ARIA structure', () => { render(); // The component should have proper div structure for screen readers // The label and score should be visible to screen readers expect(screen.getByText('Accessibility Test')).toBeInTheDocument(); expect(screen.getByText('75/100')).toBeInTheDocument(); }); }); }); describe('ScoreCard', () => { it('should render with score and rating', () => { render(); expect(screen.getByText('85/100')).toBeInTheDocument(); expect(screen.getByText('Excellent Rating')).toBeInTheDocument(); expect(screen.getByText('Test Card')).toBeInTheDocument(); }); it('should render breakdown when provided', () => { const breakdown = [ { label: 'Security', score: 90 }, { label: 'Performance', score: 80 }, ]; render(); expect(screen.getByText('Security')).toBeInTheDocument(); expect(screen.getByText('Performance')).toBeInTheDocument(); expect(screen.getByText('90/100')).toBeInTheDocument(); expect(screen.getByText('80/100')).toBeInTheDocument(); }); it('should calculate and display formula when breakdown has weights', () => { const breakdown = [ { label: 'Security', score: 90, weight: 2 }, { label: 'Performance', score: 80, weight: 1 }, ]; render(); // Formula: 90×2 + 80×1 / 100 = 87 expect(screen.getByText('90×2 + 80×1 / 100 = 87')).toBeInTheDocument(); }); it('should apply custom className', () => { const { container } = render( ); expect(container.firstChild).toHaveClass('custom-class'); }); });