Skip to content

Commit d7bbd40

Browse files
authored
fix: Hide / error on Libraries v2 pages if !librariesV2Enabled (openedx#1449)
Show an error message if the user tries to view a v2 Library while Libraries V2 are disabled in the platform.
1 parent fc94667 commit d7bbd40

File tree

8 files changed

+58
-7
lines changed

8 files changed

+58
-7
lines changed

src/library-authoring/LibraryAuthoringPage.test.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
mockXBlockFields,
1919
} from './data/api.mocks';
2020
import { mockContentSearchConfig } from '../search-manager/data/api.mock';
21+
import { studioHomeMock } from '../studio-home/__mocks__';
22+
import { getStudioHomeApiUrl } from '../studio-home/data/api';
2123
import { mockBroadcastChannel } from '../generic/data/api.mock';
2224
import { LibraryLayout } from '.';
2325
import { getLibraryCollectionsApiUrl } from './data/api';
@@ -79,7 +81,8 @@ const libraryTitle = mockContentLibrary.libraryData.title;
7981

8082
describe('<LibraryAuthoringPage />', () => {
8183
beforeEach(() => {
82-
initializeMocks();
84+
const { axiosMock } = initializeMocks();
85+
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
8386

8487
// The Meilisearch client-side API uses fetch, not Axios.
8588
fetchMock.mockReset();
@@ -787,4 +790,16 @@ describe('<LibraryAuthoringPage />', () => {
787790
});
788791
});
789792
});
793+
794+
it('Shows an error if libraries V2 is disabled', async () => {
795+
const { axiosMock } = initializeMocks();
796+
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, {
797+
...studioHomeMock,
798+
libraries_v2_enabled: false,
799+
});
800+
801+
render(<LibraryLayout />, { path, params: { libraryId: mockContentLibrary.libraryId } });
802+
await waitFor(() => { expect(axiosMock.history.get.length).toBe(1); });
803+
expect(screen.getByRole('alert')).toHaveTextContent('This page cannot be shown: Libraries v2 are disabled.');
804+
});
790805
});

