Skip to content

Commit b0ad50e

Browse files
committed
Add unit tests for ToggleDarkMode component
Signed-off-by: kartik <kartikrautan0@gmail.com>
1 parent 1272f54 commit b0ad50e

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { render, screen, fireEvent } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
5+
// ---------- Mutable store state ----------
6+
let mockBackgroundColor = '#ffffff';
7+
const mockToggleDarkMode = vi.fn();
8+
9+
vi.mock('../../store/store', () => {
10+
// Return a function that, when called with no selector, returns the store object.
11+
// When called with a selector, passes the store object through the selector.
12+
const useAppStore = (...args: unknown[]) => {
13+
const storeState = {
14+
backgroundColor: mockBackgroundColor,
15+
toggleDarkMode: mockToggleDarkMode,
16+
};
17+
if (typeof args[0] === 'function') {
18+
return (args[0] as (s: typeof storeState) => unknown)(storeState);
19+
}
20+
return storeState;
21+
};
22+
return { default: useAppStore };
23+
});
24+
25+
// ---------- Mock react-dark-mode-toggle ----------
26+
vi.mock('react-dark-mode-toggle', () => ({
27+
default: ({
28+
checked,
29+
onChange,
30+
size,
31+
className,
32+
}: {
33+
checked: boolean;
34+
onChange: () => void;
35+
size: number;
36+
className: string;
37+
}) => (
38+
<button
39+
data-testid="dark-mode-toggle"
40+
data-checked={checked}
41+
data-size={size}
42+
className={className}
43+
onClick={onChange}
44+
>
45+
Dark Mode Toggle
46+
</button>
47+
),
48+
}));
49+
50+
// ---------- Mock styled-component ----------
51+
vi.mock('../../styles/components/ToggleDarkMode', () => ({
52+
ToggleDarkModeContainer: ({
53+
children,
54+
...props
55+
}: React.PropsWithChildren<Record<string, unknown>>) => (
56+
<div {...props}>{children}</div>
57+
),
58+
}));
59+
60+
// ---------- Import after mocks ----------
61+
import ToggleDarkMode from '../../components/ToggleDarkMode';
62+
63+
// ---------- Tests ----------
64+
describe('ToggleDarkMode', () => {
65+
beforeEach(() => {
66+
vi.clearAllMocks();
67+
mockBackgroundColor = '#ffffff';
68+
document.documentElement.removeAttribute('data-theme');
69+
});
70+
71+
it('renders the toggle component', () => {
72+
render(<ToggleDarkMode />);
73+
expect(screen.getByTestId('toggle-dark-mode')).toBeInTheDocument();
74+
});
75+
76+
it('initializes isDarkMode to false when backgroundColor is #ffffff', () => {
77+
mockBackgroundColor = '#ffffff';
78+
render(<ToggleDarkMode />);
79+
const btn = screen.getByTestId('dark-mode-toggle');
80+
expect(btn.getAttribute('data-checked')).toBe('false');
81+
});
82+
83+
it('initializes isDarkMode to true when backgroundColor is #121212', () => {
84+
mockBackgroundColor = '#121212';
85+
render(<ToggleDarkMode />);
86+
const btn = screen.getByTestId('dark-mode-toggle');
87+
expect(btn.getAttribute('data-checked')).toBe('true');
88+
});
89+
90+
it('calls toggleDarkMode when clicked', () => {
91+
render(<ToggleDarkMode />);
92+
fireEvent.click(screen.getByTestId('dark-mode-toggle'));
93+
expect(mockToggleDarkMode).toHaveBeenCalledTimes(1);
94+
});
95+
96+
it('sets data-theme to dark when toggled from light mode', () => {
97+
mockBackgroundColor = '#ffffff';
98+
render(<ToggleDarkMode />);
99+
fireEvent.click(screen.getByTestId('dark-mode-toggle'));
100+
expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
101+
});
102+
103+
it('sets data-theme to light when toggled from dark mode', () => {
104+
mockBackgroundColor = '#121212';
105+
render(<ToggleDarkMode />);
106+
fireEvent.click(screen.getByTestId('dark-mode-toggle'));
107+
expect(document.documentElement.getAttribute('data-theme')).toBe('light');
108+
});
109+
110+
it('updates isDarkMode when backgroundColor prop changes', () => {
111+
mockBackgroundColor = '#ffffff';
112+
const { rerender } = render(<ToggleDarkMode />);
113+
114+
const btn = screen.getByTestId('dark-mode-toggle');
115+
expect(btn.getAttribute('data-checked')).toBe('false');
116+
117+
// Simulate store change
118+
mockBackgroundColor = '#121212';
119+
rerender(<ToggleDarkMode />);
120+
121+
expect(btn.getAttribute('data-checked')).toBe('true');
122+
});
123+
124+
it('passes size={60} to the toggle', () => {
125+
render(<ToggleDarkMode />);
126+
const btn = screen.getByTestId('dark-mode-toggle');
127+
expect(btn.getAttribute('data-size')).toBe('60');
128+
});
129+
130+
it('applies className dark-mode-toggle', () => {
131+
render(<ToggleDarkMode />);
132+
const btn = screen.getByTestId('dark-mode-toggle');
133+
expect(btn.className).toBe('dark-mode-toggle');
134+
});
135+
136+
it('handles multiple sequential toggles correctly', () => {
137+
mockBackgroundColor = '#ffffff';
138+
render(<ToggleDarkMode />);
139+
const btn = screen.getByTestId('dark-mode-toggle');
140+
141+
// First click: light → dark
142+
fireEvent.click(btn);
143+
expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
144+
expect(mockToggleDarkMode).toHaveBeenCalledTimes(1);
145+
146+
// Second click: dark → light
147+
fireEvent.click(btn);
148+
expect(document.documentElement.getAttribute('data-theme')).toBe('light');
149+
expect(mockToggleDarkMode).toHaveBeenCalledTimes(2);
150+
});
151+
});

0 commit comments

Comments
 (0)