Skip to content
Snippets Groups Projects
Commit 5bdfb65b authored by Tadeusz Miesiąc's avatar Tadeusz Miesiąc
Browse files

refactor(project drawer): changed project schema

parent a4442f0b
No related branches found
No related tags found
2 merge requests!223reset the pin numbers before search results are fetch (so the results will be...,!111feat(project info): initialised project info drawer
Pipeline #84733 passed
Showing
with 57 additions and 153 deletions
......@@ -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());
});
});
......
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();
});
});
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 }}
......
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,
};
};
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,
};
};
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,
});
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,
......
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,
});
import { z } from 'zod';
export const meshSchema = z.object({
id: z.string(),
name: z.string(),
decription: z.string(),
synonyms: z.array(z.string()),
});
......@@ -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(),
......
import { z } from 'zod';
export const taxonomySchema = z.object({
id: z.string(),
name: z.string(),
});
......@@ -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,
......
......@@ -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);
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);
......
......@@ -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>;
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment