Skip to content

Commit 25432ee

Browse files
test: add unit tests
1 parent 387613b commit 25432ee

File tree

12 files changed

+415
-7
lines changed

12 files changed

+415
-7
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ It visualizes the Call Stack, Web APIs, Tasks, Microtasks, and Render phase.
1616
![event-loop-image-1](https://github.com/user-attachments/assets/72b9efe9-1480-49a0-88d5-5c31461a4276)
1717
![event-loop-image-2](https://github.com/user-attachments/assets/b6dccbd4-58a0-44ce-a6be-73bbd549b84e)
1818

19-
2019
### Demo:
2120

2221
Feel free to try it here: https://event-loop-explorer.vercel.app/
@@ -52,7 +51,6 @@ npm run dev
5251

5352
### Future Plans:
5453

55-
- [ ] add unit tests;
5654
- [ ] handle todos in the codebase;
5755
- [ ] check js parsing edge cases, including `new Promise((res) => {res(console.log(4))})`;
5856
- [ ] replace window.confirm with error boundary
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
2+
import { ThemeToggle } from './themeToggle';
3+
import { useTheme } from 'next-themes';
4+
5+
jest.mock('next-themes', () => ({
6+
useTheme: jest.fn(),
7+
}));
8+
9+
afterEach(cleanup);
10+
11+
describe('ThemeToggle', () => {
12+
it('should render Sun and Moon icons', () => {
13+
(useTheme as jest.Mock).mockReturnValue({
14+
theme: 'dark',
15+
setTheme: jest.fn(),
16+
});
17+
render(<ThemeToggle />);
18+
19+
const moonIcon = screen.getByTestId('moon-icon');
20+
const sunIcon = screen.getByTestId('sun-icon');
21+
expect(moonIcon).toBeInTheDocument();
22+
expect(sunIcon).toBeInTheDocument();
23+
});
24+
25+
it('should toggle light theme on button click', () => {
26+
const setThemeMock = jest.fn();
27+
(useTheme as jest.Mock).mockReturnValue({
28+
theme: 'light',
29+
setTheme: setThemeMock,
30+
});
31+
render(<ThemeToggle />);
32+
const toggleButton = screen.getByRole('button', { name: 'Toggle theme' });
33+
fireEvent.click(toggleButton);
34+
expect(setThemeMock).toHaveBeenCalledWith('dark');
35+
});
36+
37+
it('should toggle dark theme on button click', () => {
38+
const setThemeMock = jest.fn();
39+
(useTheme as jest.Mock).mockReturnValue({
40+
theme: 'dark',
41+
setTheme: setThemeMock,
42+
});
43+
render(<ThemeToggle />);
44+
const toggleButton = screen.getByRole('button', { name: 'Toggle theme' });
45+
fireEvent.click(toggleButton);
46+
expect(setThemeMock).toHaveBeenCalledWith('light');
47+
});
48+
});

app/(main)/header/themeToggle.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ export function ThemeToggle() {
1414
data-testid="theme-toggle"
1515
>
1616
<Sun
17+
data-testid="sun-icon"
1718
className="absolute scale-100 dark:scale-0 rotate-0 dark:rotate-90 transition-all size-6"
1819
size={24}
1920
/>
2021
<Moon
22+
data-testid="moon-icon"
2123
className="absolute scale-0 dark:scale-100 rotate-90 dark:rotate-0 transition-all size-6"
2224
size={24}
2325
/>

app/(main)/page.test.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import Page from './page';
4+
5+
describe('Page', () => {
6+
it('renders without crashing', () => {
7+
render(<Page />);
8+
expect(screen.getByText('Event loop explorer')).toBeInTheDocument();
9+
});
10+
11+
it('renders all sections', () => {
12+
render(<Page />);
13+
expect(screen.getByText('Code Editor')).toBeInTheDocument();
14+
expect(screen.getByText('Web API')).toBeInTheDocument();
15+
expect(
16+
screen.getByText('RequestAnimationFrame callbacks')
17+
).toBeInTheDocument();
18+
expect(screen.getByText('Callstack')).toBeInTheDocument();
19+
expect(screen.getByText('Console')).toBeInTheDocument();
20+
expect(screen.getByText('Tasks Queue')).toBeInTheDocument();
21+
expect(screen.getByText('Microtasks Queue')).toBeInTheDocument();
22+
expect(screen.getByText('Event loop')).toBeInTheDocument();
23+
});
24+
});

app/layout.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import Layout from './layout';
4+
5+
describe('Layout', () => {
6+
it('renders without crashing', () => {
7+
render(
8+
<Layout>
9+
<div>Test Content</div>
10+
</Layout>
11+
);
12+
expect(screen.getByText('Test Content')).toBeInTheDocument();
13+
});
14+
});

components/progressCard.test.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import { ProgressCard } from './progressCard';
4+
5+
jest.mock('@/store/store', () => ({
6+
useTimeStore: {
7+
getState: jest.fn().mockReturnValue({ time: 1000 }),
8+
},
9+
}));
10+
11+
describe('ProgressCard Component', () => {
12+
it('should render the component with title', () => {
13+
render(<ProgressCard text="Test Title" start={0} end={1000} />);
14+
expect(screen.getByText('Test Title')).toBeInTheDocument();
15+
});
16+
});

jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const customJestConfig = {
77
testEnvironment: 'jsdom',
88
collectCoverageFrom: [
99
'{app,components,store,utils}/**/*.{ts,tsx}',
10-
'!components/chadcdn',
10+
'!components/chadcdn/*.tsx',
1111
],
1212
testMatch: ['**/*.test.(ts|tsx)'],
1313
transform: {

jest.setup.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
11
import '@testing-library/jest-dom';
2+
3+
Object.defineProperty(window, 'matchMedia', {
4+
writable: true,
5+
value: jest.fn().mockImplementation((query) => ({
6+
matches: false,
7+
media: query,
8+
onchange: null,
9+
addListener: jest.fn(), // Deprecated
10+
removeListener: jest.fn(), // Deprecated
11+
addEventListener: jest.fn(),
12+
removeEventListener: jest.fn(),
13+
dispatchEvent: jest.fn(),
14+
})),
15+
});

0 commit comments

Comments
 (0)