From 6304446b9e26c130774b3e9e2a7efdff86b539d5 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Tue, 30 Jul 2024 00:28:53 +0530 Subject: [PATCH] CIRC-2100 Adding test cases --- descriptors/ModuleDescriptor-template.json | 2 +- ramls/examples/request.json | 9 ++ ramls/request.json | 40 +++++ .../api/printEvents/PrintEventsTests.java | 147 ++++++++++++++++-- .../java/api/support/fakes/FakeOkapi.java | 2 + .../fakes/FakePrintEventStatusModule.java | 86 ++++++++++ 6 files changed, 275 insertions(+), 11 deletions(-) create mode 100644 src/test/java/api/support/fakes/FakePrintEventStatusModule.java diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 5f421a1673..f2e3bb42e7 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -185,7 +185,7 @@ }, { "id": "circulation", - "version": "14.3", + "version": "14.4", "handlers": [ { "methods": [ diff --git a/ramls/examples/request.json b/ramls/examples/request.json index efeca2d28b..228c97f1b7 100644 --- a/ramls/examples/request.json +++ b/ramls/examples/request.json @@ -45,5 +45,14 @@ "callNumber": "F16.H37 A2 9001" }, "pickupServicePointName": "Circ Desk 1" + }, + "printDetails": { + "count": 4, + "lastPrintedDate": "2024-07-29T11:54:07.000Z", + "lastPrintRequester": { + "lastName": "lastName", + "firstName": "firstName", + "middleName": "middleName" + } } } diff --git a/ramls/request.json b/ramls/request.json index 9e38fe6c7f..1b80913dbb 100644 --- a/ramls/request.json +++ b/ramls/request.json @@ -358,6 +358,46 @@ } } }, + "printDetails": { + "description": "The print details of the request", + "type": "object", + "readonly": true, + "properties": { + "count": { + "description": "Total no of times the request is printed", + "type": "integer", + "readOnly": true + }, + "lastPrintedDate": { + "description": "Recent printed time of the request", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "lastPrintRequester": { + "description": "Details of the User who printed the request recently", + "readonly": true, + "type": "object", + "properties": { + "firstName": { + "description": "first name of the user", + "type": "string", + "readonly": true + }, + "lastName": { + "description": "last name of the user", + "type": "string", + "readonly": true + }, + "middleName": { + "description": "middle name of the user", + "type": "string", + "readonly": true + } + } + } + } + }, "tags": { "type": "object", "description": "Tags", diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index 0d8b03bce7..bdc301bca3 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -3,23 +3,39 @@ import api.support.APITests; import api.support.builders.CirculationSettingBuilder; import api.support.builders.RequestBuilder; +import api.support.http.IndividualResource; +import api.support.http.UserResource; import io.vertx.core.json.JsonObject; import org.folio.circulation.support.http.client.Response; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.stream.IntStream; +import static api.support.http.CqlQuery.exactMatch; import static api.support.http.InterfaceUrls.printEventsUrl; import static api.support.matchers.ResponseStatusCodeMatcher.hasStatus; import static org.folio.HttpStatus.HTTP_CREATED; import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; class PrintEventsTests extends APITests { + private IndividualResource servicePointResource; + private UserResource userResource; + + @BeforeEach + void executeBefore() { + userResource = usersFixture.charlotte(); + servicePointResource = servicePointsFixture.cd1(); + circulationSettingsClient.deleteAll(); + } @Test void postPrintEventsTest() { @@ -27,12 +43,96 @@ void postPrintEventsTest() { .withName("printEventLogFeature") .withValue(new JsonObject().put("enablePrintLog", true))); JsonObject printRequest = getPrintEvent(); - printRequest.put("requestIds", createOneHundredRequests()); + printRequest.put("requestIds", createMultipleRequests(100, "test-")); System.out.println(printRequest.getString("requestIds")); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_CREATED)); } + @Test + void postPrintEventsAndFetchPrintDetailsInRequestApi() { + var itemBarcodePrefix = "itemBarcode-"; + + assertThat("Circulation settings enabled", circulationSettingsClient.getAll().isEmpty()); + + // creating 2 different requests and assert request details without enabling printEvent feature + var uuidList = createMultipleRequests(2, itemBarcodePrefix); + JsonObject requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + JsonObject requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should be null for request1 because the print event feature is not enabled", + requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); + assertThat("printDetails should be null for request2 because the print event feature is not enabled", + requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); + + // Enabling printEvent feature and assert request details. + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("printEventLogFeature") + .withValue(new JsonObject().put("enablePrintLog", true))); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should be null for request1 because the request is not printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); + assertThat("printDetails should be null for request2 because the request is not printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); + + // Printing both request1 and request2 + JsonObject printRequest = getPrintEvent(); + printRequest.put("requestIds", uuidList); + printRequest.put("requesterId", userResource.getId()); + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should not be null for request1 because the request is printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); + assertThat("printDetails should not be null for request2 because the request is printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); + assertPrintDetails(requestRepresentation1, 1, "2024-06-25T11:54:07.000Z"); + assertPrintDetails(requestRepresentation2, 1, "2024-06-25T11:54:07.000Z"); + + // Print both the request id again with same user. + // In this case, we will get the latest print event date and the count is increased + printRequest.put("printEventDate", "2024-06-25T14:54:07.000Z"); + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should not be null for request1 because the request is printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); + assertThat("printDetails should not be null for request2 because the request is printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); + assertPrintDetails(requestRepresentation1, 2, "2024-06-25T14:54:07.000Z"); + assertPrintDetails(requestRepresentation2, 2, "2024-06-25T14:54:07.000Z"); + + // Print only request1 with unknown user id. + // In this case, request representation won't contain lastPrintRequester detail + printRequest.put("requesterId", UUID.randomUUID()); + printRequest.put("requestIds", List.of(uuidList.get(0))); + printRequest.put("printEventDate", "2024-06-25T14:59:07.000Z"); + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should not be null for request1 because the request is printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); + assertThat("printDetails should not be null for request2 because the request is printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); + assertPrintDetails(requestRepresentation2, 2, "2024-06-25T14:54:07.000Z"); + assertThat(requestRepresentation1.getJsonObject("printDetails").getInteger("count"), is(3)); + assertThat(requestRepresentation1.getJsonObject("printDetails").getString("lastPrintedDate"), + is("2024-06-25T14:59:07.000Z")); + assertThat("lastPrintRequester object should be null because we used random uuid for user id while printing", + requestRepresentation1.getJsonObject("printDetails").getJsonObject("lastPrintRequester"), + Matchers.nullValue()); + } + @Test void postPrintEventsWhenCirculationSettingIsNotPresentTest() { JsonObject printRequest = getPrintEvent(); @@ -74,8 +174,8 @@ void postPrintEventsWithInvalidRequestId() { .withName("printEventLogFeature") .withValue(new JsonObject().put("enablePrintLog", true))); JsonObject printRequest = getPrintEvent(); - List requestIds = new ArrayList<>(createOneHundredRequests()); - requestIds.add(UUID.randomUUID()); + List requestIds = new ArrayList<>(createMultipleRequests(10, "invalid-")); + requestIds.add(UUID.randomUUID().toString()); printRequest.put("requestIds", requestIds); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); @@ -111,19 +211,46 @@ private JsonObject getPrintEvent() { return new JsonObject() .put("requesterId", "5f5751b4-e352-4121-adca-204b0c2aec43") .put("requesterName", "requester") - .put("printEventDate", "2024-06-25T14:30:00Z"); + .put("printEventDate", "2024-06-25T11:54:07.000Z"); } - private List createOneHundredRequests() { - final UUID pickupServicePointId = servicePointsFixture.cd1().getId(); + private List createMultipleRequests(int noOfRequests, String itemBarcode) { - return IntStream.range(0, 100).mapToObj(notUsed -> requestsFixture.place( + return IntStream.range(0, noOfRequests).mapToObj(i -> requestsFixture.place( new RequestBuilder() .open() .page() - .forItem(itemsFixture.basedUponSmallAngryPlanet()) - .by(usersFixture.charlotte()) + .forItem(itemsFixture.basedUponSmallAngryPlanet(itemBarcode + i)) + .by(userResource) .fulfillToHoldShelf() - .withPickupServicePointId(pickupServicePointId)).getId()).toList(); + .withRequestExpiration(LocalDate.of(2024, 7, 30)) + .withHoldShelfExpiration(LocalDate.of(2024, 8, 15)) + .withPickupServicePointId(servicePointResource.getId())).getId().toString()).toList(); + } + + private void assertRequestDetails(JsonObject representation, String id, String barcodeName) { + assertThat(representation.getString("id"), is(id)); + assertThat(representation.getString("requestType"), is("Page")); + assertThat(representation.getString("requestLevel"), is("Item")); + assertThat(representation.getString("requestDate"), is("2017-07-15T09:35:27.000Z")); + assertThat(representation.getJsonObject("item").getString("barcode"), is(barcodeName)); + assertThat(representation.getString("fulfillmentPreference"), is("Hold Shelf")); + assertThat(representation.getString("requestExpirationDate"), is("2024-07-30T23:59:59.000Z")); + assertThat(representation.getString("holdShelfExpirationDate"), is("2024-08-15")); + assertThat(representation.getString("status"), is("Open - Not yet filled")); + assertThat(representation.getString("pickupServicePointId"), is(servicePointResource.getId().toString())); + } + + private void assertPrintDetails(JsonObject representation, int count, String printEventDate) { + var printDetailObject = representation.getJsonObject("printDetails"); + var lastPrintRequesterObject = printDetailObject.getJsonObject("lastPrintRequester"); + assertThat(printDetailObject.getInteger("count"), is(count)); + assertThat(printDetailObject.getString("lastPrintedDate"), is(printEventDate)); + assertThat(lastPrintRequesterObject.getString("middleName"), + is(userResource.getJson().getJsonObject("personal").getString("middleName"))); + assertThat(lastPrintRequesterObject.getString("lastName"), + is(userResource.getJson().getJsonObject("personal").getString("lastName"))); + assertThat(lastPrintRequesterObject.getString("firstName"), + is(userResource.getJson().getJsonObject("personal").getString("firstName"))); } } diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index 1ed5b8f5b0..c146982ce8 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -427,6 +427,8 @@ public void start(Promise startFuture) throws IOException { .withChangeMetadata() .create().register(router); + new FakePrintEventStatusModule().register(router); + new FakeFeeFineOperationsModule().register(router); server.requestHandler(router) diff --git a/src/test/java/api/support/fakes/FakePrintEventStatusModule.java b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java new file mode 100644 index 0000000000..470a6e5924 --- /dev/null +++ b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java @@ -0,0 +1,86 @@ +package api.support.fakes; + +import io.vertx.core.buffer.Buffer; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import lombok.SneakyThrows; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static api.support.APITestContext.getTenantId; +import static api.support.fakes.Storage.getStorage; +import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; +import static org.folio.circulation.support.http.server.JsonHttpResponse.ok; + +public class FakePrintEventStatusModule { + + @SneakyThrows + public void register(Router router) { + router.post("/print-events-storage/print-events-status") + .handler(this::handlePrintEventStatusRequest); + + } + + private void handlePrintEventStatusRequest(RoutingContext routingContext) { + System.out.println("handlePrintEventStatusRequest **************"); + var request = routingContext.body().asJsonObject(); + var requestIds = request.getJsonArray("requestIds"); + if (requestIds.isEmpty()) { + Buffer buffer = Buffer.buffer( + "Size must be 1", "UTF-8"); + routingContext.response() + .setStatusCode(HTTP_UNPROCESSABLE_ENTITY.toInt()) + .putHeader("content-type", "text/plain; charset=utf-8") + .putHeader("content-length", Integer.toString(buffer.length())) + .write(buffer); + routingContext.response().end(); + } + var jsonObjectList = new ArrayList<>(getStorage() + .getTenantResources("/print-events-storage/print-events-entry", getTenantId()) + .values() + .stream() + .toList()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + // Sorting jsonObjectList based on PrintEventDate so that it will always return latest printEventDetail + jsonObjectList.sort((obj1, obj2) -> { + try { + Date date1 = dateFormat.parse(obj1.getString("printEventDate")); + Date date2 = dateFormat.parse(obj2.getString("printEventDate")); + return date2.compareTo(date1); + } catch (ParseException e) { + throw new RuntimeException(e); + } + }); + + Map> groupByRequestIdMap = new LinkedHashMap<>(); + requestIds.forEach(requestId -> { + var requestList = jsonObjectList.stream().filter(jsonObject -> + jsonObject.getJsonArray("requestIds").contains(requestId)) + .toList(); + groupByRequestIdMap.put((String) requestId, requestList); + }); + + var jsonObjectResponse = new JsonObject(); + var printEventStatusResponses = new ArrayList<>(); + jsonObjectResponse.put("printEventsStatusResponses", printEventStatusResponses); + requestIds.forEach(id -> { + var requestDetail = groupByRequestIdMap.get(id); + if (requestDetail !=null && !requestDetail.isEmpty()) { + var object = new JsonObject() + .put("requestId", id) + .put("count", requestDetail.size()) + .put("requesterId", requestDetail.get(0).getString("requesterId")) + .put("printEventDate", requestDetail.get(0).getString("printEventDate")); + printEventStatusResponses.add(object); + } + }); + ok(jsonObjectResponse).writeTo(routingContext.response()); + } +}