Skip to content

Commit 3112305

Browse files
committed
add tests
1 parent d4ff1b3 commit 3112305

File tree

7 files changed

+863
-5
lines changed

7 files changed

+863
-5
lines changed

src/common/components/Loader.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const Loader = (props: {
2727
...forwardProps
2828
} = props;
2929
return (
30-
<Box sx={{ width, height, position: 'relative' }}>
30+
<Box data-testid="loader" sx={{ width, height, position: 'relative' }}>
3131
<Stack
3232
direction="row"
3333
justifyContent="center"
@@ -43,15 +43,16 @@ export const Loader = (props: {
4343
if (props.render !== undefined) return <>{props.render}</>;
4444
switch (props.type) {
4545
case 'text':
46-
return <>Loading...</>;
46+
return <span data-testid="loader">Loading...</span>;
4747
case 'spinner':
4848
default:
49-
return <FontAwesomeIcon icon={faSpinner} spin />;
49+
return <FontAwesomeIcon data-testid="loader" icon={faSpinner} spin />;
5050
}
5151
}
5252
if (props.error) {
5353
return (
5454
<Chip
55+
data-testid="loader"
5556
icon={<FontAwesomeIcon icon={faExclamationCircle} />}
5657
variant="outlined"
5758
color="error"
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { render, screen, fireEvent } from '@testing-library/react';
2+
import { useEffect } from 'react';
3+
import { MemoryRouter, Route, Routes, useLocation } from 'react-router-dom';
4+
import { Account } from './Account';
5+
6+
// Mock component for the Outlet
7+
let mockOutletLocation = '';
8+
const MockOutlet = () => {
9+
const location = useLocation();
10+
useEffect(() => {
11+
mockOutletLocation = location.pathname;
12+
}, [location.pathname]);
13+
return <div data-testid="mock-outlet">Outlet Content</div>;
14+
};
15+
16+
// Mock scrollTo function since we're testing useEffect scroll behavior
17+
const mockScrollTo = jest.fn();
18+
19+
describe('Account Component', () => {
20+
afterEach(() => {
21+
jest.clearAllMocks();
22+
});
23+
24+
it('renders all tabs', () => {
25+
render(
26+
<MemoryRouter initialEntries={['/account/info']}>
27+
<Routes>
28+
<Route path="/account/*" element={<Account />}>
29+
<Route path="*" element={<MockOutlet />} />
30+
</Route>
31+
</Routes>
32+
</MemoryRouter>
33+
);
34+
35+
expect(screen.getByText('Account')).toBeInTheDocument();
36+
expect(screen.getByText('Linked Providers')).toBeInTheDocument();
37+
expect(screen.getByText('Log In Sessions')).toBeInTheDocument();
38+
expect(screen.getByText('Use Agreements')).toBeInTheDocument();
39+
});
40+
41+
it('navigates to correct route when tab is clicked', () => {
42+
render(
43+
<MemoryRouter initialEntries={['/account/info']}>
44+
<Routes>
45+
<Route path="/account/*" element={<Account />}>
46+
<Route path="*" element={<MockOutlet />} />
47+
</Route>
48+
</Routes>
49+
</MemoryRouter>
50+
);
51+
52+
fireEvent.click(screen.getByText('Linked Providers'));
53+
expect(mockOutletLocation).toContain('/account/providers');
54+
55+
fireEvent.click(screen.getByText('Log In Sessions'));
56+
expect(mockOutletLocation).toContain('/account/sessions');
57+
});
58+
59+
it('scrolls to top when tab changes', () => {
60+
render(
61+
<MemoryRouter initialEntries={['/account/info']}>
62+
<Routes>
63+
<Route path="/account/*" element={<Account />}>
64+
<Route path="*" element={<MockOutlet />} />
65+
</Route>
66+
</Routes>
67+
</MemoryRouter>
68+
);
69+
70+
const my_element = document.querySelector('main');
71+
if (!my_element) return;
72+
jest.spyOn(my_element, 'scrollTo').mockImplementation(mockScrollTo);
73+
74+
fireEvent.click(screen.getByText('Linked Providers'));
75+
expect(mockScrollTo).toHaveBeenCalledWith(0, 0);
76+
});
77+
78+
it('sets correct active tab based on current route', () => {
79+
render(
80+
<MemoryRouter initialEntries={['/account/providers']}>
81+
<Routes>
82+
<Route path="/account/*" element={<Account />}>
83+
<Route path="*" element={<MockOutlet />} />
84+
</Route>
85+
</Routes>
86+
</MemoryRouter>
87+
);
88+
89+
const providersTab = screen.getByRole('tab', { name: 'Linked Providers' });
90+
expect(providersTab).toHaveAttribute('aria-selected', 'true');
91+
});
92+
93+
it('navigates to correct routes when tabs are clicked', () => {
94+
render(
95+
<MemoryRouter initialEntries={['/account']}>
96+
<Routes>
97+
<Route path="/account/*" element={<Account />}>
98+
<Route path="*" element={<MockOutlet />} />
99+
</Route>
100+
</Routes>
101+
</MemoryRouter>
102+
);
103+
104+
// Test Account tab navigation
105+
fireEvent.click(screen.getByRole('tab', { name: 'Account' }));
106+
expect(mockOutletLocation).toBe('/account/info');
107+
108+
// Test Linked Providers tab navigation
109+
fireEvent.click(screen.getByRole('tab', { name: 'Linked Providers' }));
110+
expect(mockOutletLocation).toBe('/account/providers');
111+
112+
// Test Log In Sessions tab navigation
113+
fireEvent.click(screen.getByRole('tab', { name: 'Log In Sessions' }));
114+
expect(mockOutletLocation).toBe('/account/sessions');
115+
116+
// Test Use Agreements tab navigation
117+
fireEvent.click(screen.getByRole('tab', { name: 'Use Agreements' }));
118+
expect(mockOutletLocation).toBe('/account/use-agreements');
119+
});
120+
121+
it('handles tab clicks with correct aria controls', () => {
122+
render(
123+
<MemoryRouter initialEntries={['/account']}>
124+
<Routes>
125+
<Route path="/account/*" element={<Account />}>
126+
<Route path="*" element={<MockOutlet />} />
127+
</Route>
128+
</Routes>
129+
</MemoryRouter>
130+
);
131+
132+
const accountTab = screen.getByRole('tab', { name: 'Account' });
133+
const providersTab = screen.getByRole('tab', { name: 'Linked Providers' });
134+
const sessionsTab = screen.getByRole('tab', { name: 'Log In Sessions' });
135+
const agreementsTab = screen.getByRole('tab', { name: 'Use Agreements' });
136+
137+
expect(accountTab).toHaveAttribute('aria-controls', 'account-tabpanel');
138+
expect(providersTab).toHaveAttribute('aria-controls', 'providers-tabpanel');
139+
expect(sessionsTab).toHaveAttribute('aria-controls', 'sessions-tabpanel');
140+
expect(agreementsTab).toHaveAttribute(
141+
'aria-controls',
142+
'use-agreements-tabpanel'
143+
);
144+
});
145+
});

0 commit comments

Comments
 (0)