diff --git a/pom.xml b/pom.xml
index cf1dbb8..0454c85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,6 +55,12 @@
javafaker
1.0.2
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.3.1
+ test
+
diff --git a/src/main/java/org/hisp/dhis/actions/TrackerActions.java b/src/main/java/org/hisp/dhis/actions/TrackerActions.java
new file mode 100644
index 0000000..dbdf2ea
--- /dev/null
+++ b/src/main/java/org/hisp/dhis/actions/TrackerActions.java
@@ -0,0 +1,116 @@
+package org.hisp.dhis.actions;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.hisp.dhis.request.QueryParamsBuilder;
+import org.hisp.dhis.response.dto.ApiResponse;
+import org.hisp.dhis.response.dto.TrackerApiResponse;
+import org.hisp.dhis.utils.JsonObjectBuilder;
+
+import java.io.File;
+import java.time.Instant;
+import java.util.logging.Logger;
+
+import static org.hamcrest.Matchers.notNullValue;
+
+/**
+ * @author Gintare Vilkelyte
+ */
+public class TrackerActions
+ extends RestApiActions
+{
+ private Logger logger = Logger.getLogger( TrackerActions.class.getName() );
+
+ public TrackerActions()
+ {
+ super( "/tracker" );
+ }
+
+ public ApiResponse getJob( String jobId )
+ {
+ return this.get( "/jobs/" + jobId );
+ }
+
+ public ApiResponse waitUntilJobIsCompleted( String jobId )
+ {
+ logger.info( String.format( "Waiting until tracker job with id %s is completed", jobId ) );
+ ApiResponse response = null;
+ boolean completed = false;
+ int maxAttempts = 100;
+
+ while ( !completed && maxAttempts > 0 )
+ {
+ response = getJob( jobId );
+ response.validate().statusCode( 200 );
+ completed = response.extractList( "completed" ).contains( true );
+ maxAttempts--;
+ }
+
+ if ( maxAttempts == 0 )
+ {
+ logger.warning(
+ String.format( "Tracker job didn't complete in %d. Message: %s", maxAttempts, response.extract( "message" ) ) );
+ }
+
+ logger.info( "Tracker job is completed. Message: " + response.extract( "message" ) );
+ return response;
+ }
+
+ public TrackerApiResponse postAndGetJobReport( File file )
+ {
+ ApiResponse response = this.postFile( file );
+
+ return new TrackerApiResponse( response );
+ //return getJobReportByImportResponse( response );
+ }
+
+ public TrackerApiResponse postAndGetJobReport( File file, QueryParamsBuilder queryParamsBuilder )
+ {
+ queryParamsBuilder.add( "async=false" );
+ ApiResponse response = this.postFile( file, queryParamsBuilder );
+
+ return new TrackerApiResponse( response );
+ //return getJobReportByImportResponse( response );
+ }
+
+ public TrackerApiResponse postAndGetJobReport( JsonObject jsonObject )
+ {
+ ApiResponse response = this.post( jsonObject );
+
+ return new TrackerApiResponse( response );
+ //return getJobReportByImportResponse( response );
+ }
+
+ public TrackerApiResponse postAndGetJobReport( JsonObject jsonObject, QueryParamsBuilder queryParamsBuilder )
+ {
+ queryParamsBuilder.add( "async=false" );
+
+ ApiResponse response = this.post( jsonObject, queryParamsBuilder );
+
+ return new TrackerApiResponse( response );
+ //return getJobReportByImportResponse( response );
+ }
+
+ public TrackerApiResponse getJobReport( String jobId, String reportMode )
+ {
+ ApiResponse response = this.get( String.format( "/jobs/%s/report?reportMode=%s", jobId, reportMode ) );
+
+ // add created entities
+
+ return new TrackerApiResponse( response );
+ }
+
+ private TrackerApiResponse getJobReportByImportResponse( ApiResponse response )
+ {
+ response.validate()
+ .statusCode( 200 )
+ .body( "response.id", notNullValue() );
+
+ String jobId = response.extractString( "response.id" );
+
+ this.waitUntilJobIsCompleted( jobId );
+
+ return this.getJobReport( jobId, "FULL" );
+
+ }
+}
diff --git a/src/main/java/org/hisp/dhis/response/dto/ApiResponse.java b/src/main/java/org/hisp/dhis/response/dto/ApiResponse.java
index 82fd0c1..e810215 100644
--- a/src/main/java/org/hisp/dhis/response/dto/ApiResponse.java
+++ b/src/main/java/org/hisp/dhis/response/dto/ApiResponse.java
@@ -19,7 +19,7 @@ public Response getRaw()
return raw;
}
- private Response raw;
+ protected Response raw;
public ApiResponse( Response response )
{
diff --git a/src/main/java/org/hisp/dhis/response/dto/TrackerApiResponse.java b/src/main/java/org/hisp/dhis/response/dto/TrackerApiResponse.java
new file mode 100644
index 0000000..b4e1827
--- /dev/null
+++ b/src/main/java/org/hisp/dhis/response/dto/TrackerApiResponse.java
@@ -0,0 +1,90 @@
+package org.hisp.dhis.response.dto;
+
+import io.restassured.response.ValidatableResponse;
+import org.hamcrest.Matchers;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;
+
+/**
+ * @author Gintare Vilkelyte
+ */
+public class TrackerApiResponse
+ extends ApiResponse
+{
+
+ public TrackerApiResponse( ApiResponse response )
+ {
+ super( response.raw );
+ }
+
+ public List extractImportedTeis()
+ {
+ return this.extractList( "bundleReport.typeReportMap.TRACKED_ENTITY.objectReports.uid" );
+ }
+
+ public List extractImportedEnrollments()
+ {
+ return this.extractList( "bundleReport.typeReportMap.ENROLLMENT.objectReports.uid" );
+ }
+
+ public List extractImportedEvents()
+ {
+ return this.extractList( "bundleReport.typeReportMap.EVENT.objectReports.uid" );
+ }
+
+ public List extractImportedRelationships()
+ {
+ return this.extractList( "bundleReport.typeReportMap.RELATIONSHIP.objectReports.uid" );
+ }
+
+ public TrackerApiResponse validateSuccessfulImport()
+ {
+ validate()
+ .statusCode( 200 )
+ .body( "status", equalTo( "OK" ) )
+ .body( "stats.created", greaterThanOrEqualTo( 1 ) )
+ .body( "stats.ignored", equalTo( 0 ) )
+ .body( "stats.total", greaterThanOrEqualTo( 1 ) )
+ .body( "bundleReport.typeReportMap", notNullValue() );
+
+ return this;
+ }
+
+ public ValidatableResponse validateErrorReport()
+ {
+ return validate().statusCode( 200 )
+ .body( "stats.ignored", greaterThanOrEqualTo( 1 ) )
+ .body( "validationReport.errorReports", Matchers.notNullValue() )
+ .rootPath( "validationReport.errorReports" );
+ }
+
+ public ValidatableResponse validateWarningReport() {
+ return validate().statusCode( 200 )
+ .body( "validationReport.warningReports", Matchers.notNullValue())
+ .rootPath( "validationReport.warningReports");
+ }
+
+ public ValidatableResponse validateTeis() {
+ return validate()
+ .body( "bundleReport.typeReportMap.TRACKED_ENTITY", notNullValue() )
+ .rootPath( "bundleReport.typeReportMap.TRACKED_ENTITY" );
+ }
+
+ public ValidatableResponse validateEvents() {
+ return validate()
+ .body( "bundleReport.typeReportMap.EVENT", notNullValue() )
+ .rootPath( "bundleReport.typeReportMap.EVENT" );
+ }
+
+ public ValidatableResponse validateEnrollments()
+ {
+ return validate()
+ .body( "bundleReport.typeReportMap.ENROLLMENT", notNullValue() )
+ .rootPath( "bundleReport.typeReportMap.ENROLLMENT" );
+ }
+
+}
diff --git a/src/test/java/org/hisp/dhis/request/DataRandomizerTest.java b/src/test/java/org/hisp/dhis/request/DataRandomizerTest.java
new file mode 100644
index 0000000..cb92cef
--- /dev/null
+++ b/src/test/java/org/hisp/dhis/request/DataRandomizerTest.java
@@ -0,0 +1,24 @@
+package org.hisp.dhis.request;
+
+import org.hisp.dhis.utils.DataRandomizer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Gintare Vilkelyte
+ */
+public class DataRandomizerTest
+{
+ @ParameterizedTest
+ @CsvSource( {
+ "1,1,1"
+ } )
+ public void shouldGenerateRandomNumberBetween(int min, int max, int expected) {
+ int random = DataRandomizer.randomIntInRange( min, max );
+
+ assertEquals(random, expected);
+ }
+}