Adds new routes and URL parameters to use when viewing and performing searches on library components. These changes allow these pages to be bookmarked or shared by copy/pasting the browser's current URL. No changes were made to the UI. Use cases covered: * As an author working with content libraries, I want to easily share any component in a library with other people on my team, by copying the URL from my browser and sending it to them. * As an author working with content libraries, I want to easily share any search results with other people on my team, by copying the URL from my browser and sending it to them. * As an author working with content libraries, I want to bookmark a search in my browser and return to it at any time, with the same filters and keywords applied. * As an author of a content library with public read access, I want to easily share any component in a library with any authors on the same Open edX instance, by copying the URL from my browser and sending it to them. * As an author of a content library, I want to easily share a library's "Manage Team" page with other people on my team by copying the URL from my browser and sending it to them. * As an author working with content libraries, I want to easily share any selected sidebar tab with other people on my team, by copying the URL from my browser and sending it to them.
108 lines
3.8 KiB
TypeScript
108 lines
3.8 KiB
TypeScript
import { mockContentSearchConfig, mockSearchResult } from '../../search-manager/data/api.mock';
|
|
import {
|
|
fireEvent,
|
|
render as baseRender,
|
|
waitFor,
|
|
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/LibraryContext';
|
|
import { ComponentPicker } from '../component-picker';
|
|
import * as api from '../data/api';
|
|
import {
|
|
mockContentLibrary,
|
|
mockGetCollectionMetadata,
|
|
} from '../data/api.mocks';
|
|
import { PickLibraryContentModal } from './PickLibraryContentModal';
|
|
|
|
mockContentSearchConfig.applyMock();
|
|
mockContentLibrary.applyMock();
|
|
mockGetCollectionMetadata.applyMock();
|
|
mockSearchResult(mockResult);
|
|
|
|
const { libraryId } = mockContentLibrary;
|
|
|
|
const onClose = jest.fn();
|
|
let mockShowToast: (message: string) => void;
|
|
|
|
const render = () => baseRender(<PickLibraryContentModal isOpen onClose={onClose} />, {
|
|
path: '/library/:libraryId/collection/:collectionId/*',
|
|
params: { libraryId, collectionId: 'collectionId' },
|
|
extraWrapper: ({ children }) => (
|
|
<LibraryProvider
|
|
libraryId={libraryId}
|
|
componentPicker={ComponentPicker}
|
|
>
|
|
{children}
|
|
</LibraryProvider>
|
|
),
|
|
});
|
|
|
|
describe('<PickLibraryContentModal />', () => {
|
|
beforeEach(async () => {
|
|
const mocks = initializeMocks();
|
|
mockShowToast = mocks.mockShowToast;
|
|
mocks.axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
|
|
});
|
|
|
|
it('can pick components from the modal', async () => {
|
|
const mockAddComponentsToCollection = jest.fn();
|
|
jest.spyOn(api, 'addComponentsToCollection').mockImplementation(mockAddComponentsToCollection);
|
|
|
|
render();
|
|
|
|
// Wait for the content library to load
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Test Library')).toBeInTheDocument();
|
|
expect(screen.queryAllByText('Introduction to Testing')[0]).toBeInTheDocument();
|
|
});
|
|
|
|
// Select the first component
|
|
fireEvent.click(screen.queryAllByRole('button', { name: 'Select' })[0]);
|
|
expect(await screen.findByText('1 Selected Component')).toBeInTheDocument();
|
|
|
|
fireEvent.click(screen.queryAllByRole('button', { name: 'Add to Collection' })[0]);
|
|
|
|
await waitFor(() => {
|
|
expect(mockAddComponentsToCollection).toHaveBeenCalledWith(
|
|
libraryId,
|
|
'collectionId',
|
|
['lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd'],
|
|
);
|
|
expect(onClose).toHaveBeenCalled();
|
|
expect(mockShowToast).toHaveBeenCalledWith('Content linked successfully.');
|
|
});
|
|
});
|
|
|
|
it('show error when api call fails', async () => {
|
|
const mockAddComponentsToCollection = jest.fn().mockRejectedValue(new Error('Failed to add components'));
|
|
jest.spyOn(api, 'addComponentsToCollection').mockImplementation(mockAddComponentsToCollection);
|
|
render();
|
|
|
|
// Wait for the content library to load
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Test Library')).toBeInTheDocument();
|
|
expect(screen.queryAllByText('Introduction to Testing')[0]).toBeInTheDocument();
|
|
});
|
|
|
|
// Select the first component
|
|
fireEvent.click(screen.queryAllByRole('button', { name: 'Select' })[0]);
|
|
expect(await screen.findByText('1 Selected Component')).toBeInTheDocument();
|
|
|
|
fireEvent.click(screen.queryAllByRole('button', { name: 'Add to Collection' })[0]);
|
|
|
|
await waitFor(() => {
|
|
expect(mockAddComponentsToCollection).toHaveBeenCalledWith(
|
|
libraryId,
|
|
'collectionId',
|
|
['lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd'],
|
|
);
|
|
expect(onClose).toHaveBeenCalled();
|
|
expect(mockShowToast).toHaveBeenCalledWith('There was an error linking the content to this collection.');
|
|
});
|
|
});
|
|
});
|