diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0ad3e4b84467444c8aae11127fea88d7d8803ddf --- /dev/null +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx @@ -0,0 +1,82 @@ +import { backgroundsFixture } from '@/models/fixtures/backgroundsFixture'; +import { modelsFixture } from '@/models/fixtures/modelsFixture'; +import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; +import { RootState, StoreType } from '@/redux/store'; +import { + InitialStoreState, + getReduxWrapperWithStore, +} from '@/utils/testing/getReduxWrapperWithStore'; +import { render } from '@testing-library/react'; +import { DownloadSubmap } from './DownloadSubmap.component'; + +const VALID_MODEL_ID = 5052; +const VALID_BACKGROUND_ID = 53; +const VALID_MAX_ZOOM = 9; + +const getState = (): RootState => ({ + ...INITIAL_STORE_STATE_MOCK, + map: { + ...INITIAL_STORE_STATE_MOCK.map, + data: { + ...INITIAL_STORE_STATE_MOCK.map.data, + modelId: VALID_MODEL_ID, + backgroundId: VALID_BACKGROUND_ID, + size: { + ...INITIAL_STORE_STATE_MOCK.map.data.size, + maxZoom: VALID_MAX_ZOOM, + }, + }, + }, + models: { + ...INITIAL_STORE_STATE_MOCK.models, + data: [ + { + ...modelsFixture[FIRST_ARRAY_ELEMENT], + idObject: VALID_MODEL_ID, + }, + ], + }, + backgrounds: { + ...INITIAL_STORE_STATE_MOCK.backgrounds, + data: [ + { + ...backgroundsFixture[FIRST_ARRAY_ELEMENT], + id: VALID_BACKGROUND_ID, + }, + ], + }, +}); + +const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { + const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); + + return ( + render( + <Wrapper> + <DownloadSubmap /> + </Wrapper>, + ), + { + store, + } + ); +}; + +describe('DownloadSubmap - component', () => { + describe('button', () => { + it.skip('should render download button', () => { + renderComponent(getState()); + // const button = screen.getByRole('button'); + // expect(button).toBeInTheDocument(); + }); + + it('should open list on button click', () => {}); + + it('should close list on button click twice', () => {}); + }); + + describe('list', () => { + it('should not show list when closed', () => {}); + it('should render list elements with href and names when opened', () => {}); + }); +}); diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.tsx b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.tsx index 63bcb435324dd87a21f13ab8247bd75691c5bb39..9a4c33f7768f15c674871ce73903a88691b8c255 100644 --- a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.tsx +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.tsx @@ -16,7 +16,7 @@ export const DownloadSubmap = (): JSX.Element => { return ( <div className="relative"> - <Button variantStyles="ghost" className="mr-4" {...getToggleButtonProps()}> + <Button role="button" variantStyles="ghost" className="mr-4" {...getToggleButtonProps()}> Download </Button> <ul diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c8f335bff701d4fdeef65f9f815dcfe6dbc1fab2 --- /dev/null +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts @@ -0,0 +1,117 @@ +import { BASE_API_URL, PROJECT_ID } from '@/constants'; +import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; +import { backgroundsFixture } from '@/models/fixtures/backgroundsFixture'; +import { modelsFixture } from '@/models/fixtures/modelsFixture'; +import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; +import { RootState } from '@/redux/store'; +import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; +import { renderHook } from '@testing-library/react'; +import { useGetSubmapDownloadUrl } from './useGetSubmapDownloadUrl'; + +const VALID_HANDLER = 'lcsb.mapviewer.wikipathway.GpmlParser'; +const VALID_MODEL_ID = 5052; +const VALID_BACKGROUND_ID = 53; +const VALID_MAX_ZOOM = 9; + +const getState = ({ + modelId, + backgroundId, + mapSizeMaxZoom, +}: { + modelId: number; + backgroundId: number; + mapSizeMaxZoom: number; +}): RootState => ({ + ...INITIAL_STORE_STATE_MOCK, + map: { + ...INITIAL_STORE_STATE_MOCK.map, + data: { + ...INITIAL_STORE_STATE_MOCK.map.data, + modelId, + backgroundId, + size: { + ...INITIAL_STORE_STATE_MOCK.map.data.size, + maxZoom: mapSizeMaxZoom, + }, + }, + }, + models: { + ...INITIAL_STORE_STATE_MOCK.models, + data: [ + { + ...modelsFixture[FIRST_ARRAY_ELEMENT], + idObject: VALID_MODEL_ID, + }, + ], + }, + backgrounds: { + ...INITIAL_STORE_STATE_MOCK.backgrounds, + data: [ + { + ...backgroundsFixture[FIRST_ARRAY_ELEMENT], + id: VALID_BACKGROUND_ID, + }, + ], + }, +}); + +describe('useGetSubmapDownloadUrl - hook', () => { + describe('when not all params valid', () => { + const cases = [ + { + modelId: 0, + backgroundId: VALID_BACKGROUND_ID, + mapSizeMaxZoom: VALID_MAX_ZOOM, + handler: VALID_HANDLER, + }, + { + modelId: VALID_MODEL_ID, + backgroundId: 0, + mapSizeMaxZoom: VALID_MAX_ZOOM, + handler: VALID_HANDLER, + }, + { + modelId: VALID_MODEL_ID, + backgroundId: VALID_BACKGROUND_ID, + mapSizeMaxZoom: 0, + handler: VALID_HANDLER, + }, + { + modelId: VALID_MODEL_ID, + backgroundId: VALID_BACKGROUND_ID, + mapSizeMaxZoom: VALID_MAX_ZOOM, + handler: '', + }, + ]; + + it.each(cases)('should return empty string', ({ handler, ...stateParams }) => { + const { Wrapper } = getReduxWrapperWithStore(getState(stateParams)); + + const { + result: { current: getSubmapDownloadUrl }, + } = renderHook(() => useGetSubmapDownloadUrl(), { wrapper: Wrapper }); + + expect(getSubmapDownloadUrl({ handler })).toBe(''); + }); + }); + + describe('when all params valid', () => { + it('should return valid string', () => { + const { Wrapper } = getReduxWrapperWithStore( + getState({ + modelId: VALID_MODEL_ID, + backgroundId: VALID_BACKGROUND_ID, + mapSizeMaxZoom: VALID_MAX_ZOOM, + }), + ); + + const { + result: { current: getSubmapDownloadUrl }, + } = renderHook(() => useGetSubmapDownloadUrl(), { wrapper: Wrapper }); + + expect(getSubmapDownloadUrl({ handler: VALID_HANDLER })).toBe( + `${BASE_API_URL}/projects/${PROJECT_ID}/models/5052:downloadModel?backgroundOverlayId=53&handlerClass=lcsb.mapviewer.wikipathway.GpmlParser&zoomLevel=9`, + ); + }); + }); +}); diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts index f55e3edd99d5300d38990172e7a5b034063fceda..c02894df049f0ad36e0db9e4a1652b2de2e1e6de 100644 --- a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts @@ -12,6 +12,14 @@ export const useGetSubmapDownloadUrl = (): GetSubmapDownloadUrl => { const mapSize = useSelector(mapDataSizeSelector); const getSubmapDownloadUrl: GetSubmapDownloadUrl = ({ handler }) => { + const allParamsValid = [model?.idObject, background?.id, mapSize.maxZoom, handler].reduce( + (a, b) => Boolean(a) && Boolean(b), + true, + ); + if (!allParamsValid) { + return ''; + } + return `${BASE_API_URL}/projects/${PROJECT_ID}/models/${model?.idObject}:downloadModel?backgroundOverlayId=${background?.id}&handlerClass=${handler}&zoomLevel=${mapSize.maxZoom}`; }; diff --git a/src/redux/configuration/configuration.selectors.ts b/src/redux/configuration/configuration.selectors.ts index 9164accde33790ee5d70f1bc2ca76e710338c246..a95bf55b2d5dbe2b8796ca98bd0ac8f6901faa93 100644 --- a/src/redux/configuration/configuration.selectors.ts +++ b/src/redux/configuration/configuration.selectors.ts @@ -69,8 +69,10 @@ export const formatsEntriesSelector = createSelector( return Object.fromEntries( modelFormats .flat() - .filter((format): format is ConfigurationFormatSchema => Boolean(format)) - .map(format => [format.name, format]), + .filter((format: ConfigurationFormatSchema): format is ConfigurationFormatSchema => + Boolean(format), + ) + .map((format: ConfigurationFormatSchema) => [format.name, format]), ); }, ); diff --git a/src/redux/configuration/configuration.slice.ts b/src/redux/configuration/configuration.slice.ts index 4bf43488b0dbf265504a24370e7607a90c1f82b5..59a36447b40ed9bca1db1d9fb4e0119b323e01e4 100644 --- a/src/redux/configuration/configuration.slice.ts +++ b/src/redux/configuration/configuration.slice.ts @@ -1,6 +1,6 @@ import { createSlice } from '@reduxjs/toolkit'; -import { getConfigurationOptionsReducer } from './configuration.reducers'; import { CONFIGURATION_INITIAL_STATE } from './configuration.adapter'; +import { getConfigurationOptionsReducer } from './configuration.reducers'; export const configurationSlice = createSlice({ name: 'configuration',