Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
309 changes: 309 additions & 0 deletions src/test/java/org/folio/orders/utils/PoLineCommonUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static org.folio.rest.core.exceptions.ErrorCodes.PROHIBITED_FIELD_CHANGING;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Collection;
import java.util.Map;
import org.folio.rest.jaxrs.model.Error;
import static org.hamcrest.Matchers.contains;
import io.vertx.core.json.JsonArray;
import org.folio.orders.utils.PoLineCommonUtil;
import org.folio.rest.core.exceptions.ErrorCodes;
import java.util.Collections;
import org.folio.rest.jaxrs.model.Ongoing;
import java.util.Date;
import java.time.Instant;
import org.folio.rest.jaxrs.model.Parameter;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.junit.jupiter.params.provider.ValueSource;

@CopilotGenerated(partiallyGenerated = true)
public class PoLineCommonUtilTest {
Expand Down Expand Up @@ -247,6 +266,296 @@ void testExtractUnaffiliatedLocationsHandleNullLocationTenantId() {
assertTrue(result.contains(locations.get(1)));
}

@Test

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some styling problems

void testVerifyProtectedFieldsChangedShouldDetectScalarFieldChange() {
// TestMate-fcee0817e0fb477dda0345cf59133ea1
// Given
List<String> protectedFields = List.of("poLineNumber", "isPackage");
JsonObject objectFromStorage = new JsonObject()
.put("poLineNumber", "1000-1")
.put("isPackage", true);
JsonObject requestObject = new JsonObject()
.put("poLineNumber", "1000-2")
.put("isPackage", false);
// When
HttpException exception = assertThrows(HttpException.class, () ->
PoLineCommonUtil.verifyProtectedFieldsChanged(protectedFields, objectFromStorage, requestObject)
);
// Then
assertEquals(400, exception.getCode());
Error error = exception.getError();
assertEquals(PROHIBITED_FIELD_CHANGING.getCode(), error.getCode());
Map<String, Object> additionalProperties = error.getAdditionalProperties();
Object modifiedFields = additionalProperties.get("protectedAndModifiedFields");

assertThat((Collection<String>) modifiedFields, containsInAnyOrder("poLineNumber", "isPackage"));
}

@Test
void testVerifyProtectedFieldsChangedShouldDetectArraySizeDecrease() {
// TestMate-7c59c6e9741685700ad64171c7f676d6
// Given
String protectedField = "details.productIds";
List<String> protectedFields = List.of(protectedField);
String productIdType = UUID.randomUUID().toString();

ProductId firstProductId = new ProductId()
.withProductId("9780735245341")
.withProductIdType(productIdType);
ProductId secondProductId = new ProductId()
.withProductId("9780593492543")
.withProductIdType(productIdType);
String poLineId = UUID.randomUUID().toString();
PoLine lineFromStorage = new PoLine()
.withId(poLineId)
.withDetails(new Details().withProductIds(List.of(firstProductId, secondProductId)));

PoLine requestObject = new PoLine()
.withId(poLineId)
.withDetails(new Details().withProductIds(List.of(firstProductId)));
JsonObject lineFromStorageJson = JsonObject.mapFrom(lineFromStorage);
JsonObject requestObjectJson = JsonObject.mapFrom(requestObject);
// When
HttpException exception = assertThrows(HttpException.class, () ->
PoLineCommonUtil.verifyProtectedFieldsChanged(protectedFields, lineFromStorageJson, requestObjectJson)
);
// Then
assertEquals(400, exception.getCode());
Error error = exception.getError();
assertEquals(PROHIBITED_FIELD_CHANGING.getCode(), error.getCode());

Map<String, Object> additionalProperties = error.getAdditionalProperties();
Object modifiedFields = additionalProperties.get("protectedAndModifiedFields");
assertThat((Collection<String>) modifiedFields, contains(protectedField));
}

@Test
void testVerifyProtectedFieldsChangedShouldDetectArrayContentMismatchSameSize() {
// TestMate-557f9017f8ed07ba36247fa5b6b84c6b
// Given
String protectedField = "tags.tagList";
List<String> protectedFields = List.of(protectedField);
JsonObject objectFromStorage = new JsonObject()
.put("tags", new JsonObject()
.put("tagList", new JsonArray().add("urgent")));
JsonObject requestObject = new JsonObject()
.put("tags", new JsonObject()
.put("tagList", new JsonArray().add("normal")));
// When
HttpException exception = assertThrows(HttpException.class, () ->
PoLineCommonUtil.verifyProtectedFieldsChanged(protectedFields, objectFromStorage, requestObject)
);
// Then
assertEquals(400, exception.getCode());
Error error = exception.getError();
assertEquals(PROHIBITED_FIELD_CHANGING.getCode(), error.getCode());
Map<String, Object> additionalProperties = error.getAdditionalProperties();
Object modifiedFields = additionalProperties.get("protectedAndModifiedFields");
assertThat((Collection<String>) modifiedFields, contains(protectedField));
}

@Test
void testVerifyProtectedFieldsChangedShouldIgnoreUnprotectedFieldChanges() {
// TestMate-2cf9247ee4f691a5aa390dbf1d481c14
// Given
List<String> protectedFields = List.of("id");
String id = "11111111-1111-1111-1111-111111111111";
JsonObject objectFromStorage = new JsonObject()
.put("id", id)
.put("description", "Old Description");
JsonObject requestObject = new JsonObject()
.put("id", id)
.put("description", "New Description");
// When
JsonObject result = PoLineCommonUtil.verifyProtectedFieldsChanged(protectedFields, objectFromStorage, requestObject);
// Then
assertEquals(objectFromStorage, result);
}

@Test
void testVerifyProtectedFieldsChangedShouldHandleNestedFieldPaths() {
// TestMate-defcd112d0e57c836878823cedcaef6c
// Given
String protectedFieldPath = "cost.currency";
List<String> protectedFields = List.of(protectedFieldPath);
JsonObject objectFromStorage = new JsonObject()
.put("cost", new JsonObject()
.put("currency", "USD")
.put("listUnitPrice", 10.0));
JsonObject requestObject = new JsonObject()
.put("cost", new JsonObject()
.put("currency", "EUR")
.put("listUnitPrice", 10.0));
// When
HttpException exception = assertThrows(HttpException.class, () ->
PoLineCommonUtil.verifyProtectedFieldsChanged(protectedFields, objectFromStorage, requestObject)
);
// Then
assertEquals(400, exception.getCode());
Error error = exception.getError();
assertEquals(PROHIBITED_FIELD_CHANGING.getCode(), error.getCode());
Map<String, Object> additionalProperties = error.getAdditionalProperties();
Object modifiedFields = additionalProperties.get("protectedAndModifiedFields");
assertThat((Collection<String>) modifiedFields, contains(protectedFieldPath));
}

@Test
void testVerifyProtectedFieldsChangedShouldHandleEmptyProtectedFieldsList() {
// TestMate-69d03db6b9de005e4433ca20ca1445ee
// Given
List<String> protectedFields = Collections.emptyList();
String id = "00000000-0000-0000-0000-000000000001";

JsonObject objectFromStorage = new JsonObject()
.put("id", id)
.put("name", "Original Name")
.put("status", "Pending");

JsonObject requestObject = new JsonObject()
.put("id", UUID.fromString("00000000-0000-0000-0000-000000000002").toString())
.put("name", "Changed Name")
.put("status", "Active");
// When
JsonObject result = PoLineCommonUtil.verifyProtectedFieldsChanged(protectedFields, objectFromStorage, requestObject);
// Then
assertEquals(objectFromStorage, result);
}

@Test
void testVerifyProtectedFieldsChangedShouldDetectChangesInMultipleProtectedFields() {
// TestMate-a9add8ed0d1f7a0fe476f740af1ee27e
// Given
List<String> protectedFields = List.of("id", "source");
JsonObject objectFromStorage = new JsonObject()
.put("id", "1")
.put("source", "FOLIO")
.put("description", "Old Description");
JsonObject requestObject = new JsonObject()
.put("id", "2")
.put("source", "MARC")
.put("description", "New Description");
// When
HttpException exception = assertThrows(HttpException.class, () ->
PoLineCommonUtil.verifyProtectedFieldsChanged(protectedFields, objectFromStorage, requestObject)
);
// Then
assertEquals(400, exception.getCode());
Error error = exception.getError();
assertEquals(PROHIBITED_FIELD_CHANGING.getCode(), error.getCode());
Map<String, Object> additionalProperties = error.getAdditionalProperties();
Object modifiedFields = additionalProperties.get("protectedAndModifiedFields");
assertThat((Collection<String>) modifiedFields, containsInAnyOrder("id", "source"));
}

@ParameterizedTest

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here

@CsvSource(value = {
"reviewDate|2024-01-01T00:00:00Z",
"manualRenewal|true"
}, delimiter = '|')
void testVerifyOngoingFieldsChangedShouldThrowExceptionWhenSubscriptionFieldsModified(String fieldName, String newValue) {
// TestMate-1e7f8d73471208534f55a8712f35d569
// Given
JsonObject ongoingStorage = new JsonObject()
.put("isSubscription", true)
.put("reviewDate", "2023-01-01T00:00:00Z")
.put("manualRenewal", false);
JsonObject storageJson = new JsonObject().put("ongoing", ongoingStorage);
// Map from storage to request to ensure fields not under test remain identical during comparison
Ongoing ongoingRequest = ongoingStorage.mapTo(Ongoing.class);
if ("reviewDate".equals(fieldName)) {
ongoingRequest.setReviewDate(Date.from(Instant.parse(newValue)));
} else if ("manualRenewal".equals(fieldName)) {
ongoingRequest.setManualRenewal(Boolean.valueOf(newValue));
}
CompositePurchaseOrder requestCompPO = new CompositePurchaseOrder().withOngoing(ongoingRequest);
// When
HttpException exception = assertThrows(HttpException.class, () ->
PoLineCommonUtil.verifyOngoingFieldsChanged(storageJson, requestCompPO)
);
// Then
assertEquals(400, exception.getCode());
assertEquals(ErrorCodes.WRONG_ONGOING_SUBSCRIPTION_FIELDS_CHANGED.getCode(), exception.getError().getCode());
// Find the specific parameter related to the field being tested to avoid index-based failures
Parameter parameter = exception.getErrors().getErrors().get(0).getParameters().stream()
.filter(p -> p.getKey().equals(fieldName))
.findFirst()
.orElseThrow(() -> new AssertionError("Expected parameter not found: " + fieldName));
String expectedValue = newValue;
if ("reviewDate".equals(fieldName)) {
// Vert.x JsonObject serializes java.util.Date to epoch milliseconds by default.
// The method under test uses newObject.getValueAt(field).toString(), which results in the string of that long value.
expectedValue = String.valueOf(Instant.parse(newValue).toEpochMilli());
}
assertEquals(fieldName, parameter.getKey());
assertEquals(expectedValue, parameter.getValue());
}

@ParameterizedTest
@CsvSource(value = {
"interval|10",
"renewalDate|2024-01-15T10:30:00Z",
"reviewPeriod|5",
"manualRenewal|true"
}, delimiter = '|')
void testVerifyOngoingFieldsChangedShouldThrowExceptionWhenNonSubscriptionFieldsModified(String fieldName, String newValue) {
// TestMate-6800fce4f0684e383b323eea15366367
//given
JsonObject ongoingStorage = new JsonObject()
.put("isSubscription", false)
.put("interval", 1)
.put("renewalDate", "2023-01-15T10:30:00Z")
.put("reviewPeriod", 1)
.put("manualRenewal", false);
JsonObject storageJson = new JsonObject().put("ongoing", ongoingStorage);
Ongoing ongoingRequest = ongoingStorage.mapTo(Ongoing.class);
if ("interval".equals(fieldName)) {
ongoingRequest.setInterval(Integer.valueOf(newValue));
} else if ("renewalDate".equals(fieldName)) {
ongoingRequest.setRenewalDate(Date.from(Instant.parse(newValue)));
} else if ("reviewPeriod".equals(fieldName)) {
ongoingRequest.setReviewPeriod(Integer.valueOf(newValue));
} else if ("manualRenewal".equals(fieldName)) {
ongoingRequest.setManualRenewal(Boolean.valueOf(newValue));
}
CompositePurchaseOrder requestCompPO = new CompositePurchaseOrder().withOngoing(ongoingRequest);
//when
HttpException exception = assertThrows(HttpException.class, () ->
PoLineCommonUtil.verifyOngoingFieldsChanged(storageJson, requestCompPO)
);
//then
assertEquals(400, exception.getCode());
assertEquals(ErrorCodes.WRONG_ONGOING_NOT_SUBSCRIPTION_FIELDS_CHANGED.getCode(), exception.getError().getCode());
Parameter parameter = exception.getErrors().getErrors().get(0).getParameters().stream()
.filter(p -> p.getKey().equals(fieldName))
.findFirst()
.orElseThrow(() -> new AssertionError("Expected parameter not found: " + fieldName));
String expectedValue = newValue;
if ("renewalDate".equals(fieldName)) {
expectedValue = String.valueOf(Instant.parse(newValue).toEpochMilli());
}
assertEquals(fieldName, parameter.getKey());
assertEquals(expectedValue, parameter.getValue());
}

@ParameterizedTest
@ValueSource(booleans = {true, false})
void testVerifyOngoingFieldsChangedShouldSucceedWhenAllowedFieldsModified(boolean isSubscription) {
// TestMate-495401ee096d3b81e566755f6a634940
// Given
JsonObject ongoingStorage = new JsonObject()
.put("isSubscription", isSubscription)
.put("notes", "Original Note")
.put("manualRenewal", false);
JsonObject storageJson = new JsonObject().put("ongoing", ongoingStorage);
Ongoing ongoingRequest = new Ongoing()
.withIsSubscription(isSubscription)
.withNotes("Updated Note")
.withManualRenewal(false);
CompositePurchaseOrder requestCompPO = new CompositePurchaseOrder().withOngoing(ongoingRequest);
// When & Then
assertDoesNotThrow(() -> PoLineCommonUtil.verifyOngoingFieldsChanged(storageJson, requestCompPO));
}

private static Location createLocation(String tenantId) {
return new Location().withTenantId(tenantId);
}
Expand Down
Loading