Skip to content

Commit

Permalink
Improve component test coverage (#29)
Browse files Browse the repository at this point in the history
* Improve component test coverage

* Extend the patient summary test
  • Loading branch information
anjula-sack authored Aug 15, 2023
1 parent d53eff0 commit d8668d9
Show file tree
Hide file tree
Showing 14 changed files with 427 additions and 20 deletions.
28 changes: 14 additions & 14 deletions __mocks__/hiv-summary.mock.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
export const hivSummary = {
summary: {
whoStage: 1,
whoStageDate: 1602766530107,
cd4: "3.0",
whoStageDate: 1602766530107,
cd4: '3.0',
cd4Date: 1602766530107,
cd4Percent: "None",
cd4Percent: 'None',
cd4PercentDate: 1602766530107,
ldlValue: "LDL",
ldlDate: 1602766530107
ldlValue: 'LDL',
ldlDate: 1602766530107,
},
lastEncounter: {
startDate: "11-Jan-2019",
endDate: "",
regimenShortDisplay: "TDF/3TC/DTG",
regimenLine: "Adult first line",
regimenLongDisplay: "Tenofovir / Lamivudine / Dolutegravir",
startDate: '11-Jan-2019',
endDate: '',
regimenShortDisplay: 'TDF/3TC/DTG',
regimenLine: 'Adult first line',
regimenLongDisplay: 'Tenofovir / Lamivudine / Dolutegravir',
changeReasons: [],
regimenUuid: "9fb85385-b4fb-468c-b7c1-22f75834b4b0",
current: true
}
}
regimenUuid: '9fb85385-b4fb-468c-b7c1-22f75834b4b0',
current: true,
},
};
32 changes: 32 additions & 0 deletions __mocks__/patient-summary.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export const mockPatient = {
uuid: '330c0ec6-0ac7-4b86-9c70-29d76f0ae20a',
patientName: 'John Doe',
reportDate: '2023-08-06',
clinicName: 'Example Clinic',
mflCode: '12345',
age: 40,
uniquePatientIdentifier: 'ABC123',
nationalUniquePatientIdentifier: 'XYZ456',
birthDate: '1990-01-01',
gender: 'M',
maritalStatus: 'Married',
weight: '70 kg',
height: '180 cm',
bmi: '24.5',
bloodPressure: '120/80 mmHg',
oxygenSaturation: '98%',
respiratoryRate: '16 breaths per minute',
pulseRate: '72 beats per minute',
familyProtection: 'Intrauterine Device (IUD)',
tbScreeningOutcome: 'Negative',
allVlResults: {
value: [
{ vl: '120', vlDate: '2023-06-01' },
{ vl: '150', vlDate: '2023-07-01' },
],
},
allCd4CountResults: [
{ cd4Count: '300', cd4CountDate: '2023-06-01' },
{ cd4Count: '320', cd4CountDate: '2023-07-01' },
],
};
43 changes: 43 additions & 0 deletions __mocks__/program-summary.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export const mockProgram = {
HIV: {
ldlValue: '100',
ldlDate: '2023-08-06',
cd4: '500',
cd4Date: '2023-08-07',
cd4Percent: '30',
cd4PercentDate: '2023-08-10',
whoStage: 'Stage 2',
whoStageDate: '2023-08-11',
lastEncDetails: {
regimenShortDisplay: 'Regimen ABC',
startDate: '2023-08-01',
},
},
TB: {
tbTreatmentNumber: 'TB-123',
tbDiseaseClassification: 'TB Disease',
tbDiseaseClassificationDate: '2023-08-09',
tbPatientClassification: 'TB Patient',
lastTbEncounter: {
regimenShortDisplay: 'TB Regimen XYZ',
},
},
mchMother: {
hivStatus: 'Positive',
hivStatusDate: '2023-08-13',
onHaart: 'Yes',
onHaartDate: '2023-08-14',
},
mchChild: {
currentProphylaxisUsed: 'Prophylaxis ABC',
currentProphylaxisUsedDate: '2023-08-05',
currentFeedingOption: 'Feeding Option XYZ',
currentFeedingOptionDate: '2023-08-01',
milestonesAttained: 'Milestone 1, Milestone 2',
milestonesAttainedDate: '2023-08-02',
heiOutcome: 'HEI Outcome XYZ',
heiOutcomeDate: '2023-08-20',
hivStatus: 'Negative',
hivStatusDate: '2023-08-21',
},
};
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'@openmrs/esm-framework': '@openmrs/esm-framework/mock',
'^lodash-es/(.*)$': 'lodash/$1',
'^dexie$': require.resolve('dexie'),
'^uuid$': '<rootDir>/node_modules/@openmrs/esm-patient-common-lib/node_modules/uuid/dist/index.js',
},
collectCoverageFrom: [
'**/src/**/*.component.tsx',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import CarePanel from './care-panel.component';
import { mockComponent } from 'react-dom/test-utils';
import { mockPatient } from '../../../../__mocks__/patient-summary.mock';

jest.mock('../program-summary/program-summary.component', () => ({
__esModule: true,
default: () => <div data-testid="mocked-program-summary" />,
}));
jest.mock('../program-enrollment/program-enrollment.component', () => ({
__esModule: true,
default: () => <div data-testid="mocked-program-enrollment" />,
}));

const mockPatientUuid = mockPatient.uuid;

jest.mock('@carbon/react', () => ({
StructuredListSkeleton: () => <div data-testid="mocked-structured-list-skeleton" />,
ContentSwitcher: ({ children }) => <div data-testid="mocked-content-switcher">{children}</div>,
Switch: ({ text }) => <button>{text}</button>,
InlineLoading: () => <div data-testid="mocked-inline-loading" />,
}));

describe('CarePanel Component', () => {
it('renders without crashing', () => {
jest.spyOn(require('../hooks/useEnrollmentHistory'), 'useEnrollmentHistory').mockReturnValue({
data: [{ patientUuid: mockPatientUuid }],
isLoading: false,
isError: false,
});
render(<CarePanel patientUuid={mockPatientUuid} formEntrySub={jest.fn()} launchPatientWorkspace={jest.fn()} />);
expect(screen.getByText('Care Panel')).toBeInTheDocument();
});

it('displays loading skeleton when isLoading is true', () => {
jest.spyOn(require('../hooks/useEnrollmentHistory'), 'useEnrollmentHistory').mockReturnValue({
data: [],
isLoading: true,
isError: false,
});

render(<CarePanel patientUuid={mockPatientUuid} formEntrySub={jest.fn()} launchPatientWorkspace={jest.fn()} />);

expect(screen.getByTestId('mocked-structured-list-skeleton')).toBeInTheDocument();
expect(screen.queryByTestId('mocked-program-summary')).not.toBeInTheDocument();
expect(screen.queryByTestId('mocked-program-enrollment')).not.toBeInTheDocument();
});

it('displays error message when isError is true', () => {
jest.spyOn(require('../hooks/useEnrollmentHistory'), 'useEnrollmentHistory').mockReturnValue({
data: [],
isLoading: false,
isError: true,
});

render(<CarePanel patientUuid={mockPatientUuid} formEntrySub={jest.fn()} launchPatientWorkspace={jest.fn()} />);

expect(screen.getByText('Error loading program enrollments')).toBeInTheDocument();
expect(screen.queryByTestId('mocked-structured-list-skeleton')).not.toBeInTheDocument();
expect(screen.queryByTestId('mocked-program-summary')).not.toBeInTheDocument();
expect(screen.queryByTestId('mocked-program-enrollment')).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Tile, StructuredListSkeleton, ContentSwitcher, Switch, InlineLoading } from '@carbon/react';
import { StructuredListSkeleton, ContentSwitcher, Switch, InlineLoading } from '@carbon/react';
import styles from './care-panel.scss';
import { useEnrollmentHistory } from '../hooks/useEnrollmentHistory';
import ProgramSummary from '../program-summary/program-summary.component';
import ProgramEnrollment from '../program-enrollment/program-enrollment.component';
import PatientSummary from '../patient-summary/patient-summary.component';
import { CardHeader } from '@openmrs/esm-patient-common-lib';

interface CarePanelProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import PatientSummary from './patient-summary.component';
import { useConfig } from '@openmrs/esm-framework';
import { mockPatient } from '../../../../__mocks__/patient-summary.mock';

const mockUseConfig = useConfig as jest.Mock;

describe('PatientSummary', () => {
it('renders skeleton loader when loading', () => {
jest.spyOn(require('../hooks/usePatientSummary'), 'usePatientSummary').mockReturnValue({
data: null,
isError: false,
isLoading: true,
});

render(<PatientSummary patientUuid={mockPatient.uuid} />);
const skeletonLoader = screen.getByRole('progressbar');
expect(skeletonLoader).toBeInTheDocument();
});

it('renders error message when data retrieval fails', () => {
jest.spyOn(require('../hooks/usePatientSummary'), 'usePatientSummary').mockReturnValue({
data: null,
isError: true,
isLoading: false,
});

render(<PatientSummary patientUuid={mockPatient.uuid} />);
const errorMessage = screen.getByText('Error loading patient summary');
expect(errorMessage).toBeInTheDocument();
});

it('renders patient summary data when loaded', () => {
jest.spyOn(require('../hooks/usePatientSummary'), 'usePatientSummary').mockReturnValue({
data: mockPatient,
isError: false,
isLoading: false,
});

render(<PatientSummary patientUuid={mockPatient.uuid} />);
expect(screen.getByText(mockPatient.patientName)).toBeInTheDocument();
expect(screen.getByText(mockPatient.birthDate)).toBeInTheDocument();
expect(screen.getByText(mockPatient.reportDate)).toBeInTheDocument();
expect(screen.getByText(mockPatient.age)).toBeInTheDocument();
expect(screen.getByText(mockPatient.maritalStatus)).toBeInTheDocument();
expect(screen.getByText(mockPatient.mflCode)).toBeInTheDocument();
expect(screen.getByText(mockPatient.clinicName)).toBeInTheDocument();
expect(screen.getByText(mockPatient.nationalUniquePatientIdentifier)).toBeInTheDocument();
expect(screen.getByText(mockPatient.weight)).toBeInTheDocument();
expect(screen.getByText(mockPatient.height)).toBeInTheDocument();
expect(screen.getByText(mockPatient.bmi)).toBeInTheDocument();
expect(screen.getByText(mockPatient.bloodPressure)).toBeInTheDocument();
expect(screen.getByText(mockPatient.oxygenSaturation)).toBeInTheDocument();
expect(screen.getByText(mockPatient.pulseRate)).toBeInTheDocument();
expect(screen.getByText(mockPatient.familyProtection)).toBeInTheDocument();
expect(screen.getByText(mockPatient.respiratoryRate)).toBeInTheDocument();
expect(screen.getByText(mockPatient.tbScreeningOutcome)).toBeInTheDocument();
// TODO: Extend the test to check all the values
});

it('triggers print when print button is clicked', async () => {
jest.spyOn(require('../hooks/usePatientSummary'), 'usePatientSummary').mockReturnValue({
data: mockPatient,
isError: false,
isLoading: false,
});
const printFunction = jest.fn();
const useReactToPrintSpy = jest.spyOn(require('react-to-print'), 'useReactToPrint');

useReactToPrintSpy.mockReturnValue(printFunction);
mockUseConfig.mockReturnValue({ logo: {} });

render(<PatientSummary patientUuid={mockPatient.uuid} />);
const printButton = screen.getByText('Print', { exact: true });

act(() => {
fireEvent.click(printButton);
});

await waitFor(() => {
expect(printFunction).toHaveBeenCalledTimes(1);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useRef, useState } from 'react';
import styles from './patient-summary.scss';
import { useTranslation } from 'react-i18next';
import { useLayoutType, useSession } from '@openmrs/esm-framework';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import ProgramEnrollment, { ProgramEnrollmentProps } from './program-enrollment.component';

describe('ProgramEnrollment Component', () => {
const mockProps: ProgramEnrollmentProps = {
patientUuid: 'patient-123',
programName: 'HIV Program',
data: [
{
status: 'Active',
programName: 'HIV Program',
data: [
{
dateEnrolled: '2023-08-06',
programName: 'HIV',
whoStage: 'Stage 2',
entryPoint: 'OPD',
},
],
},
],
formEntrySub: jest.fn(),
launchPatientWorkspace: jest.fn(),
};

it('displays active program enrollment details correctly', () => {
render(<ProgramEnrollment {...mockProps} />);

expect(screen.getByText(/Current enrollment details/i)).toBeInTheDocument();
expect(screen.getByText(/HIV program/i)).toBeInTheDocument();
expect(screen.getByText(/Edit/i)).toBeInTheDocument();
expect(screen.getByText(/Discontinue/i)).toBeInTheDocument();
expect(screen.getByText(/enrolled/i)).toBeInTheDocument();
expect(screen.getByText(/2023-08-06/i)).toBeInTheDocument();
expect(screen.getByText(/WHO Stage/i)).toBeInTheDocument();
expect(screen.getByText(/Stage 2/i)).toBeInTheDocument();
expect(screen.getByText(/Entry Point/i)).toBeInTheDocument();
expect(screen.getByText(/OPD/i)).toBeInTheDocument();
});

it('displays inactive program enrollment details correctly', () => {
render(
<ProgramEnrollment
{...mockProps}
data={[
{
status: 'Inactive',
programName: 'HIV Program',
data: [
{
dateCompleted: '2023-08-06',
programName: 'HIV',
whoStage: 'Stage 2',
entryPoint: 'IPD',
},
],
},
]}
/>,
);

expect(screen.getByText(/Historic enrollment/i)).toBeInTheDocument();
expect(screen.getByText(/Edit/i)).toBeInTheDocument();
expect(screen.getByText(/Completed/i)).toBeInTheDocument();
expect(screen.getByText(/2023-08-06/i)).toBeInTheDocument();
expect(screen.getByText(/WHO Stage/i)).toBeInTheDocument();
expect(screen.getByText(/Stage 2/i)).toBeInTheDocument();
expect(screen.getByText(/Entry Point/i)).toBeInTheDocument();
expect(screen.getByText(/IPD/i)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Edit, TrashCan, Add } from '@carbon/react/icons';
import { useLayoutType, useVisit } from '@openmrs/esm-framework';
import isNull from 'lodash-es/isNull';
import { ProgramType } from '../types';
interface ProgramEnrollmentProps {
export interface ProgramEnrollmentProps {
patientUuid: string;
programName: string;
data: Array<any>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useLayoutType } from '@openmrs/esm-framework';
import { StructuredListSkeleton } from '@carbon/react';
import { ProgramType } from '../types';
interface ProgramSummaryProps {
export interface ProgramSummaryProps {
patientUuid: string;
programName: string;
}
Expand Down
Loading

0 comments on commit d8668d9

Please sign in to comment.