Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

feat(patients): adds ability to view patient #1691

Merged
merged 3 commits into from
Jan 2, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
feat(patients): add ability to view a patient
  • Loading branch information
jackcmeyer committed Jan 2, 2020
commit a73e7f086b4cd7bb22f7963ed3e3345494c590f4
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@types/react-redux": "^7.1.5",
"@types/react-router": "~5.1.2",
"@types/react-router-dom": "~5.1.0",
"@types/redux-mock-store": "~1.0.1",
"@typescript-eslint/eslint-plugin": "~2.14.0",
"@typescript-eslint/parser": "~2.14.0",
"commitizen": "~4.0.3",
Expand All @@ -82,6 +83,7 @@
"lint-staged": "~9.5.0",
"memdown": "^5.1.0",
"prettier": "~1.19.1",
"redux-mock-store": "~1.5.4",
"semantic-release": "~15.14.0",
"ts-jest": "^24.2.0"
},
Expand Down
3 changes: 3 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"givenName": "Given Name",
"familyName": "Family Name",
"dateOfBirth": "Date of Birth",
"approximateDateOfBirth": "Approximate Date of Birth",
"age": "Age",
"approximateAge": "Approximate Age",
"placeOfBirth": "Place of Birth",
"sex": "Sex",
"phoneNumber": "Phone Number",
Expand Down
49 changes: 46 additions & 3 deletions src/__tests__/containers/HospitalRun.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,28 @@ import React from 'react'
import { mount } from 'enzyme'
import { MemoryRouter } from 'react-router'
import { Provider } from 'react-redux'
import HospitalRun from '../../containers/HospitalRun'
import { mocked } from 'ts-jest/utils'
import thunk from 'redux-thunk'
import configureMockStore from 'redux-mock-store'
import NewPatient from '../../patients/new/NewPatient'
import store from '../../store'
import ViewPatient from '../../patients/view/ViewPatient'
import PatientRepository from '../../clients/db/PatientRepository'
import Patient from '../../model/Patient'
import HospitalRun from '../../containers/HospitalRun'
import Permissions from '../../util/Permissions'

const mockStore = configureMockStore([thunk])

