diff --git a/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.test.tsx b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.test.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0fe3a588ecd06ed39cb31a05821f63f31d6a3ad4 --- /dev/null +++ b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.test.tsx @@ -0,0 +1,63 @@ +/* eslint-disable no-magic-numbers */ +import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; +import { InitialStoreState } from '@/utils/testing/getReduxStoreActionsListener'; +import { StoreType } from '@/redux/store'; +import { render, screen } from '@testing-library/react'; +import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; +import { BIOENTITY_INITIAL_STATE_MOCK } from '@/redux/bioEntity/bioEntity.mock'; +import { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList.component'; + +const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { + const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); + + return ( + render( + <Wrapper> + <ConnectedBioEntitiesList /> + </Wrapper>, + ), + { + store, + } + ); +}; + +describe('ConnectedBioEntitiesList', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders loading indicator when bioEntityLoading is pending', () => { + renderComponent({ + bioEntity: { + ...BIOENTITY_INITIAL_STATE_MOCK, + loading: 'pending', + }, + }); + + const loadingIndicator = screen.getByTestId('loading-indicator'); + + expect(loadingIndicator).toBeVisible(); + }); + + it('renders list of bio entities when bioEntityData is available', () => { + const bioEntityData = [bioEntitiesContentFixture[0]]; + + renderComponent({ + bioEntity: { + ...BIOENTITY_INITIAL_STATE_MOCK, + data: [ + { + searchQueryElement: '', + loading: 'succeeded', + error: { name: '', message: '' }, + data: bioEntityData, + }, + ], + }, + }); + + expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument(); + expect(screen.queryByText(bioEntitiesContentFixture[0].bioEntity.name)).toBeVisible(); + }); +}); diff --git a/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.tsx b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..04c02e458ed6a5413190a0b832eb399ac6ef85f2 --- /dev/null +++ b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.tsx @@ -0,0 +1,30 @@ +import { + bioEntityDataListSelector, + bioEntityLoadingSelector, +} from '@/redux/bioEntity/bioEntity.selectors'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { LoadingIndicator } from '@/shared/LoadingIndicator'; +import { BioEntitiesPinsListItem } from '../../SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem'; + +export const ConnectedBioEntitiesList = (): React.ReactNode => { + const bioEntityLoading = useAppSelector(bioEntityLoadingSelector); + const bioEntityData = useAppSelector(bioEntityDataListSelector); + const isPending = bioEntityLoading === 'pending'; + + if (isPending) { + return <LoadingIndicator />; + } + + return ( + <div> + {bioEntityData && + bioEntityData.map(item => ( + <BioEntitiesPinsListItem + name={item.bioEntity.name} + pin={item.bioEntity} + key={item.bioEntity.name} + /> + ))} + </div> + ); +}; diff --git a/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/index.ts b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..beb271ba06a0417936a140296bfe6f94801d0540 --- /dev/null +++ b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/index.ts @@ -0,0 +1 @@ +export { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList.component'; diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx index 9f6a8c4c3a130a2986a2a7cb15879fa93cb6cca9..2ba8e96d0a91fd7c88bf022494114eedb3ea63ea 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx @@ -5,6 +5,7 @@ import { import { DrawerHeading } from '@/shared/DrawerHeading'; import { useSelector } from 'react-redux'; import { ReferenceGroup } from './ReferenceGroup'; +import { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList'; export const ReactionDrawer = (): React.ReactNode => { const reaction = useSelector(currentDrawerReactionSelector); @@ -23,7 +24,7 @@ export const ReactionDrawer = (): React.ReactNode => { </> } /> - <div className="flex flex-col gap-6 p-6"> + <div className="flex h-[calc(100%-93px)] max-h-[calc(100%-93px)] flex-col gap-6 overflow-y-auto p-6"> <div className="text-sm font-normal"> Type: <b className="font-semibold">{reaction.type}</b> </div> @@ -32,6 +33,7 @@ export const ReactionDrawer = (): React.ReactNode => { {referencesGrouped.map(group => ( <ReferenceGroup key={group.source} group={group} /> ))} + <ConnectedBioEntitiesList /> </div> </div> ); diff --git a/src/redux/bioEntity/bioEntity.selectors.ts b/src/redux/bioEntity/bioEntity.selectors.ts index 8bf9877d86bb70a7665c50a5f400895b585baaae..a9dfacb44e548e0202a0a6b18387e675d57ebc1d 100644 --- a/src/redux/bioEntity/bioEntity.selectors.ts +++ b/src/redux/bioEntity/bioEntity.selectors.ts @@ -22,6 +22,11 @@ export const bioEntitySelector = createSelector(rootSelector, state => state.bio export const bioEntityDataSelector = createSelector(bioEntitySelector, bioEntity => bioEntity.data); +export const bioEntityLoadingSelector = createSelector( + bioEntitySelector, + bioEntity => bioEntity.loading, +); + export const bioEntityDataListSelector = createSelector(bioEntityDataSelector, bioEntityData => bioEntityData.map(b => b.data || []).flat(), ); diff --git a/src/shared/LoadingIndicator/LoadingIndicator.component.tsx b/src/shared/LoadingIndicator/LoadingIndicator.component.tsx index 9f047575680c21cf2c0f6934e60960a5b02cb508..39a2a4139dc58b06f7a71f810502a126e71d56f0 100644 --- a/src/shared/LoadingIndicator/LoadingIndicator.component.tsx +++ b/src/shared/LoadingIndicator/LoadingIndicator.component.tsx @@ -19,5 +19,6 @@ export const LoadingIndicator = ({ height={height} width={width} className="animate-spin" + data-testid="loading-indicator" /> );