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

Merge branch 'feature/MIN-99-mirna-results' into 'development'

feat(mirna accordion): on mirna click navigate to mirnas list

See merge request !42
parents 9c89821c b867e10f
No related branches found
No related tags found
3 merge requests!223reset the pin numbers before search results are fetch (so the results will be...,!42feat(mirna accordion): on mirna click navigate to mirnas list,!41feat(chemical accordion): it's now possible to navigate from chemicals accordion to list
Pipeline #80190 passed
Showing
with 217 additions and 13 deletions
import { render, screen } from '@testing-library/react';
import { act, render, screen } from '@testing-library/react';
import { StoreType } from '@/redux/store';
import {
InitialStoreState,
......@@ -6,8 +6,11 @@ import {
} from '@/utils/testing/getReduxWrapperWithStore';
import { chemicalsFixture } from '@/models/fixtures/chemicalsFixture';
import { Accordion } from '@/shared/Accordion';
import { drawerSearchStepOneFixture } from '@/redux/drawer/drawerFixture';
import { ChemicalsAccordion } from './ChemicalsAccordion.component';
const SECOND_STEP = 2;
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
......@@ -38,4 +41,47 @@ describe('DrugsAccordion - component', () => {
});
expect(screen.getByText('Chemicals (Loading...)')).toBeInTheDocument();
});
it('should navigate user to chemical results list after clicking button', async () => {
const { store } = renderComponent({
chemicals: {
data: chemicalsFixture,
loading: 'succeeded',
error: { name: '', message: '' },
},
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
await act(() => {
navigationButton.click();
});
const {
drawer: {
searchDrawerState: { stepType, selectedValue, currentStep },
},
} = store.getState();
expect(stepType).toBe('chemicals');
expect(selectedValue).toBe(undefined);
expect(currentStep).toBe(SECOND_STEP);
});
it('should disable navigation button when there is no chemicals', async () => {
renderComponent({
chemicals: { data: [], loading: 'succeeded', error: { name: '', message: '' } },
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
expect(navigationButton).toBeDisabled();
});
it('should disable navigation button when waiting for api response', async () => {
renderComponent({
chemicals: { data: [], loading: 'pending', error: { name: '', message: '' } },
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
expect(navigationButton).toBeDisabled();
});
});
import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
import {
numberOfChemicalsSelector,
loadingChemicalsStatusSelector,
} from '@/redux/chemicals/chemicals.selectors';
import { displayChemicalsList } from '@/redux/drawer/drawer.slice';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { AccordionItem, AccordionItemHeading, AccordionItemButton } from '@/shared/Accordion';
export const ChemicalsAccordion = (): JSX.Element => {
const dispatch = useAppDispatch();
const chemicalsNumber = useAppSelector(numberOfChemicalsSelector);
const drugsState = useAppSelector(loadingChemicalsStatusSelector);
const chemicalsState = useAppSelector(loadingChemicalsStatusSelector);
const isPending = chemicalsState === 'pending';
const isSucceeded = chemicalsState === 'succeeded';
const isChemicalsEmpty = chemicalsNumber === SIZE_OF_EMPTY_ARRAY;
const onAccordionClick = (): void => {
dispatch(displayChemicalsList());
};
return (
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton variant="non-expandable">
<AccordionItemButton
variant="non-expandable"
onClick={onAccordionClick}
disabled={isPending || isChemicalsEmpty}
>
Chemicals
{drugsState === 'pending' && ' (Loading...)'}
{drugsState === 'succeeded' && ` (${chemicalsNumber})`}
{isPending && ' (Loading...)'}
{isSucceeded && ` (${chemicalsNumber})`}
</AccordionItemButton>
</AccordionItemHeading>
</AccordionItem>
......
......@@ -5,9 +5,12 @@ import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import { act, render, screen } from '@testing-library/react';
import { drawerSearchStepOneFixture } from '@/redux/drawer/drawerFixture';
import { DrugsAccordion } from './DrugsAccordion.component';
const SECOND_STEP = 2;
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
......@@ -38,4 +41,47 @@ describe('DrugsAccordion - component', () => {
});
expect(screen.getByText('Drugs (Loading...)')).toBeInTheDocument();
});
it('should navigate user to chemical results list after clicking button', async () => {
const { store } = renderComponent({
drugs: {
data: drugsFixture,
loading: 'succeeded',
error: { name: '', message: '' },
},
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
await act(() => {
navigationButton.click();
});
const {
drawer: {
searchDrawerState: { stepType, selectedValue, currentStep },
},
} = store.getState();
expect(stepType).toBe('drugs');
expect(selectedValue).toBe(undefined);
expect(currentStep).toBe(SECOND_STEP);
});
it('should disable navigation button when there is no drugs', async () => {
renderComponent({
drugs: { data: [], loading: 'succeeded', error: { name: '', message: '' } },
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
expect(navigationButton).toBeDisabled();
});
it('should disable navigation button when waiting for api response', async () => {
renderComponent({
drugs: { data: [], loading: 'pending', error: { name: '', message: '' } },
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
expect(navigationButton).toBeDisabled();
});
});
......@@ -11,6 +11,8 @@ export const DrugsAccordion = (): JSX.Element => {
const dispatch = useAppDispatch();
const isPending = drugsState === 'pending';
const isSucceeded = drugsState === 'succeeded';
const isDrugsEmpty = drugsNumber === SIZE_OF_EMPTY_ARRAY;
const onAccordionClick = (): void => {
dispatch(displayDrugsList());
......@@ -22,11 +24,11 @@ export const DrugsAccordion = (): JSX.Element => {
<AccordionItemButton
variant="non-expandable"
onClick={onAccordionClick}
disabled={isPending || drugsNumber === SIZE_OF_EMPTY_ARRAY}
disabled={isPending || isDrugsEmpty}
>
Drugs
{drugsState === 'pending' && ' (Loading...)'}
{drugsState === 'succeeded' && ` (${drugsNumber})`}
{isPending && ' (Loading...)'}
{isSucceeded && ` (${drugsNumber})`}
</AccordionItemButton>
</AccordionItemHeading>
</AccordionItem>
......
import { render, screen } from '@testing-library/react';
import { act, render, screen } from '@testing-library/react';
import { StoreType } from '@/redux/store';
import {
InitialStoreState,
......@@ -6,8 +6,11 @@ import {
} from '@/utils/testing/getReduxWrapperWithStore';
import { mirnasFixture } from '@/models/fixtures/mirnasFixture';
import { Accordion } from '@/shared/Accordion';
import { drawerSearchStepOneFixture } from '@/redux/drawer/drawerFixture';
import { MirnaAccordion } from './MirnaAccordion.component';
const SECOND_STEP = 2;
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
......@@ -38,4 +41,47 @@ describe('DrugsAccordion - component', () => {
});
expect(screen.getByText('MiRNA (Loading...)')).toBeInTheDocument();
});
it('should navigate user to mirnas results list after clicking button', async () => {
const { store } = renderComponent({
mirnas: {
data: mirnasFixture,
loading: 'succeeded',
error: { name: '', message: '' },
},
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
await act(() => {
navigationButton.click();
});
const {
drawer: {
searchDrawerState: { stepType, selectedValue, currentStep },
},
} = store.getState();
expect(stepType).toBe('mirna');
expect(selectedValue).toBe(undefined);
expect(currentStep).toBe(SECOND_STEP);
});
it('should disable navigation button when there is no mirnas', async () => {
renderComponent({
mirnas: { data: [], loading: 'succeeded', error: { name: '', message: '' } },
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
expect(navigationButton).toBeDisabled();
});
it('should disable navigation button when waiting for api response', async () => {
renderComponent({
mirnas: { data: [], loading: 'pending', error: { name: '', message: '' } },
drawer: drawerSearchStepOneFixture,
});
const navigationButton = screen.getByTestId('accordion-item-button');
expect(navigationButton).toBeDisabled();
});
});
import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
import { displayMirnaList } from '@/redux/drawer/drawer.slice';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import {
numberOfMirnasSelector,
......@@ -6,16 +9,28 @@ import {
import { AccordionItem, AccordionItemHeading, AccordionItemButton } from '@/shared/Accordion';
export const MirnaAccordion = (): JSX.Element => {
const dispatch = useAppDispatch();
const mirnaNumber = useAppSelector(numberOfMirnasSelector);
const mirnaState = useAppSelector(loadingMirnasStatusSelector);
const isPending = mirnaState === 'pending';
const isSucceeded = mirnaState === 'succeeded';
const isDrugsEmpty = mirnaNumber === SIZE_OF_EMPTY_ARRAY;
const onAccordionClick = (): void => {
dispatch(displayMirnaList());
};
return (
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton variant="non-expandable">
<AccordionItemButton
variant="non-expandable"
onClick={onAccordionClick}
disabled={isPending || isDrugsEmpty}
>
MiRNA
{mirnaState === 'pending' && ' (Loading...)'}
{mirnaState === 'succeeded' && ` (${mirnaNumber})`}
{isPending && ' (Loading...)'}
{isSucceeded && ` (${mirnaNumber})`}
</AccordionItemButton>
</AccordionItemHeading>
</AccordionItem>
......
......@@ -4,6 +4,7 @@ import type { ToolkitStore } from '@reduxjs/toolkit/dist/configureStore';
import { drugFixture } from '@/models/fixtures/drugFixtures';
import drawerReducer, {
closeDrawer,
displayChemicalsList,
displayDrugsList,
displayEntityDetails,
displayGroupedSearchResults,
......@@ -107,6 +108,19 @@ describe('drawer reducer', () => {
expect(stepType).toEqual('drugs');
});
it('should update the store after displayChemicalsList action', async () => {
const { type } = await store.dispatch(displayChemicalsList());
const {
drawerName,
searchDrawerState: { currentStep, stepType },
} = store.getState().drawer;
expect(type).toBe('drawer/displayChemicalsList');
expect(drawerName).toBe('search');
expect(currentStep).toBe(STEP.SECOND);
expect(stepType).toEqual('chemicals');
});
it('should update the store after displayGroupedSearchResults action', async () => {
const { type } = await store.dispatch(displayGroupedSearchResults());
const {
......
......@@ -28,6 +28,18 @@ export const displayDrugsListReducer = (state: DrawerState): void => {
state.searchDrawerState.stepType = 'drugs';
};
export const displayChemicalsListReducer = (state: DrawerState): void => {
state.drawerName = 'search';
state.searchDrawerState.currentStep = STEP.SECOND;
state.searchDrawerState.stepType = 'chemicals';
};
export const displayMirnaListReducer = (state: DrawerState): void => {
state.drawerName = 'search';
state.searchDrawerState.currentStep = STEP.SECOND;
state.searchDrawerState.stepType = 'mirna';
};
export const displayGroupedSearchResultsReducer = (state: DrawerState): void => {
state.searchDrawerState.currentStep = STEP.FIRST;
state.searchDrawerState.stepType = 'none';
......
......@@ -2,9 +2,11 @@ import { DrawerState } from '@/redux/drawer/drawer.types';
import { createSlice } from '@reduxjs/toolkit';
import {
closeDrawerReducer,
displayChemicalsListReducer,
displayDrugsListReducer,
displayEntityDetailsReducer,
displayGroupedSearchResultsReducer,
displayMirnaListReducer,
openDrawerReducer,
openSearchDrawerReducer,
} from './drawer.reducers';
......@@ -27,6 +29,8 @@ const drawerSlice = createSlice({
openSearchDrawer: openSearchDrawerReducer,
closeDrawer: closeDrawerReducer,
displayDrugsList: displayDrugsListReducer,
displayChemicalsList: displayChemicalsListReducer,
displayMirnaList: displayMirnaListReducer,
displayGroupedSearchResults: displayGroupedSearchResultsReducer,
displayEntityDetails: displayEntityDetailsReducer,
},
......@@ -37,6 +41,8 @@ export const {
openSearchDrawer,
closeDrawer,
displayDrugsList,
displayChemicalsList,
displayMirnaList,
displayGroupedSearchResults,
displayEntityDetails,
} = drawerSlice.actions;
......
......@@ -25,6 +25,7 @@ export const AccordionItemButton = ({
disabled={disabled}
className="flex w-full flex-row flex-nowrap justify-between text-sm"
type="button"
data-testid="accordion-item-button"
>
{children}
{ButtonIcon}
......
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