Skip to content

Commit c608bdc

Browse files
committed
tests that fail
1 parent 2d7fab4 commit c608bdc

File tree

2 files changed

+181
-1
lines changed

2 files changed

+181
-1
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import React from 'react';
2+
import { render, screen, act } from '@testing-library/react';
3+
import { MemoryRouter } from 'react-router-dom';
4+
import { MantineProvider } from '@mantine/core';
5+
import { notifications } from '@mantine/notifications';
6+
import userEvent from '@testing-library/user-event';
7+
import { vi } from 'vitest';
8+
import { ManageProfileComponent } from './ManageProfileComponent';
9+
10+
describe('ManageProfileComponent tests', () => {
11+
const renderComponent = async (
12+
getProfile: () => Promise<any>,
13+
setProfile: (data: any) => Promise<any>,
14+
firstTime: boolean = false
15+
) => {
16+
await act(async () => {
17+
render(
18+
<MemoryRouter>
19+
<MantineProvider withGlobalClasses withCssVariables forceColorScheme="light">
20+
<ManageProfileComponent
21+
getProfile={getProfile}
22+
setProfile={setProfile}
23+
firstTime={firstTime}
24+
/>
25+
</MantineProvider>
26+
</MemoryRouter>
27+
);
28+
});
29+
};
30+
31+
beforeEach(() => {
32+
vi.clearAllMocks();
33+
});
34+
35+
it('renders loading overlay when fetching profile', async () => {
36+
const getProfile = vi.fn().mockResolvedValue(new Promise(() => {})); // Never resolves
37+
const setProfile = vi.fn();
38+
39+
await renderComponent(getProfile, setProfile);
40+
41+
expect(screen.getByText(/Loading.../i)).toBeInTheDocument();
42+
});
43+
44+
it('renders profile form after successfully fetching profile', async () => {
45+
const getProfile = vi.fn().mockResolvedValue({
46+
displayName: 'John Doe',
47+
givenName: 'John',
48+
surname: 'Doe',
49+
mail: 'john.doe@example.com',
50+
discordUsername: 'johndoe#1234',
51+
});
52+
const setProfile = vi.fn();
53+
54+
await renderComponent(getProfile, setProfile);
55+
56+
expect(screen.getByLabelText('Display Name')).toHaveValue('John Doe');
57+
expect(screen.getByLabelText('First Name')).toHaveValue('John');
58+
expect(screen.getByLabelText('Last Name')).toHaveValue('Doe');
59+
expect(screen.getByLabelText('Email')).toHaveValue('john.doe@example.com');
60+
expect(screen.getByLabelText('Discord Username')).toHaveValue('johndoe#1234');
61+
});
62+
63+
it('handles profile fetch failure gracefully', async () => {
64+
const notificationsMock = vi.spyOn(notifications, 'show');
65+
const getProfile = vi.fn().mockRejectedValue(new Error('Failed to fetch profile'));
66+
const setProfile = vi.fn();
67+
68+
await renderComponent(getProfile, setProfile);
69+
70+
expect(screen.getByText(/Failed to load user profile/i)).toBeInTheDocument();
71+
expect(notificationsMock).toHaveBeenCalledWith(
72+
expect.objectContaining({
73+
message: 'Failed to load user profile',
74+
color: 'red',
75+
})
76+
);
77+
78+
notificationsMock.mockRestore();
79+
});
80+
81+
it('allows editing profile fields and saving changes', async () => {
82+
const notificationsMock = vi.spyOn(notifications, 'show');
83+
const getProfile = vi.fn().mockResolvedValue({
84+
displayName: 'John Doe',
85+
givenName: 'John',
86+
surname: 'Doe',
87+
mail: 'john.doe@example.com',
88+
discordUsername: '',
89+
});
90+
const setProfile = vi.fn().mockResolvedValue({});
91+
92+
await renderComponent(getProfile, setProfile);
93+
94+
const user = userEvent.setup();
95+
96+
// Edit fields
97+
await user.clear(screen.getByLabelText('Display Name'));
98+
await user.type(screen.getByLabelText('Display Name'), 'Jane Doe');
99+
await user.type(screen.getByLabelText('Discord Username'), 'janedoe#5678');
100+
101+
// Save changes
102+
const saveButton = screen.getByRole('button', { name: 'Save' });
103+
await user.click(saveButton);
104+
105+
expect(setProfile).toHaveBeenCalledWith({
106+
displayName: 'Jane Doe',
107+
givenName: 'John',
108+
surname: 'Doe',
109+
mail: 'john.doe@example.com',
110+
discordUsername: 'janedoe#5678',
111+
});
112+
113+
expect(notificationsMock).toHaveBeenCalledWith(
114+
expect.objectContaining({
115+
title: 'Profile updated successfully',
116+
message: 'Changes may take some time to reflect.',
117+
color: 'green',
118+
})
119+
);
120+
121+
notificationsMock.mockRestore();
122+
});
123+
124+
it('shows first-time user alert when `firstTime` is true', async () => {
125+
const getProfile = vi.fn().mockResolvedValue({
126+
displayName: '',
127+
givenName: '',
128+
surname: '',
129+
mail: 'new.user@example.com',
130+
discordUsername: '',
131+
});
132+
const setProfile = vi.fn();
133+
134+
await renderComponent(getProfile, setProfile, true);
135+
136+
expect(
137+
screen.getByText(
138+
'Your profile is incomplete. Please provide us with the information below and click Save.'
139+
)
140+
).toBeInTheDocument();
141+
});
142+
143+
it('handles profile update failure gracefully', async () => {
144+
const notificationsMock = vi.spyOn(notifications, 'show');
145+
const getProfile = vi.fn().mockResolvedValue({
146+
displayName: 'John Doe',
147+
givenName: 'John',
148+
surname: 'Doe',
149+
mail: 'john.doe@example.com',
150+
discordUsername: '',
151+
});
152+
const setProfile = vi.fn().mockRejectedValue(new Error('Failed to update profile'));
153+
154+
await renderComponent(getProfile, setProfile);
155+
156+
const user = userEvent.setup();
157+
158+
// Attempt to save without any changes
159+
const saveButton = screen.getByRole('button', { name: 'Save' });
160+
await user.click(saveButton);
161+
162+
expect(notificationsMock).toHaveBeenCalledWith(
163+
expect.objectContaining({
164+
message: 'Failed to update profile',
165+
color: 'red',
166+
})
167+
);
168+
169+
notificationsMock.mockRestore();
170+
});
171+
172+
it('disables the save button when no profile data is loaded', async () => {
173+
const getProfile = vi.fn().mockResolvedValue(null);
174+
const setProfile = vi.fn();
175+
176+
await renderComponent(getProfile, setProfile);
177+
178+
expect(screen.getByRole('button', { name: 'Save' })).toBeDisabled();
179+
});
180+
});

src/ui/pages/profile/ManageProfileComponent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export const ManageProfileComponent: React.FC<ManageProfileComponentProps> = ({
126126
/>
127127

128128
<Group mt="md">
129-
<Button type="submit" loading={loading}>
129+
<Button type="submit" loading={loading} disabled={loading || !userProfile}>
130130
Save
131131
</Button>
132132
</Group>

0 commit comments

Comments
 (0)