Skip to content

Commit 8275a55

Browse files
authored
653 minor bug cloning study puts it at back of extraction list (#711)
* fix: resolved issue with swapped study going out of place, added testing * chore: remove console log statement * chore: remove unused code
1 parent b49b10b commit 8275a55

File tree

17 files changed

+404
-44
lines changed

17 files changed

+404
-44
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const useHistory = jest.fn().mockReturnValue({
2+
push: jest.fn(),
3+
});
4+
5+
export { useHistory };

compose/neurosynth-frontend/src/components/EditStudyComponents/EditStudySwapVersionButton/EditStudySwapVersionButton.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const EditStudySwapVersionButton: React.FC = (props) => {
2727
const studyId = useStudyId();
2828
const { data: baseStudy } = useGetBaseStudyById(baseStudyId || '');
2929
const { mutateAsync: updateStudyset } = useUpdateStudyset();
30-
const updateStudysetWithNewStudyId = useProjectExtractionReplaceStudyListStatusId();
30+
const updateStudyListStatusWithNewStudyId = useProjectExtractionReplaceStudyListStatusId();
3131
const studysetId = useProjectExtractionStudysetId();
3232
const { data: studyset } = useGetStudysetById(studysetId, false);
3333
const history = useHistory();
@@ -87,8 +87,7 @@ const EditStudySwapVersionButton: React.FC = (props) => {
8787
studies: updatedStudyset,
8888
},
8989
});
90-
91-
updateStudysetWithNewStudyId(studyId, versionToSwapTo);
90+
updateStudyListStatusWithNewStudyId(studyId, versionToSwapTo);
9291
await setAnalysesInAnnotationAsIncluded(annotationId);
9392

