Skip to content

Commit c9e860a

Browse files
committed
update tests & add check for cursor validity
1 parent 4431971 commit c9e860a

File tree

5 files changed

+145
-13
lines changed

5 files changed

+145
-13
lines changed

src/recordlinker/database/mpi_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ def get_orphaned_patients(
398398
def get_orphaned_persons(
399399
session: orm.Session,
400400
limit: int | None = 50,
401-
cursor: uuid.UUID | None = None,
401+
cursor: int | None = None,
402402
) -> typing.Sequence[models.Person]:
403403
"""
404404
Retrieve orphaned Persons in the MPI database, up to the provided limit. If a

src/recordlinker/routes/person_router.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,26 @@ def get_orphaned_persons(
115115
"""
116116
Retrieve person_reference_id(s) for all Persons that are not linked to any Patients.
117117
"""
118-
persons = service.get_orphaned_persons(session, limit, cursor)
118+
# Check if the cursor is a valid Person reference_id
119+
if cursor:
120+
person = service.get_persons_by_reference_ids(session, cursor)
121+
if not person or person[0] is None:
122+
raise fastapi.HTTPException(
123+
status_code=fastapi.status.HTTP_422_UNPROCESSABLE_ENTITY,
124+
detail=[
125+
{
126+
"loc": ["query", "cursor"],
127+
"msg": "Cursor is an invalid Person reference_id",
128+
"type": "value_error",
129+
}
130+
],
131+
)
132+
# Replace the cursor with the Patient id instead of reference_id
133+
cur = person[0].id
134+
else:
135+
cur = None
136+
137+
persons = service.get_orphaned_persons(session, limit, cur)
119138
if not persons:
120139
return schemas.PaginatedRefs(
121140
data=[], meta=schemas.PaginatedMetaData(next_cursor=None, next=None)

tests/unit/database/test_mpi_service.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ def test_get_orphaned_persons_cursor(self, session: Session):
985985
person2 = models.Person(id=2)
986986
person3 = models.Person(id=3)
987987
person4 = models.Person(id=4)
988-
patient = models.Patient(person=person1, data={})
988+
patient = models.Patient(person=person4, data={})
989989
session.add_all([patient, person2, person3, person4])
990990
session.flush()
991991

@@ -996,3 +996,7 @@ def test_get_orphaned_persons_cursor(self, session: Session):
996996
person2,
997997
person3,
998998
]
999+
assert mpi_service.get_orphaned_persons(session, limit=5, cursor=person1.id) == [
1000+
person2,
1001+
person3,
1002+
]

tests/unit/routes/test_patient_router.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,9 @@ def test_no_orphaned_patients(self, client):
195195
}
196196

197197
def test_get_orphaned_patients_with_cursor(self, client):
198-
ordered_uuids = [uuid.uuid4() for _ in range(3)]
199-
ordered_uuids.sort()
200-
201-
patient1 = models.Patient(person=None, reference_id=ordered_uuids[0])
202-
patient2 = models.Patient(person=None, reference_id=ordered_uuids[1])
203-
patient3 = models.Patient(person=None, reference_id=ordered_uuids[2])
198+
patient1 = models.Patient(person=None, data={"id": 1})
199+
patient2 = models.Patient(person=None, data={"id": 2})
200+
patient3 = models.Patient(person=None, data={"id": 3})
204201
client.session.add_all([patient1, patient2, patient3])
205202
client.session.flush()
206203

@@ -211,8 +208,8 @@ def test_get_orphaned_patients_with_cursor(self, client):
211208
assert response.json() == {
212209
"data": [str(patient2.reference_id)],
213210
"meta": {
214-
"next_cursor": str(ordered_uuids[1]),
215-
"next": f"http://testserver/patient/orphaned?limit=1&cursor={str(ordered_uuids[1])}",
211+
"next_cursor": str(patient2.reference_id),
212+
"next": f"http://testserver/patient/orphaned?limit=1&cursor={str(patient2.reference_id)}",
216213
},
217214
}
218215

@@ -221,8 +218,8 @@ def test_get_orphaned_patients_with_cursor(self, client):
221218
assert response.json() == {
222219
"data": [str(patient2.reference_id), str(patient3.reference_id)],
223220
"meta": {
224-
"next_cursor": str(ordered_uuids[2]),
225-
"next": f"http://testserver/patient/orphaned?limit=2&cursor={ordered_uuids[2]}",
221+
"next_cursor": str(patient3.reference_id),
222+
"next": f"http://testserver/patient/orphaned?limit=2&cursor={str(patient3.reference_id)}",
226223
},
227224
}
228225

tests/unit/routes/test_person_router.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,115 @@ def testInvalidPersonId(self, client):
226226
def testInvalidPerson(self, client):
227227
response = client.delete(f"/person/{uuid.uuid4()}")
228228
assert response.status_code == 404
229+
230+
231+
class TestGetOrphanedPersons:
232+
def testGetOrphanedPersons(self, client):
233+
person1 = models.Person()
234+
patient1 = models.Patient(person=person1, data={})
235+
236+
person2 = models.Person()
237+
client.session.add_all([patient1, person2])
238+
client.session.flush()
239+
240+
response = client.get("/person/orphaned")
241+
assert response.status_code == 200
242+
assert response.json() == {
243+
"data": [str(person2.reference_id)],
244+
"meta": {"next_cursor": None, "next": None},
245+
}
246+
247+
def test_no_orphaned_persons(self, client):
248+
response = client.get("/person/orphaned")
249+
assert response.status_code == 200
250+
assert response.json() == {
251+
"data": [],
252+
"meta": {"next_cursor": None, "next": None},
253+
}
254+
255+
def test_get_orphaned_persons_with_limit(self, client):
256+
person1 = models.Person(id=1)
257+
person2 = models.Person(id=2)
258+
person3 = models.Person(id=3)
259+
person4 = models.Person(id=4)
260+
client.session.add_all([person1, person2, person3, person4])
261+
client.session.flush()
262+
263+
response = client.get("/person/orphaned?limit=2")
264+
assert response.status_code == 200
265+
assert response.json() == {
266+
"data": [str(person1.reference_id), str(person2.reference_id)],
267+
"meta": {
268+
"next_cursor": str(person2.reference_id),
269+
"next": f"http://testserver/person/orphaned?limit=2&cursor={str(person2.reference_id)}",
270+
},
271+
}
272+
273+
response = client.get(f"/person/orphaned?limit=2&cursor={person2.reference_id}")
274+
assert response.json() == {
275+
"data": [str(person3.reference_id), str(person4.reference_id)],
276+
"meta": {
277+
"next_cursor": str(person4.reference_id),
278+
"next": f"http://testserver/person/orphaned?limit=2&cursor={str(person4.reference_id)}",
279+
},
280+
}
281+
282+
response = client.get(f"/person/orphaned?limit=5&cursor={person2.reference_id}")
283+
assert response.json() == {
284+
"data": [str(person3.reference_id), str(person4.reference_id)],
285+
"meta": {"next_cursor": None, "next": None},
286+
}
287+
288+
def test_get_orphaned_persons_with_cursor(self, client):
289+
person1 = models.Person(reference_id=uuid.uuid4(), id=1)
290+
patient1 = models.Patient(person=person1)
291+
patient2 = models.Patient(person=None)
292+
person3 = models.Person(id=3)
293+
person4 = models.Person(id=4)
294+
client.session.add_all([patient1, patient2, person3, person4])
295+
client.session.flush()
296+
297+
# Retrieve 1 person after person 1, return no cursor
298+
response = client.get(f"/person/orphaned?&cursor={person3.reference_id}")
299+
assert response.status_code == 200
300+
assert response.json() == {
301+
"data": [str(person4.reference_id)],
302+
"meta": {
303+
"next_cursor": None,
304+
"next": None,
305+
},
306+
}
307+
308+
# Retrieve 1 person after person 1, return cursor for person 3
309+
response = client.get(f"/person/orphaned?limit=1&cursor={person1.reference_id}")
310+
assert response.json() == {
311+
"data": [str(person3.reference_id)],
312+
"meta": {
313+
"next_cursor": str(person3.reference_id),
314+
"next": f"http://testserver/person/orphaned?limit=1&cursor={str(person3.reference_id)}",
315+
},
316+
}
317+
318+
# Retrieve 2 persons after person 2, return cursor for person 4
319+
response = client.get(f"/person/orphaned?limit=2&cursor={person1.reference_id}")
320+
assert response.json() == {
321+
"data": [str(person3.reference_id), str(person4.reference_id)],
322+
"meta": {
323+
"next_cursor": str(person4.reference_id),
324+
"next": f"http://testserver/person/orphaned?limit=2&cursor={str(person4.reference_id)}",
325+
},
326+
}
327+
328+
def test_invalid_cursor(self, client):
329+
# Return 422 if bad patient reference_id is provided as cursor
330+
response = client.get(f"/person/orphaned?limit=1&cursor={uuid.uuid4()}")
331+
assert response.status_code == 422
332+
assert response.json() == {
333+
"detail": [
334+
{
335+
"loc": ["query", "cursor"],
336+
"msg": "Cursor is an invalid Person reference_id",
337+
"type": "value_error",
338+
}
339+
]
340+
}

0 commit comments

Comments
 (0)