Skip to content

Commit

Permalink
chore: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
usamaidrsk committed Nov 8, 2024
1 parent 8beb011 commit 2a54c88
Show file tree
Hide file tree
Showing 13 changed files with 1,036 additions and 20 deletions.
113 changes: 113 additions & 0 deletions __mocks__/search.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,116 @@ export const mockSearchResults = {
],
},
};

export const mockAdvancedSearchResults = [
{
patientId: 14,
uuid: 'e46dfea6-f32d-4b61-bc7d-e79fd35332a4',
identifiers: [
{
identifier: '100008E',
identifierType: {
uuid: '05a29f94-c0ed-11e2-94be-8c13b969e334',
display: 'OpenMRS ID',
},
},
],
display: '100008E - Joshua Johnson',
patientIdentifier: {
uuid: '1e6c2da6-f63f-4ea5-a595-ded69df9f882',
identifier: '100008E',
},
person: {
gender: 'M',
age: 5,
birthdate: '2019-09-25T00:00:00.000+0000',
birthdateEstimated: false,
personName: {
display: 'Joshua Johnson',
givenName: 'Joshua',
familyName: 'Johnson',
},
addresses: [
{
address1: 'Address16442',
cityVillage: 'City6442',
stateProvince: 'State6442',
country: 'Country6442',
postalCode: '20839',
preferred: true,
},
],
dead: false,
deathDate: null,
},
attributes: [
{
value: '0785434125',
attributeType: {
uuid: '14d4f066-15f5-102d-96e4-000c29c2a5d7',
display: 'Telephone Number',
},
},
],
},
{
patientId: 42,
uuid: 'a83747aa-3041-489a-a112-1c024582c83d',
identifiers: [
{
identifier: '100016H',
identifierType: {
uuid: '05a29f94-c0ed-11e2-94be-8c13b969e334',
display: 'OpenMRS ID',
},
},
],
display: '100016H - Joseph Davis',
patientIdentifier: {
uuid: '0ac0a9a0-b040-4c0a-9c35-c4e0bb52a570',
identifier: '100016H',
},
person: {
gender: 'M',
age: 30,
birthdate: '1994-10-13T00:00:00.000+0000',
birthdateEstimated: false,
personName: {
display: 'Joseph Davis',
givenName: 'Joseph',
familyName: 'Davis',
},
addresses: [
{
address1: 'Address19050',
cityVillage: 'City9050',
stateProvince: 'State9050',
country: 'Country9050',
postalCode: '46548',
preferred: true,
},
],
dead: false,
deathDate: null,
},
attributes: [
{
value: {
uuid: '1ce1b7d4-c865-4178-82b0-5932e51503d6',
display: 'Community Outreach',
links: [
{
rel: 'self',
uri: 'http://dev3.openmrs.org/openmrs/ws/rest/v1/location/1ce1b7d4-c865-4178-82b0-5932e51503d6',
resourceAlias: 'location',
},
],
},
attributeType: {
uuid: '8d87236c-c2cc-11de-8d13-0010c6dffd0f',
display: 'Health Center',
},
},
],
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const AdvancedPatientSearchComponent: React.FC<AdvancedPatientSearchProps> = ({

// Age filter
if (filters.age) {
if (patient.person.age !== filters.age) {
if (Number(patient.person.age) !== Number(filters.age)) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import React from 'react';
import { render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { useInfinitePatientSearch } from '../patient-search.resource';
import AdvancedPatientSearchComponent from './advanced-patient-search.component';
import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
import { configSchema, type PatientSearchConfig } from '../config-schema';
import { type PatientSearchResponse } from '../types';
import { mockAdvancedSearchResults } from '__mocks__';
import { PatientSearchContext } from '../patient-search-context';
import { usePersonAttributeType } from './refine-search/person-attributes.resource';

const mockUseConfig = jest.mocked(useConfig<PatientSearchConfig>);
const mockUseInfinitePatientSearch = jest.mocked(useInfinitePatientSearch);
const mockUsePersonAttributeType = jest.mocked(usePersonAttributeType);

jest.mock('../patient-search.resource', () => ({
useInfinitePatientSearch: jest.fn(),
}));

jest.mock('./refine-search/person-attributes.resource', () => ({
usePersonAttributeType: jest.fn(),
}));

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: jest.fn(() => ({
page: 1,
})),
useLocation: jest.fn(),
useSearchParams: jest.fn(() => [
{
get: jest.fn(() => 'Jos'),
},
]),
}));

const mockPatientActionContextValue = {
nonNavigationSelectPatientAction: jest.fn(),
selectPatientAction: jest.fn(),
};

const mockSearchResults: PatientSearchResponse = {
isValidating: false,
totalResults: 2,
data: mockAdvancedSearchResults as unknown as PatientSearchResponse['data'],
currentPage: 1,
setPage: jest.fn(),
hasMore: false,
isLoading: false,
fetchError: null,
};

const Wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
<PatientSearchContext.Provider value={mockPatientActionContextValue}>{children}</PatientSearchContext.Provider>
);

describe('AdvancedPatientSearchComponent', () => {
const user = userEvent.setup();

beforeEach(() => {
mockUseInfinitePatientSearch.mockReturnValue(mockSearchResults);
mockUseConfig.mockReturnValue({
...getDefaultsFromConfigSchema(configSchema),
search: {
disableTabletSearchOnKeyUp: false,
showRecentlySearchedPatients: false,
searchFields: {
fields: {
gender: {
enabled: true,
label: 'Sex',
},
dateOfBirth: {
enabled: true,
label: 'Date of Birth',
},
age: {
enabled: true,
label: 'Age',
min: 0,
},
postcode: {
enabled: true,
label: 'Postcode',
},
},
personAttributes: [
{
label: 'Phone Number',
attributeTypeUuid: '14d4f066-15f5-102d-96e4-000c29c2a5d7',
},
],
},
} as PatientSearchConfig['search'],
});
mockUsePersonAttributeType.mockReturnValue({
isLoading: false,
error: null,
data: {
format: 'java.lang.String',
uuid: '14d4f066-15f5-102d-96e4-000c29c2a5d7',
display: 'Telephone Number',
},
});
});

const renderComponent = (props = {}) => {
return render(
<Wrapper>
<AdvancedPatientSearchComponent query="Jos" {...props} />
</Wrapper>,
);
};

it('renders without crashing', () => {
renderComponent();
expect(screen.getByText('Refine search')).toBeInTheDocument();
});

it('displays search results correctly', () => {
renderComponent();
expect(screen.getByText(/2 search result/)).toBeInTheDocument();
});

describe('Filtering', () => {
it('filters by gender correctly', async () => {
renderComponent();

await user.click(screen.getByRole('tab', { name: /female/i }));
await user.click(screen.getByRole('button', { name: /apply/i }));

// expect to have 0 search result
expect(screen.getByText(/0 search result/)).toBeInTheDocument();
});

it('filters by age correctly', async () => {
renderComponent();

// Set age filter
const ageInput = screen.getByRole('spinbutton', { name: /age/i });
await user.type(ageInput, '30');
await user.click(screen.getByRole('button', { name: /apply/i }));

// expect one patient Joseph Davis
const patientBanners = screen.getAllByRole('banner');
expect(patientBanners).toHaveLength(1);
expect(within(patientBanners[0]).getByText(/Joseph Davis/i)).toBeInTheDocument();
expect(within(patientBanners[0]).getByText(/30/)).toBeInTheDocument();
});

it('filters by postcode correctly', async () => {
renderComponent();

// Set postcode filter
const postcodeInput = screen.getByRole('textbox', { name: /postcode/i });
await user.type(postcodeInput, '46548');
await user.click(screen.getByRole('button', { name: /apply/i }));

// expect one patient Joseph Davis

const patientBanners = screen.getAllByRole('banner');
expect(patientBanners).toHaveLength(1);
expect(within(patientBanners[0]).getByText(/Joseph Davis/i)).toBeInTheDocument();
});

it('filters by person attribute correctly', async () => {
renderComponent();

// Set phone number attribute filter
const phoneInput = screen.getByLabelText(/phone number/i);
await user.type(phoneInput, '0785434125');
await user.click(screen.getByRole('button', { name: /apply/i }));

// expect one patient Joshua Johnson

const patientBanners = screen.getAllByRole('banner');
expect(patientBanners).toHaveLength(1);
expect(within(patientBanners[0]).getByText(/Joshua Johnson/)).toBeInTheDocument();
});

it('combines multiple filters correctly', async () => {
renderComponent();

// Set multiple filters
await user.click(screen.getByRole('tab', { name: /any/i }));
const ageInput = screen.getByRole('spinbutton', { name: /age/i });
await user.type(ageInput, '5');
await user.click(screen.getByRole('button', { name: /apply/i }));

// expect one patient Joshua Johnson

const patientBanners = screen.getAllByRole('banner');
expect(patientBanners).toHaveLength(1);
expect(within(patientBanners[0]).getByText(/Joshua Johnson/)).toBeInTheDocument();
});

it('resets filters correctly', async () => {
renderComponent();

// Set a filter
await user.click(screen.getByRole('tab', { name: /female/i }));
await user.click(screen.getByRole('button', { name: /apply/i }));

// Reset filters
await user.click(screen.getByRole('button', { name: /reset fields/i }));

// expects all search results 2 patients
const patientBanners = screen.getAllByRole('banner');
expect(patientBanners).toHaveLength(2);
});
});

describe('Layout', () => {
it('renders in desktop layout by default', () => {
renderComponent();
const container = screen.getByText(/Refine search/i);
expect(container).toBeInTheDocument();
});

it('renders in tablet layout when specified', () => {
renderComponent({ inTabletOrOverlay: true });
const container = screen.getByText(/Refine search/i);
expect(container).toBeInTheDocument();
});
});
});
Loading

0 comments on commit 2a54c88

Please sign in to comment.