From 02870e1b99ad30db7375dff836bdff2328d96b82 Mon Sep 17 00:00:00 2001 From: alexanderkurash Date: Thu, 20 Jun 2024 16:50:24 +0300 Subject: [PATCH] CIRC-2111 Add more tests --- .../domain/CirculationSetting.java | 14 ++++ .../CirculationSettingsResource.java | 22 ++++- .../settings/CirculationSettingsTests.java | 84 +++++++++++++++++++ src/test/java/api/support/APITests.java | 3 + .../builders/CirculationSettingBuilder.java | 34 ++++++++ .../java/api/support/fakes/FakeOkapi.java | 7 ++ .../java/api/support/http/InterfaceUrls.java | 3 + .../java/api/support/http/ResourceClient.java | 4 + 8 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 src/test/java/api/settings/CirculationSettingsTests.java create mode 100644 src/test/java/api/support/builders/CirculationSettingBuilder.java diff --git a/src/main/java/org/folio/circulation/domain/CirculationSetting.java b/src/main/java/org/folio/circulation/domain/CirculationSetting.java index 25f3f1bf28..bfdd91fee3 100644 --- a/src/main/java/org/folio/circulation/domain/CirculationSetting.java +++ b/src/main/java/org/folio/circulation/domain/CirculationSetting.java @@ -4,6 +4,11 @@ import static org.folio.circulation.support.json.JsonPropertyFetcher.getObjectProperty; import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; +import java.lang.invoke.MethodHandles; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import io.vertx.core.json.JsonObject; import lombok.AllArgsConstructor; import lombok.Getter; @@ -12,6 +17,8 @@ @AllArgsConstructor(access = PRIVATE) @ToString(onlyExplicitlyIncluded = true) public class CirculationSetting { + private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); + @ToString.Include @Getter private final JsonObject representation; @@ -26,6 +33,13 @@ public class CirculationSetting { private final JsonObject value; public static CirculationSetting from(JsonObject representation) { + if (getProperty(representation, "name") == null || + getObjectProperty(representation, "value") == null) { + + log.info("from:: Circulation setting JSON is malformed: {}", representation); + return null; + } + return new CirculationSetting(representation, getProperty(representation, "id"), getProperty(representation, "name"), getObjectProperty(representation, "value")); } diff --git a/src/main/java/org/folio/circulation/resources/CirculationSettingsResource.java b/src/main/java/org/folio/circulation/resources/CirculationSettingsResource.java index f23d0dc7bb..0ef7b2bbd4 100644 --- a/src/main/java/org/folio/circulation/resources/CirculationSettingsResource.java +++ b/src/main/java/org/folio/circulation/resources/CirculationSettingsResource.java @@ -1,11 +1,15 @@ package org.folio.circulation.resources; import static org.folio.circulation.infrastructure.storage.CirculationSettingsRepository.RECORDS_PROPERTY_NAME; +import static org.folio.circulation.support.ValidationErrorFailure.singleValidationError; import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; import static org.folio.circulation.support.results.MappingFunctions.toFixedValue; +import static org.folio.circulation.support.results.Result.ofAsync; +import static org.folio.circulation.support.results.Result.succeeded; import java.lang.invoke.MethodHandles; import java.util.UUID; +import java.util.function.Function; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -15,6 +19,7 @@ import org.folio.circulation.support.http.server.JsonHttpResponse; import org.folio.circulation.support.http.server.NoContentResponse; import org.folio.circulation.support.http.server.WebContext; +import org.folio.circulation.support.results.Result; import io.vertx.core.http.HttpClient; import io.vertx.core.json.JsonObject; @@ -38,7 +43,9 @@ void create(RoutingContext routingContext) { final var circulationSetting = CirculationSetting.from(incomingRepresentation); log.debug("replace:: Creating circulation setting: {}", circulationSetting); - circulationSettingsRepository.create(circulationSetting) + ofAsync(circulationSetting) + .thenApply(refuseWhenCirculationSettingIsInvalid()) + .thenCompose(r -> r.after(circulationSettingsRepository::create)) .thenApply(r -> r.map(CirculationSetting::getRepresentation)) .thenApply(r -> r.map(JsonHttpResponse::created)) .thenAccept(context::writeResultToHttpResponse); @@ -54,12 +61,21 @@ void replace(RoutingContext routingContext) { final var circulationSetting = CirculationSetting.from(incomingRepresentation); log.debug("replace:: Replacing circulation setting : {}", circulationSetting); - circulationSettingsRepository.update(circulationSetting) + ofAsync(circulationSetting) + .thenApply(refuseWhenCirculationSettingIsInvalid()) + .thenCompose(r -> r.after(circulationSettingsRepository::update)) .thenApply(r -> r.map(CirculationSetting::getRepresentation)) .thenApply(r -> r.map(JsonHttpResponse::created)) .thenAccept(context::writeResultToHttpResponse); } + private Function, Result> + refuseWhenCirculationSettingIsInvalid() { + + return r -> r.failWhen(circulationSetting -> succeeded(circulationSetting == null), + circulationSetting -> singleValidationError("Circulation setting JSON is malformed", "", "")); + } + @Override void get(RoutingContext routingContext) { final var context = new WebContext(routingContext); @@ -95,7 +111,7 @@ void getMany(RoutingContext routingContext) { final var circulationSettingsRepository = new CirculationSettingsRepository(clients); final var query = routingContext.request().query(); - log.debug("get:: Requested circulation settings by query: {}", query); + log.info("get:: Requested circulation settings by query: {}", query); circulationSettingsRepository.findBy(query) .thenApply(multipleLoanRecordsResult -> multipleLoanRecordsResult.map(multipleRecords -> diff --git a/src/test/java/api/settings/CirculationSettingsTests.java b/src/test/java/api/settings/CirculationSettingsTests.java new file mode 100644 index 0000000000..dd79417389 --- /dev/null +++ b/src/test/java/api/settings/CirculationSettingsTests.java @@ -0,0 +1,84 @@ +package api.settings; + +import static api.support.http.InterfaceUrls.circulationSettingsUrl; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +import api.support.APITests; +import api.support.builders.CirculationSettingBuilder; +import api.support.http.CqlQuery; +import io.vertx.core.json.JsonObject; + +public class CirculationSettingsTests extends APITests { + + @Test + void crudOperationsTest() { + // Testing POST method + final var setting = circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("initial-name") + .withValue(new JsonObject().put("initial-key", "initial-value"))); + final var settingId = setting.getId(); + + // Testing GET (individual setting) method + final var settingById = circulationSettingsClient.get(settingId); + assertThat(settingById.getJson().getString("name"), is("initial-name")); + assertThat(settingById.getJson().getJsonObject("value").getString("initial-key"), + is("initial-value")); + + // Testing GET (all) method + final var anotherSetting = circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("another-name") + .withValue(new JsonObject().put("another-key", "another-value"))); + final var allSettings = circulationSettingsClient.getMany(CqlQuery.noQuery()); + assertThat(allSettings.size(), is(2)); + + // Testing DELETE method + circulationSettingsClient.delete(anotherSetting.getId()); + final var allSettingsAfterDeletion = circulationSettingsClient.getMany(CqlQuery.noQuery()); + assertThat(allSettingsAfterDeletion.size(), is(1)); + assertThat(allSettingsAfterDeletion.getFirst().getString("name"), is("initial-name")); + assertThat(allSettingsAfterDeletion.getFirst().getJsonObject("value").getString("initial-key"), + is("initial-value")); + + // Testing PUT method + circulationSettingsClient.replace(settingId, new CirculationSettingBuilder() + .withId(settingId) + .withName("new-name") + .withValue(new JsonObject().put("new-key", "new-value"))); + + final var updatedSetting = circulationSettingsClient.get(settingId); + + assertThat(updatedSetting.getJson().getString("name"), is("new-name")); + assertThat(updatedSetting.getJson().getJsonObject("value").getString("new-key"), + is("new-value")); + } + + @Test + void invalidRequestsTest() { + final var setting = circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("initial-name") + .withValue(new JsonObject().put("initial-key", "initial-value"))); + + // Testing GET with invalid ID + restAssuredClient.get(circulationSettingsUrl("/" + randomId()), 404, + "get-circulation-setting"); + + // Testing DELETE with invalid ID + restAssuredClient.delete(circulationSettingsUrl("/" + randomId()), 204, + "delete-circulation-setting"); + + // Testing PUT with malformed JSON + var putErrors = restAssuredClient.put("{\"invalid-field\": \"invalid-value\"}", + circulationSettingsUrl("/" + randomId()), 422, "put-circulation-setting"); + assertThat(putErrors.getJson().getJsonArray("errors").getJsonObject(0).getString("message"), + is("Circulation setting JSON is malformed")); + + // Testing POST with malformed JSON + var postErrors = restAssuredClient.post("{\"invalid-field\": \"invalid-value\"}", + circulationSettingsUrl(""), 422, "put-circulation-setting"); + assertThat(postErrors.getJson().getJsonArray("errors").getJsonObject(0).getString("message"), + is("Circulation setting JSON is malformed")); + } +} diff --git a/src/test/java/api/support/APITests.java b/src/test/java/api/support/APITests.java index ddc2dce289..b872ce7165 100644 --- a/src/test/java/api/support/APITests.java +++ b/src/test/java/api/support/APITests.java @@ -194,6 +194,9 @@ public abstract class APITests { protected final ResourceClient actualCostRecordsClient = ResourceClient.forActualCostRecordsStorage(); + protected final ResourceClient circulationSettingsClient = + ResourceClient.forCirculationSettings(); + protected final ServicePointsFixture servicePointsFixture = new ServicePointsFixture(servicePointsClient); diff --git a/src/test/java/api/support/builders/CirculationSettingBuilder.java b/src/test/java/api/support/builders/CirculationSettingBuilder.java new file mode 100644 index 0000000000..a33fb99345 --- /dev/null +++ b/src/test/java/api/support/builders/CirculationSettingBuilder.java @@ -0,0 +1,34 @@ +package api.support.builders; + +import java.util.UUID; + +import io.vertx.core.json.JsonObject; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.With; + +@NoArgsConstructor +@AllArgsConstructor +@With +public class CirculationSettingBuilder extends JsonBuilder implements Builder { + private UUID id = null; + private String name = null; + private JsonObject value = null; + + @Override + public JsonObject create() { + JsonObject circulationSetting = new JsonObject(); + + if (id != null) { + put(circulationSetting, "id", id); + } + if (name != null) { + put(circulationSetting, "name", name); + } + if (value != null) { + put(circulationSetting, "value", value); + } + + return circulationSetting; + } +} diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index 9cdfb40600..5cbecb8542 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -415,6 +415,13 @@ public void start(Promise startFuture) throws IOException { .withChangeMetadata() .create().register(router); + new FakeStorageModuleBuilder() + .withRecordName("circulationSettings") + .withCollectionPropertyName("circulationSettings") + .withRootPath("/circulation-settings-storage/circulation-settings") + .withChangeMetadata() + .create().register(router); + new FakeFeeFineOperationsModule().register(router); server.requestHandler(router) diff --git a/src/test/java/api/support/http/InterfaceUrls.java b/src/test/java/api/support/http/InterfaceUrls.java index fedf39d696..59d35de534 100644 --- a/src/test/java/api/support/http/InterfaceUrls.java +++ b/src/test/java/api/support/http/InterfaceUrls.java @@ -334,4 +334,7 @@ public static URL settingsStorageUrl() { return APITestContext.viaOkapiModuleUrl("/settings/entries"); } + public static URL circulationSettingsUrl(String subPath) { + return circulationModuleUrl("/circulation/settings" + subPath); + } } diff --git a/src/test/java/api/support/http/ResourceClient.java b/src/test/java/api/support/http/ResourceClient.java index 844fff542d..8e9b7d63be 100644 --- a/src/test/java/api/support/http/ResourceClient.java +++ b/src/test/java/api/support/http/ResourceClient.java @@ -272,6 +272,10 @@ public static ResourceClient forActualCostRecordsStorage() { return new ResourceClient(InterfaceUrls::actualCostRecordsStorageUrl, "actualCostRecords"); } + public static ResourceClient forCirculationSettings() { + return new ResourceClient(InterfaceUrls::circulationSettingsUrl, "circulationSettings"); + } + private ResourceClient(UrlMaker urlMaker, String collectionArrayPropertyName) { this.urlMaker = urlMaker; this.collectionArrayPropertyName = collectionArrayPropertyName;