From 692c5b5a996f0376b4007df7ba70b7e8115bae10 Mon Sep 17 00:00:00 2001 From: Vincenzo Mecca Date: Mon, 27 Mar 2023 17:57:40 +0200 Subject: [PATCH] [DURACOM-125][#8736] Check replace operation correctness feat: - Introduced ITs inside RestRepositories to check correctness of multi replacement with indexes. --- .../app/rest/BitstreamRestRepositoryIT.java | 91 +++++++++++++++++++ .../app/rest/BundleRestRepositoryIT.java | 77 ++++++++++++++++ .../app/rest/CollectionRestRepositoryIT.java | 82 ++++++++++++++++- .../app/rest/CommunityRestRepositoryIT.java | 77 ++++++++++++++++ .../app/rest/EPersonRestRepositoryIT.java | 79 +++++++++++++++- .../app/rest/GroupRestRepositoryIT.java | 65 +++++++++++++ .../dspace/app/rest/SiteRestRepositoryIT.java | 81 +++++++++++++++++ 7 files changed, 546 insertions(+), 6 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java index f9c1e469fc..d6947d7567 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamRestRepositoryIT.java @@ -15,6 +15,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -30,6 +31,9 @@ import org.dspace.app.rest.matcher.BitstreamFormatMatcher; import org.dspace.app.rest.matcher.BitstreamMatcher; import org.dspace.app.rest.matcher.BundleMatcher; import org.dspace.app.rest.matcher.HalMatcher; +import org.dspace.app.rest.matcher.MetadataMatcher; +import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.app.rest.test.MetadataPatchSuite; import org.dspace.authorize.service.ResourcePolicyService; @@ -45,6 +49,7 @@ import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.BitstreamFormatService; import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; @@ -1222,6 +1227,92 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest + parentCommunity.getLogo().getID(), expectedStatus); } + @Test + public void patchReplaceMultipleDescriptionBitstream() throws Exception { + context.turnOffAuthorisationSystem(); + + List bitstreamDescriptions = List.of( + "FIRST", + "SECOND", + "THIRD" + ); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = + CommunityBuilder.createSubCommunity(context, parentCommunity).withName("Sub Community").build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + Item publicItem1 = ItemBuilder.createItem(context, col1).withTitle("Test").build(); + + String bitstreamContent = "ThisIsSomeDummyText"; + Bitstream bitstream = null; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) { + bitstream = BitstreamBuilder. + createBitstream(context, publicItem1, is) + .withName("Bitstream") + .withMimeType("text/plain") + .build(); + } + + this.bitstreamService + .addMetadata( + context, bitstream, + MetadataSchemaEnum.DC.getName(), "description", null, + Item.ANY, bitstreamDescriptions + ); + + context.restoreAuthSystemState(); + String token = getAuthToken(admin.getEmail(), password); + + getClient(token) + .perform(get("/api/core/bitstreams/" + bitstream.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(0), 0), + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(1), 1), + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(2), 2) + ) + ) + ); + + List ops = List.of( + new ReplaceOperation("/metadata/dc.description/0", bitstreamDescriptions.get(2)), + new ReplaceOperation("/metadata/dc.description/1", bitstreamDescriptions.get(0)), + new ReplaceOperation("/metadata/dc.description/2", bitstreamDescriptions.get(1)) + ); + String requestBody = getPatchContent(ops); + getClient(token) + .perform(patch("/api/core/bitstreams/" + bitstream.getID()) + .content(requestBody) + .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(1), 2) + ) + ) + ); + getClient(token) + .perform(get("/api/core/bitstreams/" + bitstream.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", bitstreamDescriptions.get(1), 2) + ) + ) + ); + } + @Test public void testHiddenMetadataForAnonymousUser() throws Exception { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java index 96385095a2..259580f8c0 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java @@ -37,6 +37,7 @@ import org.dspace.app.rest.model.MetadataRest; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.MoveOperation; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.ResourcePolicyService; @@ -51,6 +52,8 @@ import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.service.BundleService; import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.eperson.EPerson; @@ -68,6 +71,9 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest { @Autowired ItemService itemService; + @Autowired + BundleService bundleService; + private Collection collection; private Item item; private Bundle bundle1; @@ -515,6 +521,77 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest { ))); } + @Test + public void patchReplaceMultipleDescriptionBundle() throws Exception { + context.turnOffAuthorisationSystem(); + + List bundleDescriptions = List.of( + "FIRST", + "SECOND", + "THIRD" + ); + + bundle1 = BundleBuilder.createBundle(context, item) + .withName("testname") + .build(); + + this.bundleService + .addMetadata( + context, bundle1, + MetadataSchemaEnum.DC.getName(), "description", null, + Item.ANY, bundleDescriptions + ); + + context.restoreAuthSystemState(); + String token = getAuthToken(admin.getEmail(), password); + + getClient(token) + .perform(get("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(0), 0), + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(1), 1), + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(2), 2) + ) + ) + ); + + List ops = List.of( + new ReplaceOperation("/metadata/dc.description/0", bundleDescriptions.get(2)), + new ReplaceOperation("/metadata/dc.description/1", bundleDescriptions.get(0)), + new ReplaceOperation("/metadata/dc.description/2", bundleDescriptions.get(1)) + ); + String requestBody = getPatchContent(ops); + getClient(token) + .perform(patch("/api/core/bundles/" + bundle1.getID()) + .content(requestBody) + .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(1), 2) + ) + ) + ); + getClient(token) + .perform(get("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", bundleDescriptions.get(1), 2) + ) + ) + ); + } + @Test public void deleteBundle() throws Exception { context.turnOffAuthorisationSystem(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java index ab37fac106..ee522db170 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CollectionRestRepositoryIT.java @@ -69,6 +69,7 @@ import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.EntityType; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.CollectionService; import org.dspace.core.Constants; import org.dspace.eperson.EPerson; @@ -499,13 +500,13 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes getClient(tokenParentAdmin).perform(get("/api/core/collections/" + col1.getID())) .andExpect(status().isOk()) .andExpect(jsonPath("$", - Matchers.is((CollectionMatcher.matchCollection(col1))))); + Matchers.is(CollectionMatcher.matchCollection(col1)))); String tokenCol1Admin = getAuthToken(col1Admin.getEmail(), "qwerty02"); getClient(tokenCol1Admin).perform(get("/api/core/collections/" + col1.getID())) .andExpect(status().isOk()) .andExpect(jsonPath("$", - Matchers.is((CollectionMatcher.matchCollection(col1))))); + Matchers.is(CollectionMatcher.matchCollection(col1)))); String tokenCol2Admin = getAuthToken(col2Admin.getEmail(), "qwerty03"); getClient(tokenCol2Admin).perform(get("/api/core/collections/" + col1.getID())) @@ -1206,7 +1207,7 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes ) ))) .andDo(result -> idRef - .set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));; + .set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))); getClient(authToken).perform(post("/api/core/collections") @@ -3101,6 +3102,81 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes .andExpect(status().isUnauthorized()); } + @Test + public void patchReplaceMultipleDescriptionCollection() throws Exception { + context.turnOffAuthorisationSystem(); + + List collectionDescriptions = List.of( + "FIRST", + "SECOND", + "THIRD" + ); + + parentCommunity = + CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Collection col = + CollectionBuilder.createCollection(context, parentCommunity) + .withName("MyTest") + .build(); + + this.collectionService + .addMetadata( + context, col, MetadataSchemaEnum.DC.getName(), "description", null, Item.ANY, collectionDescriptions + ); + + context.restoreAuthSystemState(); + String token = getAuthToken(admin.getEmail(), password); + + getClient(token) + .perform(get("/api/core/collections/" + col.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(0), 0), + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(1), 1), + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(2), 2) + ) + ) + ); + + List ops = List.of( + new ReplaceOperation("/metadata/dc.description/0", collectionDescriptions.get(2)), + new ReplaceOperation("/metadata/dc.description/1", collectionDescriptions.get(0)), + new ReplaceOperation("/metadata/dc.description/2", collectionDescriptions.get(1)) + ); + String requestBody = getPatchContent(ops); + getClient(token) + .perform(patch("/api/core/collections/" + col.getID()) + .content(requestBody) + .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(1), 2) + ) + ) + ); + getClient(token) + .perform(get("/api/core/collections/" + col.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", collectionDescriptions.get(1), 2) + ) + ) + ); + } + @Test public void patchMetadataCheckReindexingTest() throws Exception { context.turnOffAuthorisationSystem(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java index e084aa1746..30614e6125 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/CommunityRestRepositoryIT.java @@ -20,6 +20,7 @@ import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_ import static org.springframework.http.MediaType.parseMediaType; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -44,6 +45,8 @@ import org.dspace.app.rest.model.CommunityRest; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.model.MetadataRest; import org.dspace.app.rest.model.MetadataValueRest; +import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.app.rest.test.MetadataPatchSuite; @@ -56,6 +59,8 @@ import org.dspace.builder.GroupBuilder; import org.dspace.builder.ResourcePolicyBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.eperson.EPerson; @@ -1935,6 +1940,78 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest runPatchMetadataTests(eperson, 403); } + @Test + public void patchReplaceMultipleDescriptionCommunity() throws Exception { + context.turnOffAuthorisationSystem(); + + List communityDescriptions = List.of( + "FIRST", + "SECOND", + "THIRD" + ); + + parentCommunity = + CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + this.communityService + .addMetadata( + context, parentCommunity, + MetadataSchemaEnum.DC.getName(), "description", null, + Item.ANY, communityDescriptions + ); + + context.restoreAuthSystemState(); + String token = getAuthToken(admin.getEmail(), password); + + getClient(token) + .perform(get("/api/core/communities/" + parentCommunity.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(0), 0), + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(1), 1), + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(2), 2) + ) + ) + ); + + List ops = List.of( + new ReplaceOperation("/metadata/dc.description/0", communityDescriptions.get(2)), + new ReplaceOperation("/metadata/dc.description/1", communityDescriptions.get(0)), + new ReplaceOperation("/metadata/dc.description/2", communityDescriptions.get(1)) + ); + String requestBody = getPatchContent(ops); + getClient(token) + .perform(patch("/api/core/communities/" + parentCommunity.getID()) + .content(requestBody) + .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(1), 2) + ) + ) + ); + getClient(token) + .perform(get("/api/core/communities/" + parentCommunity.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", communityDescriptions.get(1), 2) + ) + ) + ); + } + private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Exception { context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context).withName("Community").build(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java index 8c7f80e5fb..1f09779ab0 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java @@ -72,6 +72,7 @@ import org.dspace.builder.GroupBuilder; import org.dspace.builder.WorkflowItemBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; +import org.dspace.content.Item; import org.dspace.core.I18nUtil; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; @@ -155,7 +156,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest { .andExpect(content().contentType(contentType)) .andExpect(jsonPath("$", HalMatcher.matchNoEmbeds())) .andDo(result -> idRefNoEmbeds - .set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));; + .set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))); } finally { EPersonBuilder.deleteEPerson(idRef.get()); @@ -1217,7 +1218,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.canLogIn", Matchers.is(true)));; + .andExpect(jsonPath("$.canLogIn", Matchers.is(true))); List ops2 = new ArrayList(); @@ -1295,7 +1296,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) - .andExpect(jsonPath("$.requireCertificate", Matchers.is(true)));; + .andExpect(jsonPath("$.requireCertificate", Matchers.is(true))); List ops2 = new ArrayList(); ReplaceOperation replaceOperation2 = new ReplaceOperation("/certificate",null); @@ -1858,6 +1859,78 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest { matchMetadata("eperson.firstname", newName))))); } + @Test + public void patchMultipleReplaceMetadataByAdmin() throws Exception { + + context.turnOffAuthorisationSystem(); + + String first = "First"; + String second = "Second"; + String third = "Third"; + + EPerson ePerson = EPersonBuilder.createEPerson(context) + .withEmail("Johndoe@example.com") + .build(); + + this.ePersonService + .addMetadata(context, ePerson, "eperson", "firstname", null, Item.ANY, List.of(first, second, third)); + + context.restoreAuthSystemState(); + + String token = getAuthToken(admin.getEmail(), password); + + // The replacement of the eperson.firstname value is persisted + getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("eperson.firstname", first, 0), + MetadataMatcher.matchMetadata("eperson.firstname", second, 1), + MetadataMatcher.matchMetadata("eperson.firstname", third, 2) + ) + ) + ); + + List ops = new ArrayList(); + + ReplaceOperation replaceFirst = new ReplaceOperation("/metadata/eperson.firstname/0", third); + ReplaceOperation replaceSecond = new ReplaceOperation("/metadata/eperson.firstname/1", second); + ReplaceOperation replaceThird = new ReplaceOperation("/metadata/eperson.firstname/2", first); + + ops.add(replaceFirst); + ops.add(replaceSecond); + ops.add(replaceThird); + + String patchBody = getPatchContent(ops); + + getClient(token).perform(patch("/api/eperson/epersons/" + ePerson.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("eperson.firstname", third, 0), + MetadataMatcher.matchMetadata("eperson.firstname", second, 1), + MetadataMatcher.matchMetadata("eperson.firstname", first, 2) + ) + ) + ); + + getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("eperson.firstname", third, 0), + MetadataMatcher.matchMetadata("eperson.firstname", second, 1), + MetadataMatcher.matchMetadata("eperson.firstname", first, 2) + ) + ) + ); + } + @Test public void patchOwnMetadataByNonAdminUser() throws Exception { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java index 7121e11953..fda8b15eff 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/GroupRestRepositoryIT.java @@ -40,6 +40,7 @@ import org.dspace.app.rest.exception.GroupNameNotProvidedException; import org.dspace.app.rest.matcher.EPersonMatcher; import org.dspace.app.rest.matcher.GroupMatcher; import org.dspace.app.rest.matcher.HalMatcher; +import org.dspace.app.rest.matcher.MetadataMatcher; import org.dspace.app.rest.model.GroupRest; import org.dspace.app.rest.model.MetadataRest; import org.dspace.app.rest.model.MetadataValueRest; @@ -56,6 +57,8 @@ import org.dspace.builder.GroupBuilder; import org.dspace.builder.ResourcePolicyBuilder; import org.dspace.content.Collection; import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; @@ -558,6 +561,68 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest { )); } + @Test + public void patchReplaceMultipleDescriptionGroupName() throws Exception { + context.turnOffAuthorisationSystem(); + List groupDescription = List.of( + "FIRST", + "SECOND", + "THIRD" + ); + + Group group = + GroupBuilder.createGroup(context) + .build(); + GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); + groupService + .addMetadata( + context, group, MetadataSchemaEnum.DC.getName(), "description", null, Item.ANY, groupDescription + ); + context.restoreAuthSystemState(); + String token = getAuthToken(admin.getEmail(), password); + + getClient(token) + .perform(get("/api/eperson/groups/" + group.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", groupDescription.get(0), 0), + MetadataMatcher.matchMetadata("dc.description", groupDescription.get(1), 1), + MetadataMatcher.matchMetadata("dc.description", groupDescription.get(2), 2) + ) + ) + ); + + List ops = List.of( + new ReplaceOperation("/metadata/dc.description/0", groupDescription.get(2)), + new ReplaceOperation("/metadata/dc.description/1", groupDescription.get(0)), + new ReplaceOperation("/metadata/dc.description/2", groupDescription.get(1)) + ); + String requestBody = getPatchContent(ops); + + getClient(token) + .perform( + patch("/api/eperson/groups/" + group.getID()) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON) + ) + .andExpect(status().isOk()); + + getClient(token) + .perform(get("/api/eperson/groups/" + group.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", groupDescription.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", groupDescription.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", groupDescription.get(1), 2) + ) + ) + ); + } + @Test public void patchGroupWithParentUnprocessable() throws Exception { context.turnOffAuthorisationSystem(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java index 092ea32b3f..26b01071d1 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SiteRestRepositoryIT.java @@ -9,22 +9,34 @@ package org.dspace.app.rest; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.List; import java.util.UUID; +import org.dspace.app.rest.matcher.MetadataMatcher; import org.dspace.app.rest.matcher.SiteMatcher; +import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.app.rest.test.MetadataPatchSuite; import org.dspace.builder.SiteBuilder; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.Site; +import org.dspace.content.service.SiteService; import org.dspace.eperson.EPerson; import org.hamcrest.Matchers; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; public class SiteRestRepositoryIT extends AbstractControllerIntegrationTest { + @Autowired + private SiteService siteService; + @Test public void findAll() throws Exception { @@ -77,6 +89,75 @@ public class SiteRestRepositoryIT extends AbstractControllerIntegrationTest { runPatchMetadataTests(eperson, 403); } + @Test + public void patchReplaceMultipleDescriptionSite() throws Exception { + context.turnOffAuthorisationSystem(); + + List siteDescriptions = List.of( + "FIRST", + "SECOND", + "THIRD" + ); + + Site site = SiteBuilder.createSite(context).build(); + + this.siteService + .addMetadata( + context, site, + MetadataSchemaEnum.DC.getName(), "description", null, + Item.ANY, siteDescriptions + ); + + context.restoreAuthSystemState(); + String token = getAuthToken(admin.getEmail(), password); + + getClient(token) + .perform(get("/api/core/sites/" + site.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(0), 0), + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(1), 1), + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(2), 2) + ) + ) + ); + + List ops = List.of( + new ReplaceOperation("/metadata/dc.description/0", siteDescriptions.get(2)), + new ReplaceOperation("/metadata/dc.description/1", siteDescriptions.get(0)), + new ReplaceOperation("/metadata/dc.description/2", siteDescriptions.get(1)) + ); + String requestBody = getPatchContent(ops); + getClient(token) + .perform(patch("/api/core/sites/" + site.getID()) + .content(requestBody) + .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(1), 2) + ) + ) + ); + getClient(token) + .perform(get("/api/core/sites/" + site.getID())) + .andExpect(status().isOk()) + .andExpect( + jsonPath("$.metadata", + Matchers.allOf( + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(2), 0), + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(0), 1), + MetadataMatcher.matchMetadata("dc.description", siteDescriptions.get(1), 2) + ) + ) + ); + } + private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Exception { context.turnOffAuthorisationSystem(); Site site = SiteBuilder.createSite(context).build();