Java tutorial
/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE and NOTICE files at the root of the source * tree and available online at * * http://www.dspace.org/license/ */ package org.dspace.app.rest; import static com.jayway.jsonpath.JsonPath.read; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; import static org.hamcrest.Matchers.is; 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.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import javax.ws.rs.core.MediaType; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.CharEncoding; import org.dspace.app.rest.builder.BitstreamBuilder; import org.dspace.app.rest.builder.ClaimedTaskBuilder; import org.dspace.app.rest.builder.CollectionBuilder; import org.dspace.app.rest.builder.CommunityBuilder; import org.dspace.app.rest.builder.EPersonBuilder; import org.dspace.app.rest.builder.WorkflowItemBuilder; import org.dspace.app.rest.builder.WorkspaceItemBuilder; import org.dspace.app.rest.matcher.CollectionMatcher; import org.dspace.app.rest.matcher.ItemMatcher; import org.dspace.app.rest.matcher.WorkflowItemMatcher; import org.dspace.app.rest.matcher.WorkspaceItemMatcher; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.patch.RemoveOperation; import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; import org.dspace.eperson.EPerson; import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; import org.hamcrest.Matchers; import org.junit.Ignore; import org.junit.Test; /** * Test suite for the WorkflowItem endpoint * @author Andrea Bollini (andrea.bollini at 4science.it) * */ public class WorkflowItemRestRepositoryIT extends AbstractControllerIntegrationTest { @Test /** * All the workflowitems should be returned regardless of the collection where they were created * * @throws Exception */ public void findAllTest() throws Exception { context.setCurrentUser(admin); //** GIVEN ** //1. A community-collection structure with one parent community with sub-community and two collections. 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") .withWorkflowGroup(1, admin).build(); Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2") .withWorkflowGroup(1, admin).build(); //2. Three workflow items in two different collections XmlWorkflowItem workflowItem1 = WorkflowItemBuilder.createWorkflowItem(context, col1) .withTitle("Workflow Item 1").withIssueDate("2017-10-17").build(); XmlWorkflowItem workflowItem2 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 2").withIssueDate("2016-02-13").build(); XmlWorkflowItem workflowItem3 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 3").withIssueDate("2016-02-13").build(); String token = getAuthToken(admin.getEmail(), password); getClient(token).perform(get("/api/workflow/workflowitems")).andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.containsInAnyOrder( WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem1, "Workflow Item 1", "2017-10-17"), WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem2, "Workflow Item 2", "2016-02-13"), WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem3, "Workflow Item 3", "2016-02-13")))) .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/workflow/workflowitems"))) .andExpect(jsonPath("$.page.size", is(20))).andExpect(jsonPath("$.page.totalElements", is(3))); } @Test /** * The workflowitem endpoint must provide proper pagination * * @throws Exception */ public void findAllWithPaginationTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community-collection structure with one parent community with sub-community and two collections. 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") .withWorkflowGroup(1, admin).build(); Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2") .withWorkflowGroup(1, admin).build(); //2. Three workflow items in two different collections XmlWorkflowItem workflowItem1 = WorkflowItemBuilder.createWorkflowItem(context, col1) .withTitle("Workflow Item 1").withIssueDate("2017-10-17").build(); XmlWorkflowItem workflowItem2 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 2").withIssueDate("2016-02-13").build(); XmlWorkflowItem workflowItem3 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 3").withIssueDate("2016-02-13").build(); context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); getClient(token).perform(get("/api/workflow/workflowitems").param("size", "2")).andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.containsInAnyOrder( WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem1, "Workflow Item 1", "2017-10-17"), WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem2, "Workflow Item 2", "2016-02-13")))) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.not(Matchers.contains(WorkflowItemMatcher .matchItemWithTitleAndDateIssued(workflowItem3, "Workflow Item 3", "2016-02-13"))))); getClient(token).perform(get("/api/workflow/workflowitems").param("size", "2").param("page", "1")) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.contains(WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem3, "Workflow Item 3", "2016-02-13")))) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.not(Matchers.contains( WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem1, "Workflow Item 1", "2017-10-17"), WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workflowItem2, "Workflow Item 2", "2016-02-13"))))) .andExpect(jsonPath("$.page.size", is(2))).andExpect(jsonPath("$.page.totalElements", is(3))); } @Test /** * The findAll should be available only to admins regardless to having or less a role in the workflow * * @throws Exception */ public void findAllForbiddenTest() throws Exception { context.setCurrentUser(admin); //** GIVEN ** //1. A community-collection structure with one parent community with sub-community and two collections. 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") .withWorkflowGroup(1, admin).build(); Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2") .withWorkflowGroup(1, eperson).build(); //2. Three workflow items in two different collections XmlWorkflowItem workflowItem1 = WorkflowItemBuilder.createWorkflowItem(context, col1) .withTitle("Workflow Item 1").withIssueDate("2017-10-17").build(); // these two items will be visible individually to the user XmlWorkflowItem workflowItem2 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 2").withIssueDate("2016-02-13").build(); XmlWorkflowItem workflowItem3 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 3").withIssueDate("2016-02-13").build(); String token = getAuthToken(eperson.getEmail(), password); // a normal user cannot access the workflowitems collection endpoint getClient(token).perform(get("/api/workflow/workflowitems")).andExpect(status().isForbidden()); // the workflowitems collection endpoint requires authentication getClient().perform(get("/api/workflow/workflowitems")).andExpect(status().isUnauthorized()); } @Test /** * The workflowitem resource endpoint must expose the proper structure * * @throws Exception */ public void findOneTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community-collection structure with one parent community with sub-community and two collections. 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") .withWorkflowGroup(1, admin).build(); //2. a workflow item XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").withAuthor("Smith, Donald").withAuthor("Doe, John") .withSubject("ExtraEntry").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(admin.getEmail(), password); getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "Workflow Item 1", "2017-10-17", "ExtraEntry")))); } @Test /** * The workflowitem resource endpoint should be visible only to member of the corresponding workflow step * * @throws Exception */ public void findOneForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** // 1. A community-collection structure with one parent community with sub-community and three collections // (different workflow steps and reviewers). parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity).withName("Sub Community") .build(); EPerson reviewer1 = EPersonBuilder.createEPerson(context).withEmail("reviewer1@example.com") .withPassword(password).build(); Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1") .withWorkflowGroup(1, reviewer1).build(); EPerson reviewer2 = EPersonBuilder.createEPerson(context).withEmail("reviewer2@example.com") .withPassword(password).build(); Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2") .withWorkflowGroup(2, reviewer2).build(); EPerson reviewer3 = EPersonBuilder.createEPerson(context).withEmail("reviewer3@example.com") .withPassword(password).build(); Collection col3 = CollectionBuilder.createCollection(context, child1).withName("Collection 3") .withWorkflowGroup(3, reviewer3).build(); //2. three workflow items in the three collections (this will lead to pool task) XmlWorkflowItem witem1 = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .build(); XmlWorkflowItem witem2 = WorkflowItemBuilder.createWorkflowItem(context, col2).withTitle("Workflow Item 2") .build(); XmlWorkflowItem witem3 = WorkflowItemBuilder.createWorkflowItem(context, col3).withTitle("Workflow Item 3") .build(); //3. Three claimed tasks (and corresponding workflowitems) ClaimedTask claimed1 = ClaimedTaskBuilder.createClaimedTask(context, col1, reviewer1).withTitle("Pool 1") .build(); XmlWorkflowItem wClaimed1 = claimed1.getWorkflowItem(); ClaimedTask claimed2 = ClaimedTaskBuilder.createClaimedTask(context, col2, reviewer2).withTitle("Pool 2") .build(); XmlWorkflowItem wClaimed2 = claimed2.getWorkflowItem(); ClaimedTask claimed3 = ClaimedTaskBuilder.createClaimedTask(context, col3, reviewer3).withTitle("Pool 3") .build(); XmlWorkflowItem wClaimed3 = claimed3.getWorkflowItem(); context.restoreAuthSystemState(); String rev1Token = getAuthToken(reviewer1.getEmail(), password); String rev2Token = getAuthToken(reviewer2.getEmail(), password); String rev3Token = getAuthToken(reviewer3.getEmail(), password); // anonymous users should be unable to see workflowitem regardless to their workflow status (pool/claimed) getClient().perform(get("/api/workflow/workflowitems/" + witem1.getID())) .andExpect(status().isUnauthorized()); getClient().perform(get("/api/workflow/workflowitems/" + claimed1.getID())) .andExpect(status().isUnauthorized()); // reviewer 1 should be able to access only the first workflow item of each group getClient(rev1Token).perform(get("/api/workflow/workflowitems/" + witem1.getID())) .andExpect(status().isOk()); getClient(rev1Token).perform(get("/api/workflow/workflowitems/" + witem2.getID())) .andExpect(status().isForbidden()); getClient(rev1Token).perform(get("/api/workflow/workflowitems/" + witem3.getID())) .andExpect(status().isForbidden()); getClient(rev1Token).perform(get("/api/workflow/workflowitems/" + wClaimed1.getID())) .andExpect(status().isOk()); getClient(rev1Token).perform(get("/api/workflow/workflowitems/" + wClaimed2.getID())) .andExpect(status().isForbidden()); getClient(rev1Token).perform(get("/api/workflow/workflowitems/" + wClaimed3.getID())) .andExpect(status().isForbidden()); // reviewer 2 should be able to access only the second workflow item of each group getClient(rev2Token).perform(get("/api/workflow/workflowitems/" + witem1.getID())) .andExpect(status().isForbidden()); getClient(rev2Token).perform(get("/api/workflow/workflowitems/" + witem2.getID())) .andExpect(status().isOk()); getClient(rev2Token).perform(get("/api/workflow/workflowitems/" + witem3.getID())) .andExpect(status().isForbidden()); getClient(rev2Token).perform(get("/api/workflow/workflowitems/" + wClaimed1.getID())) .andExpect(status().isForbidden()); getClient(rev2Token).perform(get("/api/workflow/workflowitems/" + wClaimed2.getID())) .andExpect(status().isOk()); getClient(rev2Token).perform(get("/api/workflow/workflowitems/" + wClaimed3.getID())) .andExpect(status().isForbidden()); // reviewer 3 should be able to access only the third workflow item of each group getClient(rev3Token).perform(get("/api/workflow/workflowitems/" + witem1.getID())) .andExpect(status().isForbidden()); getClient(rev3Token).perform(get("/api/workflow/workflowitems/" + witem2.getID())) .andExpect(status().isForbidden()); getClient(rev3Token).perform(get("/api/workflow/workflowitems/" + witem3.getID())) .andExpect(status().isOk()); getClient(rev3Token).perform(get("/api/workflow/workflowitems/" + wClaimed1.getID())) .andExpect(status().isForbidden()); getClient(rev3Token).perform(get("/api/workflow/workflowitems/" + wClaimed2.getID())) .andExpect(status().isForbidden()); getClient(rev3Token).perform(get("/api/workflow/workflowitems/" + wClaimed3.getID())) .andExpect(status().isOk()); } @Test /** * The workflowitem resource endpoint must expose the proper structure * * @throws Exception */ public void findOneRelsTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community-collection structure with one parent community with sub-community and two collections. 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") .withWorkflowGroup(1, admin).build(); //2. a workflow item XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").withAuthor("Smith, Donald").withAuthor("Doe, John") .withSubject("ExtraEntry").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(admin.getEmail(), password); getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID() + "/collection")) .andExpect(status().isOk()).andExpect(jsonPath("$", Matchers.is( CollectionMatcher.matchCollectionEntry(col1.getName(), col1.getID(), col1.getHandle())))); getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID() + "/item")) .andExpect(status().isOk()).andExpect(jsonPath("$", Matchers.is(ItemMatcher .matchItemWithTitleAndDateIssued(witem.getItem(), "Workflow Item 1", "2017-10-17")))); getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID() + "/submissionDefinition")) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.is(hasJsonPath("$.id", is("traditional"))))); } @Test /** * Check the response code for unexistent workflowitem * * @throws Exception */ public void findOneWrongIDTest() throws Exception { String token = getAuthToken(admin.getEmail(), password); getClient(token).perform(get("/api/workflow/workflowitems/" + Integer.MAX_VALUE)) .andExpect(status().isNotFound()); getClient(token).perform(get("/api/workflow/workflowitems/" + UUID.randomUUID())) .andExpect(status().isNotFound()); } @Test /** * Create three workflowitem with two different submitter and verify that the findBySubmitter return the proper * list of workflowitem for each submitter also paginating * * @throws Exception */ public void findBySubmitterTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community-collection structure with one parent community with sub-community and two collections. 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") .withWorkflowGroup(1, admin).build(); Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2") .withWorkflowGroup(1, admin).build(); //2. create two users to use as submitters EPerson submitter1 = EPersonBuilder.createEPerson(context).withEmail("submitter1@example.com").build(); EPerson submitter2 = EPersonBuilder.createEPerson(context).withEmail("submitter2@example.com").build(); // create two workflowitems with the first submitter context.setCurrentUser(submitter1); //3. Two workflow items in two different collections XmlWorkflowItem workspaceItem1 = WorkflowItemBuilder.createWorkflowItem(context, col1) .withTitle("Workflow Item 1").withIssueDate("2017-10-17").build(); XmlWorkflowItem workspaceItem2 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 2").withIssueDate("2016-02-13").build(); //4. A workflowitem for the second submitter context.setCurrentUser(submitter2); XmlWorkflowItem workspaceItem3 = WorkflowItemBuilder.createWorkflowItem(context, col2) .withTitle("Workflow Item 3").withIssueDate("2016-02-13").build(); context.restoreAuthSystemState(); // use our admin to retrieve all the workspace by submitter String token = getAuthToken(admin.getEmail(), password); // the first submitter has two workspace getClient(token) .perform(get("/api/workflow/workflowitems/search/findBySubmitter") .param("size", "20").param("uuid", submitter1.getID().toString())) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.containsInAnyOrder( WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workspaceItem1, "Workflow Item 1", "2017-10-17"), WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workspaceItem2, "Workflow Item 2", "2016-02-13")))) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.not(Matchers.contains(WorkflowItemMatcher.matchItemWithTitleAndDateIssued( workspaceItem3, "Workflow Item 3", "2016-02-13"))))) .andExpect(jsonPath("$.page.size", is(20))).andExpect(jsonPath("$.page.totalElements", is(2))); // the first submitter has two workspace so if we paginate with a 1-size windows the page 1 will contains the // second workspace getClient(token) .perform(get("/api/workflow/workflowitems/search/findBySubmitter") .param("size", "1").param("page", "1").param("uuid", submitter1.getID().toString())) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.contains(WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workspaceItem2, "Workflow Item 2", "2016-02-13")))) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.not(Matchers.contains( WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workspaceItem1, "Workflow Item 1", "2017-10-17"), WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workspaceItem3, "Workflow Item 3", "2016-02-13"))))) .andExpect(jsonPath("$.page.size", is(1))).andExpect(jsonPath("$.page.totalElements", is(2))); // the second submitter has a single workspace getClient(token) .perform(get("/api/workflow/workflowitems/search/findBySubmitter") .param("size", "20").param("uuid", submitter2.getID().toString())) .andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.workflowitems", Matchers.contains(WorkflowItemMatcher.matchItemWithTitleAndDateIssued(workspaceItem3, "Workflow Item 3", "2016-02-13")))) .andExpect(jsonPath("$.page.size", is(20))).andExpect(jsonPath("$.page.totalElements", is(1))); } @Test /** * A delete request over a workflowitem should result in abort the workflow sending the item back to the submitter * workspace * * @throws Exception */ public void deleteOneTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, admin).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. a workflow item XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").build(); Item item = witem.getItem(); //Add a bitstream to the item String bitstreamContent = "ThisIsSomeDummyText"; Bitstream bitstream = null; try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) { bitstream = BitstreamBuilder.createBitstream(context, item, is).withName("Bitstream1") .withMimeType("text/plain").build(); } context.restoreAuthSystemState(); String token = getAuthToken(admin.getEmail(), password); String tokenSubmitter = getAuthToken(submitter.getEmail(), "dspace"); // Delete the workflowitem getClient(token).perform(delete("/api/workflow/workflowitems/" + witem.getID())) .andExpect(status().is(204)); // Trying to get deleted workflowitem should fail with 404 getClient(token).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().is(404)); // the workflowitem's item should still exist getClient(token).perform(get("/api/core/items/" + item.getID())).andExpect(status().is(200)); // the workflowitem's bitstream should still exist getClient(token).perform(get("/api/core/bitstreams/" + bitstream.getID())).andExpect(status().is(200)); // a workspaceitem should exist now in the submitter workspace getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems")).andExpect(status().isOk()) .andExpect(jsonPath("$._embedded.workspaceitems", Matchers.containsInAnyOrder(WorkspaceItemMatcher.matchItemWithTitleAndDateIssued(null, "Workflow Item 1", "2017-10-17")))) .andExpect( jsonPath("$._links.self.href", Matchers.containsString("/api/submission/workspaceitems"))) .andExpect(jsonPath("$.page.size", is(20))).andExpect(jsonPath("$.page.totalElements", is(1))); } @Test /** * Test the creation of workflowitem POSTing to the resource workflowitems collection endpoint a workspaceitem (as * uri-list). This corresponds to the deposit action done by the submitter. * * @throws Exception */ public void createWorkflowItemTest() throws Exception { context.turnOffAuthorisationSystem(); // hold the id of the created workflow item AtomicReference<Integer> idRef = new AtomicReference<Integer>(); try { //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, admin).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. a workspace item WorkspaceItem wsitem = WorkspaceItemBuilder.createWorkspaceItem(context, col1) .withTitle("Submission Item").withIssueDate("2017-10-17").build(); context.restoreAuthSystemState(); // get the submitter auth token String authToken = getAuthToken(submitter.getEmail(), "dspace"); // submit the workspaceitem to start the workflow getClient(authToken).perform(post(BASE_REST_SERVER_URL + "/api/workflow/workflowitems") .content("/api/submission/workspaceitems/" + wsitem.getID()).contentType(textUriContentType)) .andExpect(status().isCreated()) .andExpect(jsonPath("$", WorkflowItemMatcher.matchItemWithTitleAndDateIssued(null, "Submission Item", "2017-10-17"))) .andDo(result -> idRef.set(read(result.getResponse().getContentAsString(), "$.id"))); // check that the workflowitem is persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + idRef.get())) .andExpect(status().isOk()).andExpect(jsonPath("$", Matchers.is(WorkflowItemMatcher .matchItemWithTitleAndDateIssued(null, "Submission Item", "2017-10-17")))); } finally { // remove the workflowitem if any WorkflowItemBuilder.deleteWorkflowItem(idRef.get()); } } @Test /** * Test invalid attempts to create workflowitem POSTing to the resource workflowitems collection endpoint an not * existing workspaceitem (as uri-list) or an empty list. This should result in a 422 error * * @throws Exception */ public void unvalidCreateWorkflowItemTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, admin).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); // get the submitter auth token String authToken = getAuthToken(submitter.getEmail(), "dspace"); // submit a not existing workspaceitem getClient(authToken).perform(post(BASE_REST_SERVER_URL + "/api/workflow/workflowitems") .content("/api/submission/workspaceitems/" + UUID.randomUUID().toString()) .contentType(textUriContentType)).andExpect(status().isUnprocessableEntity()); // submit an invalid URL getClient(authToken).perform(post(BASE_REST_SERVER_URL + "/api/workflow/workflowitems").content("") .contentType(textUriContentType)).andExpect(status().isUnprocessableEntity()); } /** * Test the exposition of validation error for missing required metadata * * @throws Exception */ public void validationErrorsRequiredMetadataTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, eperson).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. a workflow item will all the required fields XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").build(); //4. a workflow item without the dateissued required field XmlWorkflowItem witemMissingFields = WorkflowItemBuilder.createWorkflowItem(context, col1) .withTitle("Workflow Item 1").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); getClient(authToken).perform(get("/api/workflow/worfklowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()); getClient(authToken).perform(get("/api/workflow/worfklowitems/" + witemMissingFields.getID())) .andExpect(status().isOk()) .andExpect(jsonPath("$.errors[?(@.message=='error.validation.required')]", Matchers.contains(hasJsonPath("$.paths", Matchers.contains( hasJsonPath("$", Matchers.is("/sections/traditionalpageone/dc.date.issued"))))))); } @Test /** * Test the update of metadata * * @throws Exception */ public void patchUpdateMetadataTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(2, eperson).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. a workflow item XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").withSubject("ExtraEntry").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); // a simple patch to update an existent metadata List<Operation> updateTitle = new ArrayList<Operation>(); Map<String, String> value = new HashMap<String, String>(); value.put("value", "New Title"); updateTitle.add(new ReplaceOperation("/sections/traditionalpageone/dc.title/0", value)); String patchBody = getPatchContent(updateTitle); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()).andExpect(jsonPath("$", // check the new title and untouched values Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "New Title", "2017-10-17", "ExtraEntry")))); ; // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$", Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "New Title", "2017-10-17", "ExtraEntry")))); } @Test @Ignore(value = "This demonstrate the bug logged in DS-4179") /** * Verify that update of metadata is forbidden in step 1. * * @throws Exception */ public void patchUpdateMetadataStep1ForbiddenTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, eperson).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. a workflow item XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").withSubject("ExtraEntry").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); // a simple patch to update an existent metadata List<Operation> updateTitle = new ArrayList<Operation>(); Map<String, String> value = new HashMap<String, String>(); value.put("value", "New Title"); updateTitle.add(new ReplaceOperation("/sections/traditionalpageone/dc.title/0", value)); String patchBody = getPatchContent(updateTitle); getClient(authToken).perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)).andExpect(status().isForbidden()); // verify that the patch changes have been rejected getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "New Title", "2017-10-17", "ExtraEntry")))); } @Test /** * Test the update of metadata in step3 * * @throws Exception */ public void patchUpdateMetadataStep3Test() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(3, eperson).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. a workflow item XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").withSubject("ExtraEntry").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); // a simple patch to update an existent metadata List<Operation> updateTitle = new ArrayList<Operation>(); Map<String, String> value = new HashMap<String, String>(); value.put("value", "New Title"); updateTitle.add(new ReplaceOperation("/sections/traditionalpageone/dc.title/0", value)); String patchBody = getPatchContent(updateTitle); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()).andExpect(jsonPath("$", // check the new title and untouched values Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "New Title", "2017-10-17", "ExtraEntry")))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$", Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "New Title", "2017-10-17", "ExtraEntry")))); } @Test /** * Test delete of a metadata * * @throws Exception */ public void patchDeleteMetadataTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, eperson).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. some workflow items for our test XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Workflow Item 1") .withIssueDate("2017-10-17").withSubject("ExtraEntry").build(); XmlWorkflowItem witemMultipleSubjects = WorkflowItemBuilder.createWorkflowItem(context, col1) .withTitle("Workflow Item 2").withIssueDate("2017-10-17").withSubject("Subject1") .withSubject("Subject2").withSubject("Subject3").withSubject("Subject4").build(); XmlWorkflowItem witemWithTitleDateAndSubjects = WorkflowItemBuilder.createWorkflowItem(context, col1) .withTitle("Workflow Item 3").withIssueDate("2017-10-17").withSubject("Subject1") .withSubject("Subject2").withSubject("Subject3").withSubject("Subject4").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); // try to remove the title List<Operation> removeTitle = new ArrayList<Operation>(); removeTitle.add(new RemoveOperation("/sections/traditionalpageone/dc.title/0")); String patchBody = getPatchContent(removeTitle); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()) .content(patchBody).contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.errors[?(@.message=='error.validation.required')]", Matchers.contains(hasJsonPath("$.paths", Matchers.contains( hasJsonPath("$", Matchers.is("/sections/traditionalpageone/dc.title"))))))) .andExpect(jsonPath("$", // check the new title and untouched values Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, null, "2017-10-17", "ExtraEntry")))); ; // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors[?(@.message=='error.validation.required')]", Matchers.contains(hasJsonPath("$.paths", Matchers.contains( hasJsonPath("$", Matchers.is("/sections/traditionalpageone/dc.title"))))))) .andExpect(jsonPath("$", Matchers.is(WorkflowItemMatcher .matchItemWithTitleAndDateIssuedAndSubject(witem, null, "2017-10-17", "ExtraEntry")))); // try to remove a metadata in a specific position List<Operation> removeMidSubject = new ArrayList<Operation>(); removeMidSubject.add(new RemoveOperation("/sections/traditionalpagetwo/dc.subject/1")); patchBody = getPatchContent(removeMidSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witemMultipleSubjects.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject3"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Subject4"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witemMultipleSubjects.getID())) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject3"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Subject4"))); List<Operation> removeFirstSubject = new ArrayList<Operation>(); removeFirstSubject.add(new RemoveOperation("/sections/traditionalpagetwo/dc.subject/0")); patchBody = getPatchContent(removeFirstSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witemMultipleSubjects.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject3"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject4"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witemMultipleSubjects.getID())) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject3"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject4"))); List<Operation> removeLastSubject = new ArrayList<Operation>(); removeLastSubject.add(new RemoveOperation("/sections/traditionalpagetwo/dc.subject/1")); patchBody = getPatchContent(removeLastSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witemMultipleSubjects.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject3"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witemMultipleSubjects.getID())) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject3"))); List<Operation> removeFinalSubject = new ArrayList<Operation>(); removeFinalSubject.add(new RemoveOperation("/sections/traditionalpagetwo/dc.subject/0")); patchBody = getPatchContent(removeFinalSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witemMultipleSubjects.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject']").doesNotExist()); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witemMultipleSubjects.getID())) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject']").doesNotExist()); // remove all the subjects with a single operation List<Operation> removeSubjectsAllAtOnce = new ArrayList<Operation>(); removeSubjectsAllAtOnce.add(new RemoveOperation("/sections/traditionalpagetwo/dc.subject")); patchBody = getPatchContent(removeSubjectsAllAtOnce); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witemWithTitleDateAndSubjects.getID()) .content(patchBody).contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject']").doesNotExist()); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witemWithTitleDateAndSubjects.getID())) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject']").doesNotExist()); } @Test /** * Test the addition of metadata * * @throws Exception */ public void patchAddMetadataTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, eperson).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. some workflow items for our test XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withIssueDate("2017-10-17") .withSubject("ExtraEntry").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); // try to add the title List<Operation> addTitle = new ArrayList<Operation>(); // create a list of values to use in add operation List<Map<String, String>> values = new ArrayList<Map<String, String>>(); Map<String, String> value = new HashMap<String, String>(); value.put("value", "New Title"); values.add(value); addTitle.add(new AddOperation("/sections/traditionalpageone/dc.title", values)); String patchBody = getPatchContent(addTitle); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()).andExpect(jsonPath("$", // check if the new title if back and the other values untouched Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "New Title", "2017-10-17", "ExtraEntry")))); ; // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$", Matchers.is(WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem, "New Title", "2017-10-17", "ExtraEntry")))); } @Test /** * Test the addition of metadata * * @throws Exception */ public void patchAddMultipleMetadataValuesTest() throws Exception { context.turnOffAuthorisationSystem(); //** GIVEN ** //1. A community with one collection. parentCommunity = CommunityBuilder.createCommunity(context).withName("Parent Community").build(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1") .withWorkflowGroup(1, eperson).build(); //2. create a normal user to use as submitter EPerson submitter = EPersonBuilder.createEPerson(context).withEmail("submitter@example.com") .withPassword("dspace").build(); context.setCurrentUser(submitter); //3. some workflow items for our test XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1).withTitle("Test WorkflowItem") .withIssueDate("2017-10-17").build(); context.restoreAuthSystemState(); String authToken = getAuthToken(eperson.getEmail(), password); // try to add multiple subjects at once List<Operation> addSubjects = new ArrayList<Operation>(); // create a list of values to use in add operation List<Map<String, String>> values = new ArrayList<Map<String, String>>(); Map<String, String> value1 = new HashMap<String, String>(); value1.put("value", "Subject1"); Map<String, String> value2 = new HashMap<String, String>(); value2.put("value", "Subject2"); values.add(value1); values.add(value2); addSubjects.add(new AddOperation("/sections/traditionalpagetwo/dc.subject", values)); String patchBody = getPatchContent(addSubjects); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject2"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject2"))); // add a subject in the first position List<Operation> addFirstSubject = new ArrayList<Operation>(); Map<String, String> firstSubject = new HashMap<String, String>(); firstSubject.put("value", "First Subject"); addFirstSubject.add(new AddOperation("/sections/traditionalpagetwo/dc.subject/0", firstSubject)); patchBody = getPatchContent(addFirstSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Subject2"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Subject2"))); // add a subject in a central position List<Operation> addMidSubject = new ArrayList<Operation>(); Map<String, String> midSubject = new HashMap<String, String>(); midSubject.put("value", "Mid Subject"); addMidSubject.add(new AddOperation("/sections/traditionalpagetwo/dc.subject/2", midSubject)); patchBody = getPatchContent(addMidSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Mid Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][3].value", is("Subject2"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Mid Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][3].value", is("Subject2"))); // append a last subject without specifying the index List<Operation> addLastSubject = new ArrayList<Operation>(); Map<String, String> lastSubject = new HashMap<String, String>(); lastSubject.put("value", "Last Subject"); addLastSubject.add(new AddOperation("/sections/traditionalpagetwo/dc.subject/4", lastSubject)); patchBody = getPatchContent(addLastSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Mid Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][3].value", is("Subject2"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][4].value", is("Last Subject"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Mid Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][3].value", is("Subject2"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][4].value", is("Last Subject"))); // append a last subject without specifying the index List<Operation> addFinalSubject = new ArrayList<Operation>(); Map<String, String> finalSubject = new HashMap<String, String>(); finalSubject.put("value", "Final Subject"); addFinalSubject.add(new AddOperation("/sections/traditionalpagetwo/dc.subject/-", finalSubject)); patchBody = getPatchContent(addFinalSubject); getClient(authToken) .perform(patch("/api/workflow/workflowitems/" + witem.getID()).content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()).andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Mid Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][3].value", is("Subject2"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][4].value", is("Last Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][5].value", is("Final Subject"))); // verify that the patch changes have been persisted getClient(authToken).perform(get("/api/workflow/workflowitems/" + witem.getID())).andExpect(status().isOk()) .andExpect(jsonPath("$.errors").doesNotExist()) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][0].value", is("First Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][1].value", is("Subject1"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][2].value", is("Mid Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][3].value", is("Subject2"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][4].value", is("Last Subject"))) .andExpect(jsonPath("$.sections.traditionalpagetwo['dc.subject'][5].value", is("Final Subject"))); } }