Skip to content

Commit

Permalink
(fix) - O3-4017 - Ward App - ward view should refresh data after acti…
Browse files Browse the repository at this point in the history
…ons on patients (#1327)

* (fix) - O3-4017 - Ward App - ward view should refresh data after actions on patients

* clean up tests

* update esm-framework
  • Loading branch information
chibongho authored Oct 4, 2024
1 parent a18801b commit 74a8af6
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 371 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,6 @@ results.xml
moduleName

.env

# vim
.swp
Binary file removed packages/esm-ward-app/.fetch.swp
Binary file not shown.
54 changes: 54 additions & 0 deletions packages/esm-ward-app/mock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { mockAdmissionLocation, mockInpatientAdmissions, mockInpatientRequest } from '__mocks__';
import { useAdmissionLocation } from './src/hooks/useAdmissionLocation';
import { useInpatientAdmission } from './src/hooks/useInpatientAdmission';
import { createAndGetWardPatientGrouping } from './src/ward-view/ward-view.resource';
import { useInpatientRequest } from './src/hooks/useInpatientRequest';
import { useWardPatientGrouping } from './src/hooks/useWardPatientGrouping';

jest.mock('./src/hooks/useAdmissionLocation', () => ({
useAdmissionLocation: jest.fn(),
}));
jest.mock('./src/hooks/useInpatientAdmission', () => ({
useInpatientAdmission: jest.fn(),
}));
jest.mock('./src/hooks/useInpatientRequest', () => ({
useInpatientRequest: jest.fn(),
}));
jest.mock('./src/hooks/useWardPatientGrouping', () => ({
useWardPatientGrouping: jest.fn(),
}));
const mockAdmissionLocationResponse = jest.mocked(useAdmissionLocation).mockReturnValue({
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
admissionLocation: mockAdmissionLocation,
});
const mockInpatientAdmissionResponse = jest.mocked(useInpatientAdmission).mockReturnValue({
data: mockInpatientAdmissions,
hasMore: false,
loadMore: jest.fn(),
isValidating: false,
isLoading: false,
error: undefined,
mutate: jest.fn(),
totalCount: mockInpatientAdmissions.length,
});

const mockInpatientRequestResponse = jest.mocked(useInpatientRequest).mockReturnValue({
inpatientRequests: mockInpatientRequest,
hasMore: false,
loadMore: jest.fn(),
isValidating: false,
isLoading: false,
error: undefined,
mutate: jest.fn(),
totalCount: mockInpatientRequest.length,
});

export const mockWardPatientGroupDetails = jest.mocked(useWardPatientGrouping).mockReturnValue({
admissionLocationResponse: mockAdmissionLocationResponse(),
inpatientAdmissionResponse: mockInpatientAdmissionResponse(),
inpatientRequestResponse: mockInpatientRequestResponse(),
...createAndGetWardPatientGrouping(mockInpatientAdmissions, mockAdmissionLocation, mockInpatientRequest),
});
3 changes: 1 addition & 2 deletions packages/esm-ward-app/src/hooks/useBeds.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { openmrsFetch, restBaseUrl, useOpenmrsFetchAll } from '@openmrs/esm-framework';
import useSWR from 'swr';
import { restBaseUrl, useOpenmrsFetchAll } from '@openmrs/esm-framework';
import { type Bed, type BedStatus } from '../types/index';

interface BedSearchCriteria {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import { Movement } from '@carbon/react/icons';
import { Button, InlineNotification } from '@carbon/react';
import { ArrowRightIcon, isDesktop, launchWorkspace, useLayoutType } from '@openmrs/esm-framework';
import { useInpatientRequest } from '../hooks/useInpatientRequest';
import { Movement } from '@carbon/react/icons';
import { ArrowRightIcon, isDesktop, launchWorkspace, useAppContext, useLayoutType } from '@openmrs/esm-framework';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { type WardPatientGroupDetails } from '../types';
import styles from './admission-requests.scss';

const AdmissionRequestsBar = () => {
const { inpatientRequests, isLoading, error } = useInpatientRequest(['ADMIT', 'TRANSFER']);
const wardPatientGrouping = useAppContext<WardPatientGroupDetails>('ward-patients-group');
const { inpatientRequests, isLoading, error } = wardPatientGrouping?.inpatientRequestResponse ?? {};
const { t } = useTranslation();
const layout = useLayoutType();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,23 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import { launchWorkspace, useAppContext } from '@openmrs/esm-framework';
import { screen } from '@testing-library/react';
import { launchWorkspace } from '@openmrs/esm-framework';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { renderWithSwr } from 'tools';
import { mockInpatientRequest } from '__mocks__';
import { useInpatientRequest } from '../hooks/useInpatientRequest';
import { mockWardPatientGroupDetails } from '../../mock';
import AdmissionRequestsBar from './admission-requests-bar.component';

jest.mock('../hooks/useInpatientRequest', () => ({
useInpatientRequest: jest.fn(),
}));

const mockInpatientRequestResponse = {
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
inpatientRequests: [mockInpatientRequest],
};

jest.mocked(useInpatientRequest).mockReturnValue(mockInpatientRequestResponse);
jest.mocked(useAppContext).mockReturnValue(mockWardPatientGroupDetails());

describe('Admission Requests Button', () => {
it('call launch workspace when clicked on manage button', async () => {
it('should launch workspace when clicked on manage button', async () => {
const user = userEvent.setup();
renderWithSwr(<AdmissionRequestsBar />);

await user.click(screen.getByRole('button', { name: /manage/i }));
expect(launchWorkspace).toHaveBeenCalled();
});

it('there should be one admission request', () => {
it('should have one admission request', () => {
renderWithSwr(<AdmissionRequestsBar />);

expect(screen.getByText('1 admission request')).toBeInTheDocument();
Expand Down
50 changes: 7 additions & 43 deletions packages/esm-ward-app/src/ward-view-header/ward-metrics.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useInpatientAdmission } from '../hooks/useInpatientAdmission';
import useWardLocation from '../hooks/useWardLocation';
import { screen } from '@testing-library/react';
import { useAppContext } from '@openmrs/esm-framework';
import { mockWardPatientGroupDetails } from '../../mock';

const wardMetrics = [
{ name: 'patients', key: 'patients', defaultTranslation: 'Patients' },
Expand All @@ -35,66 +36,29 @@ jest.mock('../hooks/useWardLocation', () =>
}),
);

const mockUseWardLocation = jest.mocked(useWardLocation);

jest.mock('../hooks/useBeds', () => ({
useBeds: jest.fn(),
}));

jest.mock('../hooks/useAdmissionLocation', () => ({
useAdmissionLocation: jest.fn(),
}));
jest.mock('../hooks/useInpatientAdmission', () => ({
useInpatientAdmission: jest.fn(),
}));

jest.mock('../hooks/useInpatientRequest', () => ({
useInpatientRequest: jest.fn(),
}));

jest.mocked(useBeds).mockReturnValue({
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
beds: mockWardBeds,
totalCount: mockWardBeds.length,
hasMore: false,
loadMore: jest.fn(),
});

const mockAdmissionLocationResponse = jest.mocked(useAdmissionLocation).mockReturnValue({
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
admissionLocation: mockAdmissionLocation,
});
const mockInpatientAdmissionResponse = jest.mocked(useInpatientAdmission).mockReturnValue({
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
inpatientAdmissions: mockInpatientAdmissions,
});

const inpatientAdmissionsUuidMap = getInpatientAdmissionsUuidMap(mockInpatientAdmissions);
const mockWardPatientGroupDetails = {
admissionLocationResponse: mockAdmissionLocationResponse(),
inpatientAdmissionResponse: mockInpatientAdmissionResponse(),
...createAndGetWardPatientGrouping(mockInpatientAdmissions, mockAdmissionLocation, mockInpatientRequest),
};
jest.mocked(useAppContext).mockReturnValue(mockWardPatientGroupDetails);
jest.mocked(useAppContext).mockReturnValue(mockWardPatientGroupDetails());
describe('Ward Metrics', () => {
it('Should display metrics of in the ward ', () => {
mockUseWardLocation.mockReturnValueOnce({
location: null,
isLoadingLocation: false,
errorFetchingLocation: null,
invalidLocation: true,
});
const bedMetrics = getWardMetrics(mockWardBeds, mockWardPatientGroupDetails);
const bedMetrics = getWardMetrics(mockWardBeds, mockWardPatientGroupDetails());
renderWithSwr(<WardMetrics />);
for (let [key, value] of Object.entries(bedMetrics)) {
const fieldName = wardMetrics.find((metric) => metric.name == key)?.defaultTranslation;
expect(screen.getByText(fieldName)).toBeInTheDocument();
expect(screen.getByText(fieldName!)).toBeInTheDocument();
}
});
});
3 changes: 2 additions & 1 deletion packages/esm-ward-app/src/ward-view/ward-view.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const WardViewMain = () => {
hasMore: hasMoreInpatientAdmissions,
loadMore: loadMoreInpatientAdmissions,
} = wardPatientsGrouping?.inpatientAdmissionResponse ?? {};
const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module');

const scrollToLoadMoreTrigger = useRef<HTMLDivElement>(null);
useEffect(
Expand Down Expand Up @@ -127,7 +128,7 @@ const WardViewMain = () => {
return (
<div className={classNames(styles.wardViewMain, { [styles.verticalTiling]: isVertical })}>
{wardBeds}
{bedLayouts?.length == 0 && (
{bedLayouts?.length == 0 && isBedManagementModuleInstalled && (
<InlineNotification
kind="warning"
lowContrast={true}
Expand Down
90 changes: 15 additions & 75 deletions packages/esm-ward-app/src/ward-view/ward-view.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,16 @@ import {
getDefaultsFromConfigSchema,
useAppContext,
useConfig,
useFeatureFlag
useFeatureFlag,
} from '@openmrs/esm-framework';
import { screen } from '@testing-library/react';
import { mockAdmissionLocation, mockInpatientAdmissions, mockInpatientRequest } from '__mocks__';
import React from 'react';
import { useParams } from 'react-router-dom';
import { renderWithSwr } from 'tools';
import { mockWardPatientGroupDetails } from '../../mock';
import { configSchema } from '../config-schema';
import { useAdmissionLocation } from '../hooks/useAdmissionLocation';
import { useInpatientAdmission } from '../hooks/useInpatientAdmission';
import { useInpatientRequest } from '../hooks/useInpatientRequest';
import useWardLocation from '../hooks/useWardLocation';
import { useWardPatientGrouping } from '../hooks/useWardPatientGrouping';
import WardView from './ward-view.component';
import { createAndGetWardPatientGrouping } from './ward-view.resource';

jest.mocked(useConfig).mockReturnValue({
...getDefaultsFromConfigSchema<ConfigSchema>(configSchema),
Expand All @@ -42,54 +37,6 @@ jest.mock('react-router-dom', () => ({
}));
const mockUseParams = useParams as jest.Mock;

jest.mock('../hooks/useAdmissionLocation', () => ({
useAdmissionLocation: jest.fn(),
}));
jest.mock('../hooks/useInpatientAdmission', () => ({
useInpatientAdmission: jest.fn(),
}));
jest.mock('../hooks/useInpatientRequest', () => ({
useInpatientRequest: jest.fn(),
}));
jest.mock('../hooks/useWardPatientGrouping', () => ({
useWardPatientGrouping: jest.fn(),
}));
const mockAdmissionLocationResponse = jest.mocked(useAdmissionLocation).mockReturnValue({
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
admissionLocation: mockAdmissionLocation,
});
const mockInpatientAdmissionResponse = jest.mocked(useInpatientAdmission).mockReturnValue({
data: mockInpatientAdmissions,
hasMore: false,
loadMore: jest.fn(),
isValidating: false,
isLoading: false,
error: undefined,
mutate: jest.fn(),
totalCount: 1
});

const mockInpatientRequestResponse = jest.mocked(useInpatientRequest).mockReturnValue({
inpatientRequests: mockInpatientRequest,
hasMore: false,
loadMore: jest.fn(),
isValidating: false,
isLoading: false,
error: undefined,
mutate: jest.fn(),
totalCount: 1
})

const mockWardPatientGroupDetails = jest.mocked(useWardPatientGrouping).mockReturnValue({
admissionLocationResponse: mockAdmissionLocationResponse(),
inpatientAdmissionResponse: mockInpatientAdmissionResponse(),
inpatientRequestResponse: mockInpatientRequestResponse(),
...createAndGetWardPatientGrouping(mockInpatientAdmissions, mockAdmissionLocation, mockInpatientRequest),
});

jest.mocked(useAppContext).mockReturnValue(mockWardPatientGroupDetails());

const intersectionObserverMock = () => ({
Expand All @@ -98,6 +45,8 @@ const intersectionObserverMock = () => ({
window.IntersectionObserver = jest.fn().mockImplementation(intersectionObserverMock);

describe('WardView', () => {
let replacedProperty: jest.ReplaceProperty<any> | null = null;

it('renders the session location when no location provided in URL', () => {
renderWithSwr(<WardView />);
const header = screen.getByRole('heading', { name: 'mock location' });
Expand Down Expand Up @@ -145,38 +94,29 @@ describe('WardView', () => {
expect(invalidText).toBeInTheDocument();
});

it('screen should render warning if backend module installed and no beds configured', () => {
it('should render warning if backend module installed and no beds configured', () => {
// override the default response so that no beds are returned
jest.mocked(useAdmissionLocation).mockReturnValue({
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
admissionLocation: { ...mockAdmissionLocation, bedLayouts: [] },
});
const replacedProperty = jest.replaceProperty(mockWardPatientGroupDetails(), 'bedLayouts', []);
replacedProperty = jest.replaceProperty(mockWardPatientGroupDetails(), 'bedLayouts', []);

mockUseFeatureFlag.mockReturnValueOnce(true);
mockUseFeatureFlag.mockReturnValue(true);

renderWithSwr(<WardView />);
const noBedsConfiguredForThisLocation = screen.queryByText('No beds configured for this location');
expect(noBedsConfiguredForThisLocation).toBeInTheDocument();
replacedProperty.restore();
});

it('screen not should render warning if backend module installed and no beds configured', () => {
it('should not render warning if backend module installed and no beds configured', () => {
// override the default response so that no beds are returned
jest.mocked(useAdmissionLocation).mockReturnValue({
error: undefined,
mutate: jest.fn(),
isValidating: false,
isLoading: false,
admissionLocation: { ...mockAdmissionLocation, bedLayouts: [] },
});
mockUseFeatureFlag.mockReturnValueOnce(false);
replacedProperty = jest.replaceProperty(mockWardPatientGroupDetails(), 'bedLayouts', []);
mockUseFeatureFlag.mockReturnValue(false);

renderWithSwr(<WardView />);
const noBedsConfiguredForThisLocation = screen.queryByText('No beds configured for this location');
expect(noBedsConfiguredForThisLocation).not.toBeInTheDocument();
});

afterEach(() => {
replacedProperty?.restore();
replacedProperty = null;
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { type InpatientRequest } from '../../types';

interface AdmissionRequestsWorkspaceProps {}
const AdmissionRequestsWorkspace: React.FC<AdmissionRequestsWorkspaceProps> = () => {
// note: useAppContext() does not work here for some reason, so we call `useInpatientRequest`
// directly. See: https://openmrs.atlassian.net/browse/O3-4020
const {
inpatientRequests,
isLoading: isLoadingInpatientRequests,
Expand Down
Loading

0 comments on commit 74a8af6

Please sign in to comment.