describe('HospitalRun', () => {
describe('routing', () => {
it('should render the new patient screen when /patients/new is accessed', () => {
const wrapper = mount(
<Provider store={store}>
<Provider
store={mockStore({
title: 'test',
user: { permissions: [Permissions.WritePatients] },
})}
>
<MemoryRouter initialEntries={['/patients/new']}>
<HospitalRun />
</MemoryRouter>
Expand All @@ -20,5 +33,35 @@ describe('HospitalRun', () => {

expect(wrapper.find(NewPatient)).toHaveLength(1)
})

it('should render the view patient screen when /patients/:id is accessed', async () => {
jest.spyOn(PatientRepository, 'find')
const mockedPatientRepository = mocked(PatientRepository, true)
const patient = {
id: '123',
prefix: 'test',
givenName: 'test',
familyName: 'test',
suffix: 'test',
} as Patient

mockedPatientRepository.find.mockResolvedValue(patient)

const wrapper = mount(
<Provider
store={mockStore({
title: 'test',
user: { permissions: [Permissions.ReadPatients] },
patient,
})}
>
<MemoryRouter initialEntries={['/patients/123']}>
<HospitalRun />
</MemoryRouter>
</Provider>,
)

expect(wrapper.find(ViewPatient)).toHaveLength(1)
})
})
})
105 changes: 105 additions & 0 deletions src/__tests__/patients/patient-slice.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { AnyAction } from 'redux'
import { mocked } from 'ts-jest/utils'
import patient, {
getPatientStart,
getPatientSuccess,
fetchPatient,
} from '../../patients/patient-slice'
import Patient from '../../model/Patient'
import PatientRepository from '../../clients/db/PatientRepository'

describe('patients slice', () => {
beforeEach(() => {
jest.resetAllMocks()
})

describe('patients reducer', () => {
it('should create the proper initial state with empty patients array', () => {
const patientStore = patient(undefined, {} as AnyAction)
expect(patientStore.isLoading).toBeFalsy()
expect(patientStore.patient).toEqual({
id: '',
rev: '',
sex: '',
dateOfBirth: '',
})
})

it('should handle the GET_PATIENT_START action', () => {
const patientStore = patient(undefined, {
type: getPatientStart.type,
})

expect(patientStore.isLoading).toBeTruthy()
})

it('should handle the GET_PATIENT_SUCCESS actions', () => {
const expectedPatient = {
id: '123',
rev: '123',
sex: 'male',
dateOfBirth: new Date().toISOString(),
giveName: 'test',
} as Patient
const patientStore = patient(undefined, {
type: getPatientSuccess.type,
payload: {
...expectedPatient,
},
})

expect(patientStore.isLoading).toBeFalsy()
expect(patientStore.patient).toEqual(expectedPatient)
})
})

describe('fetchPatient()', () => {
it('should dispatch the GET_PATIENT_START action', async () => {
const dispatch = jest.fn()
const getState = jest.fn()
jest.spyOn(PatientRepository, 'find')
const expectedPatientId = '12345'
const expectedPatient = { id: expectedPatientId } as Patient
const mockedPatientRepository = mocked(PatientRepository, true)
mockedPatientRepository.find.mockResolvedValue(expectedPatient)

await fetchPatient(expectedPatientId)(dispatch, getState, null)

expect(dispatch).toHaveBeenCalledWith({ type: getPatientStart.type })
})

it('should call the PatientRepository find method with the correct patient id', async () => {
const dispatch = jest.fn()
const getState = jest.fn()
jest.spyOn(PatientRepository, 'find')
const expectedPatientId = '12345'
const expectedPatient = { id: expectedPatientId } as Patient
const mockedPatientRepository = mocked(PatientRepository, true)
mockedPatientRepository.find.mockResolvedValue(expectedPatient)
jest.spyOn(PatientRepository, 'find')

await fetchPatient(expectedPatientId)(dispatch, getState, null)

expect(PatientRepository.find).toHaveBeenCalledWith(expectedPatientId)
})

it('should dispatch the GET_PATIENT_SUCCESS action with the correct data', async () => {
const dispatch = jest.fn()
const getState = jest.fn()
jest.spyOn(PatientRepository, 'find')
const expectedPatientId = '12345'
const expectedPatient = { id: expectedPatientId } as Patient
const mockedPatientRepository = mocked(PatientRepository, true)
mockedPatientRepository.find.mockResolvedValue(expectedPatient)

await fetchPatient(expectedPatientId)(dispatch, getState, null)

expect(dispatch).toHaveBeenCalledWith({
type: getPatientSuccess.type,
payload: {
...expectedPatient,
},
})
})
})
})
190 changes: 190 additions & 0 deletions src/__tests__/patients/view/ViewPatient.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import '../../../__mocks__/matchMediaMock'
import React from 'react'
import { Provider } from 'react-redux'
import { mount } from 'enzyme'
import { mocked } from 'ts-jest/utils'
import { act } from 'react-dom/test-utils'
import { MemoryRouter, Route } from 'react-router-dom'
import Patient from '../../../model/Patient'
import PatientRepository from '../../../clients/db/PatientRepository'
import * as titleUtil from '../../../util/useTitle'
import ViewPatient from '../../../patients/view/ViewPatient'
import store from '../../../store'

describe('ViewPatient', () => {
const patient = {
id: '123',
prefix: 'prefix',
givenName: 'givenName',
familyName: 'familyName',
suffix: 'suffix',
sex: 'male',
type: 'charity',
occupation: 'occupation',
preferredLanguage: 'preferredLanguage',
phoneNumber: 'phoneNumber',
email: '[email protected]',
address: 'address',
dateOfBirth: new Date().toISOString(),
} as Patient

const setup = () => {
jest.spyOn(PatientRepository, 'find')
const mockedPatientRepository = mocked(PatientRepository, true)
mockedPatientRepository.find.mockResolvedValue(patient)
jest.mock('react-router-dom', () => ({
useParams: () => ({
id: '123',
}),
}))

const wrapper = mount(
<Provider store={store}>
<MemoryRouter initialEntries={['/patients/123']}>
<Route path="/patients/:id">
<ViewPatient />
</Route>
</MemoryRouter>
</Provider>,
)

wrapper.update()
return wrapper
}

beforeEach(() => {
jest.restoreAllMocks()
})

it('should render a header with the patients given, family, and suffix', async () => {
jest.spyOn(titleUtil, 'default')
await act(async () => {
await setup()
})
expect(titleUtil.default).toHaveBeenCalledWith(
`${patient.givenName} ${patient.familyName} ${patient.suffix}`,
)
})

it('should render the sex select', () => {
const wrapper = setup()

const sexSelect = wrapper.findWhere((w) => w.prop('name') === 'sex')
expect(sexSelect.prop('value')).toEqual(patient.sex)
expect(sexSelect.prop('label')).toEqual('patient.sex')
expect(sexSelect.prop('isEditable')).toBeFalsy()
})

it('should render the patient type select', () => {
const wrapper = setup()

const typeSelect = wrapper.findWhere((w) => w.prop('name') === 'type')
expect(typeSelect.prop('value')).toEqual(patient.type)
expect(typeSelect.prop('label')).toEqual('patient.type')
expect(typeSelect.prop('isEditable')).toBeFalsy()
})

it('should render the age of the patient', () => {
const wrapper = setup()

const ageInput = wrapper.findWhere((w) => w.prop('name') === 'age')
expect(ageInput.prop('value')).toEqual('0')
expect(ageInput.prop('label')).toEqual('patient.age')
expect(ageInput.prop('isEditable')).toBeFalsy()
})

it('should render the date of the birth of the patient', () => {
const wrapper = setup()

const dateOfBirthInput = wrapper.findWhere((w) => w.prop('name') === 'dateOfBirth')
expect(dateOfBirthInput.prop('value')).toEqual(new Date(patient.dateOfBirth))
expect(dateOfBirthInput.prop('label')).toEqual('patient.dateOfBirth')
expect(dateOfBirthInput.prop('isEditable')).toBeFalsy()
})

it('should render the occupation of the patient', () => {
const wrapper = setup()

const dateOfBirthInput = wrapper.findWhere((w) => w.prop('name') === 'occupation')
expect(dateOfBirthInput.prop('value')).toEqual(patient.occupation)
expect(dateOfBirthInput.prop('label')).toEqual('patient.occupation')
expect(dateOfBirthInput.prop('isEditable')).toBeFalsy()
})

it('should render the preferred language of the patient', () => {
const wrapper = setup()

const dateOfBirthInput = wrapper.findWhere((w) => w.prop('name') === 'preferredLanguage')
expect(dateOfBirthInput.prop('value')).toEqual(patient.preferredLanguage)
expect(dateOfBirthInput.prop('label')).toEqual('patient.preferredLanguage')
expect(dateOfBirthInput.prop('isEditable')).toBeFalsy()
})

it('should render the phone number of the patient', () => {
const wrapper = setup()

const dateOfBirthInput = wrapper.findWhere((w) => w.prop('name') === 'phoneNumber')
expect(dateOfBirthInput.prop('value')).toEqual(patient.phoneNumber)
expect(dateOfBirthInput.prop('label')).toEqual('patient.phoneNumber')
expect(dateOfBirthInput.prop('isEditable')).toBeFalsy()
})

it('should render the email of the patient', () => {
const wrapper = setup()

const dateOfBirthInput = wrapper.findWhere((w) => w.prop('name') === 'email')
expect(dateOfBirthInput.prop('value')).toEqual(patient.email)
expect(dateOfBirthInput.prop('label')).toEqual('patient.email')
expect(dateOfBirthInput.prop('isEditable')).toBeFalsy()
})

it('should render the address of the patient', () => {
const wrapper = setup()

const dateOfBirthInput = wrapper.findWhere((w) => w.prop('name') === 'address')
expect(dateOfBirthInput.prop('value')).toEqual(patient.address)
expect(dateOfBirthInput.prop('label')).toEqual('patient.address')
expect(dateOfBirthInput.prop('isEditable')).toBeFalsy()
})

it('should render the age and date of birth as approximate if patient.isApproximateDateOfBirth is true', async () => {
jest.restoreAllMocks()
const patientWithApproximateDob = {
...patient,
isApproximateDateOfBirth: true,
} as Patient
jest.spyOn(PatientRepository, 'find')
const mockedPatientRepository = mocked(PatientRepository, true)
mockedPatientRepository.find.mockResolvedValue(patientWithApproximateDob)
jest.mock('react-router-dom', () => ({
useParams: () => ({
id: '123',
}),
}))

let wrapper: any
await act(async () => {
wrapper = await mount(
<Provider store={store}>
<MemoryRouter initialEntries={['/patients/123']}>
<Route path="/patients/:id">
<ViewPatient />
</Route>
</MemoryRouter>
</Provider>,
)
})

wrapper.update()

const ageInput = wrapper.findWhere((w) => w.prop('name') === 'age')
expect(ageInput.prop('value')).toEqual('0')
expect(ageInput.prop('label')).toEqual('patient.approximateAge')
expect(ageInput.prop('isEditable')).toBeFalsy()

const dateOfBirthInput = wrapper.findWhere((w) => w.prop('name') === 'dateOfBirth')
expect(dateOfBirthInput.prop('value')).toEqual(new Date(patient.dateOfBirth))
expect(dateOfBirthInput.prop('label')).toEqual('patient.approximateDateOfBirth')
expect(dateOfBirthInput.prop('isEditable')).toBeFalsy()
})
})
Loading