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

Commit

Permalink
feat(caregoal): add care goals to patient (#2360)
Browse files Browse the repository at this point in the history
* feat(caregoal): add care goals to patient

* feat(caregoal): improve tests

* feat(caregoal): applying recommended changes from review

Co-authored-by: Maksim Sinik <[email protected]>
Co-authored-by: Jack Meyer <[email protected]>
  • Loading branch information
3 people authored Sep 7, 2020
1 parent 08d7965 commit 8eb8f6f
Show file tree
Hide file tree
Showing 25 changed files with 1,483 additions and 2 deletions.
101 changes: 101 additions & 0 deletions src/__tests__/patients/care-goals/AddCareGoalModal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Modal } from '@hospitalrun/components'
import { mount } from 'enzyme'
import { createMemoryHistory } from 'history'
import React from 'react'
import { act } from 'react-dom/test-utils'
import { Router } from 'react-router-dom'

import AddCareGoalModal from '../../../patients/care-goals/AddCareGoalModal'
import CareGoalForm from '../../../patients/care-goals/CareGoalForm'
import PatientRepository from '../../../shared/db/PatientRepository'
import CareGoal, { CareGoalStatus, CareGoalAchievementStatus } from '../../../shared/model/CareGoal'
import Patient from '../../../shared/model/Patient'

describe('Add Care Goal Modal', () => {
const patient = {
givenName: 'given Name',
fullName: 'full name',
careGoals: [] as CareGoal[],
} as Patient

const onCloseSpy = jest.fn()
const setup = () => {
jest.spyOn(PatientRepository, 'find').mockResolvedValue(patient)
jest.spyOn(PatientRepository, 'saveOrUpdate')
const history = createMemoryHistory()
const wrapper = mount(
<Router history={history}>
<AddCareGoalModal patient={patient} show onCloseButtonClick={onCloseSpy} />
</Router>,
)

wrapper.update()
return { wrapper }
}

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

it('should render a modal', () => {
const { wrapper } = setup()

const modal = wrapper.find(Modal)
const sucessButton = modal.prop('successButton')
const closeButton = modal.prop('closeButton')

expect(modal).toHaveLength(1)
expect(modal.prop('title')).toEqual('patient.careGoal.new')
expect(sucessButton?.children).toEqual('patient.careGoal.new')
expect(sucessButton?.icon).toEqual('add')
expect(closeButton?.children).toEqual('actions.cancel')
})

it('should render a care goal form', () => {
const { wrapper } = setup()

const careGoalForm = wrapper.find(CareGoalForm)
expect(careGoalForm).toHaveLength(1)
})

it('should save care goal when save button is clicked and close', async () => {
const expectedCreatedDate = new Date()
Date.now = jest.fn().mockReturnValue(expectedCreatedDate)

const expectedCareGoal = {
id: '123',
description: 'some description',
startDate: new Date().toISOString(),
dueDate: new Date().toISOString(),
note: '',
priority: 'medium',
status: CareGoalStatus.Accepted,
achievementStatus: CareGoalAchievementStatus.InProgress,
createdOn: expectedCreatedDate,
}

const { wrapper } = setup()
await act(async () => {
const careGoalForm = wrapper.find(CareGoalForm)
const onChange = careGoalForm.prop('onChange') as any
await onChange(expectedCareGoal)
})

wrapper.update()

await act(async () => {
const modal = wrapper.find(Modal)
const sucessButton = modal.prop('successButton')
const onClick = sucessButton?.onClick as any
await onClick()
})

expect(PatientRepository.saveOrUpdate).toHaveBeenCalledTimes(1)
expect(PatientRepository.saveOrUpdate).toHaveBeenCalledWith({
...patient,
careGoals: [expectedCareGoal],
})

expect(onCloseSpy).toHaveBeenCalledTimes(1)
})
})
292 changes: 292 additions & 0 deletions src/__tests__/patients/care-goals/CareGoalForm.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
import { Alert } from '@hospitalrun/components'
import { addMonths, addDays } from 'date-fns'
import { mount } from 'enzyme'
import React from 'react'
import { act } from 'react-dom/test-utils'

import CareGoalForm from '../../../patients/care-goals/CareGoalForm'
import CareGoal, { CareGoalStatus, CareGoalAchievementStatus } from '../../../shared/model/CareGoal'

