import React from 'react'; import { render, screen, waitFor, act, fireEvent } from '@testing-library/react'; import MainContainer from './MainContainer'; import { ResourceBrowserPlugin, ResourceBrowserSourceWithPlugin, PluginLaunchModeType } from '../types'; import { mockSource, mockResource, mockSourceWithPlugin } from '../__mocks__/MockModels'; import SourceList from '../SourceList/SourceList'; // Import Functional Component jest.mock('../SourceList/SourceList'); // Mock the Functional Component const ActualSourceList = jest.requireActual('../SourceList/SourceList').default; // Grab the real copy of it as normally we don't want the mock const MockSourceList = SourceList as jest.MockedFunction; // Cast the mocked function so TS stops complaining MockSourceList.mockImplementation(ActualSourceList); // Return the actual function unless overridden import ResourceLauncher from '../ResourceLauncher/ResourceLauncher'; // Import Functional Component jest.mock('../ResourceLauncher/ResourceLauncher'); // Mock the Functional Component const ActualResourceLauncher = jest.requireActual('../ResourceLauncher/ResourceLauncher').default; // Grab the real copy of it as normally we don't want the mock const MockResourceLauncher = ResourceLauncher as jest.MockedFunction; // Cast the mocked function so TS stops complaining MockResourceLauncher.mockImplementation(ActualResourceLauncher); // Return the actual function unless overridden import SourceDropdown from '../SourceDropdown/SourceDropdown'; // Import Functional Component jest.mock('../SourceDropdown/SourceDropdown'); // Mock the Functional Component const ActualSourceDropdown = jest.requireActual('../SourceDropdown/SourceDropdown').default; // Grab the real copy of it as normally we don't want the mock const MockSourceDropdown = SourceDropdown as jest.MockedFunction; // Cast the mocked function so TS stops complaining MockSourceDropdown.mockImplementation(ActualSourceDropdown); // Return the actual function unless overridden import SourceDropdownContainer from '../SourceDropdownContainer/SourceDropdownContainer'; jest.mock('../SourceDropdownContainer/SourceDropdownContainer', () => { return jest.fn().mockReturnValue(
); }); const mockSourceBrowserComponent = jest.fn(); const defaultProps = { title: '', titleAriaProps: {}, allowedTypes: undefined, sources: [], selectedSource: null, onSourceSelect: jest.fn(), onChange: jest.fn(), onClose: jest.fn(), preselectedResource: null, plugin: null, pluginMode: null, searchEnabled: false, }; describe('MainContainer', () => { it('clicking close button should call the onClose callback', async () => { const onClose = jest.fn(); render(); await act(() => fireEvent.click(screen.getByRole('button', { name: 'Close Select Asset dialog' }))); expect(onClose).toHaveBeenCalled(); }); it('should render Environment Selector title', () => { render(); expect(screen.getByText('Select myasset')).toBeInTheDocument(); expect(screen.queryByText('Environment Selector')).not.toBeInTheDocument(); }); it('should render title in Sentence case', () => { const titles = ['Select Asset', 'Select MyAsset', 'another title']; titles.forEach((title) => { render(); const expectedTitle = title.charAt(0).toUpperCase() + title.slice(1).toLowerCase(); expect(screen.getByText(expectedTitle)).toBeInTheDocument(); }); }); describe('no source selected', () => { it('should not render source selector dropdown', () => { render(); expect(MockSourceDropdown).not.toHaveBeenCalled(); }); it('should not render plugin UI', () => { render(); expect(mockSourceBrowserComponent).not.toHaveBeenCalled(); }); it('should render resource launcher list when searchEnabled using provided props', () => { const sources: ResourceBrowserSourceWithPlugin[] = []; const onSourceSelect = jest.fn(); render(); expect(MockResourceLauncher).toHaveBeenCalledWith({ sources, onSourceSelect }, {}); }); it('should render source list using provided props', () => { const sources: ResourceBrowserSourceWithPlugin[] = []; const onSourceSelect = jest.fn(); render(); expect(MockSourceList).toHaveBeenCalledWith({ sources, onSourceSelect }, {}); }); }); describe('source selected', () => { const source = mockSource({ type: 'dam' }); it('it should create a default source switcher if header portal not requested and sources > 1', async () => { const source1 = mockSourceWithPlugin(); const source2 = mockSourceWithPlugin(); const plugin = { type: 'dam', createHeaderPortal: false, sourceBrowserComponent: jest.fn, renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: jest.fn(), renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; render( , ); expect(SourceDropdownContainer).toHaveBeenCalled(); }); it('it should not create a default source switcher if header portal not requested and sources < 2', async () => { const source1 = mockSourceWithPlugin(); const plugin = { type: 'dam', createHeaderPortal: false, sourceBrowserComponent: jest.fn, renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: jest.fn(), renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; render( , ); expect(SourceDropdownContainer).not.toHaveBeenCalled(); }); describe('Browser mode', () => { it('should create header portal for plugin', async () => { const mockFunctionalComponent = jest.fn().mockReturnValue(
Source UI has been rendered
); const mockSourceBrowserComponent = jest.fn().mockReturnValue(mockFunctionalComponent); const plugin = { type: 'dam', createHeaderPortal: true, sourceBrowserComponent: mockSourceBrowserComponent, renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: jest.fn(), renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; render(); expect(mockSourceBrowserComponent).toHaveBeenCalled(); await waitFor(() => { expect(mockFunctionalComponent).toHaveBeenCalledWith( expect.objectContaining({ headerPortal: expect.any(Element), }), {}, ); }); }); it('preselectedResource: should pass expected params to plugin UI generator functional component', async () => { const mockFunctionalComponent = jest.fn().mockReturnValue(
Source UI has been rendered
); const mockSourceBrowserComponent = jest.fn().mockReturnValue(mockFunctionalComponent); const plugin = { type: 'dam', createHeaderPortal: true, sourceBrowserComponent: mockSourceBrowserComponent, renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: jest.fn(), renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; const resource = mockResource(); const props = { allowedTypes: ['image'], preselectedResource: resource, }; render(); expect(mockSourceBrowserComponent).toHaveBeenCalled(); await waitFor(() => { expect(mockFunctionalComponent).toHaveBeenCalledWith( expect.objectContaining({ source: source, allowedTypes: props.allowedTypes, headerPortal: expect.any(Element), preselectedResource: resource, }), {}, ); }); }); it('browseTo: should pass expected params to plugin UI generator functional component', async () => { const mockFunctionalComponent = jest.fn().mockReturnValue(
Source UI has been rendered
); const mockSourceBrowserComponent = jest.fn().mockReturnValue(mockFunctionalComponent); const plugin = { type: 'dam', createHeaderPortal: true, sourceBrowserComponent: mockSourceBrowserComponent, renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: jest.fn(), renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; const resource = mockResource(); const browseTo = { resourceId: resource.id, sourceId: resource.source.id }; const props = { allowedTypes: ['image'], }; render( , ); expect(mockSourceBrowserComponent).toHaveBeenCalled(); await waitFor(() => { expect(mockFunctionalComponent).toHaveBeenCalledWith( expect.objectContaining({ source: source, allowedTypes: props.allowedTypes, headerPortal: expect.any(Element), browseTo, }), {}, ); }); }); it('should pass onSelected to plugin UI generator FC when invoked calls change and close functions', async () => { const mockFunctionalComponent = jest.fn().mockReturnValue(
Source UI has been rendered
); const mockSourceBrowserComponent = jest.fn().mockReturnValue(mockFunctionalComponent); const plugin = { type: 'dam', createHeaderPortal: true, sourceBrowserComponent: mockSourceBrowserComponent, renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: jest.fn(), renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; const onChange = jest.fn(); const onClose = jest.fn(); render( , ); expect(mockSourceBrowserComponent).toHaveBeenCalled(); await waitFor(() => { expect(mockFunctionalComponent).toHaveBeenCalledWith( expect.objectContaining({ onSelected: expect.any(Function), searchEnabled: true, }), {}, ); }); const resource = mockResource(); const { onSelected } = mockFunctionalComponent.mock.calls[0][0]; onSelected(resource); expect(onChange).toHaveBeenCalledWith(resource); expect(onClose).toHaveBeenCalled(); }); }); describe('Search mode', () => { it('should create header portal for plugin', async () => { const mockFunctionalComponent = jest.fn().mockReturnValue(
Source search UI has been rendered
); const mockSourceSearchComponent = jest.fn().mockReturnValue(mockFunctionalComponent); const plugin = { type: 'dam', createHeaderPortal: true, sourceBrowserComponent: jest.fn, renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: mockSourceSearchComponent, renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; render( , ); expect(mockSourceSearchComponent).toHaveBeenCalled(); await waitFor(() => { expect(mockFunctionalComponent).toHaveBeenCalledWith( expect.objectContaining({ headerPortal: expect.any(Element), }), {}, ); }); }); it('should pass expected params to plugin UI generator functional component', async () => { const mockFunctionalComponent = jest.fn().mockReturnValue(
Source search UI has been rendered
); const mockSourceSearchComponent = jest.fn().mockReturnValue(mockFunctionalComponent); const plugin = { type: 'dam', createHeaderPortal: true, sourceBrowserComponent: jest.fn(), renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: mockSourceSearchComponent, renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; const props = { allowedTypes: ['image'], }; render( , ); expect(mockSourceSearchComponent).toHaveBeenCalled(); await waitFor(() => { expect(mockFunctionalComponent).toHaveBeenCalledWith( expect.objectContaining({ source: source, allowedTypes: props.allowedTypes, headerPortal: expect.any(Element), query: 'myQuery', }), {}, ); }); }); it('should pass onSelected to plugin UI generator FC when invoked calls change and close functions', async () => { const mockFunctionalComponent = jest.fn().mockReturnValue(
Source search UI has been rendered
); const mockSourceSearchComponent = jest.fn().mockReturnValue(mockFunctionalComponent); const plugin = { type: 'dam', createHeaderPortal: true, sourceBrowserComponent: jest.fn(), renderSelectedResource: jest.fn(), useResolveResource: jest.fn(), sourceSearchComponent: mockSourceSearchComponent, renderResourceLauncher: jest.fn(), } as ResourceBrowserPlugin; const onChange = jest.fn(); const onClose = jest.fn(); render( , ); expect(mockSourceSearchComponent).toHaveBeenCalled(); await waitFor(() => { expect(mockFunctionalComponent).toHaveBeenCalledWith( expect.objectContaining({ onSelected: expect.any(Function), searchEnabled: true, }), {}, ); }); const resource = mockResource(); const { onSelected } = mockFunctionalComponent.mock.calls[0][0]; onSelected(resource); expect(onChange).toHaveBeenCalledWith(resource); expect(onClose).toHaveBeenCalled(); }); }); }); });