Skip to content

Commit 8213c94

Browse files
test: add tests for NavbarDesktop (#368)
1 parent c1e92ac commit 8213c94

File tree

2 files changed

+459
-158
lines changed

2 files changed

+459
-158
lines changed
Lines changed: 82 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,94 @@
1+
import { render, screen } from '@testing-library/react';
2+
import userEvent from '@testing-library/user-event';
3+
import { NavbarDesktop } from '../NavbarDesktop';
4+
import { Props, routeList } from '../navbar-utils';
5+
6+
// Mock external dependencies
17
jest.mock('@/components/ui/slider', () => ({
2-
Slider: () => <div data-testid="sync-slider" />,
8+
Slider: () => <div data-testid="sync-slider">slider</div>,
39
}));
10+
411
jest.mock('@/components/ui/switch', () => ({
512
Switch: ({ onCheckedChange }: any) => (
613
<button onClick={() => onCheckedChange(true)}>toggle</button>
714
),
815
}));
9-
jest.mock('@/components/utils/ExportTasks', () => ({
10-
exportTasksAsJSON: jest.fn(),
11-
exportTasksAsTXT: jest.fn(),
12-
}));
13-
jest.mock('../navbar-utils', () => ({
14-
...jest.requireActual('../navbar-utils'),
15-
deleteAllTasks: jest.fn(),
16+
17+
jest.mock('@/components/ui/dropdown-menu', () => ({
18+
DropdownMenu: ({ children }: any) => <div>{children}</div>,
19+
DropdownMenuTrigger: ({ children }: any) => <div>{children}</div>,
20+
DropdownMenuContent: ({ children }: any) => <div>{children}</div>,
21+
DropdownMenuItem: ({ children, onClick, onSelect }: any) => (
22+
<div onClick={onClick} onMouseDown={(e) => onSelect?.(e)}>
23+
{children}
24+
</div>
25+
),
26+
DropdownMenuLabel: ({ children }: any) => <div>{children}</div>,
1627
}));
28+
1729
jest.mock('@/components/ui/dialog', () => ({
1830
Dialog: ({ children }: any) => <div>{children}</div>,
1931
DialogTrigger: ({ children }: any) => <div>{children}</div>,
2032
DialogContent: ({ children }: any) => (
21-
<div data-testid="export-dialog">{children}</div>
33+
<div data-testid="dialog">{children}</div>
2234
),
2335
DialogHeader: ({ children }: any) => <div>{children}</div>,
2436
DialogTitle: ({ children }: any) => <h2>{children}</h2>,
2537
DialogDescription: ({ children }: any) => <p>{children}</p>,
2638
}));
27-
import { render, screen } from '@testing-library/react';
28-
import userEvent from '@testing-library/user-event';
29-
import { NavbarDesktop } from '../NavbarDesktop';
30-
import { Props, routeList } from '../navbar-utils';
3139

32-
jest.mock('../navbar-utils', () => ({
33-
deleteAllTasks: jest.fn(),
34-
handleLogout: jest.fn(),
35-
routeList: [
36-
{ href: '#', label: 'Home' },
37-
{ href: '#tasks', label: 'Tasks' },
38-
{ href: '#setup-guide', label: 'Setup Guide' },
39-
{ href: '#faq', label: 'FAQ' },
40-
],
40+
jest.mock('@/components/ui/avatar', () => ({
41+
Avatar: ({ children }: any) => <div>{children}</div>,
42+
AvatarImage: () => <img alt="avatar" />,
43+
AvatarFallback: ({ children }: any) => <button>{children}</button>,
44+
}));
45+
46+
jest.mock('@/components/utils/ThemeModeToggle', () => ({
47+
ModeToggle: () => <div data-testid="mode-toggle" />,
4148
}));
49+
4250
jest.mock('@/components/HomeComponents/DevLogs/DevLogs', () => ({
43-
DevLogs: () => <div data-testid="dev-logs-dialog" />,
51+
DevLogs: () => <div data-testid="dev-logs" />,
52+
}));
53+
54+
jest.mock('@/components/utils/TaskAutoSync', () => ({
55+
useTaskAutoSync: jest.fn(),
56+
}));
57+
58+
jest.mock('@/components/utils/ExportTasks', () => ({
59+
exportTasksAsJSON: jest.fn(),
60+
exportTasksAsTXT: jest.fn(),
4461
}));
4562

4663
jest.mock('@/components/utils/URLs', () => ({
4764
url: {
4865
githubRepoURL: 'https://github.com/test/repo',
4966
},
5067
}));
68+
69+
jest.mock('../navbar-utils', () => ({
70+
routeList: [
71+
{ href: '#', label: 'Home' },
72+
{ href: '#tasks', label: 'Tasks' },
73+
{ href: '#faq', label: 'FAQ' },
74+
],
75+
deleteAllTasks: jest.fn(),
76+
handleLogout: jest.fn(),
77+
}));
78+
5179
const mockSetIsLoading = jest.fn();
5280

53-
const mockProps: Props = {
54-
imgurl: 'http://example.com/image.png',
81+
const baseProps: Props = {
82+
imgurl: 'http://example.com/avatar.png',
5583
email: 'test@example.com',
5684
encryptionSecret: 'secret',
5785
origin: 'http://localhost:3000',
58-
UUID: '1234-5678',
86+
UUID: 'uuid',
5987
tasks: [],
6088
};
6189

62-
const extendedProps = {
63-
...mockProps,
90+
const props = {
91+
...baseProps,
6492
isLoading: false,
6593
setIsLoading: mockSetIsLoading,
6694
};
@@ -69,30 +97,28 @@ describe('NavbarDesktop', () => {
6997
afterEach(() => {
7098
jest.clearAllMocks();
7199
});
72-
it('renders the navigation links correctly', () => {
73-
render(<NavbarDesktop {...extendedProps} />);
100+
101+
it('renders navigation links', () => {
102+
render(<NavbarDesktop {...props} />);
74103

75104
routeList.forEach((route) => {
76105
expect(screen.getByText(route.label)).toBeInTheDocument();
77106
});
78107
});
79-
it('opens user menu and displays email', async () => {
80-
render(<NavbarDesktop {...extendedProps} />);
81108

82-
const avatarFallback = screen.getByText('CN');
83-
await userEvent.click(avatarFallback);
109+
it('opens user menu and shows email', async () => {
110+
render(<NavbarDesktop {...props} />);
84111

85-
expect(screen.getAllByText('test@example.com')[0]).toBeInTheDocument();
112+
await userEvent.click(screen.getByText('CN'));
113+
expect(screen.getAllByText('test@example.com').length).toBeGreaterThan(0);
86114
});
87115

88-
it('opens github link when clicked', async () => {
116+
it('opens GitHub repo in new tab', async () => {
89117
const openSpy = jest.spyOn(window, 'open').mockImplementation(() => null);
90118

91-
const user = userEvent.setup();
92-
render(<NavbarDesktop {...extendedProps} />);
93-
94-
await user.click(screen.getByText('CN'));
95-
await user.click(screen.getByText('GitHub'));
119+
render(<NavbarDesktop {...props} />);
120+
await userEvent.click(screen.getByText('CN'));
121+
await userEvent.click(screen.getByText('GitHub'));
96122

97123
expect(openSpy).toHaveBeenCalledWith(
98124
'https://github.com/test/repo',
@@ -101,46 +127,40 @@ describe('NavbarDesktop', () => {
101127

102128
openSpy.mockRestore();
103129
});
104-
it('exports tasks as TXT and triggers export handler', async () => {
105-
const user = userEvent.setup();
106-
const { exportTasksAsTXT } = require('@/components/utils/ExportTasks');
107-
108-
render(<NavbarDesktop {...extendedProps} />);
109130

110-
await user.click(screen.getByText('CN'));
111-
await user.click(screen.getByText('Export tasks'));
112-
113-
expect(screen.getByText(/Would you like to download/i)).toBeInTheDocument();
131+
it('exports tasks as TXT', async () => {
132+
const { exportTasksAsTXT } = require('@/components/utils/ExportTasks');
114133

115-
await user.click(screen.getByText('Download .txt'));
134+
render(<NavbarDesktop {...props} />);
135+
await userEvent.click(screen.getByText('CN'));
136+
await userEvent.click(screen.getByText('Export tasks'));
137+
await userEvent.click(screen.getByText('Download .txt'));
116138

117139
expect(exportTasksAsTXT).toHaveBeenCalledWith([]);
118140
});
141+
119142
it('exports tasks as JSON', async () => {
120143
const { exportTasksAsJSON } = require('@/components/utils/ExportTasks');
121144

122-
render(<NavbarDesktop {...extendedProps} />);
123-
145+
render(<NavbarDesktop {...props} />);
124146
await userEvent.click(screen.getByText('CN'));
125147
await userEvent.click(screen.getByText('Export tasks'));
126148
await userEvent.click(screen.getByText('Download .json'));
127149

128150
expect(exportTasksAsJSON).toHaveBeenCalledWith([]);
129151
});
130-
it('shows slider when auto sync is enabled', async () => {
131-
const user = userEvent.setup();
132-
render(<NavbarDesktop {...extendedProps} />);
133152

134-
await user.click(screen.getByText('CN'));
135-
await user.click(screen.getByText('toggle'));
153+
it('enables auto sync and shows slider', async () => {
154+
render(<NavbarDesktop {...props} />);
155+
156+
await userEvent.click(screen.getByText('CN'));
157+
await userEvent.click(screen.getByText('toggle'));
136158

137159
expect(screen.getByTestId('sync-slider')).toBeInTheDocument();
138160
});
139-
});
140161

141-
describe('NavbarDesktop snapshot', () => {
142-
it('renders correctly', () => {
143-
const { asFragment } = render(<NavbarDesktop {...extendedProps} />);
162+
it('renders consistently (snapshot)', () => {
163+
const { asFragment } = render(<NavbarDesktop {...props} />);
144164
expect(asFragment()).toMatchSnapshot();
145165
});
146166
});

0 commit comments

Comments
 (0)