// @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();
});
});