Skip to content

Commit

Permalink
feat(viewpatients): refactor code as recommended
Browse files Browse the repository at this point in the history
Change Page interface, Fix failing tests

fix HospitalRun#1969
  • Loading branch information
akshay-ap committed May 1, 2020
1 parent 11b6c8b commit 5308f5f
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 84 deletions.
31 changes: 29 additions & 2 deletions src/__tests__/patients/list/ViewPatients.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,31 @@ describe('Patients', () => {
beforeEach(() => {
jest.resetAllMocks()
jest.spyOn(PatientRepository, 'findAll')
jest.spyOn(PatientRepository, 'searchPaged')
jest.spyOn(PatientRepository, 'findAllPaged')

mockedPatientRepository.findAll.mockResolvedValue([])
mockedPatientRepository.findAllPaged.mockResolvedValue(
new Promise<Page<Patient>>((resolve) => {
const pagedResult: Page<Patient> = {
content: [],
hasPrevious: false,
hasNext: false,
}
resolve(pagedResult)
}),
)

mockedPatientRepository.searchPaged.mockResolvedValue(
new Promise<Page<Patient>>((resolve) => {
const pagedResult: Page<Patient> = {
content: [],
hasPrevious: false,
hasNext: false,
}
resolve(pagedResult)
}),
)
})

describe('layout', () => {
Expand Down Expand Up @@ -147,9 +171,12 @@ describe('Patients', () => {
expect(searchPatientsSpy).toHaveBeenLastCalledWith(
expectedSearchText,
{
sorts: [{ field: 'code', direction: 'desc' }],
sorts: [
{ field: 'fullName', direction: 'asc' },
{ field: 'code', direction: 'asc' },
],
},
{ limit: 1, skip: 0 },
{ number: 1, size: 1 },
)
})
})
Expand Down
61 changes: 35 additions & 26 deletions src/__tests__/patients/patients-slice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import '../../__mocks__/matchMediaMock'
import { AnyAction } from 'redux'
import { mocked } from 'ts-jest/utils'
import { UnpagedRequest } from 'clients/db/PageRequest'
import Page from 'clients/Page'
import Patient from 'model/Patient'
import patients, {
fetchPatientsStart,
fetchPatientsSuccess,
Expand Down Expand Up @@ -54,6 +56,34 @@ describe('patients slice', () => {
})

describe('searchPatients', () => {
beforeEach(() => {
const mockedPatientRepository = mocked(PatientRepository, true)
jest.spyOn(PatientRepository, 'findAllPaged')
jest.spyOn(PatientRepository, 'searchPaged')

mockedPatientRepository.findAllPaged.mockResolvedValue(
new Promise<Page<Patient>>((resolve) => {
const pagedResult: Page<Patient> = {
content: [],
hasPrevious: false,
hasNext: false,
}
resolve(pagedResult)
}),
)

mockedPatientRepository.searchPaged.mockResolvedValue(
new Promise<Page<Patient>>((resolve) => {
const pagedResult: Page<Patient> = {
content: [],
hasPrevious: false,
hasNext: false,
}
resolve(pagedResult)
}),
)
})

it('should dispatch the FETCH_PATIENTS_START action', async () => {
const dispatch = jest.fn()
const getState = jest.fn()
Expand Down Expand Up @@ -91,36 +121,15 @@ describe('patients slice', () => {
const dispatch = jest.fn()
const getState = jest.fn()

const expectedPatients = {
content: [
{
id: '123',
fullName: 'test test',
isApproximateDateOfBirth: false,
givenName: 'test',
familyName: 'test',
code: 'P12345',
sex: 'male',
dateOfBirth: new Date().toISOString(),
phoneNumber: '99999999',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
rev: '',
},
],
hasNext: false,
hasPrevious: false,
pageRequest: UnpagedRequest,
}

const mockedPatientRepository = mocked(PatientRepository, true)
mockedPatientRepository.searchPaged.mockResolvedValue(expectedPatients)

await searchPatients('search string')(dispatch, getState, null)

expect(dispatch).toHaveBeenLastCalledWith({
type: fetchPatientsSuccess.type,
payload: expectedPatients,
payload: {
content: [],
hasPrevious: false,
hasNext: false,
},
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions src/clients/Page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PageRequest from './db/PageRequest'

export default interface Page<T extends AbstractDBModel> {
content: T[]
hasNext?: boolean
hasPrevious?: boolean
hasNext: boolean
hasPrevious: boolean
pageRequest?: PageRequest
}
9 changes: 6 additions & 3 deletions src/clients/db/PageRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export default interface PageRequest {
limit: number | undefined
skip: number
number: number | undefined
size: number | undefined
}
export const UnpagedRequest: PageRequest = {
number: undefined,
size: undefined,
}
export const UnpagedRequest: PageRequest = { limit: undefined, skip: 0 }
64 changes: 36 additions & 28 deletions src/clients/db/PatientRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Patient from '../../model/Patient'
import Repository from './Repository'
import { patients } from '../../config/pouchdb'
import PageRequest, { UnpagedRequest } from './PageRequest'
import SortRequest, { Unsorted } from './SortRequest'

const formatPatientCode = (prefix: string, sequenceNumber: string) => `${prefix}${sequenceNumber}`

Expand All @@ -13,7 +14,7 @@ export class PatientRepository extends Repository<Patient> {
constructor() {
super(patients)
patients.createIndex({
index: { fields: ['code', 'fullName'] },
index: { fields: ['fullName', 'code'] },
})
}

Expand All @@ -37,40 +38,47 @@ export class PatientRepository extends Repository<Patient> {
async searchPaged(
text: string,
pageRequest: PageRequest = UnpagedRequest,
sortRequest: SortRequest = Unsorted,
): Promise<Page<Patient>> {
return super
.search({
selector: {
$or: [
{
fullName: {
$regex: RegExp(text, 'i'),
},
},
{
code: text,
},
],
const selector: any = {
$or: [
{
fullName: {
$regex: RegExp(text, 'i'),
},
},
{
code: text,
},
skip: pageRequest.skip,
limit: pageRequest.limit,
],
}
sortRequest.sorts.forEach((s) => {
selector[s.field] = { $gt: null }
})

const result = await super
.search({
selector,
limit: pageRequest.size,
skip:
pageRequest.number && pageRequest.size ? (pageRequest.number - 1) * pageRequest.size : 0,
sort:
sortRequest.sorts.length > 0
? sortRequest.sorts.map((s) => ({ [s.field]: s.direction }))
: undefined,
})
.then(
(searchedData) =>
new Promise<Page<Patient>>((resolve) => {
const pagedResult: Page<Patient> = {
content: searchedData,
pageRequest,
hasNext: pageRequest.limit !== undefined && searchedData.length === pageRequest.limit,
hasPrevious: pageRequest.skip > 0,
}
resolve(pagedResult)
}),
)
.catch((err) => {
console.log(err)
return err
})

const pagedResult: Page<Patient> = {
content: result,
pageRequest,
hasNext: pageRequest.size !== undefined && result.length === pageRequest.size,
hasPrevious: pageRequest.number !== undefined && pageRequest.number > 1,
}
return pagedResult
}

async save(entity: Patient): Promise<Patient> {
Expand Down
13 changes: 7 additions & 6 deletions src/clients/db/Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,19 @@ export default class Repository<T extends AbstractDBModel> {
const result = await this.db.find({
selector,
sort: sort.sorts.length > 0 ? sort.sorts.map((s) => ({ [s.field]: s.direction })) : undefined,
limit: pageRequest.limit,
skip: pageRequest.skip,
limit: pageRequest.size,
skip:
pageRequest.number && pageRequest.size ? (pageRequest.number - 1) * pageRequest.size : 0,
})
const mappedResult = result.docs.map(mapDocument)

const pagedResult: Page<T> = {
content: mappedResult,
hasNext: pageRequest.limit !== undefined && mappedResult.length === pageRequest.limit,
hasPrevious: pageRequest.skip > 0,
hasNext: pageRequest.size !== undefined && mappedResult.length === pageRequest.size,
hasPrevious: pageRequest.number !== undefined && pageRequest.number > 1,
pageRequest: {
skip: pageRequest.skip,
limit: pageRequest.limit,
size: pageRequest.size,
number: pageRequest.number,
},
}
return pagedResult
Expand Down
28 changes: 17 additions & 11 deletions src/patients/list/ViewPatients.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ const ViewPatients = () => {

const setButtonToolBar = useButtonToolbarSetter()
const [userPageRequest, setUserPageRequest] = useState<PageRequest>({
skip: 0,
limit: 1,
size: 1,
number: 1,
})

const setNextPageRequest = () => {
setUserPageRequest((p) => {
if (p.limit) {
if (p && p.number && p.number >= 0 && p.size) {
const newPageRequest: PageRequest = {
limit: p.limit,
skip: p.skip + p.limit,
number: p.number + 1,
size: p.size,
}
return newPageRequest
}
Expand All @@ -45,10 +45,10 @@ const ViewPatients = () => {

const setPreviousPageRequest = () => {
setUserPageRequest((p) => {
if (p.limit) {
if (p.number && p.size) {
return {
limit: p.limit,
skip: p.skip - p.limit,
number: p.number - 1,
size: p.size,
}
}
return p
Expand All @@ -60,14 +60,20 @@ const ViewPatients = () => {

useEffect(() => {
const sortRequest: SortRequest = {
sorts: [{ field: 'code', direction: 'desc' }],
sorts: [
{ field: 'fullName', direction: 'asc' },
{ field: 'code', direction: 'asc' },
],
}
dispatch(searchPatients(debouncedSearchText, sortRequest, userPageRequest))
}, [dispatch, debouncedSearchText, userPageRequest])

useEffect(() => {
const sortRequest: SortRequest = {
sorts: [{ field: 'code', direction: 'desc' }],
sorts: [
{ field: 'fullName', direction: 'asc' },
{ field: 'code', direction: 'asc' },
],
}
dispatch(fetchPatients(sortRequest, userPageRequest))

Expand Down Expand Up @@ -136,7 +142,7 @@ const ViewPatients = () => {
<PageComponent
hasNext={patients.hasNext}
hasPrevious={patients.hasPrevious}
pageNumber={userPageRequest.limit && userPageRequest.skip / userPageRequest.limit + 1}
pageNumber={userPageRequest.number}
setPreviousPageRequest={setPreviousPageRequest}
setNextPageRequest={setNextPageRequest}
/>
Expand Down
8 changes: 2 additions & 6 deletions src/patients/patients-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ const initialState: PatientsState = {
content: [],
hasNext: false,
hasPrevious: false,
pageRequest: {
skip: 0,
limit: 1,
},
},
}

Expand All @@ -42,8 +38,8 @@ const patientsSlice = createSlice({
export const { fetchPatientsStart, fetchPatientsSuccess } = patientsSlice.actions

export const fetchPatients = (
sortRequest: SortRequest,
pageRequest: PageRequest,
sortRequest: SortRequest = Unsorted,
pageRequest: PageRequest = UnpagedRequest,
): AppThunk => async (dispatch) => {
dispatch(fetchPatientsStart())
const patients = await PatientRepository.findAllPaged(sortRequest, pageRequest)
Expand Down

0 comments on commit 5308f5f

Please sign in to comment.