Skip to content
Snippets Groups Projects
Commit e82dbe4c authored by Mateusz Bolewski's avatar Mateusz Bolewski
Browse files

Merge branch 'feat/bioentity-from-map' into 'development'

Feat/bioentity from map

See merge request !71
parents 19bfa400 ca33ca5a
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...,!71Feat/bioentity from map
Pipeline #82597 passed
Showing
with 342 additions and 5 deletions
/* eslint-disable no-magic-numbers */
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import { DRAWER_INITIAL_STATE } from '@/redux/drawer/drawer.constants';
import { StoreType } from '@/redux/store';
import {
bioEntitiesContentFixture,
bioEntityContentFixture,
} from '@/models/fixtures/bioEntityContentsFixture';
import { FIRST_ARRAY_ELEMENT } from '@/constants/common';
import { BioEntityDrawer } from './BioEntityDrawer.component';
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
return (
render(
<Wrapper>
<BioEntityDrawer />
</Wrapper>,
),
{
store,
}
);
};
describe('BioEntityDrawer - component', () => {
beforeEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
});
describe("when there's NO matching bioEntity", () => {
beforeEach(() =>
renderComponent({
bioEntity: {
data: [],
loading: 'succeeded',
error: { message: '', name: '' },
},
drawer: DRAWER_INITIAL_STATE,
}),
);
it('should not show drawer content', () => {
expect(screen.queryByText('Compartment:')).toBeNull();
expect(screen.queryByText('Full name:')).toBeNull();
expect(screen.queryByText('Annotations:')).toBeNull();
expect(screen.queryByText('Source:')).toBeNull();
});
});
describe('when there IS a matching bioEntity', () => {
const { bioEntity } = bioEntitiesContentFixture[FIRST_ARRAY_ELEMENT];
it('should show drawer header', () => {
renderComponent({
bioEntity: {
data: [
{
searchQueryElement: '',
loading: 'succeeded',
error: { name: '', message: '' },
data: bioEntitiesContentFixture,
},
],
loading: 'succeeded',
error: { message: '', name: '' },
},
drawer: {
...DRAWER_INITIAL_STATE,
bioEntityDrawerState: {
bioentityId: bioEntity.id,
},
},
});
expect(screen.getByText(bioEntity.stringType, { exact: false })).toBeInTheDocument();
expect(screen.getByText(bioEntity.name, { exact: false })).toBeInTheDocument();
});
it('should show drawer bioEntity full name', () => {
renderComponent({
bioEntity: {
data: [
{
searchQueryElement: '',
loading: 'succeeded',
error: { name: '', message: '' },
data: [
{
...bioEntityContentFixture,
bioEntity: {
...bioEntityContentFixture.bioEntity,
fullName: 'BioEntity Full Name',
},
},
],
},
],
loading: 'succeeded',
error: { message: '', name: '' },
},
drawer: {
...DRAWER_INITIAL_STATE,
bioEntityDrawerState: {
bioentityId: bioEntityContentFixture.bioEntity.id,
},
},
});
expect(screen.getByText('Full name:', { exact: false })).toBeInTheDocument();
expect(screen.getByText('BioEntity Full Name', { exact: false })).toBeInTheDocument();
});
it("should not show drawer bioEntity full name if it doesn't exists", () => {
renderComponent({
bioEntity: {
data: [
{
searchQueryElement: '',
loading: 'succeeded',
error: { name: '', message: '' },
data: [
{
...bioEntityContentFixture,
bioEntity: {
...bioEntityContentFixture.bioEntity,
fullName: null,
},
},
],
},
],
loading: 'succeeded',
error: { message: '', name: '' },
},
drawer: {
...DRAWER_INITIAL_STATE,
bioEntityDrawerState: {
bioentityId: bioEntityContentFixture.bioEntity.id,
},
},
});
expect(screen.queryByText('Full name:')).toBeNull();
});
it('should show list of annotations ', () => {
renderComponent({
bioEntity: {
data: [
{
searchQueryElement: '',
loading: 'succeeded',
error: { name: '', message: '' },
data: bioEntitiesContentFixture,
},
],
loading: 'succeeded',
error: { message: '', name: '' },
},
drawer: {
...DRAWER_INITIAL_STATE,
bioEntityDrawerState: {
bioentityId: bioEntity.id,
},
},
});
expect(screen.getByText('Annotations:')).toBeInTheDocument();
expect(screen.getByText(bioEntity.references[0].type, { exact: false })).toBeInTheDocument();
expect(
screen.getByText(bioEntity.references[0].resource, { exact: false }),
).toBeInTheDocument();
});
});
});
import { DrawerHeading } from '@/shared/DrawerHeading';
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { searchedFromMapBioEntityElement } from '@/redux/bioEntity/bioEntity.selectors';
import { Icon } from '@/shared/Icon';
export const BioEntityDrawer = (): React.ReactNode => {
const bioEntityData = useAppSelector(searchedFromMapBioEntityElement);
if (!bioEntityData) {
return null;
}
return (
<div className="h-full max-h-full" data-testid="bioentity-drawer">
<DrawerHeading
title={
<>
<span className="font-normal">{bioEntityData.stringType}:</span>&nbsp;
{bioEntityData.name}
</>
}
/>
<div className="flex flex-col gap-6 p-6">
<div className="text-sm font-normal">
Compartment: <b className="font-semibold">{bioEntityData.compartment}</b>
</div>
{bioEntityData.fullName && (
<div className="text-sm font-normal">
Full name: <b className="font-semibold">{bioEntityData.fullName}</b>
</div>
)}
<h3 className="font-semibold">Annotations:</h3>
{bioEntityData.references.map(reference => {
return (
<a
className="pl-3 text-sm font-normal"
href={reference.link?.toString()}
key={reference.id}
target="_blank"
>
<div className="flex justify-between">
<span>
Source:{' '}
<b className="font-semibold">
{reference?.type} ({reference.resource})
</b>
</span>
<Icon name="arrow" className="h-6 w-6 fill-font-500" />
</div>
</a>
);
})}
</div>
</div>
);
};
import { FIRST_ARRAY_ELEMENT } from '@/constants/common';
import { reactionsFixture } from '@/models/fixtures/reactionFixture';
import {
openBioEntityDrawerById,
openReactionDrawerById,
openSearchDrawerWithSelectedTab,
openSubmapsDrawer,
......@@ -13,6 +14,7 @@ import {
} from '@/utils/testing/getReduxWrapperWithStore';
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
import type {} from 'redux-thunk/extend-redux';
import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture';
import { Drawer } from './Drawer.component';
const renderComponent = (initialStore?: InitialStoreState): { store: StoreType } => {
......@@ -109,4 +111,33 @@ describe('Drawer - component', () => {
await waitFor(() => expect(screen.getByTestId('reaction-drawer')).toBeInTheDocument());
});
});
describe('bioEntity drawer', () => {
it.skip('should open drawer and display bioEntity', async () => {
const { id } = bioEntitiesContentFixture[FIRST_ARRAY_ELEMENT].bioEntity;
const { store } = renderComponent({
bioEntity: {
data: [
{
searchQueryElement: '',
loading: 'succeeded',
error: { name: '', message: '' },
data: bioEntitiesContentFixture,
},
],
loading: 'succeeded',
error: { message: '', name: '' },
},
});
expect(screen.queryByTestId('bioentity-drawer')).not.toBeInTheDocument();
await act(() => {
store.dispatch(openBioEntityDrawerById(id));
});
await waitFor(() => expect(screen.getByTestId('bioentity-drawer')).toBeInTheDocument());
});
});
});
......@@ -5,6 +5,7 @@ import { twMerge } from 'tailwind-merge';
import { ReactionDrawer } from './ReactionDrawer';
import { SearchDrawerWrapper as SearchDrawerContent } from './SearchDrawerWrapper';
import { SubmapsDrawer } from './SubmapsDrawer';
import { BioEntityDrawer } from './BioEntityDrawer/BioEntityDrawer.component';
export const Drawer = (): JSX.Element => {
const { isOpen, drawerName } = useAppSelector(drawerSelector);
......@@ -20,6 +21,7 @@ export const Drawer = (): JSX.Element => {
{isOpen && drawerName === 'search' && <SearchDrawerContent />}
{isOpen && drawerName === 'submaps' && <SubmapsDrawer />}
{isOpen && drawerName === 'reaction' && <ReactionDrawer />}
{isOpen && drawerName === 'bio-entity' && <BioEntityDrawer />}
</div>
);
};
......@@ -25,6 +25,7 @@ const INITIAL_STATE: InitialStoreState = {
selectedSearchElement: 'aspirin',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
},
drugs: {
data: [
......
......@@ -44,6 +44,7 @@ describe('SearchDrawerWrapper - component', () => {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
},
});
......@@ -63,6 +64,7 @@ describe('SearchDrawerWrapper - component', () => {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
},
});
......
import { FIRST_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
import { FIRST_ARRAY_ELEMENT, SECOND_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture';
import { ELEMENT_SEARCH_RESULT_MOCK_ALIAS } from '@/models/mocks/elementSearchResultMock';
import { apiPath } from '@/redux/apiPath';
......@@ -27,11 +27,19 @@ describe('handleAliasResults - util', () => {
handleAliasResults(dispatch)(ELEMENT_SEARCH_RESULT_MOCK_ALIAS);
});
it('should run getBioEntityAction', async () => {
it('should run openBioEntityDrawerById as first action', async () => {
await waitFor(() => {
const actions = store.getActions();
expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual('project/getMultiBioEntity/pending');
expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual('drawer/openBioEntityDrawerById');
});
});
it('should run getMultiBioEntity as second action', async () => {
await waitFor(() => {
const actions = store.getActions();
expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
expect(actions[SECOND_ARRAY_ELEMENT].type).toEqual('project/getMultiBioEntity/pending');
});
});
});
import { getMultiBioEntity } from '@/redux/bioEntity/bioEntity.thunks';
import { openBioEntityDrawerById } from '@/redux/drawer/drawer.slice';
import { AppDispatch } from '@/redux/store';
import { ElementSearchResult } from '@/types/models';
......@@ -6,6 +7,8 @@ import { ElementSearchResult } from '@/types/models';
export const handleAliasResults =
(dispatch: AppDispatch) =>
async ({ id }: ElementSearchResult): Promise<void> => {
dispatch(openBioEntityDrawerById(id));
dispatch(
getMultiBioEntity({
searchQueries: [id.toString()],
......
......@@ -3,7 +3,10 @@ import { rootSelector } from '@/redux/root/root.selectors';
import { MultiSearchData } from '@/types/fetchDataState';
import { BioEntity, BioEntityContent } from '@/types/models';
import { createSelector } from '@reduxjs/toolkit';
import { currentSelectedSearchElement } from '../drawer/drawer.selectors';
import {
currentSearchedBioEntityId,
currentSelectedSearchElement,
} from '../drawer/drawer.selectors';
import { currentModelIdSelector, modelsDataSelector } from '../models/models.selectors';
export const bioEntitySelector = createSelector(rootSelector, state => state.bioEntity);
......@@ -17,6 +20,17 @@ export const bioEntitiesForSelectedSearchElement = createSelector(
),
);
export const searchedFromMapBioEntityElement = createSelector(
bioEntitiesForSelectedSearchElement,
currentSearchedBioEntityId,
(bioEntitiesState, currentBioEntityId): BioEntity | undefined => {
return (
bioEntitiesState &&
bioEntitiesState.data?.find(({ bioEntity }) => bioEntity.id === currentBioEntityId)?.bioEntity
);
},
);
export const loadingBioEntityStatusSelector = createSelector(
bioEntitiesForSelectedSearchElement,
state => state?.loading,
......
......@@ -11,4 +11,5 @@ export const DRAWER_INITIAL_STATE: DrawerState = {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
};
import { STEP } from '@/constants/searchDrawer';
import type {
DrawerState,
OpenBioEntityDrawerByIdAction,
OpenReactionDrawerByIdAction,
OpenSearchDrawerWithSelectedTabReducerAction,
} from '@/redux/drawer/drawer.types';
......@@ -86,3 +87,13 @@ export const openReactionDrawerByIdReducer = (
state.drawerName = 'reaction';
state.reactionDrawerState.reactionId = action.payload;
};
export const openBioEntityDrawerByIdReducer = (
state: DrawerState,
action: OpenBioEntityDrawerByIdAction,
): void => {
state.isOpen = true;
state.drawerName = 'bio-entity';
state.bioEntityDrawerState.bioentityId = action.payload;
state.searchDrawerState.selectedSearchElement = action.payload.toString();
};
......@@ -36,6 +36,16 @@ export const currentStepTypeSelector = createSelector(
state => state.stepType,
);
export const bioEntityDrawerStateSelector = createSelector(
drawerSelector,
state => state.bioEntityDrawerState,
);
export const currentSearchedBioEntityId = createSelector(
bioEntityDrawerStateSelector,
state => state.bioentityId,
);
export const resultListSelector = createSelector(
rootSelector,
currentStepTypeSelector,
......
......@@ -7,6 +7,7 @@ import {
displayEntityDetailsReducer,
displayGroupedSearchResultsReducer,
openDrawerReducer,
openBioEntityDrawerByIdReducer,
openReactionDrawerByIdReducer,
openSearchDrawerWithSelectedTabReducer,
openSubmapsDrawerReducer,
......@@ -29,6 +30,7 @@ const drawerSlice = createSlice({
displayGroupedSearchResults: displayGroupedSearchResultsReducer,
displayEntityDetails: displayEntityDetailsReducer,
openReactionDrawerById: openReactionDrawerByIdReducer,
openBioEntityDrawerById: openBioEntityDrawerByIdReducer,
},
});
......@@ -44,6 +46,7 @@ export const {
displayGroupedSearchResults,
displayEntityDetails,
openReactionDrawerById,
openBioEntityDrawerById,
} = drawerSlice.actions;
export default drawerSlice.reducer;
......@@ -14,11 +14,16 @@ export type ReactionDrawerState = {
reactionId?: number;
};
export type BioEntityDrawerState = {
bioentityId?: number;
};
export type DrawerState = {
isOpen: boolean;
drawerName: DrawerName;
searchDrawerState: SearchDrawerState;
reactionDrawerState: ReactionDrawerState;
bioEntityDrawerState: BioEntityDrawerState;
};
export type OpenSearchDrawerWithSelectedTabReducerPayload = string;
......@@ -27,3 +32,6 @@ export type OpenSearchDrawerWithSelectedTabReducerAction =
export type OpenReactionDrawerByIdPayload = number;
export type OpenReactionDrawerByIdAction = PayloadAction<OpenReactionDrawerByIdPayload>;
export type OpenBioEntityDrawerByIdPayload = number;
export type OpenBioEntityDrawerByIdAction = PayloadAction<OpenBioEntityDrawerByIdPayload>;
......@@ -11,6 +11,7 @@ export const initialStateFixture: DrawerState = {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
};
export const openedDrawerSubmapsFixture: DrawerState = {
......@@ -24,6 +25,7 @@ export const openedDrawerSubmapsFixture: DrawerState = {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
};
export const drawerSearchStepOneFixture: DrawerState = {
......@@ -37,6 +39,7 @@ export const drawerSearchStepOneFixture: DrawerState = {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
};
export const drawerSearchDrugsStepTwoFixture: DrawerState = {
......@@ -50,6 +53,7 @@ export const drawerSearchDrugsStepTwoFixture: DrawerState = {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
};
export const drawerSearchChemicalsStepTwoFixture: DrawerState = {
......@@ -63,4 +67,5 @@ export const drawerSearchChemicalsStepTwoFixture: DrawerState = {
selectedSearchElement: '',
},
reactionDrawerState: {},
bioEntityDrawerState: {},
};
......@@ -6,4 +6,5 @@ export type DrawerName =
| 'export'
| 'legend'
| 'submaps'
| 'reaction';
| 'reaction'
| 'bio-entity';
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