Skip to content

Commit

Permalink
test: add tracker program metadata and test environment set-up (#165)
Browse files Browse the repository at this point in the history
* test: add tracker program metadata

- Enhanced metadata in test containers to include a tracker program.
- Implemented functionality for adding tracked entities with enrollment into the newly included tracker program.

* fix: using DHIS2 Formatter
  • Loading branch information
JohanGHole authored Nov 17, 2023
1 parent eeba189 commit 0734909
Show file tree
Hide file tree
Showing 6 changed files with 41,011 additions and 39 deletions.
28 changes: 14 additions & 14 deletions rapidpro-docker/rapidpro/stack/startup.sh
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
#!/bin/sh
set -ex # fail on any error & print commands as they're run
if [ "x$MANAGEPY_COLLECTSTATIC" = "xon" ]; then
/venv/bin/python manage.py collectstatic --noinput --no-post-process
/venv/bin/python manage.py collectstatic --noinput --no-post-process
fi
if [ "x$CLEAR_COMPRESSOR_CACHE" = "xon" ]; then
/venv/bin/python clear-compressor-cache.py
/venv/bin/python clear-compressor-cache.py
fi
if [ "x$MANAGEPY_COMPRESS" = "xon" ]; then
/venv/bin/python manage.py compress --extension=".haml" --force -v0
/venv/bin/python manage.py compress --extension=".haml" --force -v0
fi
if [ "x$MANAGEPY_INIT_DB" = "xon" ]; then
set +x # make sure the password isn't echoed to stdout
echo "*:*:*:*:$(echo \"$DATABASE_URL\" | cut -d'@' -f1 | cut -d':' -f3)" > $HOME/.pgpass
set -x
chmod 0600 $HOME/.pgpass
/venv/bin/python manage.py dbshell < init_db.sql
rm $HOME/.pgpass
set +x # make sure the password isn't echoed to stdout
echo "*:*:*:*:$(echo \"$DATABASE_URL\" | cut -d'@' -f1 | cut -d':' -f3)" > $HOME/.pgpass
set -x
chmod 0600 $HOME/.pgpass
/venv/bin/python manage.py dbshell < init_db.sql
rm $HOME/.pgpass
fi
if [ "x$MANAGEPY_MIGRATE" = "xon" ]; then
/venv/bin/python manage.py migrate
/venv/bin/python manage.py migrate
fi
if [ "x$MANAGEPY_IMPORT_GEOJSON" = "xon" ]; then
echo "Downloading geojson for relation_ids $OSM_RELATION_IDS"
/venv/bin/python manage.py download_geojson $OSM_RELATION_IDS
/venv/bin/python manage.py import_geojson ./geojson/*.json
echo "Imported geojson for relation_ids $OSM_RELATION_IDS"
echo "Downloading geojson for relation_ids $OSM_RELATION_IDS"
/venv/bin/python manage.py download_geojson $OSM_RELATION_IDS
/venv/bin/python manage.py import_geojson ./geojson/*.json
echo "Imported geojson for relation_ids $OSM_RELATION_IDS"
fi
$STARTUP_CMD
214 changes: 190 additions & 24 deletions src/test/java/org/hisp/dhis/integration/rapidpro/Environment.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,14 @@
import org.hisp.dhis.api.model.v40_0.OrganisationUnitLevel;
import org.hisp.dhis.api.model.v40_0.RefOrganisationUnit;
import org.hisp.dhis.api.model.v40_0.RefUserRole;
import org.hisp.dhis.api.model.v40_0.TrackedEntity;
import org.hisp.dhis.api.model.v40_0.TrackerReportImportReport;
import org.hisp.dhis.api.model.v40_0.User;
import org.hisp.dhis.api.model.v40_0.UserCredentialsDto;
import org.hisp.dhis.api.model.v40_0.WebMessage;
import org.hisp.dhis.api.model.v40_0.WebapiControllerTrackerViewAttribute;
import org.hisp.dhis.api.model.v40_0.WebapiControllerTrackerViewRelationshipItemEnrollment;
import org.hisp.dhis.api.model.v40_0.WebapiControllerTrackerViewRelationshipItemEvent;
import org.hisp.dhis.integration.sdk.Dhis2ClientBuilder;
import org.hisp.dhis.integration.sdk.api.Dhis2Client;
import org.hisp.dhis.integration.sdk.api.Dhis2Response;
Expand All @@ -62,12 +67,16 @@
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import static io.restassured.RestAssured.given;
Expand All @@ -77,6 +86,12 @@ public final class Environment
{
public static final String DHIS_IMAGE_NAME = System.getProperty( "dhis.image.name" );

private static final Logger LOGGER = LoggerFactory.getLogger( Environment.class );

private static final Network RAPIDPRO_NETWORK = Network.builder().build();

private static final Network DHIS2_NETWORK = Network.builder().build();

public static String ORG_UNIT_ID;

public static Dhis2Client DHIS2_CLIENT;
Expand All @@ -89,11 +104,11 @@ public final class Environment

public static String RAPIDPRO_API_TOKEN;

private static final Logger LOGGER = LoggerFactory.getLogger( Environment.class );
public static RequestSpecification RAPIDPRO_REQUEST_SPEC;

private static final Network RAPIDPRO_NETWORK = Network.builder().build();
public static RequestSpecification RAPIDPRO_API_REQUEST_SPEC;

private static final Network DHIS2_NETWORK = Network.builder().build();
public static PostgreSQLContainer<?> DHIS2_DB_CONTAINER;

private static GenericContainer<?> RAPIDPRO_CONTAINER;

Expand All @@ -103,12 +118,6 @@ public final class Environment

private static GenericContainer<?> MAILROOM_CONTAINER;

public static RequestSpecification RAPIDPRO_REQUEST_SPEC;

public static RequestSpecification RAPIDPRO_API_REQUEST_SPEC;

public static PostgreSQLContainer<?> DHIS2_DB_CONTAINER;

static
{
try
Expand All @@ -129,10 +138,16 @@ public final class Environment
}
}

private Environment()
{

}

private static void setUpDhis2()
throws
IOException,
InterruptedException
InterruptedException,
ParseException
{
String dhis2ApiUrl = String.format( "http://%s:%s/api", DHIS2_CONTAINER.getHost(),
DHIS2_CONTAINER.getFirstMappedPort() );
Expand All @@ -156,7 +171,9 @@ private static void setUpDhis2()
importMetaData( Objects.requireNonNull( orgUnitLevelId ) );
addOrgUnitToAdminUser( ORG_UNIT_ID );
addOrgUnitToDataSet( ORG_UNIT_ID );
addOrgUnitToTrackerProgram( ORG_UNIT_ID );
createDhis2Users( ORG_UNIT_ID );
createDhis2TrackedEntitiesWithEnrollment( ORG_UNIT_ID );
runAnalytics();
}

Expand All @@ -183,25 +200,22 @@ private static void setUpRapidPro()
.when()
.post( "/org/signup/" ).then().statusCode( 302 );

importFlowUnderTest();
importTestFlow( "flow.json" );
importTestFlow( "laboratoryTestingFlow.json" );
importTestFlow( "specimenCollectionFlow.json" );

RAPIDPRO_API_TOKEN = generateRapidProApiToken();
RAPIDPRO_API_REQUEST_SPEC = new RequestSpecBuilder().setBaseUri( RAPIDPRO_API_URL )
.addHeader( "Authorization", "Token " + RAPIDPRO_API_TOKEN ).build();
System.setProperty( "rapidpro.api.token", RAPIDPRO_API_TOKEN );
}

private Environment()
{

}

private static void importFlowUnderTest()
private static void importTestFlow( String fileName )
throws
IOException
{
String flowDefinition = StreamUtils.copyToString(
Thread.currentThread().getContextClassLoader().getResourceAsStream( "flow.json" ),
Thread.currentThread().getContextClassLoader().getResourceAsStream( fileName ),
Charset.defaultCharset() );

String sessionId = fetchRapidProSessionId( "[email protected]", "12345678" );
Expand Down Expand Up @@ -362,6 +376,15 @@ private static void addOrgUnitToDataSet( String orgUnitId )
.close();
}

private static void addOrgUnitToTrackerProgram( String orgUnitId )
throws
IOException
{
DHIS2_CLIENT.post( "programs/w0qPtIW0JYu/organisationUnits/{orgUnitId}", orgUnitId )
.transfer()
.close();
}

public static void createDhis2Users( String orgUnitId )
{
int phoneNumber = 21000000;
Expand Down Expand Up @@ -407,6 +430,143 @@ public static String createDhis2User( String orgUnitId, String phoneNumber )
return dhis2Response.returnAs( WebMessage.class ).getResponse().get().get( "uid" );
}

public static void createDhis2TrackedEntitiesWithEnrollment( String orgUnitId )
throws
IOException,
ParseException
{
createDhis2TrackedEntitiesWithEnrollment( orgUnitId, 10 );
}

public static void createDhis2TrackedEntitiesWithEnrollment( String orgUnitId, int numOfTrackedEntities )
throws
IOException,
ParseException
{
int phoneNumber = 50100;
int patientId = 1000000;
for ( int i = 0; i < numOfTrackedEntities; i++ )
{
String firstName = new Faker().name().firstName();
createDhis2TrackedEntityWithEnrollment( orgUnitId, "55" + phoneNumber, "ID-" + patientId, firstName );
phoneNumber++;
patientId++;
}
}

public static String createDhis2TrackedEntityWithEnrollment( String orgUnitId, String phoneNumber,
String patientUID, String firstName )
throws
IOException,
ParseException
{
List<String> programStageIds = List.of( "ZP5HZ87wzc0" );
TrackedEntity trackedEntity = new TrackedEntity()
.withOrgUnit( orgUnitId )
.withTrackedEntityType( "MCPQUTHX1Ze" )
.withEnrollments(
List.of( createDhis2EnrollmentWithProgramStageEvents( orgUnitId, phoneNumber, patientUID, firstName,
programStageIds ) ) );

String enrollmentId = DHIS2_CLIENT.post( "tracker" )
.withResource( Map.of( "trackedEntities", List.of( trackedEntity ) ) )
.withParameter( "async", "false" )
.transfer()
.returnAs( TrackerReportImportReport.class ).getBundleReport().get().getTypeReportMap().get()
.getAdditionalProperties().get( "ENROLLMENT" ).getObjectReports().get().get( 0 ).getUid().get()
.toString();
return enrollmentId;
}

public static String createDhis2TrackedEntityWithEnrollment( String orgUnitId, String phoneNumber,
String patientUID, String firstName,
List<String> programStageIds )
throws
IOException,
ParseException
{
TrackedEntity trackedEntity = new TrackedEntity()
.withOrgUnit( orgUnitId )
.withTrackedEntityType( "MCPQUTHX1Ze" )
.withEnrollments(
List.of( createDhis2EnrollmentWithProgramStageEvents( orgUnitId, phoneNumber, patientUID, firstName,
programStageIds ) ) );

String enrollmentId = DHIS2_CLIENT.post( "tracker" )
.withResource( Map.of( "trackedEntities", List.of( trackedEntity ) ) )
.withParameter( "async", "false" )
.transfer()
.returnAs( TrackerReportImportReport.class ).getBundleReport().get().getTypeReportMap().get()
.getAdditionalProperties().get( "ENROLLMENT" ).getObjectReports().get().get( 0 ).getUid().get()
.toString();
return enrollmentId;
}

public static WebapiControllerTrackerViewRelationshipItemEnrollment createDhis2EnrollmentWithProgramStageEvents(
String orgUnitId, String phoneNumber, String patientUID, String firstName, List<String> programStageIds )
{
List<WebapiControllerTrackerViewRelationshipItemEvent> events = new ArrayList<>();
String today = new SimpleDateFormat( "yyyy-MM-dd" ).format( new Date() );
Faker faker = new Faker();
String lastName = faker.name().lastName();
Date dateOfBirth = faker.date().past( 365 * 60, TimeUnit.DAYS );
SimpleDateFormat dmyFormat = new SimpleDateFormat( "yyyy-MM-dd" );
String dateOfBirthFmt = dmyFormat.format( dateOfBirth );
String gender = "Male";
for ( String programStage : programStageIds )
{
events.add( new WebapiControllerTrackerViewRelationshipItemEvent()
.withProgramStage( programStage )
.withOrgUnit( orgUnitId )
.withScheduledAt( today )
.withProgram( "w0qPtIW0JYu" )
.withStatus( WebapiControllerTrackerViewRelationshipItemEvent.Status.SCHEDULE ) );
}
return new WebapiControllerTrackerViewRelationshipItemEnrollment()
.withOrgUnit( orgUnitId )
.withProgram( "w0qPtIW0JYu" )
.withEnrolledAt( today )
.withAttributes(
List.of(
new WebapiControllerTrackerViewAttribute().withAttribute( "sB1IHYu2xQT" )
.withValue( firstName ),
new WebapiControllerTrackerViewAttribute().withAttribute( "ENRjVGxVL6l" )
.withValue( lastName ),
new WebapiControllerTrackerViewAttribute().withAttribute( "HlKXyR5qr2e" )
.withValue( patientUID ),
new WebapiControllerTrackerViewAttribute().withAttribute( "fctSQp5nAYl" )
.withValue( phoneNumber ),
new WebapiControllerTrackerViewAttribute().withAttribute( "oindugucx72" )
.withValue( gender ),
new WebapiControllerTrackerViewAttribute().withAttribute( "NI0QRzJvQ0k" )
.withValue( dateOfBirthFmt )
) )
.withOccurredAt( today )
.withStatus( WebapiControllerTrackerViewRelationshipItemEnrollment.Status.ACTIVE )
.withEvents( events );
}

public static void deleteDhis2TrackedEntities( String orgUnitId )
throws
IOException
{
Iterable<TrackedEntity> trackedEntitiesIterable = DHIS2_CLIENT.get( "tracker/trackedEntities" )
.withoutPaging()
.withParameter( "program", "w0qPtIW0JYu" )
.withParameter( "orgUnit", orgUnitId )
.transfer()
.returnAs( TrackedEntity.class, "instances" );

for ( TrackedEntity trackedEntity : trackedEntitiesIterable )
{
DHIS2_CLIENT.post( "tracker" )
.withResource( Map.of( "trackedEntities", List.of( trackedEntity ) ) )
.withParameter( "importStrategy", "DELETE" )
.transfer()
.close();
}
}

private static String fetchRapidProSessionId( String username, String password )
{
ExtractableResponse<Response> loginPageResponse = given( RAPIDPRO_REQUEST_SPEC ).when()
Expand Down Expand Up @@ -437,16 +597,22 @@ private static void importMetaData( String orgUnitLevelId )
throws
IOException
{
String metaData = StreamUtils.copyToString(
String mlagMetaData = StreamUtils.copyToString(
Thread.currentThread().getContextClassLoader().getResourceAsStream( "MLAG00_1.2.1_DHIS2.36.json" ),
Charset.defaultCharset() ).replaceAll( "<OU_LEVEL_DISTRICT_UID>", orgUnitLevelId )
.replaceAll( "<OU_LEVEL_FACILITY_UID>", orgUnitLevelId );

WebMessage webMessage = DHIS2_CLIENT.post( "metadata" )
.withResource( metaData )
String afiMetaData = StreamUtils.copyToString(
Thread.currentThread().getContextClassLoader()
.getResourceAsStream( "IDS_AFI_COMPLETE_1.0.0_DHIS2.38.json" ),
Charset.defaultCharset() );
WebMessage webMessageMlag = DHIS2_CLIENT.post( "metadata" )
.withResource( mlagMetaData )
.withParameter( "atomicMode", "NONE" ).transfer().returnAs( WebMessage.class );

assertEquals( WebMessage.Status.OK, webMessage.getStatus() );
WebMessage webMessageAfi = DHIS2_CLIENT.post( "metadata" )
.withResource( afiMetaData )
.withParameter( "atomicMode", "NONE" ).transfer().returnAs( WebMessage.class );
assertEquals( WebMessage.Status.OK, webMessageMlag.getStatus() );
assertEquals( WebMessage.Status.OK, webMessageAfi.getStatus() );
}

private static void createOrgUnitLevel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public class PullReportsRouteBuilderFunctionalTestCase extends AbstractFunctiona
public void doBeforeEach()
{
flowUuid = given( RAPIDPRO_API_REQUEST_SPEC ).get( "flows.json" ).then().extract()
.path( "results[0].uuid" );
.path( "results.find { it.name == 'Flow Under Test' }.uuid" );
System.setProperty( "rapidpro.flow.uuids", flowUuid );
}

Expand Down
Loading

0 comments on commit 0734909

Please sign in to comment.