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

feat(imaging): create basic imaging module #2250

Merged
merged 15 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
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
2 changes: 2 additions & 0 deletions src/HospitalRun.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useSelector } from 'react-redux'
import { Redirect, Route, Switch } from 'react-router-dom'

import Dashboard from './dashboard/Dashboard'
import Imagings from './imagings/Imagings'
import Incidents from './incidents/Incidents'
import Labs from './labs/Labs'
import Breadcrumbs from './page-header/breadcrumbs/Breadcrumbs'
Expand Down Expand Up @@ -53,6 +54,7 @@ const HospitalRun = () => {
<Route path="/labs" component={Labs} />
<Route path="/incidents" component={Incidents} />
<Route path="/settings" component={Settings} />
<Route path="/imagings" component={Imagings} />
Copy link
Member

Choose a reason for hiding this comment

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

Let's just go with /imaging for the route name

</Switch>
</div>
<Toaster autoClose={5000} hideProgressBar draggable />
Expand Down
50 changes: 50 additions & 0 deletions src/__tests__/HospitalRun.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import thunk from 'redux-thunk'

import Dashboard from '../dashboard/Dashboard'
import HospitalRun from '../HospitalRun'
import ViewImagings from '../imagings/ViewImagings'
import Incidents from '../incidents/Incidents'
import ViewLabs from '../labs/ViewLabs'
import { addBreadcrumbs } from '../page-header/breadcrumbs/breadcrumbs-slice'
import Appointments from '../scheduling/appointments/Appointments'
import Settings from '../settings/Settings'
import ImagingRepository from '../shared/db/ImagingRepository'
import LabRepository from '../shared/db/LabRepository'
import Permissions from '../shared/model/Permissions'
import { RootState } from '../shared/store'
Expand Down Expand Up @@ -170,6 +172,54 @@ describe('HospitalRun', () => {
})
})

