diff --git a/src/library-authoring/component-picker/ComponentPicker.test.tsx b/src/library-authoring/component-picker/ComponentPicker.test.tsx index cd4c7f71a..8d6858d2c 100644 --- a/src/library-authoring/component-picker/ComponentPicker.test.tsx +++ b/src/library-authoring/component-picker/ComponentPicker.test.tsx @@ -1,20 +1,35 @@ +import type MockAdapter from 'axios-mock-adapter'; + +import { mockContentSearchConfig, mockSearchResult } from '../../search-manager/data/api.mock'; import { initializeMocks, fireEvent, render, screen, + waitFor, + within, } from '../../testUtils'; +import mockResult from '../__mocks__/library-search.json'; +import mockCollectionResult from '../__mocks__/collection-search.json'; import { - mockGetContentLibraryV2List, mockContentLibrary, + mockGetCollectionMetadata, + mockGetContentLibraryV2List, mockLibraryBlockMetadata, } from '../data/api.mocks'; +import { getXBlockBaseApiUrl } from '../data/api'; + import { ComponentPicker } from './ComponentPicker'; -mockGetContentLibraryV2List.applyMock(); mockContentLibrary.applyMock(); +mockContentSearchConfig.applyMock(); +mockGetCollectionMetadata.applyMock(); +mockGetContentLibraryV2List.applyMock(); mockLibraryBlockMetadata.applyMock(); +let axiosMock: MockAdapter; +let mockShowToast: (message: string) => void; + jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useSearchParams: () => { @@ -29,10 +44,137 @@ jest.mock('react-router-dom', () => ({ describe('', () => { beforeEach(() => { - initializeMocks(); + const mocks = initializeMocks(); + axiosMock = mocks.axiosMock; + mockShowToast = mocks.mockShowToast; + axiosMock.onPost(getXBlockBaseApiUrl()).reply(200, {}); + + mockSearchResult(mockResult); + }); + + it('should pick component using the component card button', async () => { + render(); + + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + fireEvent.click(screen.getByDisplayValue(/lib:sampletaxonomyorg1:tl1/i)); + + fireEvent.click(screen.getByText('Next')); + + // Wait for the content library to load + expect(await screen.findByText('Content library')).toBeInTheDocument(); + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + + // Click the add component from the component card + fireEvent.click(screen.queryAllByRole('button', { name: 'Add' })[0]); + + await waitFor(() => { + expect(axiosMock.history.post.length).toBe(1); + expect(axiosMock.history.post[0].url).toBe(getXBlockBaseApiUrl()); + expect(axiosMock.history.post[0].data).toBe(JSON.stringify({ + parent_locator: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical1', + library_content_key: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', + })); + }); + }); + + it('should show toast if error on api call', async () => { + axiosMock.onPost(getXBlockBaseApiUrl()).reply(500, {}); + render(); + + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + fireEvent.click(screen.getByDisplayValue(/lib:sampletaxonomyorg1:tl1/i)); + + fireEvent.click(screen.getByText('Next')); + + // Wait for the content library to load + expect(await screen.findByText('Content library')).toBeInTheDocument(); + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + + // Click the add component from the component card + fireEvent.click(screen.queryAllByRole('button', { name: 'Add' })[0]); + + await waitFor(() => { + expect(axiosMock.history.post.length).toBe(1); + expect(axiosMock.history.post[0].url).toBe(getXBlockBaseApiUrl()); + expect(axiosMock.history.post[0].data).toBe(JSON.stringify({ + parent_locator: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical1', + library_content_key: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', + })); + expect(mockShowToast).toHaveBeenCalledWith('Failed to add component to course'); + }); + }); + + it('should pick component using the component sidebar', async () => { + render(); + + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + fireEvent.click(screen.getByDisplayValue(/lib:sampletaxonomyorg1:tl1/i)); + + fireEvent.click(screen.getByText('Next')); + + // Wait for the content library to load + expect(await screen.findByText('Content library')).toBeInTheDocument(); + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + + // Click on the component card to open the sidebar + fireEvent.click(screen.queryAllByText('Introduction to Testing')[0]); + + const sidebar = await screen.findByTestId('library-sidebar'); + + // Click the add component from the component sidebar + fireEvent.click(within(sidebar).getByRole('button', { name: 'Add to Course' })); + + await waitFor(() => { + expect(axiosMock.history.post.length).toBe(1); + expect(axiosMock.history.post[0].url).toBe(getXBlockBaseApiUrl()); + expect(axiosMock.history.post[0].data).toBe(JSON.stringify({ + parent_locator: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical1', + library_content_key: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', + })); + }); + }); + + it('should pick component inside a collection using the card', async () => { + render(); + + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + fireEvent.click(screen.getByDisplayValue(/lib:sampletaxonomyorg1:tl1/i)); + + fireEvent.click(screen.getByText('Next')); + + // Wait for the content library to load + expect(await screen.findByText('Content library')).toBeInTheDocument(); + expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + + // Click on the collection card to open the sidebar + fireEvent.click(screen.queryAllByText('Collection 1')[0]); + + const sidebar = await screen.findByTestId('library-sidebar'); + + // Mock the collection search result + mockSearchResult(mockCollectionResult); + + // Click the add component from the component card + fireEvent.click(within(sidebar).getByRole('button', { name: 'Open' })); + + // Wait for the collection to load + await screen.findByText(/← Change Library/i); + await screen.findByText('Introduction to Testing'); + + // Click the add component from the component card + fireEvent.click(screen.queryAllByRole('button', { name: 'Add' })[0]); + + await waitFor(() => { + expect(axiosMock.history.post.length).toBe(1); + expect(axiosMock.history.post[0].url).toBe(getXBlockBaseApiUrl()); + expect(axiosMock.history.post[0].data).toBe(JSON.stringify({ + parent_locator: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical1', + library_content_key: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', + })); + }); }); - it('should render the library list', async () => { + it('should pick component inside a collection using the sidebar', async () => { render(); expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); @@ -43,5 +185,37 @@ describe('', () => { // Wait for the content library to load expect(await screen.findByText('Content library')).toBeInTheDocument(); expect(await screen.findByText('Test Library 1')).toBeInTheDocument(); + + // Click on the collection card to open the sidebar + fireEvent.click(screen.queryAllByText('Collection 1')[0]); + + const sidebar = await screen.findByTestId('library-sidebar'); + + // Mock the collection search result + mockSearchResult(mockCollectionResult); + + // Click the add component from the component card + fireEvent.click(within(sidebar).getByRole('button', { name: 'Open' })); + + // Wait for the collection to load + await screen.findByText(/← Change Library/i); + await screen.findByText('Introduction to Testing'); + + // Click on the collection card to open the sidebar + fireEvent.click(screen.getByText('Introduction to Testing')); + + const collectionSidebar = await screen.findByTestId('library-sidebar'); + + // Click the add component from the collection sidebar + fireEvent.click(within(collectionSidebar).getByRole('button', { name: 'Add to Course' })); + + await waitFor(() => { + expect(axiosMock.history.post.length).toBe(1); + expect(axiosMock.history.post[0].url).toBe(getXBlockBaseApiUrl()); + expect(axiosMock.history.post[0].data).toBe(JSON.stringify({ + parent_locator: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@vertical1', + library_content_key: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd', + })); + }); }); });