From 5bdfb65b7129f98c8df3dd7703192c6670806201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tadeusz=20Miesi=C4=85c?= <tadeusz.miesiac@gmail.com> Date: Mon, 22 Jan 2024 11:45:17 +0100 Subject: [PATCH] refactor(project drawer): changed project schema --- .../Map/Drawer/Drawer.component.test.tsx | 8 ++-- .../ProjectInfoDrawer.component.test.tsx | 38 +++++++++---------- .../ProjectInfoDrawer.component.tsx | 18 ++++++--- .../ProjectInfoDrawer/hooks/useDisease.ts | 37 ------------------ .../ProjectInfoDrawer/hooks/useOrganism.ts | 37 ------------------ src/models/fixtures/meshFixture.ts | 8 ---- src/models/fixtures/projectFixture.ts | 2 +- src/models/fixtures/taxonomyFixture.ts | 8 ---- src/models/meshSchema.ts | 8 ---- src/models/{project.ts => projectSchema.ts} | 7 +++- src/models/taxonomySchema.ts | 6 --- src/redux/project/project.reducers.test.ts | 4 +- src/redux/project/project.selectors.ts | 12 +++--- src/redux/project/project.thunks.ts | 6 +-- src/types/models.ts | 6 +-- .../initialize/useInitializeStore.test.ts | 5 ++- 16 files changed, 57 insertions(+), 153 deletions(-) delete mode 100644 src/components/Map/Drawer/ProjectInfoDrawer/hooks/useDisease.ts delete mode 100644 src/components/Map/Drawer/ProjectInfoDrawer/hooks/useOrganism.ts delete mode 100644 src/models/fixtures/meshFixture.ts delete mode 100644 src/models/fixtures/taxonomyFixture.ts delete mode 100644 src/models/meshSchema.ts rename src/models/{project.ts => projectSchema.ts} (85%) delete mode 100644 src/models/taxonomySchema.ts diff --git a/src/components/Map/Drawer/Drawer.component.test.tsx b/src/components/Map/Drawer/Drawer.component.test.tsx index fb4be23d..2499e7f3 100644 --- a/src/components/Map/Drawer/Drawer.component.test.tsx +++ b/src/components/Map/Drawer/Drawer.component.test.tsx @@ -104,10 +104,10 @@ describe('Drawer - component', () => { }); expect(screen.queryByTestId('reaction-drawer')).not.toBeInTheDocument(); - - store.dispatch(getReactionsByIds([id])); - store.dispatch(openReactionDrawerById(id)); - + await act(() => { + store.dispatch(getReactionsByIds([id])); + store.dispatch(openReactionDrawerById(id)); + }); await waitFor(() => expect(screen.getByTestId('reaction-drawer')).toBeInTheDocument()); }); }); diff --git a/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.test.tsx b/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.test.tsx index 560ab58a..bfad3705 100644 --- a/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.test.tsx +++ b/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.test.tsx @@ -1,4 +1,3 @@ -import { HttpStatusCode } from 'axios'; import { act } from 'react-dom/test-utils'; import { render, screen } from '@testing-library/react'; import { @@ -7,15 +6,9 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { projectFixture } from '@/models/fixtures/projectFixture'; import { StoreType } from '@/redux/store'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; import { MODEL_WITH_DESCRIPTION } from '@/models/mocks/modelsMock'; -import { meshFixture } from '@/models/fixtures/meshFixture'; -import { apiPath } from '@/redux/apiPath'; -import { taxonomyFixture } from '@/models/fixtures/taxonomyFixture'; import { ProjectInfoDrawer } from './ProjectInfoDrawer.component'; -const mockedAxiosClient = mockNetworkResponse(); - const MOCKED_STORE: InitialStoreState = { project: { data: { ...projectFixture }, @@ -44,10 +37,6 @@ const renderComponent = (initialStore?: InitialStoreState): { store: StoreType } }; describe('ProjectInfoDrawer', () => { - beforeEach(() => { - mockedAxiosClient.reset(); - }); - it('should render the project name', () => { renderComponent(MOCKED_STORE); @@ -72,9 +61,6 @@ describe('ProjectInfoDrawer', () => { }); it('should render the disease link with name and href', async () => { - mockedAxiosClient - .onGet(apiPath.getMesh(projectFixture.disease.resource)) - .reply(HttpStatusCode.Ok, meshFixture); await act(() => { renderComponent(MOCKED_STORE); }); @@ -82,15 +68,12 @@ describe('ProjectInfoDrawer', () => { const diseaseLink = screen.getByText(/Disease:/i); expect(diseaseLink).toBeInTheDocument(); - const linkelement = screen.getByRole('link', { name: meshFixture.name }); + const linkelement = screen.getByRole('link', { name: projectFixture.diseaseName }); expect(linkelement).toBeInTheDocument(); expect(linkelement).toHaveAttribute('href', projectFixture.disease.link); }); it('should fetch diesease name when diseaseId is provided', async () => { - mockedAxiosClient - .onGet(apiPath.getTaxonomy(projectFixture.organism.resource)) - .reply(HttpStatusCode.Ok, taxonomyFixture); await act(() => { renderComponent(MOCKED_STORE); }); @@ -98,7 +81,7 @@ describe('ProjectInfoDrawer', () => { const organismLink = screen.getByText(/Organism:/i); expect(organismLink).toBeInTheDocument(); - const linkelement = screen.getByRole('link', { name: taxonomyFixture.name }); + const linkelement = screen.getByRole('link', { name: projectFixture.organismName }); expect(linkelement).toBeInTheDocument(); expect(linkelement).toHaveAttribute('href', projectFixture.organism.link); }); @@ -114,4 +97,21 @@ describe('ProjectInfoDrawer', () => { ); expect(downloadButton).toHaveAttribute('download', 'sourceFile.txt'); }); + + it('should render the description when it exists', () => { + renderComponent(MOCKED_STORE); + + const desc = screen.getByTestId('project-description'); + + expect(desc.innerHTML).toContain( + 'For information on content, functionalities and referencing the Parkinson\'s disease map, click <a href="http://pdmap.uni.lu" target="_blank">here</a>', + ); + }); + + it.skip('should not render the description when it does not exist', () => { + renderComponent(); + + const descriptionElement = screen.queryByText('This is the project description.'); + expect(descriptionElement).not.toBeInTheDocument(); + }); }); diff --git a/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx b/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx index 439a017a..31823981 100644 --- a/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx +++ b/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx @@ -1,16 +1,23 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { projectNameSelector, versionSelector } from '@/redux/project/project.selectors'; +import { + diseaseNameSelector, + projectNameSelector, + versionSelector, + organismNameSelector, + diseaseLinkSelector, + organismLinkSelector, +} from '@/redux/project/project.selectors'; import { DrawerHeading } from '@/shared/DrawerHeading'; import { apiPath } from '@/redux/apiPath'; import { LinkButton } from '@/shared/LinkButton'; import { mainMapModelDescriptionSelector } from '@/redux/models/models.selectors'; import './ProjectInfoDrawer.styles.css'; -import { useDisease } from './hooks/useDisease'; -import { useOrganism } from './hooks/useOrganism'; export const ProjectInfoDrawer = (): JSX.Element => { - const { diseaseName, diseaseLink } = useDisease(); - const { organismName, organismLink } = useOrganism(); + const diseaseName = useAppSelector(diseaseNameSelector); + const diseaseLink = useAppSelector(diseaseLinkSelector); + const organismLink = useAppSelector(organismLinkSelector); + const organismName = useAppSelector(organismNameSelector); const projectName = useAppSelector(projectNameSelector); const version = useAppSelector(versionSelector); const description = useAppSelector(mainMapModelDescriptionSelector); @@ -68,6 +75,7 @@ export const ProjectInfoDrawer = (): JSX.Element => { </LinkButton> {description && ( <div + data-testid="project-description" className="anchor-tag mt-7 rounded-lg bg-cultured px-4 py-2" // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML={{ __html: description }} diff --git a/src/components/Map/Drawer/ProjectInfoDrawer/hooks/useDisease.ts b/src/components/Map/Drawer/ProjectInfoDrawer/hooks/useDisease.ts deleted file mode 100644 index 9c99905c..00000000 --- a/src/components/Map/Drawer/ProjectInfoDrawer/hooks/useDisease.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useEffect, useState } from 'react'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { diseaseIdSelector, diseaseLinkSelector } from '@/redux/project/project.selectors'; -import { Mesh } from '@/types/models'; -import { apiPath } from '@/redux/apiPath'; -import { axiosInstance } from '@/services/api/utils/axiosInstance'; - -type UseDiseaseReturnType = { - diseaseName: string; - diseaseLink?: string; -}; - -export const useDisease = (): UseDiseaseReturnType => { - const [diseaseName, setDiseaseName] = useState<string>(''); - const diseaseId = useAppSelector(diseaseIdSelector); - const diseaseLink = useAppSelector(diseaseLinkSelector); - - useEffect(() => { - const getDiseaseName = async (id: string): Promise<void> => { - try { - const mesh = await axiosInstance.get<Mesh>(apiPath.getMesh(id)); - setDiseaseName(mesh.data.name); - } catch (error) { - /* empty */ - } - }; - - if (diseaseId) { - getDiseaseName(diseaseId); - } - }, [diseaseId]); - - return { - diseaseName, - diseaseLink, - }; -}; diff --git a/src/components/Map/Drawer/ProjectInfoDrawer/hooks/useOrganism.ts b/src/components/Map/Drawer/ProjectInfoDrawer/hooks/useOrganism.ts deleted file mode 100644 index bff0276e..00000000 --- a/src/components/Map/Drawer/ProjectInfoDrawer/hooks/useOrganism.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { apiPath } from '@/redux/apiPath'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { organismIdSelector, organismLinkSelector } from '@/redux/project/project.selectors'; -import { axiosInstance } from '@/services/api/utils/axiosInstance'; -import { Taxonomy } from '@/types/models'; -import { useState, useEffect } from 'react'; - -type UseOrganismReturnType = { - organismName: string; - organismLink?: string; -}; - -export const useOrganism = (): UseOrganismReturnType => { - const [organismName, setOrganismName] = useState<string>(''); - const organismId = useAppSelector(organismIdSelector); - const organismLink = useAppSelector(organismLinkSelector); - - useEffect(() => { - const getOrganismName = async (id: string): Promise<void> => { - try { - const taxonomy = await axiosInstance.get<Taxonomy>(apiPath.getTaxonomy(id)); - setOrganismName(taxonomy.data.name); - } catch (error) { - /* empty */ - } - }; - - if (organismId) { - getOrganismName(organismId); - } - }, [organismId]); - - return { - organismName, - organismLink, - }; -}; diff --git a/src/models/fixtures/meshFixture.ts b/src/models/fixtures/meshFixture.ts deleted file mode 100644 index 753cc1bb..00000000 --- a/src/models/fixtures/meshFixture.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ZOD_SEED } from '@/constants'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { createFixture } from 'zod-fixture'; -import { meshSchema } from '../meshSchema'; - -export const meshFixture = createFixture(meshSchema, { - seed: ZOD_SEED, -}); diff --git a/src/models/fixtures/projectFixture.ts b/src/models/fixtures/projectFixture.ts index 99e01bb3..06868af6 100644 --- a/src/models/fixtures/projectFixture.ts +++ b/src/models/fixtures/projectFixture.ts @@ -1,7 +1,7 @@ import { ZOD_SEED } from '@/constants'; // eslint-disable-next-line import/no-extraneous-dependencies import { createFixture } from 'zod-fixture'; -import { projectSchema } from '../project'; +import { projectSchema } from '../projectSchema'; export const projectFixture = createFixture(projectSchema, { seed: ZOD_SEED, diff --git a/src/models/fixtures/taxonomyFixture.ts b/src/models/fixtures/taxonomyFixture.ts deleted file mode 100644 index 99b5db53..00000000 --- a/src/models/fixtures/taxonomyFixture.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ZOD_SEED } from '@/constants'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { createFixture } from 'zod-fixture'; -import { taxonomySchema } from '../taxonomySchema'; - -export const taxonomyFixture = createFixture(taxonomySchema, { - seed: ZOD_SEED, -}); diff --git a/src/models/meshSchema.ts b/src/models/meshSchema.ts deleted file mode 100644 index c78ff933..00000000 --- a/src/models/meshSchema.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { z } from 'zod'; - -export const meshSchema = z.object({ - id: z.string(), - name: z.string(), - decription: z.string(), - synonyms: z.array(z.string()), -}); diff --git a/src/models/project.ts b/src/models/projectSchema.ts similarity index 85% rename from src/models/project.ts rename to src/models/projectSchema.ts index 844fe680..517d7b0c 100644 --- a/src/models/project.ts +++ b/src/models/projectSchema.ts @@ -6,8 +6,9 @@ import { overviewImageView } from './overviewImageView'; export const projectSchema = z.object({ version: z.string(), disease, + diseaseName: z.string(), organism, - idObject: z.number(), + organismName: z.string(), status: z.string(), directory: z.string(), progress: z.number(), @@ -15,7 +16,9 @@ export const projectSchema = z.object({ logEntries: z.boolean(), name: z.string(), sharedInMinervaNet: z.boolean(), - owner: z.string(), + owner: z.object({ + login: z.string(), + }), projectId: z.string(), creationDate: z.string(), mapCanvasType: z.string(), diff --git a/src/models/taxonomySchema.ts b/src/models/taxonomySchema.ts deleted file mode 100644 index cfc3d9e2..00000000 --- a/src/models/taxonomySchema.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { z } from 'zod'; - -export const taxonomySchema = z.object({ - id: z.string(), - name: z.string(), -}); diff --git a/src/redux/project/project.reducers.test.ts b/src/redux/project/project.reducers.test.ts index 28b9ef70..744f7252 100644 --- a/src/redux/project/project.reducers.test.ts +++ b/src/redux/project/project.reducers.test.ts @@ -4,14 +4,14 @@ import { ToolkitStoreWithSingleSlice, createStoreInstanceUsingSliceReducer, } from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { HttpStatusCode } from 'axios'; import { apiPath } from '../apiPath'; import projectReducer from './project.slice'; import { getProjectById } from './project.thunks'; import { ProjectState } from './project.types'; -const mockedAxiosClient = mockNetworkResponse(); +const mockedAxiosClient = mockNetworkNewAPIResponse(); const INITIAL_STATE: ProjectState = { data: undefined, diff --git a/src/redux/project/project.selectors.ts b/src/redux/project/project.selectors.ts index 198295bf..6ae2769e 100644 --- a/src/redux/project/project.selectors.ts +++ b/src/redux/project/project.selectors.ts @@ -42,9 +42,9 @@ export const projectNameSelector = createSelector( projectData => projectData?.name, ); -export const diseaseIdSelector = createSelector( +export const diseaseNameSelector = createSelector( projectDataSelector, - projectData => projectData?.disease.resource, + projectData => projectData?.diseaseName, ); export const diseaseLinkSelector = createSelector( @@ -52,14 +52,14 @@ export const diseaseLinkSelector = createSelector( projectData => projectData?.disease.link, ); -export const organismIdSelector = createSelector( +export const organismLinkSelector = createSelector( projectDataSelector, - projectData => projectData?.organism.resource, + projectData => projectData?.organism.link, ); -export const organismLinkSelector = createSelector( +export const organismNameSelector = createSelector( projectDataSelector, - projectData => projectData?.organism.link, + projectData => projectData?.organismName, ); export const versionSelector = createSelector(projectDataSelector, state => state?.version); diff --git a/src/redux/project/project.thunks.ts b/src/redux/project/project.thunks.ts index f3d9fbe2..649f867d 100644 --- a/src/redux/project/project.thunks.ts +++ b/src/redux/project/project.thunks.ts @@ -1,5 +1,5 @@ -import { projectSchema } from '@/models/project'; -import { axiosInstance } from '@/services/api/utils/axiosInstance'; +import { projectSchema } from '@/models/projectSchema'; +import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; import { Project } from '@/types/models'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; import { createAsyncThunk } from '@reduxjs/toolkit'; @@ -8,7 +8,7 @@ import { apiPath } from '../apiPath'; export const getProjectById = createAsyncThunk( 'project/getProjectById', async (id: string): Promise<Project | undefined> => { - const response = await axiosInstance.get<Project>(apiPath.getProjectById(id)); + const response = await axiosInstanceNewAPI.get<Project>(apiPath.getProjectById(id)); const isDataValid = validateDataUsingZodSchema(response.data, projectSchema); diff --git a/src/types/models.ts b/src/types/models.ts index db056dc4..8ad656d4 100644 --- a/src/types/models.ts +++ b/src/types/models.ts @@ -20,7 +20,6 @@ import { mapOverlay, uploadedOverlayFileContentSchema, } from '@/models/mapOverlay'; -import { meshSchema } from '@/models/meshSchema'; import { mapModelSchema } from '@/models/modelSchema'; import { organism } from '@/models/organism'; import { overlayBioEntitySchema } from '@/models/overlayBioEntitySchema'; @@ -30,14 +29,13 @@ import { overviewImageLinkModel, } from '@/models/overviewImageLink'; import { overviewImageView } from '@/models/overviewImageView'; -import { projectSchema } from '@/models/project'; +import { projectSchema } from '@/models/projectSchema'; import { reactionSchema } from '@/models/reaction'; import { reactionLineSchema } from '@/models/reactionLineSchema'; import { referenceSchema } from '@/models/referenceSchema'; import { sessionSchemaValid } from '@/models/sessionValidSchema'; import { statisticsSchema } from '@/models/statisticsSchema'; import { targetSchema } from '@/models/targetSchema'; -import { taxonomySchema } from '@/models/taxonomySchema'; import { z } from 'zod'; export type Project = z.infer<typeof projectSchema>; @@ -74,5 +72,3 @@ export type Color = z.infer<typeof colorSchema>; export type Statistics = z.infer<typeof statisticsSchema>; export type CompartmentPathway = z.infer<typeof compartmentPathwaySchema>; export type CompartmentPathwayDetails = z.infer<typeof compartmentPathwayDetailsSchema>; -export type Mesh = z.infer<typeof meshSchema>; -export type Taxonomy = z.infer<typeof taxonomySchema>; diff --git a/src/utils/initialize/useInitializeStore.test.ts b/src/utils/initialize/useInitializeStore.test.ts index d1b7da08..1a99f715 100644 --- a/src/utils/initialize/useInitializeStore.test.ts +++ b/src/utils/initialize/useInitializeStore.test.ts @@ -9,13 +9,14 @@ import { modelsDataSelector } from '@/redux/models/models.selectors'; import { overlaysDataSelector } from '@/redux/overlays/overlays.selectors'; import { projectDataSelector } from '@/redux/project/project.selectors'; import { initDataLoadingInitialized } from '@/redux/root/init.selectors'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { mockNetworkNewAPIResponse, mockNetworkResponse } from '@/utils/mockNetworkResponse'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { renderHook, waitFor } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import * as hook from './useInitializeStore'; const mockedAxiosClient = mockNetworkResponse(); +const mockedAxiosNEWApiClient = mockNetworkNewAPIResponse(); describe('useInitializeStore - hook', () => { describe('when fired', () => { @@ -24,7 +25,7 @@ describe('useInitializeStore - hook', () => { mockedAxiosClient .onGet(apiPath.getAllOverlaysByProjectIdQuery(PROJECT_ID, { publicOverlay: true })) .reply(HttpStatusCode.Ok, overlaysFixture); - mockedAxiosClient + mockedAxiosNEWApiClient .onGet(apiPath.getProjectById(PROJECT_ID)) .reply(HttpStatusCode.Ok, projectFixture); mockedAxiosClient -- GitLab