describe('/imagings', () => {
it('should render the Imagings component when /imagings is accessed', async () => {
jest.spyOn(ImagingRepository, 'findAll').mockResolvedValue([])
const store = mockStore({
title: 'test',
user: { user: { id: '123' }, permissions: [Permissions.ViewImagings] },
imagings: { imagings: [] },
breadcrumbs: { breadcrumbs: [] },
components: { sidebarCollapsed: false },
} as any)

let wrapper: any
await act(async () => {
wrapper = await mount(
<Provider store={store}>
<MemoryRouter initialEntries={['/imagings']}>
<HospitalRun />
</MemoryRouter>
</Provider>,
)
})
wrapper.update()

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

it('should render the dashboard if the user does not have permissions to view imagings', () => {
jest.spyOn(LabRepository, 'findAll').mockResolvedValue([])
const store = mockStore({
title: 'test',
user: { user: { id: '123' }, permissions: [] },
breadcrumbs: { breadcrumbs: [] },
components: { sidebarCollapsed: false },
} as any)

const wrapper = mount(
<Provider store={store}>
<MemoryRouter initialEntries={['/imagings']}>
<HospitalRun />
</MemoryRouter>
</Provider>,
)

expect(wrapper.find(ViewImagings)).toHaveLength(0)
expect(wrapper.find(Dashboard)).toHaveLength(1)
})
})

describe('/settings', () => {
it('should render the Settings component when /settings is accessed', async () => {
const store = mockStore({
Expand Down
74 changes: 74 additions & 0 deletions src/__tests__/imagings/Imagings.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { mount } from 'enzyme'
import React from 'react'
import { Provider } from 'react-redux'
import { MemoryRouter } from 'react-router-dom'
import createMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

import Imagings from '../../imagings/Imagings'
import NewImagingRequest from '../../imagings/requests/NewImagingRequest'
import ImagingRepository from '../../shared/db/ImagingRepository'
import PatientRepository from '../../shared/db/PatientRepository'
import Imaging from '../../shared/model/Imaging'
import Patient from '../../shared/model/Patient'
import Permissions from '../../shared/model/Permissions'
import { RootState } from '../../shared/store'

const mockStore = createMockStore<RootState, any>([thunk])

describe('Imagings', () => {
jest.spyOn(ImagingRepository, 'findAll').mockResolvedValue([])
jest
.spyOn(ImagingRepository, 'find')
.mockResolvedValue({ id: '1234', requestedOn: new Date().toISOString() } as Imaging)
jest
.spyOn(PatientRepository, 'find')
.mockResolvedValue({ id: '12345', fullName: 'test test' } as Patient)

describe('routing', () => {
describe('/imagings/new', () => {
it('should render the new imaging request screen when /imagings/new is accessed', () => {
const store = mockStore({
title: 'test',
user: { permissions: [Permissions.RequestImaging] },
breadcrumbs: { breadcrumbs: [] },
components: { sidebarCollapsed: false },
imaging: {
imaging: { id: 'imagingId', patient: 'patient' } as Imaging,
patient: { id: 'patientId', fullName: 'some name' },
error: {},
},
} as any)

const wrapper = mount(
<Provider store={store}>
<MemoryRouter initialEntries={['/imagings/new']}>
<Imagings />
</MemoryRouter>
</Provider>,
)

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

it('should not navigate to /imagings/new if the user does not have RequestLab permissions', () => {
const store = mockStore({
title: 'test',
user: { permissions: [] },
breadcrumbs: { breadcrumbs: [] },
components: { sidebarCollapsed: false },
} as any)

const wrapper = mount(
<Provider store={store}>
<MemoryRouter initialEntries={['/imagings/new']}>
<Imagings />
</MemoryRouter>
</Provider>,
)

expect(wrapper.find(NewImagingRequest)).toHaveLength(0)
})
})
})
})
156 changes: 156 additions & 0 deletions src/__tests__/imagings/ViewImagings.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { Table } from '@hospitalrun/components'
import { act } from '@testing-library/react'
import { mount, ReactWrapper } from 'enzyme'
import { createMemoryHistory } from 'history'
import React from 'react'
import { Provider } from 'react-redux'
import { Router } from 'react-router-dom'
import createMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

import ViewImagings from '../../imagings/ViewImagings'
import * as ButtonBarProvider from '../../page-header/button-toolbar/ButtonBarProvider'
import * as titleUtil from '../../page-header/title/useTitle'
import ImagingRepository from '../../shared/db/ImagingRepository'
import Imaging from '../../shared/model/Imaging'
import Permissions from '../../shared/model/Permissions'
import { RootState } from '../../shared/store'

const mockStore = createMockStore<RootState, any>([thunk])

describe('View Imagings', () => {
describe('title', () => {
let titleSpy: any
beforeEach(async () => {
const store = mockStore({
title: '',
user: { permissions: [Permissions.ViewImagings, Permissions.RequestLab] },
imagings: { imagings: [] },
} as any)
titleSpy = jest.spyOn(titleUtil, 'default')
jest.spyOn(ImagingRepository, 'findAll').mockResolvedValue([])
await act(async () => {
await mount(
<Provider store={store}>
<Router history={createMemoryHistory()}>
<ViewImagings />
</Router>
</Provider>,
)
})
Copy link
Member

Choose a reason for hiding this comment

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

lately, we have been putting this kind of setup in a setup function. I think we should continue this pattern since it makes it easy to make sure each test is not dependent on a previous test.

Each describe can share the setup function. i.e. one setup function for the whole test suite.

})

it('should have the title', () => {
expect(titleSpy).toHaveBeenCalledWith('imagings.label')
})
})

describe('button bar', () => {
it('should display button to add new imaging request', async () => {
const store = mockStore({
title: '',
user: { permissions: [Permissions.ViewImagings, Permissions.RequestImaging] },
imagings: { imagings: [] },
} as any)
const setButtonToolBarSpy = jest.fn()
jest.spyOn(ButtonBarProvider, 'useButtonToolbarSetter').mockReturnValue(setButtonToolBarSpy)
jest.spyOn(ImagingRepository, 'findAll').mockResolvedValue([])
await act(async () => {
await mount(
<Provider store={store}>
<Router history={createMemoryHistory()}>
<ViewImagings />
</Router>
</Provider>,
)
})

const actualButtons: React.ReactNode[] = setButtonToolBarSpy.mock.calls[0][0]
expect((actualButtons[0] as any).props.children).toEqual('imagings.requests.new')
})

it('should not display button to add new imaging request if the user does not have permissions', async () => {
const store = mockStore({
title: '',
user: { permissions: [Permissions.ViewImagings] },
imagings: { imagings: [] },
} as any)
const setButtonToolBarSpy = jest.fn()
jest.spyOn(ButtonBarProvider, 'useButtonToolbarSetter').mockReturnValue(setButtonToolBarSpy)
jest.spyOn(ImagingRepository, 'findAll').mockResolvedValue([])
await act(async () => {
await mount(
<Provider store={store}>
<Router history={createMemoryHistory()}>
<ViewImagings />
</Router>
</Provider>,
)
})

const actualButtons: React.ReactNode[] = setButtonToolBarSpy.mock.calls[0][0]
expect(actualButtons).toEqual([])
})
})

describe('table', () => {
let wrapper: ReactWrapper
let history: any
const expectedImaging = {
code: 'I-1234',
id: '1234',
type: 'imaging type',
patient: 'patient',
status: 'requested',
requestedOn: '2020-03-30T04:43:20.102Z',
requestedBy: 'some user',
} as Imaging

beforeEach(async () => {
const store = mockStore({
title: '',
user: { permissions: [Permissions.ViewImagings, Permissions.RequestImaging] },
imagings: { imagings: [expectedImaging] },
} as any)
history = createMemoryHistory()

jest.spyOn(ImagingRepository, 'findAll').mockResolvedValue([expectedImaging])
await act(async () => {
wrapper = await mount(
<Provider store={store}>
<Router history={history}>
<ViewImagings />
</Router>
</Provider>,
)
})

wrapper.update()
})

it('should render a table with data', () => {
const table = wrapper.find(Table)
const columns = table.prop('columns')
expect(columns[0]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.code', key: 'code' }),
)
expect(columns[1]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.type', key: 'type' }),
)
expect(columns[2]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.requestedOn', key: 'requestedOn' }),
)
expect(columns[3]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.patient', key: 'patient' }),
)
expect(columns[4]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.requestedBy', key: 'requestedBy' }),
)
expect(columns[5]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.status', key: 'status' }),
)

expect(table.prop('data')).toEqual([expectedImaging])
})
})
})
Loading