Skip to content

Commit d66a42d

Browse files
committed
refactor(outline-sidebar): extract back navigation helper
1 parent 8dea05b commit d66a42d

10 files changed

Lines changed: 324 additions & 264 deletions

src/course-outline/outline-sidebar/AddSidebar.test.tsx

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -433,24 +433,6 @@ describe('AddSidebar', () => {
433433
);
434434
});
435435

436-
it('back from subsection opens section', async () => {
437-
const user = userEvent.setup();
438-
const section = outlineChildren[0];
439-
const subsection = section.childInfo.children[0];
440-
selectedContainerState = {
441-
currentId: subsection.id,
442-
subsectionId: subsection.id,
443-
sectionId: section.id,
444-
};
445-
renderComponent();
446-
447-
const back = await screen.findByRole('button', { name: 'Back' });
448-
await user.click(back);
449-
450-
expect(openContainerSidebar).toHaveBeenCalledWith(section.id, undefined, section.id, 0);
451-
expect(clearSelection).not.toHaveBeenCalled();
452-
});
453-
454436
it('back from subsection without section clears selection', async () => {
455437
const user = userEvent.setup();
456438
const section = outlineChildren[0];
@@ -467,20 +449,4 @@ describe('AddSidebar', () => {
467449
expect(clearSelection).toHaveBeenCalled();
468450
expect(openContainerSidebar).not.toHaveBeenCalled();
469451
});
470-
471-
it('back from section clears selection', async () => {
472-
const user = userEvent.setup();
473-
const section = outlineChildren[0];
474-
selectedContainerState = {
475-
currentId: section.id,
476-
sectionId: section.id,
477-
};
478-
renderComponent();
479-
480-
const back = await screen.findByRole('button', { name: 'Back' });
481-
await user.click(back);
482-
483-
expect(clearSelection).toHaveBeenCalled();
484-
expect(openContainerSidebar).not.toHaveBeenCalled();
485-
});
486452
});

src/course-outline/outline-sidebar/AddSidebar.tsx

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { COURSE_BLOCK_NAMES } from '@src/constants';
2929
import { BlockCardButton } from '@src/generic/sidebar/BlockCardButton';
3030
import AlertMessage from '@src/generic/alert-message';
3131
import { useCourseItemData } from '@src/course-outline/data/apiHooks';
32+
import { navigateBackFromSelection } from './back-navigation';
3233
import { useOutlineSidebarContext } from './OutlineSidebarContext';
3334
import messages from './messages';
3435

@@ -390,42 +391,12 @@ export const AddSidebar = () => {
390391

391392
const handleBack = () => {
392393
stopCurrentFlow();
393-
394-
if (!selectedContainerState) {
395-
return;
396-
}
397-
398-
const { currentId, subsectionId, sectionId } = selectedContainerState;
399-
const sectionIndex = sections.findIndex((section) => section.id === sectionId);
400-
const section = sectionIndex >= 0 ? sections[sectionIndex] : undefined;
401-
const subsectionIndex = section
402-
?.childInfo.children.findIndex((subsection) => subsection.id === subsectionId) ?? -1;
403-
404-
if (currentId === subsectionId) {
405-
if (sectionId) {
406-
openContainerSidebar(sectionId, undefined, sectionId, sectionIndex >= 0 ? sectionIndex : undefined);
407-
return;
408-
}
409-
clearSelection();
410-
return;
411-
}
412-
413-
if (currentId === sectionId) {
414-
clearSelection();
415-
return;
416-
}
417-
418-
if (subsectionId) {
419-
openContainerSidebar(
420-
subsectionId,
421-
subsectionId,
422-
sectionId,
423-
subsectionIndex >= 0 ? subsectionIndex : undefined,
424-
);
425-
return;
426-
}
427-
428-
clearSelection();
394+
navigateBackFromSelection({
395+
selectedContainerState,
396+
sections,
397+
openContainer: openContainerSidebar,
398+
clearSelection,
399+
});
429400
};
430401

431402
return (

src/course-outline/outline-sidebar/OutlineAlignSidebar.test.tsx

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -131,55 +131,7 @@ describe('OutlineAlignSidebar', () => {
131131
});
132132
});
133133