src/library-authoring/LibraryAuthoringPage.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import classNames from 'classnames';
44
import { StudioFooter } from '@edx/frontend-component-footer';
55
import { useIntl } from '@edx/frontend-platform/i18n';
66
import {
7+
Alert,
78
Badge,
89
Breadcrumb,
910
Button,
@@ -25,6 +26,7 @@ import Loading from '../generic/Loading';
2526
import SubHeader from '../generic/sub-header/SubHeader';
2627
import Header from '../header';
2728
import NotFoundAlert from '../generic/NotFoundAlert';
29+
import { useStudioHome } from '../studio-home/hooks';
2830
import {
2931
ClearFiltersButton,
3032
FilterByBlockType,
@@ -143,6 +145,12 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
143145
const location = useLocation();
144146
const navigate = useNavigate();
145147

148+
const {
149+
isLoadingPage: isLoadingStudioHome,
150+
isFailedLoadingPage: isFailedLoadingStudioHome,
151+
librariesV2Enabled,
152+
} = useStudioHome();
153+
146154
const {
147155
libraryId,
148156
libraryData,
@@ -178,6 +186,14 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
178186
return <Loading />;
179187
}
180188

189+
if (!isLoadingStudioHome && (!librariesV2Enabled || isFailedLoadingStudioHome)) {
190+
return (
191+
<Alert variant="danger">
192+
{intl.formatMessage(messages.librariesV2DisabledError)}
193+
</Alert>
194+
);
195+
}
196+
181197
// istanbul ignore if: this should never happen
182198
if (activeKey === undefined) {
183199
return <NotFoundAlert />;

src/library-authoring/add-content/AddContentWorkflow.test.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
} from '../data/api.mocks';
2020
import { mockBroadcastChannel, mockClipboardEmpty } from '../../generic/data/api.mock';
2121
import { mockContentSearchConfig, mockSearchResult } from '../../search-manager/data/api.mock';
22+
import { studioHomeMock } from '../../studio-home/__mocks__';
23+
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
2224
import LibraryLayout from '../LibraryLayout';
2325

2426
mockContentSearchConfig.applyMock();
@@ -46,8 +48,12 @@ const renderOpts = {
4648
};
4749

4850
describe('AddContentWorkflow test', () => {
51+
beforeEach(() => {
52+
const { axiosMock } = initializeMocks();
53+
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
54+
});
55+
4956
it('can create an HTML component', async () => {
50-
initializeMocks();
5157
render(<LibraryLayout />, renderOpts);
5258

5359
// Click "New [Component]"
@@ -84,7 +90,6 @@ describe('AddContentWorkflow test', () => {
8490
});
8591

8692
it('can create a Problem component', async () => {
87-
initializeMocks();
8893
render(<LibraryLayout />, renderOpts);
8994

9095
// Click "New [Component]"
@@ -119,7 +124,6 @@ describe('AddContentWorkflow test', () => {
119124
});
120125

121126
it('can create a Video component', async () => {
122-
initializeMocks();
123127
render(<LibraryLayout />, renderOpts);
124128

125129
// Click "New [Component]"

src/library-authoring/add-content/PickLibraryContentModal.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
screen,
77
initializeMocks,
88
} from '../../testUtils';
9+
import { studioHomeMock } from '../../studio-home/__mocks__';
10+
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
911
import mockResult from '../__mocks__/library-search.json';
1012
import { LibraryProvider } from '../common/context';
1113
import { ComponentPickerModal } from '../component-picker';
@@ -16,7 +18,6 @@ import {
1618
} from '../data/api.mocks';
1719
import { PickLibraryContentModal } from './PickLibraryContentModal';
1820

19-
initializeMocks();
2021
mockContentSearchConfig.applyMock();
2122
mockContentLibrary.applyMock();
2223
mockGetCollectionMetadata.applyMock();
@@ -45,6 +46,7 @@ describe('<PickLibraryContentModal />', () => {
4546
beforeEach(() => {
4647
const mocks = initializeMocks();
4748
mockShowToast = mocks.mockShowToast;
49+
mocks.axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
4850
});
4951

5052
it('can pick components from the modal', async () => {

src/library-authoring/component-picker/ComponentPicker.test.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ jest.mock('react-router-dom', () => ({
2727
},
2828
}),
2929
}));
30+
jest.mock('../../studio-home/hooks', () => ({
31+
useStudioHome: () => ({
32+
isLoadingPage: false,
33+
isFailedLoadingPage: false,
34+
librariesV2Enabled: true,
35+
}),
36+
}));
3037
mockContentLibrary.applyMock();
3138
mockContentSearchConfig.applyMock();
3239
mockGetCollectionMetadata.applyMock();

src/library-authoring/messages.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ const messages = defineMessages({
111111
defaultMessage: 'Change Library',
112112
description: 'Breadcrumbs link to return to library selection',
113113
},
114+
librariesV2DisabledError: {
115+
id: 'authoring.alert.error.libraries.v2.disabled',
116+
defaultMessage: 'This page cannot be shown: Libraries v2 are disabled.',
117+
description: 'Error message shown to users when trying to load a libraries V2 page while libraries v2 are disabled.',
118+
},
114119
});
115120

116121
export default messages;

src/studio-home/StudioHome.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const StudioHome = () => {
4747
setShowNewCourseContainer,
4848
librariesV1Enabled,
4949
librariesV2Enabled,
50-
} = useStudioHome(isPaginationCoursesEnabled);
50+
} = useStudioHome();
5151

5252
const v1LibraryTab = librariesV1Enabled && location?.pathname.split('/').pop() === 'libraries-v1';
5353
const showV2LibraryURL = librariesV2Enabled && !v1LibraryTab;

src/studio-home/hooks.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useEffect, useState } from 'react';
22
import { useLocation } from 'react-router-dom';
33
import { useDispatch, useSelector } from 'react-redux';
4+
import { getConfig } from '@edx/frontend-platform';
45

56
import { RequestStatus } from '../data/constants';
67
import { COURSE_CREATOR_STATES } from '../constants';
@@ -14,9 +15,10 @@ import {
1415
} from './data/selectors';
1516
import { updateSavingStatuses } from './data/slice';
1617

17-
const useStudioHome = (isPaginated = false) => {
18+
const useStudioHome = () => {
1819
const location = useLocation();
1920
const dispatch = useDispatch();
21+
const isPaginated = getConfig().ENABLE_HOME_PAGE_COURSE_API_V2;
2022
const studioHomeData = useSelector(getStudioHomeData);
2123
const studioHomeCoursesParams = useSelector(getStudioHomeCoursesParams);
2224
const { isFiltered } = studioHomeCoursesParams;

0 commit comments

Comments
 (0)