Skip to content

Commit

Permalink
chore(#123): Enhance Automated Tests for CHT & OpenMRS Endpoints in M…
Browse files Browse the repository at this point in the history
…ediator (#152)

Co-authored-by: Tom Wier <thomas@medic.org>
Co-authored-by: Maria Lorena Rodriguez Viruel <marialorenarodriguezviruel@mbp-de-maria.lan>
Co-authored-by: Maria Lorena Rodriguez Viruel <marialorenarodriguezviruel@MacBook-Pro-de-Maria.local>
  • Loading branch information
4 people authored Feb 14, 2025
1 parent cc3d748 commit fef3183
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 57 deletions.
50 changes: 50 additions & 0 deletions mediator/src/utils/tests/openmrs_sync.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,55 @@ describe('OpenMRS Sync', () => {

expect(openmrs.createOpenMRSResource).toHaveBeenCalledWith(fhirObservation);
});
it('does not send incoming Encounters to FHIR and CHT if OpenMRS identifier exists', async () => {
const lastUpdated = new Date();
lastUpdated.setMinutes(lastUpdated.getMinutes() - 30);

const openMRSPatient = PatientFactory.build();
openMRSPatient.meta = { lastUpdated: lastUpdated };
const openMRSEncounter = EncounterFactory.build();
openMRSEncounter.meta = { lastUpdated: lastUpdated };
openMRSEncounter.subject = {
reference: `Patient/${openMRSPatient.id}`
};
const openMRSObservation = ObservationFactory.build();
openMRSObservation.encounter = { reference: 'Encounter/' + openMRSEncounter.id }

jest.spyOn(fhir, 'getFhirResourcesSince').mockResolvedValueOnce({
data: [],
status: 200,
});

jest.spyOn(openmrs, 'getOpenMRSResourcesSince').mockResolvedValueOnce({
data: [openMRSEncounter, openMRSPatient, openMRSObservation],
status: 200,
});

jest.spyOn(fhir, 'getFHIRPatientResource').mockResolvedValueOnce({
data: { entry: [{ resource: openMRSPatient }] },
status: 200,
});

jest.spyOn(fhir, 'getFhirResourceByIdentifier').mockResolvedValue({
data: { total: 1, entry: [ { resource: openMRSPatient } ] },
status: 200,
});

jest.spyOn(fhir, 'updateFhirResource').mockResolvedValue({
data: [],
status: 201,
});

jest.spyOn(fhir, 'createFhirResource')

const startTime = new Date();
startTime.setHours(startTime.getHours() - 1);
const comparison = await syncEncounters(startTime);

expect(fhir.getFhirResourcesSince).toHaveBeenCalled();
expect(openmrs.getOpenMRSResourcesSince).toHaveBeenCalled();

expect(fhir.updateFhirResource).not.toHaveBeenCalled();
});
});
});
29 changes: 21 additions & 8 deletions mediator/test/cht-resource-factories.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { randomUUID } from 'crypto';
import { Factory } from 'rosie';