9493
history.push(`/projects/${projectId}/extraction/studies/${versionToSwapTo}`);
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
import { render, screen } from '@testing-library/react';
2+
import userEvent from '@testing-library/user-event';
3+
import { useGetExtractionSummary, useGetStudysetById } from 'hooks';
4+
import { EExtractionStatus } from 'pages/ExtractionPage/ExtractionPage';
5+
import {
6+
useProjectExtractionAddOrUpdateStudyListStatus,
7+
useProjectExtractionStudyStatusList,
8+
} from 'pages/Projects/ProjectPage/ProjectStore';
9+
import { Router } from 'react-router-dom';
10+
import EditStudyToolbar from './EditStudyToolbar';
11+
import { IStudyExtractionStatus } from 'hooks/projects/useGetProjects';
12+
import { useStudyId } from 'pages/Studies/StudyStore';
13+
14+
jest.mock('hooks');
15+
jest.mock('pages/Projects/ProjectPage/ProjectStore.ts');
16+
jest.mock('pages/Studies/StudyStore.ts');
17+
18+
describe('EditStudyToolbar Component', () => {
19+
const historyMock = {
20+
push: jest.fn(),
21+
location: {},
22+
listen: jest.fn(),
23+
};
24+
25+
it('should render', () => {
26+
render(
27+
<Router history={historyMock as any}>
28+
<EditStudyToolbar />
29+
</Router>
30+
);
31+
});
32+
33+
it.each([
34+
[0, 0, 0, 0, 0],
35+
[0, 10, 0, 0, 10],
36+
[10, 0, 0, 0, 0],
37+
[7, 14, 50, 7, 14],
38+
])(
39+
'testing completed: %i and total: %i',
40+
async (completed, total, expectedPercentage, expectedCompleted, expectedTotal) => {
41+
const extractionSummary = useGetExtractionSummary('');
42+
extractionSummary.completed = completed;
43+
extractionSummary.total = total;
44+
render(
45+
<Router history={historyMock as any}>
46+
<EditStudyToolbar />
47+
</Router>
48+
);
49+
expect(screen.getByText(`${expectedPercentage}%`)).toBeInTheDocument();
50+
51+
userEvent.hover(screen.getByText(`${expectedPercentage}%`));
52+
const tooltip = await screen.findByRole('tooltip');
53+
expect(tooltip).toBeInTheDocument();
54+
expect(tooltip).toHaveTextContent(
55+
`${expectedCompleted} / ${expectedTotal} studies marked as complete`
56+
);
57+
}
58+
);
59+
60+
it('should show the done all icon', () => {
61+
useGetExtractionSummary('').completed = 21;
62+
useGetExtractionSummary('').total = 21;
63+
render(
64+
<Router history={historyMock as any}>
65+
<EditStudyToolbar />
66+
</Router>
67+
);
68+
expect(screen.getByTestId('DoneAllIcon')).toBeInTheDocument();
69+
});
70+
71+
it('should move on to the specification phase', () => {
72+
useGetExtractionSummary('').completed = 21;
73+
useGetExtractionSummary('').total = 21;
74+
render(
75+
<Router history={historyMock as any}>
76+
<EditStudyToolbar />
77+
</Router>
78+
);
79+
userEvent.click(screen.getByTestId('DoneAllIcon'));
80+
expect(historyMock.push).toHaveBeenCalledWith('/projects/project-id/meta-analyses');
81+
});
82+
83+
it('should set to completed', () => {
84+
render(
85+
<Router history={historyMock as any}>
86+
<EditStudyToolbar />
87+
</Router>
88+
);
89+
const checkIcon = screen.getByTestId('CheckIcon');
90+
userEvent.click(checkIcon);
91+
expect(useProjectExtractionAddOrUpdateStudyListStatus()).toHaveBeenCalledWith(
92+
'study-id',
93+
EExtractionStatus.COMPLETED
94+
);
95+
});
96+
97+
it('should set to saved for later', () => {
98+
render(
99+
<Router history={historyMock as any}>
100+
<EditStudyToolbar />
101+
</Router>
102+
);
103+
const bookmarkIcon = screen.getByTestId('BookmarkIcon');
104+
userEvent.click(bookmarkIcon);
105+
expect(useProjectExtractionAddOrUpdateStudyListStatus()).toHaveBeenCalledWith(
106+
'study-id',
107+
EExtractionStatus.SAVEDFORLATER
108+
);
109+
});
110+
111+
it('should move to previous study', () => {
112+
// ARRANGE
113+
Storage.prototype.getItem = jest.fn().mockReturnValue(EExtractionStatus.SAVEDFORLATER); // mock localStorage
114+
(useStudyId as jest.Mock).mockReturnValue('study-2');
115+
useGetStudysetById().data = {
116+
studies: [{ id: 'study-0' }, { id: 'study-0.5' }, { id: 'study-2' }, { id: 'study-3' }],
117+
};
118+
(useProjectExtractionStudyStatusList as jest.Mock).mockReturnValue([
119+
{
120+
id: 'study-0',
121+
status: EExtractionStatus.SAVEDFORLATER,
122+
},
123+
{
124+
id: 'study-0.5',
125+
status: EExtractionStatus.UNCATEGORIZED,
126+
},
127+
{
128+
id: 'study-1',
129+
status: EExtractionStatus.COMPLETED,
130+
},
131+
{
132+
id: 'study-2',
133+
status: EExtractionStatus.SAVEDFORLATER,
134+
},
135+
{
136+
id: 'study-3',
137+
status: EExtractionStatus.COMPLETED,
138+
},
139+
] as IStudyExtractionStatus[]);
140+
141+
render(
142+
<Router history={historyMock as any}>
143+
<EditStudyToolbar />
144+
</Router>
145+
);
146+
// ACT
147+
userEvent.click(screen.getByTestId('ArrowBackIcon'));
148+
// ASSERT
149+
expect(historyMock.push).toHaveBeenCalledWith(
150+
'/projects/project-id/extraction/studies/study-0'
151+
);
152+
});
153+
154+
it('should disable if no previous study', () => {
155+
// ARRANGE
156+
Storage.prototype.getItem = jest.fn().mockReturnValue(EExtractionStatus.SAVEDFORLATER); // mock localStorage
157+
(useStudyId as jest.Mock).mockReturnValue('study-2');
158+
useGetStudysetById().data = {
159+
studies: [{ id: 'study-1' }, { id: 'study-2' }, { id: 'study-3' }],
160+
};
161+
(useProjectExtractionStudyStatusList as jest.Mock).mockReturnValue([
162+
{
163+
id: 'study-1',
164+
status: EExtractionStatus.UNCATEGORIZED,
165+
},
166+
{
167+
id: 'study-2',
168+
status: EExtractionStatus.SAVEDFORLATER,
169+
},
170+
{
171+
id: 'study-3',
172+
status: EExtractionStatus.COMPLETED,
173+
},
174+
] as IStudyExtractionStatus[]);
175+
176+
render(
177+
<Router history={historyMock as any}>
178+
<EditStudyToolbar />
179+
</Router>
180+
);
181+
// ACT
182+
const arrowBackIcon = screen.getByTestId('ArrowBackIcon').parentElement;
183+
// ASSERT
184+
expect(arrowBackIcon).toBeDisabled();
185+
});
186+
187+
it('should move to next study', () => {
188+
// ARRANGE
189+
Storage.prototype.getItem = jest.fn().mockReturnValue(EExtractionStatus.COMPLETED); // mock localStorage
190+
(useStudyId as jest.Mock).mockReturnValue('study-2');
191+
useGetStudysetById().data = {
192+
studies: [
193+
{ id: 'study-1' },
194+
{ id: 'study-2' },
195+
{ id: 'study-3' },
196+
{ id: 'study-4' },
197+
{ id: 'study-5' },
198+
],
199+
};
200+
(useProjectExtractionStudyStatusList as jest.Mock).mockReturnValue([
201+
{
202+
id: 'study-1',
203+
status: EExtractionStatus.UNCATEGORIZED,
204+
},
205+
{
206+
id: 'study-2',
207+
status: EExtractionStatus.COMPLETED,
208+
},
209+
{
210+
id: 'study-3',
211+
status: EExtractionStatus.SAVEDFORLATER,
212+
},
213+
{
214+
id: 'study-4',
215+
status: EExtractionStatus.UNCATEGORIZED,
216+
},
217+
{
218+
id: 'study-5',
219+
status: EExtractionStatus.COMPLETED,
220+
},
221+
] as IStudyExtractionStatus[]);
222+
223+
render(
224+
<Router history={historyMock as any}>
225+
<EditStudyToolbar />
226+
</Router>
227+
);
228+
// ACT
229+
userEvent.click(screen.getByTestId('ArrowForwardIcon'));
230+
// ASSERT
231+
expect(historyMock.push).toHaveBeenCalledWith(
232+
'/projects/project-id/extraction/studies/study-5'
233+
);
234+
});
235+
236+
it('should disable if no next study', () => {
237+
// ARRANGE
238+
Storage.prototype.getItem = jest.fn().mockReturnValue(EExtractionStatus.SAVEDFORLATER); // mock localStorage
239+
(useStudyId as jest.Mock).mockReturnValue('study-2');
240+
useGetStudysetById().data = {
241+
studies: [{ id: 'study-1' }, { id: 'study-2' }, { id: 'study-3' }],
242+
};
243+
(useProjectExtractionStudyStatusList as jest.Mock).mockReturnValue([
244+
{
245+
id: 'study-1',
246+
status: EExtractionStatus.UNCATEGORIZED,
247+
},
248+
{
249+
id: 'study-2',
250+
status: EExtractionStatus.SAVEDFORLATER,
251+
},
252+
{
253+
id: 'study-3',
254+
status: EExtractionStatus.UNCATEGORIZED,
255+
},
256+
] as IStudyExtractionStatus[]);
257+
258+
render(
259+
<Router history={historyMock as any}>
260+
<EditStudyToolbar />
261+
</Router>
262+
);
263+
// ACT
264+
const arrowBackIcon = screen.getByTestId('ArrowForwardIcon').parentElement;
265+
// ASSERT
266+
expect(arrowBackIcon).toBeDisabled();
267+
});
268+
});

0 commit comments

Comments
 (0)