1- import { render , screen } from '@testing-library/ react'
2- import userEvent from '@testing-library/user-event '
1+ import React from 'react'
2+ import { render , screen , fireEvent , waitFor } from '@testing-library/react '
33import { ThemeToggle } from '../ThemeToggle'
44import { ThemeContext } from '@/lib/theme'
5- import React , { useState } from 'react'
6-
7- const renderWithTheme = ( initialTheme : 'light' | 'dark' = 'light' ) => {
8- const Wrapper : React . FC < { children : React . ReactNode } > = ( { children } ) => {
9- const [ theme , setTheme ] = useState < 'light' | 'dark' > ( initialTheme )
10- return (
11- < ThemeContext . Provider value = { { theme, setTheme } } >
12- { children }
13- </ ThemeContext . Provider >
14- )
15- }
16- return render ( < ThemeToggle /> , { wrapper : Wrapper } )
5+
6+ // Mock ThemeProvider for testing
7+ const MockThemeProvider = ( { children, initialTheme = 'light' } : { children : React . ReactNode , initialTheme ?: 'light' | 'dark' } ) => {
8+ const [ theme , setTheme ] = React . useState < 'light' | 'dark' > ( initialTheme )
9+
10+ return (
11+ < ThemeContext . Provider value = { { theme, setTheme } } >
12+ { children }
13+ </ ThemeContext . Provider >
14+ )
15+ }
16+
17+ const renderWithTheme = ( component : React . ReactElement , initialTheme : 'light' | 'dark' = 'light' ) => {
18+ return render (
19+ < MockThemeProvider initialTheme = { initialTheme } >
20+ { component }
21+ </ MockThemeProvider >
22+ )
1723}
1824
1925describe ( 'ThemeToggle' , ( ) => {
2026 it ( 'renders the theme toggle button' , ( ) => {
21- renderWithTheme ( )
22- const button = screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } )
23- expect ( button ) . toBeInTheDocument ( )
27+ renderWithTheme ( < ThemeToggle /> )
28+ expect ( screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } ) ) . toBeInTheDocument ( )
2429 } )
2530
2631 it ( 'toggles theme when clicked' , async ( ) => {
27- renderWithTheme ( 'light' )
32+ renderWithTheme ( < ThemeToggle /> )
2833 const button = screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } )
29- expect ( button ) . toHaveTextContent ( '🌙' )
30- await userEvent . click ( button )
34+
35+ // Initially should show sun icon (light theme - click to go dark )
3136 expect ( button ) . toHaveTextContent ( '☀️' )
32- await userEvent . click ( button )
33- expect ( button ) . toHaveTextContent ( '🌙' )
37+
38+ fireEvent . click ( button )
39+
40+ // After click, should show moon icon (dark theme - click to go light)
41+ await waitFor ( ( ) => {
42+ expect ( button ) . toHaveTextContent ( '🌙' )
43+ } )
3444 } )
3545
3646 it ( 'displays correct icon for light theme' , ( ) => {
37- renderWithTheme ( 'light' )
38- const button = screen . getByRole ( 'button' )
39- expect ( button ) . toHaveTextContent ( '🌙 ' )
47+ renderWithTheme ( < ThemeToggle /> , 'light' )
48+ const button = screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } )
49+ expect ( button ) . toHaveTextContent ( '☀️ ' )
4050 } )
4151
4252 it ( 'displays correct icon for dark theme' , ( ) => {
43- renderWithTheme ( 'dark' )
44- const button = screen . getByRole ( 'button' )
53+ renderWithTheme ( < ThemeToggle /> , 'dark' )
54+ const button = screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } )
55+ expect ( button ) . toHaveTextContent ( '🌙' )
56+ } )
57+
58+ it ( 'shows default icon during server-side rendering' , ( ) => {
59+ renderWithTheme ( < ThemeToggle /> )
60+ const button = screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } )
61+
62+ // During SSR, should always show the sun icon (light theme default)
63+ expect ( button ) . toHaveTextContent ( '☀️' )
64+ } )
65+
66+ it ( 'handles hydration correctly' , async ( ) => {
67+ renderWithTheme ( < ThemeToggle /> )
68+ const button = screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } )
69+
70+ // Initially shows sun icon (light theme - SSR state)
4571 expect ( button ) . toHaveTextContent ( '☀️' )
72+
73+ // After hydration, should still show the sun icon (light theme)
74+ await waitFor ( ( ) => {
75+ expect ( button ) . toHaveTextContent ( '☀️' )
76+ } )
77+
78+ // Click to test theme switching to dark
79+ fireEvent . click ( button )
80+
81+ // Verify the icon changes after clicking
82+ await waitFor ( ( ) => {
83+ const newButton = screen . getByRole ( 'button' , { name : / t o g g l e t h e m e / i } )
84+ expect ( newButton ) . not . toHaveTextContent ( '☀️' )
85+ } )
4686 } )
4787} )
0 commit comments