import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { describe, expect, it, vi } from 'vitest'; import { ThemeProvider, useTheme } from '../theme-provider'; // Mock next-themes const mockSetTheme = vi.fn(); let mockTheme = 'dark'; let mockResolvedTheme = 'dark'; vi.mock('next-themes', () => ({ ThemeProvider: ({ children }: { children: React.ReactNode }) => <>{children}, useTheme: () => ({ theme: mockTheme, resolvedTheme: mockResolvedTheme, setTheme: (t: string) => { mockSetTheme(t); mockTheme = t; mockResolvedTheme = t; }, }), })); // Test consumer component function ThemeConsumer() { const { theme, toggleTheme } = useTheme(); return (
{theme}
); } describe('ThemeProvider', () => { beforeEach(() => { mockTheme = 'dark'; mockResolvedTheme = 'dark'; vi.clearAllMocks(); }); it('renders children', () => { render(
Child content
, ); expect(screen.getByText('Child content')).toBeInTheDocument(); }); it('defaults to dark theme', () => { render( , ); expect(screen.getByTestId('theme')).toHaveTextContent('dark'); }); it('toggles theme to light', async () => { const user = userEvent.setup(); render( , ); await user.click(screen.getByText('Toggle')); expect(mockSetTheme).toHaveBeenCalledWith('light'); }); it('toggles theme back to dark', async () => { mockTheme = 'light'; mockResolvedTheme = 'light'; const user = userEvent.setup(); render( , ); await user.click(screen.getByText('Toggle')); expect(mockSetTheme).toHaveBeenCalledWith('dark'); }); }); describe('useTheme', () => { it('returns dark as default outside provider', () => { render(); expect(screen.getByTestId('theme')).toHaveTextContent('dark'); }); });