Skip to content

Commit 276304a

Browse files
committed
Add tests for profile setting selector component
1 parent d9203ad commit 276304a

5 files changed

Lines changed: 188 additions & 5 deletions

File tree

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { setInitialGlobalState } from '@/test/__mocks__/store';
2+
3+
import { MemoryRouter } from 'react-router-dom';
4+
5+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
6+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
7+
8+
import { useProfileStore } from '@/store';
9+
10+
import { ProfileSettingsSelector } from './ProfileSettingsSelector';
11+
12+
const mockGetRecordProfileId = jest.fn();
13+
14+
jest.mock('@/common/helpers/record.helper', () => ({
15+
getRecordProfileId: () => mockGetRecordProfileId(),
16+
}));
17+
18+
describe('ProfileSettingsSelector', () => {
19+
const mockProfileId = 'profile-id';
20+
const mockSetSelectedProfileSettingsId = jest.fn();
21+
22+
const renderComponent = () => {
23+
setInitialGlobalState([
24+
{
25+
store: useProfileStore,
26+
state: {
27+
selectedProfileSettingsId: '32',
28+
setSelectedProfileSettingsId: mockSetSelectedProfileSettingsId,
29+
},
30+
},
31+
]);
32+
33+
const queryClient = new QueryClient({
34+
defaultOptions: { queries: { retry: false } },
35+
});
36+
queryClient.setQueryData(
37+
['profileSettingsMeta', mockProfileId],
38+
[
39+
{
40+
id: 15,
41+
name: 'fifteen',
42+
},
43+
{
44+
id: 32,
45+
name: 'thirty-two',
46+
},
47+
],
48+
);
49+
50+
return render(
51+
<QueryClientProvider client={queryClient}>
52+
<MemoryRouter>
53+
<ProfileSettingsSelector />
54+
</MemoryRouter>
55+
</QueryClientProvider>,
56+
);
57+
};
58+
59+
it('renders the component', () => {
60+
renderComponent();
61+
62+
expect(screen.getByTestId('profile-settings-selector-button')).toBeInTheDocument();
63+
});
64+
65+
it('clicking button shows menu', () => {
66+
renderComponent();
67+
68+
fireEvent.click(screen.getByTestId('profile-settings-selector-button'));
69+
70+
expect(screen.getByTestId('profile-settings-selector-menu')).toBeInTheDocument();
71+
});
72+
73+
it('profile setting currently in use is disabled', async () => {
74+
mockGetRecordProfileId.mockReturnValue(mockProfileId);
75+
76+
renderComponent();
77+
78+
fireEvent.click(screen.getByTestId('profile-settings-selector-button'));
79+
80+
await waitFor(() => {
81+
expect(screen.getByText('thirty-two')).toBeDisabled();
82+
});
83+
});
84+
85+
it('clicking a setting selects it', async () => {
86+
mockGetRecordProfileId.mockReturnValue(mockProfileId);
87+
88+
renderComponent();
89+
90+
fireEvent.click(screen.getByTestId('profile-settings-selector-button'));
91+
fireEvent.click(screen.getByText('fifteen'));
92+
93+
await waitFor(() => {
94+
expect(screen.queryByTestId('profile-settings-selector-menu')).not.toBeInTheDocument();
95+
expect(mockSetSelectedProfileSettingsId).toHaveBeenCalledWith('15');
96+
});
97+
});
98+
});

