Skip to content

Commit

Permalink
fix: Hide / error on Libraries v2 pages if !librariesV2Enabled (#1449)
Browse files Browse the repository at this point in the history
Show an error message if the user tries to view a v2 Library while Libraries V2 are disabled in the platform.
  • Loading branch information
pomegranited authored Nov 5, 2024
1 parent fc94667 commit d7bbd40
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 7 deletions.
17 changes: 16 additions & 1 deletion src/library-authoring/LibraryAuthoringPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
mockXBlockFields,
} from './data/api.mocks';
import { mockContentSearchConfig } from '../search-manager/data/api.mock';
import { studioHomeMock } from '../studio-home/__mocks__';
import { getStudioHomeApiUrl } from '../studio-home/data/api';
import { mockBroadcastChannel } from '../generic/data/api.mock';
import { LibraryLayout } from '.';
import { getLibraryCollectionsApiUrl } from './data/api';
Expand Down Expand Up @@ -79,7 +81,8 @@ const libraryTitle = mockContentLibrary.libraryData.title;

describe('<LibraryAuthoringPage />', () => {
beforeEach(() => {
initializeMocks();
const { axiosMock } = initializeMocks();
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);

// The Meilisearch client-side API uses fetch, not Axios.
fetchMock.mockReset();
Expand Down Expand Up @@ -787,4 +790,16 @@ describe('<LibraryAuthoringPage />', () => {
});
});
});

it('Shows an error if libraries V2 is disabled', async () => {
const { axiosMock } = initializeMocks();
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, {
...studioHomeMock,
libraries_v2_enabled: false,
});

render(<LibraryLayout />, { path, params: { libraryId: mockContentLibrary.libraryId } });
await waitFor(() => { expect(axiosMock.history.get.length).toBe(1); });
expect(screen.getByRole('alert')).toHaveTextContent('This page cannot be shown: Libraries v2 are disabled.');
});
});
16 changes: 16 additions & 0 deletions src/library-authoring/LibraryAuthoringPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import classNames from 'classnames';
import { StudioFooter } from '@edx/frontend-component-footer';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Alert,
Badge,
Breadcrumb,
Button,
Expand All @@ -25,6 +26,7 @@ import Loading from '../generic/Loading';
import SubHeader from '../generic/sub-header/SubHeader';
import Header from '../header';
import NotFoundAlert from '../generic/NotFoundAlert';
import { useStudioHome } from '../studio-home/hooks';
import {
ClearFiltersButton,
FilterByBlockType,
Expand Down Expand Up @@ -143,6 +145,12 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
const location = useLocation();
const navigate = useNavigate();

const {
isLoadingPage: isLoadingStudioHome,
isFailedLoadingPage: isFailedLoadingStudioHome,
librariesV2Enabled,
} = useStudioHome();

const {
libraryId,
libraryData,
Expand Down Expand Up @@ -178,6 +186,14 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
return <Loading />;
}

if (!isLoadingStudioHome && (!librariesV2Enabled || isFailedLoadingStudioHome)) {
return (
<Alert variant="danger">
{intl.formatMessage(messages.librariesV2DisabledError)}
</Alert>
);
}

// istanbul ignore if: this should never happen
if (activeKey === undefined) {
return <NotFoundAlert />;
Expand Down
10 changes: 7 additions & 3 deletions src/library-authoring/add-content/AddContentWorkflow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
} from '../data/api.mocks';
import { mockBroadcastChannel, mockClipboardEmpty } from '../../generic/data/api.mock';
import { mockContentSearchConfig, mockSearchResult } from '../../search-manager/data/api.mock';
import { studioHomeMock } from '../../studio-home/__mocks__';
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
import LibraryLayout from '../LibraryLayout';

mockContentSearchConfig.applyMock();
Expand Down Expand Up @@ -46,8 +48,12 @@ const renderOpts = {
};

describe('AddContentWorkflow test', () => {
beforeEach(() => {
const { axiosMock } = initializeMocks();
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
});

it('can create an HTML component', async () => {
initializeMocks();
render(<LibraryLayout />, renderOpts);

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

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

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

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

// Click "New [Component]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
screen,
initializeMocks,
} from '../../testUtils';
import { studioHomeMock } from '../../studio-home/__mocks__';
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
import mockResult from '../__mocks__/library-search.json';
import { LibraryProvider } from '../common/context';
import { ComponentPickerModal } from '../component-picker';
Expand All @@ -16,7 +18,6 @@ import {
} from '../data/api.mocks';
import { PickLibraryContentModal } from './PickLibraryContentModal';

initializeMocks();
mockContentSearchConfig.applyMock();
mockContentLibrary.applyMock();
mockGetCollectionMetadata.applyMock();
Expand Down Expand Up @@ -45,6 +46,7 @@ describe('<PickLibraryContentModal />', () => {
beforeEach(() => {
const mocks = initializeMocks();
mockShowToast = mocks.mockShowToast;
mocks.axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
});

it('can pick components from the modal', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ jest.mock('react-router-dom', () => ({
},
}),
}));
jest.mock('../../studio-home/hooks', () => ({
useStudioHome: () => ({
isLoadingPage: false,
isFailedLoadingPage: false,
librariesV2Enabled: true,
}),
}));
mockContentLibrary.applyMock();
mockContentSearchConfig.applyMock();
mockGetCollectionMetadata.applyMock();
Expand Down
5 changes: 5 additions & 0 deletions src/library-authoring/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ const messages = defineMessages({
defaultMessage: 'Change Library',
description: 'Breadcrumbs link to return to library selection',
},
librariesV2DisabledError: {
id: 'authoring.alert.error.libraries.v2.disabled',
defaultMessage: 'This page cannot be shown: Libraries v2 are disabled.',
description: 'Error message shown to users when trying to load a libraries V2 page while libraries v2 are disabled.',
},
});

export default messages;
2 changes: 1 addition & 1 deletion src/studio-home/StudioHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const StudioHome = () => {
setShowNewCourseContainer,
librariesV1Enabled,
librariesV2Enabled,
} = useStudioHome(isPaginationCoursesEnabled);
} = useStudioHome();

const v1LibraryTab = librariesV1Enabled && location?.pathname.split('/').pop() === 'libraries-v1';
const showV2LibraryURL = librariesV2Enabled && !v1LibraryTab;
Expand Down
4 changes: 3 additions & 1 deletion src/studio-home/hooks.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { getConfig } from '@edx/frontend-platform';

import { RequestStatus } from '../data/constants';
import { COURSE_CREATOR_STATES } from '../constants';
Expand All @@ -14,9 +15,10 @@ import {
} from './data/selectors';
import { updateSavingStatuses } from './data/slice';

const useStudioHome = (isPaginated = false) => {
const useStudioHome = () => {
const location = useLocation();
const dispatch = useDispatch();
const isPaginated = getConfig().ENABLE_HOME_PAGE_COURSE_API_V2;
const studioHomeData = useSelector(getStudioHomeData);
const studioHomeCoursesParams = useSelector(getStudioHomeCoursesParams);
const { isFiltered } = studioHomeCoursesParams;
Expand Down

0 comments on commit d7bbd40

Please sign in to comment.