describe('Care Goal Form', () => {
const onCareGoalChangeSpy = jest.fn()
const careGoal = {
description: 'some description',
startDate: new Date().toISOString(),
dueDate: addMonths(new Date(), 1).toISOString(),
note: '',
priority: 'medium',
status: CareGoalStatus.Accepted,
achievementStatus: CareGoalAchievementStatus.InProgress,
} as CareGoal

const setup = (disabled = false, initializeCareGoal = true, error?: any) => {
const wrapper = mount(
<CareGoalForm
careGoal={initializeCareGoal ? careGoal : {}}
disabled={disabled}
careGoalError={error}
onChange={onCareGoalChangeSpy}
/>,
)

return wrapper
}

it('should render a description input', () => {
const wrapper = setup()

const descriptionInput = wrapper.findWhere((w) => w.prop('name') === 'description')

expect(descriptionInput).toHaveLength(1)
expect(descriptionInput.prop('label')).toEqual('patient.careGoal.description')
expect(descriptionInput.prop('isRequired')).toBeTruthy()
expect(descriptionInput.prop('value')).toBe(careGoal.description)
})

it('should call onChange handler when description changes', () => {
const expectedDescription = 'some new description'
const wrapper = setup(false, false)

act(() => {
const descriptionInput = wrapper.findWhere((w) => w.prop('name') === 'description')
const onChange = descriptionInput.prop('onChange') as any
onChange({ currentTarget: { value: expectedDescription } })
})

expect(onCareGoalChangeSpy).toHaveBeenCalledWith({ description: expectedDescription })
})

it('should render a priority selector', () => {
const wrapper = setup()

const priority = wrapper.findWhere((w) => w.prop('name') === 'priority')

expect(priority).toHaveLength(1)
expect(priority.prop('label')).toEqual('patient.careGoal.priority.label')
expect(priority.prop('isRequired')).toBeTruthy()
expect(priority.prop('defaultSelected')[0].value).toBe(careGoal.priority)
expect(priority.prop('options')).toEqual([
{
label: 'patient.careGoal.priority.low',
value: 'low',
},
{
label: 'patient.careGoal.priority.medium',
value: 'medium',
},
{
label: 'patient.careGoal.priority.high',
value: 'high',
},
])
})

it('should call onChange handler when priority changes', () => {
const expectedPriority = 'high'
const wrapper = setup(false, false)

act(() => {
const prioritySelector = wrapper.findWhere((w) => w.prop('name') === 'priority')
const onChange = prioritySelector.prop('onChange') as any
onChange([expectedPriority])
})

expect(onCareGoalChangeSpy).toHaveBeenCalledWith({ priority: expectedPriority })
})

it('should render a status selector', () => {
const wrapper = setup()

const status = wrapper.findWhere((w) => w.prop('name') === 'status')

expect(status).toHaveLength(1)
expect(status.prop('label')).toEqual('patient.careGoal.status')
expect(status.prop('isRequired')).toBeTruthy()
expect(status.prop('defaultSelected')[0].value).toBe(careGoal.status)
expect(status.prop('options')).toEqual(
Object.values(CareGoalStatus).map((v) => ({ label: v, value: v })),
)
})

it('should call onChange handler when status changes', () => {
const expectedStatus = CareGoalStatus.OnHold
const wrapper = setup(false, false)

act(() => {
const statusSelector = wrapper.findWhere((w) => w.prop('name') === 'status')
const onChange = statusSelector.prop('onChange') as any
onChange([expectedStatus])
})

expect(onCareGoalChangeSpy).toHaveBeenCalledWith({ status: expectedStatus })
})

it('should render the achievement status selector', () => {
const wrapper = setup()

const achievementStatus = wrapper.findWhere((w) => w.prop('name') === 'achievementStatus')
expect(achievementStatus).toHaveLength(1)
expect(achievementStatus.prop('label')).toEqual('patient.careGoal.achievementStatus')
expect(achievementStatus.prop('isRequired')).toBeTruthy()
expect(achievementStatus.prop('defaultSelected')[0].value).toBe(careGoal.achievementStatus)
expect(achievementStatus.prop('options')).toEqual(
Object.values(CareGoalAchievementStatus).map((v) => ({ label: v, value: v })),
)
})

it('should call onChange handler when achievement status change', () => {
const expectedAchievementStatus = CareGoalAchievementStatus.Improving
const wrapper = setup(false, false)

act(() => {
const achievementStatusSelector = wrapper.findWhere(
(w) => w.prop('name') === 'achievementStatus',
)
const onChange = achievementStatusSelector.prop('onChange') as any
onChange([expectedAchievementStatus])
})

expect(onCareGoalChangeSpy).toHaveBeenCalledWith({
achievementStatus: expectedAchievementStatus,
})
})

it('should render a start date picker', () => {
const wrapper = setup()

const startDatePicker = wrapper.findWhere((w) => w.prop('name') === 'startDate')
expect(startDatePicker).toHaveLength(1)
expect(startDatePicker.prop('label')).toEqual('patient.careGoal.startDate')
expect(startDatePicker.prop('isRequired')).toBeTruthy()
expect(startDatePicker.prop('value')).toEqual(new Date(careGoal.startDate))
})

it('should call onChange handler when start date change', () => {
const expectedStartDate = addDays(1, new Date().getDate())
const wrapper = setup(false, false)

act(() => {
const startDatePicker = wrapper.findWhere((w) => w.prop('name') === 'startDate')
const onChange = startDatePicker.prop('onChange') as any
onChange(expectedStartDate)
})

expect(onCareGoalChangeSpy).toHaveBeenCalledWith({ startDate: expectedStartDate.toISOString() })
})

it('should render a due date picker', () => {
const wrapper = setup()

const dueDatePicker = wrapper.findWhere((w) => w.prop('name') === 'dueDate')
expect(dueDatePicker).toHaveLength(1)
expect(dueDatePicker.prop('label')).toEqual('patient.careGoal.dueDate')
expect(dueDatePicker.prop('isRequired')).toBeTruthy()
expect(dueDatePicker.prop('value')).toEqual(new Date(careGoal.dueDate))
})

it('should call onChange handler when due date change', () => {
const expectedDueDate = addDays(31, new Date().getDate())
const wrapper = setup(false, false)

act(() => {
const dueDatePicker = wrapper.findWhere((w) => w.prop('name') === 'dueDate')
const onChange = dueDatePicker.prop('onChange') as any
onChange(expectedDueDate)
})

expect(onCareGoalChangeSpy).toHaveBeenCalledWith({ dueDate: expectedDueDate.toISOString() })
})

it('should render a note input', () => {
const wrapper = setup()

const noteInput = wrapper.findWhere((w) => w.prop('name') === 'note')
expect(noteInput).toHaveLength(1)
expect(noteInput.prop('label')).toEqual('patient.careGoal.note')
expect(noteInput.prop('isRequired')).toBeFalsy()
expect(noteInput.prop('value')).toEqual(careGoal.note)
})

it('should call onChange handler when note change', () => {
const expectedNote = 'some new note'
const wrapper = setup(false, false)

act(() => {
const noteInput = wrapper.findWhere((w) => w.prop('name') === 'note')
const onChange = noteInput.prop('onChange') as any
onChange({ currentTarget: { value: expectedNote } })
})

expect(onCareGoalChangeSpy).toHaveBeenCalledWith({ note: expectedNote })
})

it('should render all the forms fields disabled if the form is disabled', () => {
const wrapper = setup(true)

const description = wrapper.findWhere((w) => w.prop('name') === 'description')
const priority = wrapper.findWhere((w) => w.prop('name') === 'priority')
const status = wrapper.findWhere((w) => w.prop('name') === 'status')
const achievementStatus = wrapper.findWhere((w) => w.prop('name') === 'achievementStatus')
const startDate = wrapper.findWhere((w) => w.prop('name') === 'startDate')
const dueDate = wrapper.findWhere((w) => w.prop('name') === 'dueDate')
const note = wrapper.findWhere((w) => w.prop('name') === 'note')

expect(description.prop('isEditable')).toBeFalsy()
expect(priority.prop('isEditable')).toBeFalsy()
expect(status.prop('isEditable')).toBeFalsy()
expect(achievementStatus.prop('isEditable')).toBeFalsy()
expect(startDate.prop('isEditable')).toBeFalsy()
expect(dueDate.prop('isEditable')).toBeFalsy()
expect(note.prop('isEditable')).toBeFalsy()
})

it('should render the forms field in an error state', () => {
const expectedError = {
message: 'some error message',
description: 'some description error',
status: 'some status error',
achievementStatus: 'some achievement status error',
priority: 'some priority error',
startDate: 'some start date error',
dueDate: 'some due date error',
note: 'some note error',
}

const wrapper = setup(false, false, expectedError)

const alert = wrapper.find(Alert)
const descriptionInput = wrapper.findWhere((w) => w.prop('name') === 'description')
const prioritySelector = wrapper.findWhere((w) => w.prop('name') === 'priority')
const statusSelector = wrapper.findWhere((w) => w.prop('name') === 'status')
const achievementStatusSelector = wrapper.findWhere(
(w) => w.prop('name') === 'achievementStatus',
)
const startDatePicker = wrapper.findWhere((w) => w.prop('name') === 'startDate')
const dueDatePicker = wrapper.findWhere((w) => w.prop('name') === 'dueDate')
const noteInput = wrapper.findWhere((w) => w.prop('name') === 'note')

expect(alert).toHaveLength(1)
expect(alert.prop('message')).toEqual(expectedError.message)

expect(descriptionInput.prop('isInvalid')).toBeTruthy()
expect(descriptionInput.prop('feedback')).toEqual(expectedError.description)

expect(prioritySelector.prop('isInvalid')).toBeTruthy()
// expect(prioritySelector.prop('feedback')).toEqual(expectedError.priority)

expect(statusSelector.prop('isInvalid')).toBeTruthy()
// expect(statusSelector.prop('feedback')).toEqual(expectedError.status)

expect(achievementStatusSelector.prop('isInvalid')).toBeTruthy()
// expect(achievementStatusSelector.prop('feedback')).toEqual(expectedError.achievementStatus)

expect(startDatePicker.prop('isInvalid')).toBeTruthy()
expect(startDatePicker.prop('feedback')).toEqual(expectedError.startDate)

expect(dueDatePicker.prop('isInvalid')).toBeTruthy()
expect(dueDatePicker.prop('feedback')).toEqual(expectedError.dueDate)

expect(noteInput.prop('isInvalid')).toBeTruthy()
expect(noteInput.prop('feedback')).toEqual(expectedError.note)
})
})
Loading

1 comment on commit 8eb8f6f

@vercel
Copy link

@vercel vercel bot commented on 8eb8f6f Sep 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.