From 273731475eddf7dc99819fc2a7fe6cee97e7a836 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrian=20Or=C5=82=C3=B3w?= <adrian.orlow@fishbrain.com>
Date: Fri, 12 Jan 2024 15:07:24 +0100
Subject: [PATCH] test: add tests for submap download (partial)

---
 .../DownloadSubmap.component.test.tsx         |  82 ++++++++++++
 .../DownloadSubmap.component.tsx              |   2 +-
 .../utils/useGetSubmapDownloadUrl.test.ts     | 117 ++++++++++++++++++
 .../utils/useGetSubmapDownloadUrl.ts          |   8 ++
 .../configuration/configuration.selectors.ts  |   6 +-
 .../configuration/configuration.slice.ts      |   2 +-
 6 files changed, 213 insertions(+), 4 deletions(-)
 create mode 100644 src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx
 create mode 100644 src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts

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 00000000..0ad3e4b8
--- /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 63bcb435..9a4c33f7 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 00000000..c8f335bf
--- /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 f55e3edd..c02894df 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 9164accd..a95bf55b 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 4bf43488..59a36447 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',
-- 
GitLab