test(08-01): add failing tests for ThemeToggle component
- Test renders three buttons: Light, Dark, System - Test default state is System when localStorage is empty - Test clicking Dark adds .dark class to documentElement - Test clicking Light removes .dark class from documentElement - Test clicking Dark writes to localStorage key r2b-theme - Test active/inactive aria-pressed state - Test group has aria-label="Theme"
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
// @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(<ThemeToggle />);
|
||||
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(<ThemeToggle />);
|
||||
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(<ThemeToggle />);
|
||||
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(<ThemeToggle />);
|
||||
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(<ThemeToggle />);
|
||||
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(<ThemeToggle />);
|
||||
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(<ThemeToggle />);
|
||||
expect(screen.getByRole('group', { name: 'Theme' })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user