// @vitest-environment jsdom import { describe, it, expect, beforeEach } from 'vitest'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ThemeToggle } from './ThemeToggle'; describe('ThemeToggle', () => { beforeEach(() => { // Reset DOM and localStorage before each test document.documentElement.classList.remove('dark'); localStorage.clear(); }); it('renders three buttons: Light, Dark, System', () => { render(); expect(screen.getByRole('button', { name: /light/i })).toBeInTheDocument(); expect(screen.getByRole('button', { name: /dark/i })).toBeInTheDocument(); expect(screen.getByRole('button', { name: /system/i })).toBeInTheDocument(); }); it('default state is System (aria-pressed="true" on System button) when localStorage is empty', () => { render(); const systemButton = screen.getByRole('button', { name: /system/i }); const lightButton = screen.getByRole('button', { name: /light/i }); const darkButton = screen.getByRole('button', { name: /dark/i }); expect(systemButton).toHaveAttribute('aria-pressed', 'true'); expect(lightButton).toHaveAttribute('aria-pressed', 'false'); expect(darkButton).toHaveAttribute('aria-pressed', 'false'); }); it('clicking Dark adds .dark class to document.documentElement', async () => { const user = userEvent.setup(); render(); const darkButton = screen.getByRole('button', { name: /dark/i }); await user.click(darkButton); expect(document.documentElement.classList.contains('dark')).toBe(true); }); it('clicking Light removes .dark class from document.documentElement', async () => { const user = userEvent.setup(); // Start with dark class applied document.documentElement.classList.add('dark'); render(); const lightButton = screen.getByRole('button', { name: /light/i }); await user.click(lightButton); expect(document.documentElement.classList.contains('dark')).toBe(false); }); it('clicking Dark writes "dark" to localStorage under key "r2b-theme"', async () => { const user = userEvent.setup(); render(); const darkButton = screen.getByRole('button', { name: /dark/i }); await user.click(darkButton); expect(localStorage.getItem('r2b-theme')).toBe('dark'); }); it('active button has aria-pressed="true", others have aria-pressed="false"', async () => { const user = userEvent.setup(); render(); const darkButton = screen.getByRole('button', { name: /dark/i }); await user.click(darkButton); expect(darkButton).toHaveAttribute('aria-pressed', 'true'); expect(screen.getByRole('button', { name: /light/i })).toHaveAttribute('aria-pressed', 'false'); expect(screen.getByRole('button', { name: /system/i })).toHaveAttribute('aria-pressed', 'false'); }); it('component group has aria-label="Theme"', () => { render(); expect(screen.getByRole('group', { name: 'Theme' })).toBeInTheDocument(); }); });