Skip to content

Commit c20fca4

Browse files
committed
feat: remove ENABLE_COURSE_OUTLINE_NEW_DESIGN
1 parent b2a4b9c commit c20fca4

29 files changed

Lines changed: 255 additions & 1150 deletions

src/course-outline/CourseOutline.test.tsx

Lines changed: 35 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getConfig, setConfig } from '@edx/frontend-platform';
1+
import { getConfig } from '@edx/frontend-platform';
22
import { cloneDeep } from 'lodash';
33
import { closestCorners } from '@dnd-kit/core';
44
import { logError } from '@edx/frontend-platform/logging';
@@ -9,8 +9,7 @@ import { executeThunk } from '@src/utils';
99
import configureModalMessages from '@src/generic/configure-modal/messages';
1010
import pasteButtonMessages from '@src/generic/clipboard/paste-component/messages';
1111
import { getApiBaseUrl, getClipboardUrl } from '@src/generic/data/api';
12-
import { postXBlockBaseApiUrl } from '@src/course-unit/data/api';
13-
import { COMPONENT_TYPES } from '@src/generic/block-type-utils/constants';
12+
import { ContainerType } from '@src/generic/key-utils';
1413
import { getDownstreamApiUrl } from '@src/generic/unlink-modal/data/api';
1514
import { CourseAuthoringProvider } from '@src/CourseAuthoringContext';
1615
import {
@@ -31,7 +30,8 @@ import {
3130
getCourseBestPracticesApiUrl,
3231
getCourseLaunchApiUrl,
3332
getCourseOutlineIndexApiUrl,
34-
getCourseReindexApiUrl,
33+
// FIXME: reindex is not used
34+
// getCourseReindexApiUrl,
3535
getXBlockApiUrl,
3636
getCourseBlockApiUrl,
3737
getCourseItemApiUrl,
@@ -53,14 +53,13 @@ import {
5353
courseSectionMock,
5454
courseSubsectionMock,
5555
} from './__mocks__';
56-
import { COURSE_BLOCK_NAMES, VIDEO_SHARING_OPTIONS } from './constants';
56+
import { COURSE_BLOCK_NAMES } from './constants';
5757
import CourseOutline from './CourseOutline';
5858

5959
import messages from './messages';
6060
import headerMessages from './header-navigations/messages';
6161
import cardHeaderMessages from './card-header/messages';
6262
import enableHighlightsModalMessages from './enable-highlights-modal/messages';
63-
import statusBarMessages from './status-bar/messages';
6463
import subsectionMessages from './subsection-card/messages';
6564
import pageAlertMessages from './page-alerts/messages';
6665
import {
@@ -74,9 +73,8 @@ let axiosMock: import('axios-mock-adapter/types');
7473
let store;
7574
const mockPathname = '/foo-bar';
7675
const courseId = '123';
77-
const getContainerKey = jest.fn().mockReturnValue('lct:org:lib:unit:1');
78-
const getContainerType = jest.fn().mockReturnValue('unit');
7976
const clearSelection = jest.fn();
77+
const startCurrentFlow = jest.fn();
8078
let selectedContainerId: string | undefined;
8179
let courseOutlineIndexMock = cloneDeep(originalCourseOutlineIndexMock);
8280

@@ -85,6 +83,7 @@ jest.mock('@src/course-outline/outline-sidebar/OutlineSidebarContext', () => ({
8583
...jest.requireActual('@src/course-outline/outline-sidebar/OutlineSidebarContext'),
8684
useOutlineSidebarContext: () => ({
8785
...jest.requireActual('@src/course-outline/outline-sidebar/OutlineSidebarContext').useOutlineSidebarContext(),
86+
startCurrentFlow,
8887
clearSelection,
8988
selectedContainerState: (() => (selectedContainerId ? { currentId: selectedContainerId } : undefined))(),
9089
}),
@@ -109,24 +108,6 @@ jest.mock('./data/api', () => ({
109108
getTagsCount: () => jest.fn().mockResolvedValue({}),
110109
}));
111110

112-
// Mock LibraryAndComponentPicker to call onComponentSelected on click
113-
jest.mock('@src/library-authoring/component-picker', () => ({
114-
LibraryAndComponentPicker: (props) => {
115-
const onClick = () => {
116-
// eslint-disable-next-line react/prop-types
117-
props.onComponentSelected({
118-
usageKey: getContainerKey(),
119-
blockType: getContainerType(),
120-
});
121-
};
122-
return (
123-
<button type="submit" onClick={onClick}>
124-
Dummy button
125-
</button>
126-
);
127-
},
128-
}));
129-
130111
jest.mock('@edx/frontend-platform/logging', () => ({
131112
logError: jest.fn(),
132113
}));
@@ -250,6 +231,7 @@ describe('<CourseOutline />', () => {
250231
expect(queryByRole('button', { name: 'Dismiss' })).not.toBeInTheDocument();
251232
});
252233

234+
/* FIXME: reindex is missing/was moved
253235
it('check reindex and render success alert is correctly', async () => {
254236
const { findByText, findByTestId } = renderComponent();
255237
@@ -262,59 +244,6 @@ describe('<CourseOutline />', () => {
262244
expect(await findByText(messages.alertSuccessDescription.defaultMessage)).toBeInTheDocument();
263245
});
264246
265-
it('check video sharing option udpates correctly', async () => {
266-
const { findByLabelText } = renderComponent();
267-
268-
axiosMock
269-
.onPost(getCourseBlockApiUrl(courseId), {
270-
metadata: {
271-
video_sharing_options: VIDEO_SHARING_OPTIONS.allOff,
272-
},
273-
})
274-
.reply(200);
275-
const optionDropdown = await findByLabelText(statusBarMessages.videoSharingTitle.defaultMessage);
276-
await act(
277-
async () => fireEvent.change(optionDropdown, { target: { value: VIDEO_SHARING_OPTIONS.allOff } }),
278-
);
279-
280-
expect(axiosMock.history.post.length).toBe(3);
281-
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
282-
metadata: {
283-
video_sharing_options: VIDEO_SHARING_OPTIONS.allOff,
284-
},
285-
}));
286-
});
287-
288-
it('check video sharing option shows error on failure', async () => {
289-
renderComponent();
290-
291-
axiosMock
292-
.onPost(getCourseBlockApiUrl(courseId), {
293-
metadata: {
294-
video_sharing_options: VIDEO_SHARING_OPTIONS.allOff,
295-
},
296-
})
297-
.reply(500);
298-
const optionDropdown = await screen.findByLabelText(statusBarMessages.videoSharingTitle.defaultMessage);
299-
await act(
300-
async () => fireEvent.change(optionDropdown, { target: { value: VIDEO_SHARING_OPTIONS.allOff } }),
301-
);
302-
303-
expect(axiosMock.history.post.length).toBe(3);
304-
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
305-
metadata: {
306-
video_sharing_options: VIDEO_SHARING_OPTIONS.allOff,
307-
},
308-
}));
309-
310-
const alertElements = screen.queryAllByRole('alert');
311-
expect(alertElements.find(
312-
(el) => el.classList.contains('alert-content'),
313-
)).toHaveTextContent(
314-
'Unable to save changes. Please try again.',
315-
);
316-
});
317-
318247
it('render error alert after failed reindex correctly', async () => {
319248
const { findByText, findByTestId } = renderComponent();
320249
@@ -326,6 +255,7 @@ describe('<CourseOutline />', () => {
326255
327256
expect(await findByText('Request failed with status code 500')).toBeInTheDocument();
328257
});
258+
*/
329259

330260
it('check that new section list is saved when dragged', async () => {
331261
const { findAllByRole, findByTestId } = renderComponent();
@@ -480,118 +410,66 @@ describe('<CourseOutline />', () => {
480410
});
481411

482412
it('adds a unit from library correctly', async () => {
483-
getContainerKey.mockReturnValue('lct:org:lib:unit:1');
484-
getContainerKey.mockReturnValue('unit');
413+
const user = userEvent.setup();
485414
renderComponent();
486415
const [sectionElement] = await screen.findAllByTestId('section-card');
487416
const [subsectionElement] = await within(sectionElement).findAllByTestId('subsection-card');
488417
const units = await within(subsectionElement).findAllByTestId('unit-card');
489418
expect(units.length).toBe(1);
490419

491-
axiosMock
492-
.onPost(postXBlockBaseApiUrl())
493-
.reply(200, {
494-
locator: 'block-v1:UNIX+UX1+2025_T3+type@vertical+block@vertical1e842129',
495-
parent_locator: 'parent',
496-
});
497-
498420
const addUnitFromLibraryButton = within(subsectionElement).getByRole('button', {
499421
name: /use unit from library/i,
500422
});
501-
fireEvent.click(addUnitFromLibraryButton);
502-
503-
// click dummy button to execute onComponentSelected prop.
504-
const dummyBtn = await screen.findByRole('button', { name: 'Dummy button' });
505-
fireEvent.click(dummyBtn);
506-
507-
await waitFor(() => expect(axiosMock.history.post.length).toBe(3));
423+
await user.click(addUnitFromLibraryButton);
508424

425+
// Start the add existing unit flow
509426
const [section] = courseOutlineIndexMock.courseStructure.childInfo.children;
510427
const [subsection] = section.childInfo.children;
511-
await waitFor(() => {
512-
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
513-
type: COMPONENT_TYPES.libraryV2,
514-
category: 'vertical',
515-
parent_locator: subsection.id,
516-
library_content_key: getContainerKey(),
517-
}));
428+
expect(startCurrentFlow).toHaveBeenCalledWith({
429+
flowType: ContainerType.Unit,
430+
parentLocator: subsection.id,
431+
grandParentLocator: section.id,
518432
});
519433
});
520434

521435
it('adds a subsection from library correctly', async () => {
522-
getContainerKey.mockReturnValue('lct:org:lib:subsection:1');
523-
getContainerKey.mockReturnValue('subsection');
436+
const user = userEvent.setup();
524437
renderComponent();
525438
const [sectionElement] = await screen.findAllByTestId('section-card');
526439
const subsections = await within(sectionElement).findAllByTestId('subsection-card');
527440
expect(subsections.length).toBe(2);
528441

529-
axiosMock
530-
.onPost(postXBlockBaseApiUrl())
531-
.reply(200, {
532-
locator: 'block-v1:UNIX+UX1+2025_T3+type@sequential+block@sequential45d4d95a',
533-
parent_locator: 'block-v1:UNIX+UX1+2025_T3+type@chapter+block@chaptersda1',
534-
});
535-
536442
const addSubsectionFromLibraryButton = within(sectionElement).getByRole('button', {
537443
name: /use subsection from library/i,
538444
});
539-
fireEvent.click(addSubsectionFromLibraryButton);
540-
541-
// click dummy button to execute onComponentSelected prop.
542-
const dummyBtn = await screen.findByRole('button', { name: 'Dummy button' });
543-
fireEvent.click(dummyBtn);
544-
545-
await waitFor(() => expect(axiosMock.history.post.length).toBe(3));
445+
await user.click(addSubsectionFromLibraryButton);
546446

447+
// Start the add existing subsection flow
547448
const [section] = courseOutlineIndexMock.courseStructure.childInfo.children;
548-
await waitFor(() => {
549-
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
550-
type: COMPONENT_TYPES.libraryV2,
551-
category: 'sequential',
552-
parent_locator: section.id,
553-
library_content_key: getContainerKey(),
554-
}));
449+
expect(startCurrentFlow).toHaveBeenCalledWith({
450+
flowType: ContainerType.Subsection,
451+
parentLocator: section.id,
452+
grandParentLocator: undefined,
555453
});
556454
});
557455

558456
it('adds a section from library correctly', async () => {
559457
const user = userEvent.setup();
560-
getContainerKey.mockReturnValue('lct:org:lib:section:1');
561-
getContainerKey.mockReturnValue('section');
562458
renderComponent();
563459
const sections = await screen.findAllByTestId('section-card');
564460
expect(sections.length).toBe(4);
565461

566-
axiosMock
567-
.onPost(postXBlockBaseApiUrl())
568-
.reply(200, {
569-
locator: 'block-v1:UNIX+UX1+2025_T3+type@chapter+block@chaptersdafdd',
570-
courseKey: 'course-v1:UNIX+UX1+2025_T3',
571-
});
572-
axiosMock
573-
.onGet(getXBlockApiUrl('block-v1:UNIX+UX1+2025_T3+type@chapter+block@chaptersdafdd'))
574-
.reply(200, courseSectionMock);
575-
576462
const addSectionFromLibraryButton = await screen.findByRole('button', {
577463
name: /use section from library/i,
578464
});
579465
await user.click(addSectionFromLibraryButton);
580466

581-
// click dummy button to execute onComponentSelected prop.
582-
const dummyBtn = await screen.findByRole('button', { name: 'Dummy button' });
583-
fireEvent.click(dummyBtn);
584-
585-
await waitFor(() => expect(axiosMock.history.post.length).toBe(3));
586-
587-
const courseUsageKey = courseOutlineIndexMock.courseStructure.id;
588-
await waitFor(() => {
589-
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
590-
type: COMPONENT_TYPES.libraryV2,
591-
category: 'chapter',
592-
parent_locator: courseUsageKey,
593-
library_content_key: getContainerKey(),
594-
}));
467+
// Start the add existring section flow
468+
const courseBlockId = courseOutlineIndexMock.courseStructure.id;
469+
expect(startCurrentFlow).toHaveBeenCalledWith({
470+
flowType: ContainerType.Section,
471+
parentLocator: courseBlockId,
472+
grandParentLocator: undefined,
595473
});
596474
});
597475

@@ -820,6 +698,7 @@ describe('<CourseOutline />', () => {
820698
});
821699

822700
it('check whether section, subsection and unit is deleted when corresponding delete button is clicked', async () => {
701+
const user = userEvent.setup();
823702
renderComponent();
824703
// get section, subsection and unit
825704
const [section] = courseOutlineIndexMock.courseStructure.childInfo.children;
@@ -831,22 +710,18 @@ describe('<CourseOutline />', () => {
831710
selectedContainerId = section.id;
832711

833712
const checkDeleteBtn = async (item, element, elementName) => {
834-
await waitFor(() => {
835-
expect(screen.queryByText(item.displayName)).toBeInTheDocument();
836-
});
713+
expect(within(element).getByText(item.displayName)).toBeInTheDocument();
837714

838715
axiosMock.onDelete(getCourseItemApiUrl(item.id)).reply(200);
839716

840717
const menu = await within(element).findByTestId(`${elementName}-card-header__menu-button`);
841-
fireEvent.click(menu);
718+
await user.click(menu);
842719
const deleteButton = await within(element).findByTestId(`${elementName}-card-header__menu-delete-button`);
843-
fireEvent.click(deleteButton);
720+
await user.click(deleteButton);
844721
const confirmButton = await screen.findByRole('button', { name: 'Delete' });
845-
fireEvent.click(confirmButton);
722+
await user.click(confirmButton);
846723

847-
await waitFor(() => {
848-
expect(screen.queryByText(item.displayName)).not.toBeInTheDocument();
849-
});
724+
expect(element).not.toBeInTheDocument();
850725
};
851726

852727
// delete unit, subsection and then section in order.
@@ -2614,10 +2489,6 @@ describe('<CourseOutline />', () => {
26142489
});
26152490

26162491
it('check that the new status bar and expand bar is shown when flag is set', async () => {
2617-
setConfig({
2618-
...getConfig(),
2619-
ENABLE_COURSE_OUTLINE_NEW_DESIGN: 'true',
2620-
});
26212492
renderComponent();
26222493
const btn = await screen.findByRole('button', { name: 'Collapse all' });
26232494
expect(btn).toBeInTheDocument();

0 commit comments

Comments
 (0)