src/features/edit/components/EditSection/ProfileSettingsSelector.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ export const ProfileSettingsSelector = () => {
4646

4747
return (
4848
<div className="profile-settings-selector" ref={ref}>
49-
<Button ariaHaspopup="menu" ariaExpanded={isMenuEnabled} onClick={toggleIsMenuEnabled}>
49+
<Button
50+
data-testid="profile-settings-selector-button"
51+
ariaHaspopup="menu"
52+
ariaExpanded={isMenuEnabled}
53+
onClick={toggleIsMenuEnabled}
54+
>
5055
<Settings />
5156
</Button>
5257
{isMenuEnabled && (

src/features/edit/hooks/useEditPage.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jest.mock('react-router-dom', () => ({
2626

2727
const mockProcessResource = jest.fn();
2828
const mockFetchQuery = jest.fn();
29+
const mockGenerateRecord = jest.fn();
2930
const mockResourceQueryOptions = jest.fn((id: string) => ({ queryKey: ['resource', id] }));
3031

3132
jest.mock('@tanstack/react-query', () => ({
@@ -36,6 +37,7 @@ jest.mock('@tanstack/react-query', () => ({
3637

3738
jest.mock('@/features/resources', () => ({
3839
generateResourceQueryOptions: (id: string) => mockResourceQueryOptions(id),
40+
useRecordGeneration: () => ({ generateRecord: mockGenerateRecord }),
3941
useResourceProcessing: () => ({ processResource: mockProcessResource }),
4042
}));
4143

@@ -409,4 +411,54 @@ describe('useEditPage', () => {
409411
expect(mockSetRecord).toHaveBeenCalledWith(mockRecord);
410412
});
411413
});
414+
415+
describe('applyUpdatedSettingsToResource', () => {
416+
const mockProfileSettingsId = 'settings-id';
417+
it('calls generateRecord, processResource and applies result to stores on success', async () => {
418+
mockProcessResource.mockResolvedValue(mockProcessedResource);
419+
mockGenerateRecord.mockReturnValue(null);
420+
421+
const { result } = renderHook(() => useEditPage());
422+
423+
await act(async () => {
424+
await result.current.applyUpdatedSettingsToResource(mockProfileSettingsId);
425+
});
426+
427+
expect(mockSetIsLoading).toHaveBeenCalledWith(true);
428+
expect(mockGenerateRecord).toHaveBeenCalledWith({});
429+
expect(mockProcessResource).toHaveBeenCalledWith({ profileSettingsId: mockProfileSettingsId });
430+
expect(mockSetSchema).toHaveBeenCalledWith(mockProcessedResource.schema);
431+
expect(mockSetUserValues).toHaveBeenCalledWith(mockProcessedResource.userValues);
432+
expect(mockSetIsLoading).toHaveBeenCalledWith(false);
433+
});
434+
435+
it('does not apply to stores when processResource returns null', async () => {
436+
mockProcessResource.mockResolvedValue(null);
437+
438+
const { result } = renderHook(() => useEditPage());
439+
440+
await act(async () => {
441+
await result.current.applyUpdatedSettingsToResource(mockProfileSettingsId);
442+
});
443+
444+
expect(mockSetSchema).not.toHaveBeenCalled();
445+
});
446+
447+
it('reports error status message when processResource throws', async () => {
448+
mockProcessResource.mockRejectedValue(new Error('load error'));
449+
450+
const { result } = renderHook(() => useEditPage());
451+
452+
await act(async () => {
453+
await result.current.applyUpdatedSettingsToResource(mockProfileSettingsId);
454+
});
455+
456+
expect(UserNotificationFactory.createMessage).toHaveBeenCalledWith(
457+
StatusType.error,
458+
'ld.errorApplyingProfileSettings',
459+
);
460+
expect(mockAddStatusMessagesItem).toHaveBeenCalled();
461+
expect(mockSetIsLoading).toHaveBeenCalledWith(false);
462+
});
463+
});
412464
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
export const initNewResource = jest.fn();
22
export const loadResource = jest.fn();
3+
export const applyUpdatedSettingsToResource = jest.fn();
34

45
jest.mock('@/features/edit/hooks/useEditPage', () => ({
56
useEditPage: () => ({
67
initNewResource,
78
loadResource,
9+
applyUpdatedSettingsToResource,
810
}),
911
}));

src/views/Edit/Edit.test.tsx

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import { getMockedImportedConstant } from '@/test/__mocks__/common/constants/constants.mock';
22
import '@/test/__mocks__/common/helpers/pageScrolling.helper.mock';
3-
import { initNewResource, loadResource } from '@/test/__mocks__/features/edit/hooks/useEditPage.mock';
3+
import {
4+
applyUpdatedSettingsToResource,
5+
initNewResource,
6+
loadResource,
7+
} from '@/test/__mocks__/features/edit/hooks/useEditPage.mock';
48
import { clearRecordState } from '@/test/__mocks__/features/resources/hooks/useRecordNavigation.mock';
5-
import { setInitialGlobalState } from '@/test/__mocks__/store';
9+
import { setInitialGlobalState, setUpdatedGlobalState } from '@/test/__mocks__/store';
610

711
import * as Router from 'react-router-dom';
812

9-
import { act, render, screen } from '@testing-library/react';
13+
import { act, render, screen, waitFor } from '@testing-library/react';
1014

1115
import * as BibframeConstants from '@/common/constants/bibframe.constants';
1216
import { Edit } from '@/views';
@@ -52,7 +56,10 @@ describe('Edit', () => {
5256
setInitialGlobalState([
5357
{
5458
store: useProfileStore,
55-
state: { selectedProfile: recordState },
59+
state: {
60+
selectedProfile: recordState,
61+
selectedProfileSettingsId: null,
62+
},
5663
},
5764
]);
5865

@@ -101,4 +108,23 @@ describe('Edit', () => {
101108

102109
expect(initNewResource).not.toHaveBeenCalled();
103110
});
111+
112+
test('changing profile settings ID applies settings', async () => {
113+
jest.spyOn(Router, 'useParams').mockReturnValue({ resourceId: 'testResourceId' });
114+
115+
await renderComponent(null);
116+
117+
setUpdatedGlobalState([
118+
{
119+
store: useProfileStore,
120+
updatedState: {
121+
selectedProfileSettingsId: 'changed',
122+
},
123+
},
124+
]);
125+
126+
await waitFor(() => {
127+
expect(applyUpdatedSettingsToResource).toHaveBeenCalled();
128+
});
129+
});
104130
});

0 commit comments

Comments
 (0)