Skip to content

Commit 64ffadd

Browse files
authored
feat: Capa problem types submenu [FC-0059] (#1207)
1 parent d99a09e commit 64ffadd

File tree

9 files changed

+418
-35
lines changed

9 files changed

+418
-35
lines changed

src/library-authoring/LibraryAuthoringPage.test.tsx

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,4 +530,108 @@ describe('<LibraryAuthoringPage />', () => {
530530
});
531531
});
532532
});
533+
534+
it('filter by capa problem type', async () => {
535+
mockUseParams.mockReturnValue({ libraryId: libraryData.id });
536+
axiosMock.onGet(getContentLibraryApiUrl(libraryData.id)).reply(200, libraryData);
537+
538+
const problemTypes = {
539+
'Multiple Choice': 'choiceresponse',
540+
Checkboxes: 'multiplechoiceresponse',
541+
'Numerical Input': 'numericalresponse',
542+
Dropdown: 'optionresponse',
543+
'Text Input': 'stringresponse',
544+
};
545+
546+
render(<RootWrapper />);
547+
548+
// Ensure the search endpoint is called
549+
await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
550+
const filterButton = screen.getByRole('button', { name: /type/i });
551+
fireEvent.click(filterButton);
552+
553+
const openProblemItem = screen.getByTestId('open-problem-item-button');
554+
fireEvent.click(openProblemItem);
555+
556+
const validateSubmenu = async (submenuText : string) => {
557+
const submenu = screen.getByText(submenuText);
558+
expect(submenu).toBeInTheDocument();
559+
fireEvent.click(submenu);
560+
561+
await waitFor(() => {
562+
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
563+
body: expect.stringContaining(`content.problem_types = ${problemTypes[submenuText]}`),
564+
method: 'POST',
565+
headers: expect.anything(),
566+
});
567+
});
568+
569+
fireEvent.click(submenu);
570+
await waitFor(() => {
571+
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
572+
body: expect.not.stringContaining(`content.problem_types = ${problemTypes[submenuText]}`),
573+
method: 'POST',
574+
headers: expect.anything(),
575+
});
576+
});
577+
};
578+
579+
// Validate per submenu
580+
// eslint-disable-next-line no-restricted-syntax
581+
for (const key of Object.keys(problemTypes)) {
582+
// eslint-disable-next-line no-await-in-loop
583+
await validateSubmenu(key);
584+
}
585+
586+
// Validate click on Problem type
587+
const problemMenu = screen.getByText('Problem');
588+
expect(problemMenu).toBeInTheDocument();
589+
fireEvent.click(problemMenu);
590+
await waitFor(() => {
591+
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
592+
body: expect.stringContaining('block_type = problem'),
593+
method: 'POST',
594+
headers: expect.anything(),
595+
});
596+
});
597+
598+
fireEvent.click(problemMenu);
599+
await waitFor(() => {
600+
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
601+
body: expect.not.stringContaining('block_type = problem'),
602+
method: 'POST',
603+
headers: expect.anything(),
604+
});
605+
});
606+
607+
// Validate clear filters
608+
const submenu = screen.getByText('Checkboxes');
609+
expect(submenu).toBeInTheDocument();
610+
fireEvent.click(submenu);
611+
612+
const clearFitlersButton = screen.getByRole('button', { name: /clear filters/i });
613+
fireEvent.click(clearFitlersButton);
614+
await waitFor(() => {
615+
expect(fetchMock).toHaveBeenLastCalledWith(searchEndpoint, {
616+
body: expect.not.stringContaining(`content.problem_types = ${problemTypes.Checkboxes}`),
617+
method: 'POST',
618+
headers: expect.anything(),
619+
});
620+
});
621+
});
622+
623+
it('empty type filter', async () => {
624+
mockUseParams.mockReturnValue({ libraryId: libraryData.id });
625+
axiosMock.onGet(getContentLibraryApiUrl(libraryData.id)).reply(200, libraryData);
626+
fetchMock.post(searchEndpoint, returnEmptyResult, { overwriteRoutes: true });
627+
628+
render(<RootWrapper />);
629+
630+
await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); });
631+
632+
const filterButton = screen.getByRole('button', { name: /type/i });
633+
fireEvent.click(filterButton);
634+
635+
expect(screen.getByText(/no matching components/i)).toBeInTheDocument();
636+
});
533637
});

src/search-manager/FilterBy.scss

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,19 @@
99
.clear-filter-button:hover {
1010
color: $info-900 !important;
1111
}
12+
13+
.problem-menu-item {
14+
.pgn__menu-item-text {
15+
width: 100%;
16+
}
17+
18+
.pgn__form-checkbox > div:first-of-type {
19+
width: 100%;
20+
}
21+
22+
.problem-sub-menu-item {
23+
position: absolute;
24+
left: 3.8rem;
25+
top: -3rem;
26+
}
27+
}

0 commit comments

Comments
 (0)