const PlaceFactory = Factory.define('place')
export const PlaceFactory = Factory.define('place')
.option('placeId', randomUUID())
.attr('name', 'CHP Branch One')
.attr('type', 'district_hospital')
.attr('parent', ['placeId'], function (placeId) {
.attr('placeId', ['placeId'], function (placeId) {
return placeId;
});

Expand All @@ -14,28 +14,32 @@ const ContactFactory = Factory.define('contact')
.attr('phone', '+2868917046');

export const UserFactory = Factory.define('user')
.option('placeId')
.option('parentPlace')
.attr('password', 'Dakar1234')
.attr('username', 'maria')
.attr('type', 'chw')
.attr('place', ['placeId'], function (placeId) {
return PlaceFactory.build({}, { placeId });
.attr('place', ['parentPlace'], function (parentPlace) {
return {
"name": "Mary's Area",
"type": "health_center",
"parent": parentPlace
};
})
.attr('contact', function () {
return ContactFactory.build();
});

export const PatientFactory = Factory.define('patient')
.option('placeId')
.option('place')
.attr('name', 'John Test')
.attr('phone', '+2548277217095')
.attr('date_of_birth', '1980-06-06')
.attr('sex', 'male')
.attr('type', 'person')
.attr('role', 'patient')
.attr('contact_type', 'patient')
.attr('place', ['placeId'], function (placeId) {
return placeId;
.attr('place', ['place'], function (place) {
return place;
});

const DocsFieldsFactory = Factory.define('fields')
Expand Down Expand Up @@ -80,3 +84,12 @@ export const TaskReportFactory = Factory.define('report')
return [DocsFactory.build({}, { placeId, contactId, patientId })];
})
.attr('new_edits', false);

export const HeightWeightReportFactory = Factory.define('report')
.option('patientUuid')
.attr('_meta', { 'form': 'HEIGHT_WEIGHT' })
.attr('patient_uuid', ['patientUuid'], function (patientUuid) {
return patientUuid;
})
.attr('height', 172)
.attr('weight', 65);
16 changes: 8 additions & 8 deletions mediator/test/e2e-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ MEDIATORDIR="${BASEDIR}/mediator"
export NODE_ENV=integration
export NODE_TLS_REJECT_UNAUTHORIZED=0

export OPENMRS_HOST=openmrs
export OPENMRS_USERNAME=admin
export OPENMRS_PASSWORD=Admin123

echo 'Cleanup from last test, in case of interruptions...'
cd $BASEDIR
./startup.sh destroy


export OPENMRS_HOST=openmrs
export OPENMRS_USERNAME=admin
export OPENMRS_PASSWORD=Admin123

echo 'Pulling Docker images with retry mechanism...'
services=("haproxy" "healthcheck" "api" "sentinel" "nginx" "couchdb")
max_retries=3
Expand Down Expand Up @@ -46,10 +47,12 @@ for service in "${services[@]}"; do
done

echo 'Starting the interoperability containers...'
./startup.sh up-openmrs
./startup.sh up-test

echo 'Waiting for configurator to finish...'
docker container wait chis-interop-cht-configurator-1
echo 'Waiting for OpenMRS to be ready'
sleep 280

cd $MEDIATORDIR
export OPENHIM_API_URL='https://localhost:8080'
Expand All @@ -64,9 +67,6 @@ export CHT_PASSWORD='password'
export OPENMRS_CHANNEL_URL='http://localhost:5001/openmrs'
export OPENMRS_CHANNEL_USERNAME='interop-client'
export OPENMRS_CHANNEL_PASSWORD='interop-password'

echo 'Waiting for OpenMRS to be ready'
sleep 280
echo 'Executing mediator e2e tests...'
npm run test -t workflows.spec.ts

Expand Down
67 changes: 67 additions & 0 deletions mediator/test/openmrs-resource-factories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { randomUUID } from 'crypto';
import { Factory } from 'rosie';

export const OpenMRSPatientFactory = new Factory()
.option('placeId')
.attr('resourceType', 'Patient')
.attr('id', () => randomUUID())
.attr('meta', () => ({
versionId: '2',
lastUpdated: new Date().toISOString(),
source: 'cht#rjEgeBRWROBrChB7'
}))
.attr('text', () => ({
status: 'generated',
div: '<div xmlns="http://www.w3.org/1999/xhtml"><div class="hapiHeaderText">OpenMRS <b>PATIENT </b></div><table class="hapiPropertyTable"><tbody><tr><td>Identifier</td><td>52802</td></tr><tr><td>Date of birth</td><td><span>06 June 1980</span></td></tr></tbody></table></div>'
}))
.attr('identifier', () => [
{
id: randomUUID(),
use: 'official',
type: { text: 'CHT Patient ID' },
value: Math.floor(Math.random() * 100000).toString()
},
{
id: randomUUID(),
use: 'secondary',
type: { text: 'CHT Document ID' },
value: randomUUID()
},
{
id: randomUUID(),
use: 'secondary',
type: { text: 'OpenMRS Patient UUID' },
value: randomUUID()
}
])
.attr('name', () => [
{
id: randomUUID(),
family: 'Patient',
given: ['OpenMRS']
}
])
.attr('telecom', () => [
{
id: randomUUID(),
value: '+2548277217095'
}
])
.attr('gender', 'male')
.attr('birthDate', '1980-06-06')
.attr('address', ['placeId'], (placeId) => [
{
id: randomUUID(),
line: ['123 Main St'],
city: 'Nairobi',
country: 'Kenya',
extension: [{
extension: [
{
url: 'http://fhir.openmrs.org/ext/address#address4',
valueString: `FCHV Area [${placeId}]`
}
]
}]
}
]);
Loading

0 comments on commit fef3183

Please sign in to comment.