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

Commit a2993b8

Browse files
committed
2 parents 55043fa + dddf221 commit a2993b8

17 files changed

+761
-28
lines changed

package.json

+12-12
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
"private": false,
66
"license": "MIT",
77
"dependencies": {
8-
"@hospitalrun/components": "~0.30.2",
8+
"@hospitalrun/components": "~0.30.3",
99
"@reduxjs/toolkit": "~1.2.1",
10-
"@semantic-release/changelog": "~3.0.4",
10+
"@semantic-release/changelog": "~5.0.0",
1111
"@semantic-release/git": "~7.0.16",
12-
"@semantic-release/release-notes-generator": "~7.3.0",
12+
"@semantic-release/release-notes-generator": "~9.0.0",
1313
"@types/pouchdb-find": "~6.3.4",
1414
"bootstrap": "~4.4.1",
1515
"date-fns": "~2.9.0",
16-
"i18next": "~19.0.1",
16+
"i18next": "~19.1.0",
1717
"i18next-browser-languagedetector": "~4.0.1",
1818
"i18next-xhr-backend": "~3.2.2",
1919
"node-sass": "~4.13.0",
@@ -49,14 +49,14 @@
4949
"@commitlint/config-conventional": "~8.3.3",
5050
"@commitlint/core": "~8.3.3",
5151
"@commitlint/prompt": "~8.3.3",
52-
"@semantic-release/changelog": "~3.0.4",
52+
"@semantic-release/changelog": "~5.0.0",
5353
"@semantic-release/commit-analyzer": "~6.3.0",
5454
"@semantic-release/git": "~7.0.16",
5555
"@semantic-release/github": "~5.5.5",
56-
"@semantic-release/release-notes-generator": "~7.3.0",
56+
"@semantic-release/release-notes-generator": "~9.0.0",
5757
"@testing-library/react": "~9.4.0",
5858
"@testing-library/react-hooks": "~3.2.1",
59-
"@types/jest": "~24.9.0",
59+
"@types/jest": "~25.1.0",
6060
"@types/node": "~13.5.0",
6161
"@types/pouchdb": "~6.4.0",
6262
"@types/react": "~16.9.17",
@@ -65,19 +65,19 @@
6565
"@types/react-router": "~5.1.2",
6666
"@types/react-router-dom": "~5.1.0",
6767
"@types/redux-mock-store": "~1.0.1",
68-
"@typescript-eslint/eslint-plugin": "~2.17.0",
69-
"@typescript-eslint/parser": "~2.17.0",
68+
"@typescript-eslint/eslint-plugin": "~2.18.0",
69+
"@typescript-eslint/parser": "~2.18.0",
7070
"commitizen": "~4.0.3",
7171
"commitlint-config-cz": "~0.12.1",
7272
"coveralls": "~3.0.9",
73-
"cross-env": "~6.0.3",
74-
"cz-conventional-changelog": "~3.0.2",
73+
"cross-env": "~7.0.0",
74+
"cz-conventional-changelog": "~3.1.0",
7575
"dateformat": "~3.0.3",
7676
"enzyme": "~3.11.0",
7777
"enzyme-adapter-react-16": "~1.15.2",
7878
"eslint": "~6.8.0",
7979
"eslint-config-airbnb": "~18.0.1",
80-
"eslint-config-prettier": "~6.9.0",
80+
"eslint-config-prettier": "~6.10.0",
8181
"eslint-plugin-import": "~2.20.0",
8282
"eslint-plugin-jest": "~23.6.0",
8383
"eslint-plugin-jsx-a11y": "~6.2.3",

src/__tests__/clients/db/PatientRepository.test.ts

+52
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { patients } from 'config/pouchdb'
22
import PatientRepository from 'clients/db/PatientRepository'
33
import Patient from 'model/Patient'
44
import { fromUnixTime } from 'date-fns'
5+
import { updatePatientStart } from 'patients/patient-slice'
56

67
describe('patient repository', () => {
78
describe('find', () => {
@@ -105,6 +106,57 @@ describe('patient repository', () => {
105106
})
106107
})
107108

109+
describe('saveOrUpdate', () => {
110+
it('should save the patient if an id was not on the entity', async () => {
111+
const newPatient = await PatientRepository.saveOrUpdate({
112+
fullName: 'test1 test1',
113+
} as Patient)
114+
115+
expect(newPatient.id).toBeDefined()
116+
117+
await patients.remove(await patients.get(newPatient.id))
118+
})
119+
120+
it('should update the patient if one was already existing', async () => {
121+
const existingPatient = await PatientRepository.save({
122+
fullName: 'test test',
123+
} as Patient)
124+
125+
const updatedPatient = await PatientRepository.saveOrUpdate(existingPatient)
126+
127+
expect(updatedPatient.id).toEqual(existingPatient.id)
128+
129+
await patients.remove(await patients.get(existingPatient.id))
130+
})
131+
132+
it('should update the existing fields', async () => {
133+
const existingPatient = await PatientRepository.save({
134+
fullName: 'test test',
135+
} as Patient)
136+
existingPatient.fullName = 'changed'
137+
138+
const updatedPatient = await PatientRepository.saveOrUpdate(existingPatient)
139+
140+
expect(updatedPatient.fullName).toEqual('changed')
141+
142+
await patients.remove(await patients.get(existingPatient.id))
143+
})
144+
145+
it('should add new fields without changing existing fields', async () => {
146+
const existingPatient = await PatientRepository.save({
147+
fullName: 'test test',
148+
} as Patient)
149+
existingPatient.givenName = 'givenName'
150+
151+
const updatedPatient = await PatientRepository.saveOrUpdate(existingPatient)
152+
153+
expect(updatedPatient.fullName).toEqual(existingPatient.fullName)
154+
expect(updatedPatient.givenName).toEqual('givenName')
155+
156+
await patients.remove(await patients.get(existingPatient.id))
157+
})
158+
})
159+
108160
describe('delete', () => {
109161
it('should delete the patient', async () => {
110162
const patientToDelete = await PatientRepository.save({

src/__tests__/patients/patient-slice.test.ts

+78
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import patient, {
44
getPatientStart,
55
getPatientSuccess,
66
fetchPatient,
7+
updatePatientStart,
8+
updatePatientSuccess,
9+
updatePatient,
710
} from '../../patients/patient-slice'
811
import Patient from '../../model/Patient'
912
import PatientRepository from '../../clients/db/PatientRepository'
@@ -47,6 +50,34 @@ describe('patients slice', () => {
4750
expect(patientStore.isLoading).toBeFalsy()
4851
expect(patientStore.patient).toEqual(expectedPatient)
4952
})
53+
54+
it('should handle the UPDATE_PATIENT_START action', () => {
55+
const patientStore = patient(undefined, {
56+
type: updatePatientStart.type,
57+
})
58+
59+
expect(patientStore.isLoading).toBeTruthy()
60+
})
61+
62+
it('should handle the UPDATE_PATIENT_SUCCESS action', () => {
63+
const expectedPatient = {
64+
id: '123',
65+
rev: '123',
66+
sex: 'male',
67+
dateOfBirth: new Date().toISOString(),
68+
givenName: 'test',
69+
familyName: 'test',
70+
}
71+
const patientStore = patient(undefined, {
72+
type: updatePatientSuccess.type,
73+
payload: {
74+
...expectedPatient,
75+
},
76+
})
77+
78+
expect(patientStore.isLoading).toBeFalsy()
79+
expect(patientStore.patient).toEqual(expectedPatient)
80+
})
5081
})
5182

5283
describe('fetchPatient()', () => {
@@ -98,4 +129,51 @@ describe('patients slice', () => {
98129
})
99130
})
100131
})
132+
133+
describe('update patient', () => {
134+
it('should dispatch the UPDATE_PATIENT_START action', async () => {
135+
const dispatch = jest.fn()
136+
const getState = jest.fn()
137+
jest.spyOn(PatientRepository, 'saveOrUpdate')
138+
const expectedPatientId = '12345'
139+
const expectedPatient = { id: expectedPatientId } as Patient
140+
const mockedPatientRepository = mocked(PatientRepository, true)
141+
mockedPatientRepository.saveOrUpdate.mockResolvedValue(expectedPatient)
142+
143+
await updatePatient(expectedPatient)(dispatch, getState, null)
144+
145+
expect(dispatch).toHaveBeenCalledWith({ type: updatePatientStart.type })
146+
})
147+
148+
it('should call the PatientRepository saveOrUpdate function with the correct data', async () => {
149+
const dispatch = jest.fn()
150+
const getState = jest.fn()
151+
jest.spyOn(PatientRepository, 'saveOrUpdate')
152+
const expectedPatientId = '12345'
153+
const expectedPatient = { id: expectedPatientId } as Patient
154+
const mockedPatientRepository = mocked(PatientRepository, true)
155+
mockedPatientRepository.saveOrUpdate.mockResolvedValue(expectedPatient)
156+
157+
await updatePatient(expectedPatient)(dispatch, getState, null)
158+
159+
expect(PatientRepository.saveOrUpdate).toHaveBeenCalledWith(expectedPatient)
160+
})
161+
162+
it('should dispatch the UPDATE_PATIENT_SUCCESS action with the correct data', async () => {
163+
const dispatch = jest.fn()
164+
const getState = jest.fn()
165+
jest.spyOn(PatientRepository, 'saveOrUpdate')
166+
const expectedPatientId = '12345'
167+
const expectedPatient = { id: expectedPatientId } as Patient
168+
const mockedPatientRepository = mocked(PatientRepository, true)
169+
mockedPatientRepository.saveOrUpdate.mockResolvedValue(expectedPatient)
170+
171+
await updatePatient(expectedPatient)(dispatch, getState, null)
172+
173+
expect(dispatch).toHaveBeenCalledWith({
174+
type: updatePatientSuccess.type,
175+
payload: expectedPatient,
176+
})
177+
})
178+
})
101179
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import '../../../__mocks__/matchMediaMock'
2+
import React from 'react'
3+
import { ReactWrapper, mount } from 'enzyme'
4+
import { Modal, Alert } from '@hospitalrun/components'
5+
import { act } from '@testing-library/react'
6+
import { Typeahead } from 'react-bootstrap-typeahead'
7+
import NewRelatedPersonModal from '../../../patients/related-persons/NewRelatedPersonModal'
8+
import TextInputWithLabelFormGroup from '../../../components/input/TextInputWithLabelFormGroup'
9+
10+
describe('New Related Person Modal', () => {
11+
describe('layout', () => {
12+
let wrapper: ReactWrapper
13+
beforeEach(() => {
14+
wrapper = mount(
15+
<NewRelatedPersonModal
16+
show
17+
onSave={jest.fn()}
18+
onCloseButtonClick={jest.fn()}
19+
toggle={jest.fn()}
20+
/>,
21+
)
22+
})
23+
24+
it('should render a modal', () => {
25+
const modal = wrapper.find(Modal)
26+
expect(modal).toHaveLength(1)
27+
expect(modal.prop('show')).toBeTruthy()
28+
})
29+
30+
it('should render a patient search typeahead', () => {
31+
const patientSearchTypeahead = wrapper.find(Typeahead)
32+
33+
expect(patientSearchTypeahead).toHaveLength(1)
34+
expect(patientSearchTypeahead.prop('placeholder')).toEqual('patient.relatedPerson')
35+
})
36+
37+
it('should render a relationship type text input', () => {
38+
const relationshipTypeTextInput = wrapper.findWhere((w) => w.prop('name') === 'type')
39+
40+
expect(relationshipTypeTextInput).toHaveLength(1)
41+
expect(relationshipTypeTextInput.type()).toBe(TextInputWithLabelFormGroup)
42+
expect(relationshipTypeTextInput.prop('name')).toEqual('type')
43+
expect(relationshipTypeTextInput.prop('isEditable')).toBeTruthy()
44+
expect(relationshipTypeTextInput.prop('label')).toEqual(
45+
'patient.relatedPersons.relationshipType',
46+
)
47+
})
48+
49+
it('should render a cancel button', () => {
50+
const cancelButton = wrapper.findWhere((w) => w.text() === 'actions.cancel')
51+
52+
expect(cancelButton).toHaveLength(1)
53+
})
54+
55+
it('should render an add new related person button button', () => {
56+
const modal = wrapper.find(Modal)
57+
expect(modal.prop('successButton').children).toEqual('patient.relatedPersons.new')
58+
})
59+
})
60+
61+
describe('save', () => {
62+
let wrapper: ReactWrapper
63+
let onSaveSpy = jest.fn()
64+
beforeEach(() => {
65+
onSaveSpy = jest.fn()
66+
wrapper = mount(
67+
<NewRelatedPersonModal
68+
show
69+
onSave={onSaveSpy}
70+
onCloseButtonClick={jest.fn()}
71+
toggle={jest.fn()}
72+
/>,
73+
)
74+
})
75+
76+
it('should call the save function with the correct data', () => {
77+
act(() => {
78+
const patientTypeahead = wrapper.find(Typeahead)
79+
patientTypeahead.prop('onChange')([{ id: '123' }])
80+
})
81+
wrapper.update()
82+
83+
act(() => {
84+
const relationshipTypeTextInput = wrapper.findWhere((w) => w.prop('name') === 'type')
85+
relationshipTypeTextInput.prop('onChange')({ target: { value: 'relationship' } })
86+
})
87+
wrapper.update()
88+
89+
const addNewButton = wrapper.findWhere((w) => w.text() === 'patient.relatedPersons.new')
90+
act(() => {
91+
;(wrapper.find(Modal).prop('successButton') as any).onClick(
92+
{} as React.MouseEvent<HTMLButtonElement, MouseEvent>,
93+
)
94+
})
95+
expect(onSaveSpy).toHaveBeenCalledTimes(1)
96+
expect(onSaveSpy).toHaveBeenCalledWith({
97+
patientId: '123',
98+
type: 'relationship',
99+
})
100+
})
101+
102+
it('should display an error message if given name or relationship type is not entered.', () => {
103+
act(() => {
104+
wrapper
105+
.find(Modal)
106+
.prop('successButton')
107+
.onClick({} as React.MouseEvent<HTMLButtonElement, MouseEvent>)
108+
})
109+
110+
wrapper.update()
111+
112+
const errorAlert = wrapper.find(Alert)
113+
expect(onSaveSpy).not.toHaveBeenCalled()
114+
expect(errorAlert).toHaveLength(1)
115+
expect(errorAlert.prop('message')).toEqual(
116+
'patient.relatedPersons.error.relatedPersonRequired patient.relatedPersons.error.relationshipTypeRequired',
117+
)
118+
})
119+
})
120+
})

0 commit comments

Comments
 (0)