134-
it('back button from subsection selects section', async () => {
135-
jest
136-
.spyOn(OutlineSidebarContext, 'useOutlineSidebarContext')
137-
.mockReturnValue({
138-
selectedContainerState: {
139-
currentId: 'subsection-1',
140-
subsectionId: 'subsection-1',
141-
sectionId: 'section-1',
142-
},
143-
clearSelection,
144-
openContainerSidebar,
145-
} as any);
146-
147-
render(<OutlineAlignSidebar />);
148-
149-
const backButton = await screen.findByRole('button', { name: /back/i });
150-
backButton.click();
151-
152-
expect(openContainerSidebar).toHaveBeenCalledWith('section-1', undefined, 'section-1', 0);
153-
expect(setCurrentSelection).toHaveBeenCalledWith({
154-
currentId: 'section-1',
155-
sectionId: 'section-1',
156-
index: 0,
157-
});
158-
});
159-
160-
it('back button from subsection without section clears selection', async () => {
161-
jest
162-
.spyOn(OutlineSidebarContext, 'useOutlineSidebarContext')
163-
.mockReturnValue({
164-
selectedContainerState: {
165-
currentId: 'subsection-1',
166-
subsectionId: 'subsection-1',
167-
},
168-
clearSelection,
169-
openContainerSidebar,
170-
} as any);
171-
172-
render(<OutlineAlignSidebar />);
173-
174-
const backButton = await screen.findByRole('button', { name: /back/i });
175-
backButton.click();
176-
177-
expect(clearSelection).toHaveBeenCalled();
178-
expect(setCurrentSelection).toHaveBeenCalledWith(undefined);
179-
expect(openContainerSidebar).not.toHaveBeenCalled();
180-
});
181-
182-
it('back button from section clears selection', async () => {
134+
it('back button clears align selection when parent selection does not exist', async () => {
183135
jest
184136
.spyOn(OutlineSidebarContext, 'useOutlineSidebarContext')
185137
.mockReturnValue({
@@ -198,32 +150,6 @@ describe('OutlineAlignSidebar', () => {
198150

199151
expect(clearSelection).toHaveBeenCalled();
200152
expect(setCurrentSelection).toHaveBeenCalledWith(undefined);
201-
});
202-
203-
it('back button handles missing section when selecting subsection parent', async () => {
204-
jest
205-
.spyOn(OutlineSidebarContext, 'useOutlineSidebarContext')
206-
.mockReturnValue({
207-
selectedContainerState: {
208-
currentId: 'unit-1',
209-
subsectionId: 'subsection-1',
210-
sectionId: 'missing-section',
211-
},
212-
clearSelection,
213-
openContainerSidebar,
214-
} as any);
215-
216-
render(<OutlineAlignSidebar />);
217-
218-
const backButton = await screen.findByRole('button', { name: /back/i });
219-
backButton.click();
220-
221-
expect(openContainerSidebar).toHaveBeenCalledWith('subsection-1', 'subsection-1', 'missing-section', undefined);
222-
expect(setCurrentSelection).toHaveBeenCalledWith({
223-
currentId: 'subsection-1',
224-
subsectionId: 'subsection-1',
225-
sectionId: 'missing-section',
226-
index: undefined,
227-
});
153+
expect(openContainerSidebar).not.toHaveBeenCalled();
228154
});
229155
});

src/course-outline/outline-sidebar/OutlineAlignSidebar.tsx

Lines changed: 8 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useContentData } from '@src/content-tags-drawer/data/apiHooks';
22
import { useCourseAuthoringContext } from '@src/CourseAuthoringContext';
33
import { useCourseOutlineContext } from '@src/course-outline/CourseOutlineContext';
44
import { AlignSidebar } from '@src/generic/sidebar/AlignSidebar';
5+
import { navigateBackFromSelection } from './back-navigation';
56
import { useOutlineSidebarContext } from './OutlineSidebarContext';
67

78
/**
@@ -17,60 +18,13 @@ export const OutlineAlignSidebar = () => {
1718
const { data: contentData } = useContentData(sidebarContentId);
1819

1920
const handleBack = () => {
20-
const { currentId, subsectionId, sectionId } = selectedContainerState || {};
21-
const sectionIndex = sections.findIndex((section) => section.id === sectionId);
22-
const section = sectionIndex >= 0 ? sections[sectionIndex] : undefined;
23-
const subsectionIndex = section
24-
?.childInfo.children.findIndex((subsection) => subsection.id === subsectionId) ?? -1;
25-
26-
// istanbul ignore next
27-
if (!currentId) {
28-
clearSelection();
29-
setCurrentSelection(undefined);
30-
return;
31-
}
32-
33-
if (currentId === subsectionId) {
34-
if (sectionId) {
35-
openContainerSidebar(sectionId, undefined, sectionId, sectionIndex >= 0 ? sectionIndex : undefined);
36-
setCurrentSelection({
37-
currentId: sectionId,
38-
sectionId,
39-
index: sectionIndex >= 0 ? sectionIndex : undefined,
40-
});
41-
return;
42-
}
43-
clearSelection();
44-
setCurrentSelection(undefined);
45-
return;
46-
}
47-
48-
if (currentId === sectionId) {
49-
clearSelection();
50-
setCurrentSelection(undefined);
51-
return;
52-
}
53-
54-
if (subsectionId) {
55-
openContainerSidebar(
56-
subsectionId,
57-
subsectionId,
58-
sectionId,
59-
subsectionIndex >= 0 ? subsectionIndex : undefined,
60-
);
61-
setCurrentSelection({
62-
currentId: subsectionId,
63-
subsectionId,
64-
sectionId,
65-
index: subsectionIndex >= 0 ? subsectionIndex : undefined,
66-
});
67-
return;
68-
}
69-
70-
// istanbul ignore next
71-
clearSelection();
72-
// istanbul ignore next
73-
setCurrentSelection(undefined);
21+
navigateBackFromSelection({
22+
selectedContainerState,
23+
sections,
24+
openContainer: openContainerSidebar,
25+
clearSelection,
26+
onSelectionChange: setCurrentSelection,
27+
});
7428
};
7529

7630
return (

0 commit comments

Comments
 (0)