You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ar...@apache.org on 2022/05/20 13:01:20 UTC

[fineract] branch develop updated: Datatable integration test

This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 64bfe3376 Datatable integration test
64bfe3376 is described below

commit 64bfe33766c2dd3223e5a0e23dd1fab9804f3ebd
Author: Jose Alberto Hernandez <al...@MacBook-Pro.local>
AuthorDate: Mon May 9 14:37:31 2022 -0500

    Datatable integration test
---
 build.gradle                                       |  2 +-
 .../infrastructure/core/service/DateUtils.java     |  3 +
 .../dataqueries/api/DatatablesApiResource.java     |  4 -
 .../service/GenericDataServiceImpl.java            | 19 +++--
 .../service/ReadWriteNonCoreDataServiceImpl.java   |  3 +-
 .../fineract/integrationtests/common/Utils.java    | 46 ++++++++++++
 .../EntityDatatableChecksIntegrationTest.java      | 20 +++++
 .../common/system/DatatableHelper.java             | 43 +++++++++++
 .../common/system/DatatableIntegrationTest.java    | 87 ++++++++++++++++++++++
 9 files changed, 216 insertions(+), 11 deletions(-)

diff --git a/build.gradle b/build.gradle
index 03a22692b..409e723c2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -117,7 +117,7 @@ allprojects  {
     spotless {
         format 'misc', {
             target '**/*.md', '**/*.properties', '**/.gitignore', '**/.openapi-generator-ignore', '**/*.yml', '**/*.xml', '**/**.json', '**/*.sql'
-            targetExclude '**/build/**', '**/bin/**', '**/.settings/**', '**/.idea/**', '**/.gradle/**', '**/gradlew.bat', '**/licenses/**', '**/banner.txt'
+            targetExclude '**/build/**', '**/bin/**', '**/.settings/**', '**/.idea/**', '**/.gradle/**', '**/gradlew.bat', '**/licenses/**', '**/banner.txt', '.vscode/**'
             indentWithSpaces(4)
             endWithNewline()
             trimTrailingWhitespace()
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java
index 93e48d63f..b39a3acc2 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java
@@ -37,6 +37,9 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
 
 public final class DateUtils {
 
+    public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    public static final DateTimeFormatter DEFAULT_DATETIME_FORMATER = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_FORMAT);
+
     private DateUtils() {
 
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DatatablesApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DatatablesApiResource.java
index 41ceaec4d..915435007 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DatatablesApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DatatablesApiResource.java
@@ -53,7 +53,6 @@ import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
 import org.apache.fineract.infrastructure.dataqueries.service.GenericDataService;
 import org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataService;
 import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
@@ -71,7 +70,6 @@ public class DatatablesApiResource {
     private final ReadWriteNonCoreDataService readWriteNonCoreDataService;
     private final ToApiJsonSerializer<GenericResultsetData> toApiJsonSerializer;
     private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
-    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(DatatablesApiResource.class);
 
     @Autowired
     public DatatablesApiResource(final PlatformSecurityContext context, final GenericDataService genericDataService,
@@ -259,8 +257,6 @@ public class DatatablesApiResource {
     public String getDatatableManyEntry(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId,
             @PathParam("datatableId") final Long datatableId, @QueryParam("order") final String order, @Context final UriInfo uriInfo) {
 
-        LOG.debug("::1 we came in the getDatatbleManyEntry apiRessource method");
-
         this.context.authenticatedUser().validateHasDatatableReadPermission(datatable);
 
         final GenericResultsetData results = this.readWriteNonCoreDataService.retrieveDataTableGenericResultSet(datatable, apptableId,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java
index c305c8cfc..bbd8e1243 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/GenericDataServiceImpl.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.List;
 import javax.sql.DataSource;
 import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
 import org.apache.fineract.infrastructure.core.service.database.DatabaseIndependentQueryService;
 import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
@@ -32,8 +33,6 @@ import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeader
 import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnValueData;
 import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
 import org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoundException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -47,7 +46,6 @@ public class GenericDataServiceImpl implements GenericDataService {
     private final JdbcTemplate jdbcTemplate;
     private final DataSource dataSource;
     private final DatabaseIndependentQueryService databaseIndependentQueryService;
-    private static final Logger LOG = LoggerFactory.getLogger(GenericDataServiceImpl.class);
 
     @Autowired
     public GenericDataServiceImpl(final RoutingDataSource dataSource, final JdbcTemplate jdbcTemplate,
@@ -169,9 +167,10 @@ public class GenericDataServiceImpl implements GenericDataService {
                             writer.append(
                                     "[" + localDate.getYear() + ", " + localDate.getMonthValue() + ", " + localDate.getDayOfMonth() + "]");
                         } else if (currColType.equals("DATETIME")) {
-                            final LocalDateTime localDateTime = LocalDateTime.parse(currVal);
+                            final LocalDateTime localDateTime = LocalDateTime.parse(formatDateTimeValue(currVal),
+                                    DateUtils.DEFAULT_DATETIME_FORMATER);
                             writer.append("[" + localDateTime.getYear() + ", " + localDateTime.getMonthValue() + ", "
-                                    + localDateTime.getDayOfMonth() + " " + localDateTime.getHour() + ", " + localDateTime.getMinute()
+                                    + localDateTime.getDayOfMonth() + ", " + localDateTime.getHour() + ", " + localDateTime.getMinute()
                                     + ", " + localDateTime.getSecond() + ", " + localDateTime.get(ChronoField.MILLI_OF_SECOND) + "]");
                         } else {
                             writer.append(doubleQuote + replace(currVal, doubleQuote, slashDoubleQuote) + doubleQuote);
@@ -262,4 +261,14 @@ public class GenericDataServiceImpl implements GenericDataService {
             throw new DatatableNotFoundException(datatable);
         }
     }
+
+    private String formatDateTimeValue(String dateTimeValue) {
+        if (dateTimeValue.length() > 19) {
+            dateTimeValue = dateTimeValue.substring(0, 19);
+        }
+        if (dateTimeValue.contains("T")) {
+            dateTimeValue = dateTimeValue.replace("T", " ");
+        }
+        return dateTimeValue;
+    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
index 7db6c1c20..de7353ef2 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
@@ -1710,7 +1710,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
             // ignores id and foreign key fields
             // also ignores locale and dateformat fields that are used for
             // validating numeric and date data
-            if (!(key.equalsIgnoreCase("id") || key.equalsIgnoreCase(keyFieldName) || key.equals("locale") || key.equals("dateFormat"))) {
+            if (!(key.equalsIgnoreCase("id") || key.equalsIgnoreCase(keyFieldName) || key.equals("locale") || key.equals("dateFormat")
+                    || key.equals(DataTableApiConstant.CREATEDAT_FIELD_NAME) || key.equals(DataTableApiConstant.UPDATEDAT_FIELD_NAME))) {
                 notFound = true;
                 // matches incoming fields with and without underscores (spaces
                 // and underscores considered the same)
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java
index 9d7bb3b4f..69f841105 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java
@@ -23,6 +23,9 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.fail;
 
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
@@ -37,8 +40,12 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.ZoneId;
+import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.TimeZone;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -59,6 +66,7 @@ public final class Utils {
 
     private static final Logger LOG = LoggerFactory.getLogger(Utils.class);
     private static final SecureRandom random = new SecureRandom();
+    private static final Gson gson = new Gson();
 
     public static final String TENANT_PARAM_NAME = "tenantIdentifier";
     public static final String DEFAULT_TENANT = "default";
@@ -157,6 +165,20 @@ public final class Utils {
         return (T) JsonPath.from(json).get(jsonAttributeToGetBack);
     }
 
+    public static List<String> performServerGetList(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+            final String getURL, final String jsonAttributeToGetBack) {
+        final JsonPath jsonPath = given().spec(requestSpec).expect().spec(responseSpec).log().ifError().when().get(getURL).jsonPath();
+        List<String> items = jsonPath.getList(jsonAttributeToGetBack);
+        return items;
+    }
+
+    public static JsonElement performServerGetArray(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+            final String getURL, final int position, final String jsonAttributeToGetBack) {
+        final JsonPath jsonPath = given().spec(requestSpec).expect().spec(responseSpec).log().ifError().when().get(getURL).jsonPath();
+        List<Map<String, Object>> items = jsonPath.getList("$");
+        return gson.fromJson(((ArrayList) items.get(position).get(jsonAttributeToGetBack)).toString(), JsonArray.class);
+    }
+
     public static String performGetTextResponse(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
             final String getURL) {
         return given().spec(requestSpec).expect().spec(responseSpec).log().ifError().when().get(getURL).andReturn().asString();
@@ -251,6 +273,12 @@ public final class Utils {
         return dateFormat.format(dateToBeConvert.getTime());
     }
 
+    public static String convertDateToURLFormat(final Calendar dateToBeConvert, final String dateGormat) {
+        DateFormat dateFormat = new SimpleDateFormat(dateGormat);
+        dateFormat.setTimeZone(Utils.getTimeZoneOfTenant());
+        return dateFormat.format(dateToBeConvert.getTime());
+    }
+
     public static LocalDate getLocalDateOfTenant() {
         LocalDate today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
         final ZoneId zone = ZoneId.of(TENANT_TIME_ZONE);
@@ -264,6 +292,24 @@ public final class Utils {
         return TimeZone.getTimeZone(TENANT_TIME_ZONE);
     }
 
+    public static Date convertJsonElementAsDate(JsonElement jsonElement) {
+        if (jsonElement.isJsonArray()) {
+            JsonArray jsonArray = jsonElement.getAsJsonArray();
+            Calendar calendar = Calendar.getInstance();
+            calendar.set(Calendar.YEAR, jsonArray.get(0).getAsInt());
+            calendar.set(Calendar.MONTH, jsonArray.get(1).getAsInt() - 1);
+            calendar.set(Calendar.DATE, jsonArray.get(2).getAsInt());
+            // If the Array includes Time
+            if (jsonArray.size() > 3) {
+                calendar.set(Calendar.HOUR, jsonArray.get(3).getAsInt());
+                calendar.set(Calendar.MINUTE, jsonArray.get(4).getAsInt());
+                calendar.set(Calendar.SECOND, jsonArray.get(5).getAsInt());
+            }
+            return calendar.getTime();
+        }
+        return null;
+    }
+
     public static String performServerTemplatePost(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
             final String postURL, final String legalFormType, final File file, final String locale, final String dateFormat) {
 
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java
index ce9cac217..190416d34 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java
@@ -81,6 +81,26 @@ public class EntityDatatableChecksIntegrationTest {
         this.datatableHelper = new DatatableHelper(this.requestSpec, this.responseSpec);
     }
 
+    @Test
+    public void validateCreateDeleteDatatableCheck() {
+        // creating datatable
+        String datatableName = this.datatableHelper.createDatatable(CLIENT_APP_TABLE_NAME, false);
+        DatatableHelper.verifyDatatableCreatedOnServer(this.requestSpec, this.responseSpec, datatableName);
+
+        // creating new entity datatable check
+        Integer entityDatatableCheckId = this.entityDatatableChecksHelper.createEntityDatatableCheck(CLIENT_APP_TABLE_NAME, datatableName,
+                100, null);
+        assertNotNull(entityDatatableCheckId, "ERROR IN CREATING THE ENTITY DATATABLE CHECK");
+
+        // deleting entity datatable check
+        entityDatatableCheckId = this.entityDatatableChecksHelper.deleteEntityDatatableCheck(entityDatatableCheckId);
+        assertNotNull(entityDatatableCheckId, "ERROR IN DELETING THE ENTITY DATATABLE CHECK");
+
+        // deleting the datatable
+        String deletedDataTableName = this.datatableHelper.deleteDatatable(datatableName);
+        assertEquals(datatableName, deletedDataTableName, "ERROR IN DELETING THE DATATABLE");
+    }
+
     @Test
     public void validateCreateDeleteEntityDatatableCheck() {
         // creating datatable
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java
index eb966d404..8ab185f31 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableHelper.java
@@ -21,9 +21,12 @@ package org.apache.fineract.integrationtests.common.system;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import com.google.gson.Gson;
+import com.google.gson.JsonElement;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import org.apache.fineract.integrationtests.common.Utils;
@@ -48,6 +51,33 @@ public class DatatableHelper {
                 getTestDatatableAsJSON(apptableName, multiRow), "resourceIdentifier");
     }
 
+    public Integer createDatatableEntry(final String apptableName, final String datatableName, final Integer apptableId,
+            final boolean genericResultSet, final String dateFormat) {
+        return Utils.performServerPost(
+                this.requestSpec, this.responseSpec, DATATABLE_URL + "/" + datatableName + "/" + apptableId + "?genericResultSet="
+                        + Boolean.toString(genericResultSet) + "&" + Utils.TENANT_IDENTIFIER,
+                getTestDatatableEntryAsJSON(dateFormat), "resourceId");
+    }
+
+    public String readDatatableEntry(final String datatableName, final Integer resourceId, final boolean genericResultset) {
+        return Utils.performServerGet(this.requestSpec, this.responseSpec, DATATABLE_URL + "/" + datatableName + "/" + resourceId
+                + "?genericResultSet=" + String.valueOf(genericResultset) + "&" + Utils.TENANT_IDENTIFIER);
+    }
+
+    public List<String> readDatatableEntry(final String datatableName, final Integer resourceId, final boolean genericResultset,
+            final String jsonAttributeToGetBack) {
+        return Utils.performServerGetList(this.requestSpec, this.responseSpec, DATATABLE_URL + "/" + datatableName + "/" + resourceId
+                + "?genericResultSet=" + String.valueOf(genericResultset) + "&" + Utils.TENANT_IDENTIFIER, jsonAttributeToGetBack);
+    }
+
+    public Date readDatatableEntry(final String datatableName, final Integer resourceId, final boolean genericResultset, final int position,
+            final String jsonAttributeToGetBack) {
+        final JsonElement jsonElement = Utils.performServerGetArray(this.requestSpec, this.responseSpec, DATATABLE_URL + "/" + datatableName
+                + "/" + resourceId + "?genericResultSet=" + String.valueOf(genericResultset) + "&" + Utils.TENANT_IDENTIFIER, position,
+                jsonAttributeToGetBack);
+        return Utils.convertJsonElementAsDate(jsonElement);
+    }
+
     public String deleteDatatable(final String datatableName) {
         return Utils.performServerDelete(this.requestSpec, this.responseSpec,
                 DATATABLE_URL + "/" + datatableName + "?" + Utils.TENANT_IDENTIFIER, "resourceIdentifier");
@@ -84,6 +114,19 @@ public class DatatableHelper {
         return requestJsonString;
     }
 
+    public static String getTestDatatableEntryAsJSON(final String dateFormat) {
+        final HashMap<String, Object> map = new HashMap<>();
+        map.put("Spouse Name", Utils.randomNameGenerator("Spouse_Name_", 5));
+        map.put("Number of Dependents", Utils.randomNumberGenerator(1));
+        map.put("Date of Approval", Utils.convertDateToURLFormat(Calendar.getInstance(), dateFormat));
+        map.put("locale", "en");
+        map.put("dateFormat", dateFormat);
+
+        String requestJsonString = new Gson().toJson(map);
+        LOG.info("map : {}", requestJsonString);
+        return requestJsonString;
+    }
+
     public static List<HashMap<String, Object>> addDatatableColumns(List<HashMap<String, Object>> datatableColumnsList, String columnName,
             String columnType, boolean isMandatory, Integer length) {
 
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableIntegrationTest.java
new file mode 100644
index 000000000..8dd165acd
--- /dev/null
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/system/DatatableIntegrationTest.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests.common.system;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import io.restassured.builder.RequestSpecBuilder;
+import io.restassured.builder.ResponseSpecBuilder;
+import io.restassured.http.ContentType;
+import io.restassured.specification.RequestSpecification;
+import io.restassured.specification.ResponseSpecification;
+import java.util.Date;
+import java.util.List;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class DatatableIntegrationTest {
+
+    private RequestSpecification requestSpec;
+    private ResponseSpecification responseSpec;
+    private DatatableHelper datatableHelper;
+
+    private static final String CLIENT_APP_TABLE_NAME = "m_client";
+
+    @BeforeEach
+    public void setup() {
+        Utils.initializeRESTAssured();
+        this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+        this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+        this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+        this.datatableHelper = new DatatableHelper(this.requestSpec, this.responseSpec);
+    }
+
+    @Test
+    public void validateCreateReadDeleteDatatable() {
+        // creating datatable for client entity
+        String datatableName = this.datatableHelper.createDatatable(CLIENT_APP_TABLE_NAME, false);
+        DatatableHelper.verifyDatatableCreatedOnServer(this.requestSpec, this.responseSpec, datatableName);
+
+        // creating client with datatables
+        final Integer clientID = ClientHelper.createClientAsPerson(requestSpec, responseSpec);
+
+        // creating new client datatable entry
+        final boolean genericResultSet = true;
+        Integer datatableResourceID = this.datatableHelper.createDatatableEntry(CLIENT_APP_TABLE_NAME, datatableName, clientID,
+                genericResultSet, "yyyy-MM-dd");
+        assertNotNull(datatableResourceID, "ERROR IN CREATING THE ENTITY DATATABLE RECORD");
+
+        // Read the Datatable entry generated with genericResultSet in true (default)
+        final List<String> items = this.datatableHelper.readDatatableEntry(datatableName, clientID, genericResultSet, "data");
+        assertEquals(1, items.size());
+
+        // Read the Datatable entry generated with genericResultSet in false
+        final Date valueDate = this.datatableHelper.readDatatableEntry(datatableName, clientID, !genericResultSet, 0, "Date of Approval");
+        assertNotNull(valueDate, "ERROR IN GETTING THE DATE VALUE FROM DATATABLE RECORD");
+        assertInstanceOf(Date.class, valueDate);
+
+        // deleting datatable entries
+        Integer appTableId = this.datatableHelper.deleteDatatableEntries(datatableName, clientID, "clientId");
+        assertEquals(clientID, appTableId, "ERROR IN DELETING THE DATATABLE ENTRIES");
+
+        // deleting the datatable
+        String deletedDataTableName = this.datatableHelper.deleteDatatable(datatableName);
+        assertEquals(datatableName, deletedDataTableName, "ERROR IN DELETING THE DATATABLE");
+    }
+
+}