package pro.taskana.task.rest; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static pro.taskana.common.rest.RestHelper.TEMPLATE; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.time.Instant; import java.time.temporal.ChronoUnit; import javax.sql.DataSource; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.ParameterizedTypeReference; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import pro.taskana.classification.rest.models.ClassificationSummaryRepresentationModel; import pro.taskana.common.rest.Mapping; import pro.taskana.common.rest.RestHelper; import pro.taskana.common.rest.TaskanaSpringBootTest; import pro.taskana.common.rest.models.TaskanaPagedModel; import pro.taskana.sampledata.SampleDataGenerator; import pro.taskana.task.api.TaskState; import pro.taskana.task.api.models.ObjectReference; import pro.taskana.task.rest.models.TaskRepresentationModel; import pro.taskana.task.rest.models.TaskSummaryRepresentationModel; import pro.taskana.workbasket.rest.models.WorkbasketSummaryRepresentationModel; /** Test Task Controller. */ @TaskanaSpringBootTest class TaskControllerIntTest { private static final ParameterizedTypeReference<TaskanaPagedModel<TaskSummaryRepresentationModel>> TASK_SUMMARY_PAGE_MODEL_TYPE = new ParameterizedTypeReference<TaskanaPagedModel<TaskSummaryRepresentationModel>>() {}; private static final ParameterizedTypeReference<TaskRepresentationModel> TASK_MODEL_TYPE = ParameterizedTypeReference.forType(TaskRepresentationModel.class); private static RestTemplate template; private final RestHelper restHelper; private final DataSource dataSource; @Value("${taskana.schemaName:TASKANA}") public String schemaName; @Autowired TaskControllerIntTest(RestHelper restHelper, DataSource dataSource) { this.restHelper = restHelper; this.dataSource = dataSource; } @BeforeAll static void init() { template = RestHelper.TEMPLATE; } void resetDb() { SampleDataGenerator sampleDataGenerator = new SampleDataGenerator(dataSource, schemaName); sampleDataGenerator.generateSampleData(); } @Test void testGetAllTasks() { ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS), HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(25); } @Test void testGetAllTasksByWorkbasketId() { ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(22); } @Test void testGetAllTasksByWorkbasketIdWithinMultiplePlannedTimeIntervals() { Instant firstInstant = Instant.now().minus(7, ChronoUnit.DAYS); Instant secondInstant = Instant.now().minus(10, ChronoUnit.DAYS); Instant thirdInstant = Instant.now().minus(10, ChronoUnit.DAYS); Instant fourthInstant = Instant.now().minus(11, ChronoUnit.DAYS); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&planned=" + firstInstant + ",," + secondInstant + "," + thirdInstant + "," + "," + fourthInstant + "&sort-by=planned", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(6); } @Test void testGetAllTasksByWorkbasketIdWithinSinglePlannedTimeInterval() { Instant plannedFromInstant = Instant.now().minus(6, ChronoUnit.DAYS); Instant plannedToInstant = Instant.now().minus(3, ChronoUnit.DAYS); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&planned-from=" + plannedFromInstant + "&planned-until=" + plannedToInstant + "&sort-by=planned", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(3); } @Test void testGetAllTasksByWorkbasketIdWithinSingleIndefinitePlannedTimeInterval() { Instant plannedFromInstant = Instant.now().minus(6, ChronoUnit.DAYS); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&planned-from=" + plannedFromInstant + "&sort-by=planned", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(4); } @Test void testGetAllTasksByWorkbasketIdWithInvalidPlannedParamsCombination() { ThrowingCallable httpCall = () -> TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&planned=2020-01-22T09:44:47.453Z,," + "2020-01-19T07:44:47.453Z,2020-01-19T19:44:47.453Z," + ",2020-01-18T09:44:47.453Z" + "&planned-from=2020-01-19T07:44:47.453Z" + "&sort-by=planned", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThatThrownBy(httpCall) .isInstanceOf(HttpClientErrorException.class) .hasMessageContaining("400"); } @Test void testGetAllTasksByWorkbasketIdWithinMultipleDueTimeIntervals() { Instant firstInstant = Instant.now().minus(7, ChronoUnit.DAYS); Instant secondInstant = Instant.now().minus(10, ChronoUnit.DAYS); Instant thirdInstant = Instant.now().minus(10, ChronoUnit.DAYS); Instant fourthInstant = Instant.now().minus(11, ChronoUnit.DAYS); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&due=" + firstInstant + ",," + secondInstant + "," + thirdInstant + "," + "," + fourthInstant + "&sort-by=due", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(6); } @Test void should_ReturnAllTasksByWildcardSearch_For_ProvidedSearchValue() { ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?wildcard-search-value=%99%" + "&wildcard-search-fields=NAME,custom_3,CuStOM_4", HttpMethod.GET, new HttpEntity<String>(restHelper.getHeadersAdmin()), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(4); } @Test void should_ThrowException_When_ProvidingInvalidWildcardSearchParameters() { ThrowingCallable httpCall = () -> TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?wildcard-search-value=%rt%", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThatThrownBy(httpCall) .isInstanceOf(HttpClientErrorException.class) .hasMessageContaining("400") .extracting(ex -> ((HttpClientErrorException) ex).getStatusCode()) .isEqualTo(HttpStatus.BAD_REQUEST); ThrowingCallable httpCall2 = () -> TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?wildcard-search-fields=NAME,CUSTOM_3,CUSTOM_4", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThatThrownBy(httpCall2) .isInstanceOf(HttpClientErrorException.class) .hasMessageContaining("400") .extracting(ex -> ((HttpClientErrorException) ex).getStatusCode()) .isEqualTo(HttpStatus.BAD_REQUEST); } @Test void testGetAllTasksByWorkbasketIdWithinSingleDueTimeInterval() { Instant dueFromInstant = Instant.now().minus(8, ChronoUnit.DAYS); Instant dueToInstant = Instant.now().minus(3, ChronoUnit.DAYS); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&due-from=" + dueFromInstant + "&due-until=" + dueToInstant + "&sort-by=due", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(9); } @Test void testGetAllTasksByWorkbasketIdWithinSingleIndefiniteDueTimeInterval() { Instant dueToInstant = Instant.now().minus(1, ChronoUnit.DAYS); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&due-until=" + dueToInstant + "&sort-by=due", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(6); } @Test void testGetAllTasksByWorkbasketIdWithInvalidDueParamsCombination() { ThrowingCallable httpCall = () -> TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-id=WBI:100000000000000000000000000000000001" + "&due=2020-01-22T09:44:47.453Z,," + "2020-01-19T07:44:47.453Z,2020-01-19T19:44:47.453Z," + ",2020-01-18T09:44:47.453Z" + "&due-from=2020-01-19T07:44:47.453Z" + "&sort-by=planned", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThatThrownBy(httpCall) .isInstanceOf(HttpClientErrorException.class) .hasMessageContaining("400"); } @Test void testGetAllTasksByWorkbasketKeyAndDomain() { HttpEntity<String> request = new HttpEntity<>(restHelper.getHeadersUser_1_2()); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-key=USER-1-2&domain=DOMAIN_A", HttpMethod.GET, request, TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(20); } @Test void testGetAllTasksByExternalId() { ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?external-id=ETI:000000000000000000000000000000000003," + "ETI:000000000000000000000000000000000004", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(2); } @Test void testExceptionIfKeyIsSetButDomainIsMissing() { HttpEntity<String> request = new HttpEntity<>(restHelper.getHeadersUser_1_2()); ThrowingCallable httpCall = () -> TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?workbasket-key=USER-1-2", HttpMethod.GET, request, TASK_SUMMARY_PAGE_MODEL_TYPE); assertThatThrownBy(httpCall) .isInstanceOf(HttpClientErrorException.class) .hasMessageContaining("400"); } @Test void testGetAllTasksWithAdminRole() { ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS), HttpMethod.GET, new HttpEntity<>(restHelper.getHeadersAdmin()), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getContent()).hasSize(73); } @Test void testGetAllTasksKeepingFilters() { ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?por.type=VNR&por.value=22334455&sort-by=por.value&order=desc", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF).getHref()) .endsWith("/api/v1/tasks?por.type=VNR&por.value=22334455&sort-by=por.value&order=desc"); } @Test void testThrowsExceptionIfInvalidFilterIsUsed() { ThrowingCallable httpCall = () -> TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?invalid=VNR", HttpMethod.GET, restHelper.defaultRequest(), TASK_SUMMARY_PAGE_MODEL_TYPE); assertThatThrownBy(httpCall) .isInstanceOf(HttpClientErrorException.class) .hasMessageContaining("[invalid]") .extracting(ex -> ((HttpClientErrorException) ex).getStatusCode()) .isEqualTo(HttpStatus.BAD_REQUEST); } @Test void testGetLastPageSortedByPorValue() { HttpEntity<String> request = new HttpEntity<>(restHelper.getHeadersAdmin()); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?state=READY,CLAIMED&sort-by=por.value&order=desc&page-size=5&page=14", HttpMethod.GET, request, TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getContent()).hasSize(1); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.LAST).getHref()) .contains("page=14"); assertThat("TKI:100000000000000000000000000000000000") .isEqualTo(response.getBody().getContent().iterator().next().getTaskId()); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF).getHref()) .endsWith( "/api/v1/tasks?" + "state=READY,CLAIMED&sort-by=por.value&order=desc&page-size=5&page=14"); assertThat(response.getBody().getLink(IanaLinkRelations.FIRST)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.LAST)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.PREV)).isNotNull(); } @Test void testGetLastPageSortedByDueWithHiddenTasksRemovedFromResult() { resetDb(); // required because // ClassificationControllerIntTest.testGetQueryByPorSecondPageSortedByType changes // tasks and this test depends on the tasks as they are in sampledata HttpEntity<String> request = new HttpEntity<>(restHelper.getHeadersTeamlead_1()); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?sort-by=due&order=desc", HttpMethod.GET, request, TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getContent()).hasSize(25); response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?sort-by=due&order=desc&page-size=5&page=5", HttpMethod.GET, request, TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat((response.getBody()).getContent()).hasSize(5); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.LAST).getHref()) .contains("page=5"); assertThat("TKI:000000000000000000000000000000000023") .isEqualTo(response.getBody().getContent().iterator().next().getTaskId()); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF).getHref()) .endsWith("/api/v1/tasks?sort-by=due&order=desc&page-size=5&page=5"); assertThat(response.getBody().getLink(IanaLinkRelations.FIRST)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.LAST)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.PREV)).isNotNull(); } @Test void testGetQueryByPorSecondPageSortedByType() { resetDb(); // required because // ClassificationControllerIntTest.testGetQueryByPorSecondPageSortedByType changes // tasks and this test depends on the tasks as they are in sampledata HttpEntity<String> request = new HttpEntity<>(restHelper.getHeadersTeamlead_1()); ResponseEntity<TaskanaPagedModel<TaskSummaryRepresentationModel>> response = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS) + "?por.company=00&por.system=PASystem&por.instance=00&" + "por.type=VNR&por.value=22334455&sort-by=por.type&" + "order=asc&page-size=5&page=2", HttpMethod.GET, request, TASK_SUMMARY_PAGE_MODEL_TYPE); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody().getContent()) .extracting(TaskSummaryRepresentationModel::getTaskId) .containsOnly("TKI:000000000000000000000000000000000013"); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getRequiredLink(IanaLinkRelations.SELF).getHref()) .endsWith( "/api/v1/tasks?por.company=00&por.system=PASystem&por.instance=00&" + "por.type=VNR&por.value=22334455&sort-by=por.type&order=asc&" + "page-size=5&page=2"); assertThat(response.getBody().getLink(IanaLinkRelations.FIRST)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.LAST)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.PREV)).isNotNull(); } @Test void should_NotGetEmptyAttachmentList_When_GettingTaskWithAttachment() { ResponseEntity<TaskRepresentationModel> response = template.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID, "TKI:000000000000000000000000000000000002"), HttpMethod.GET, new HttpEntity<>(restHelper.getHeadersAdmin()), TASK_MODEL_TYPE); TaskRepresentationModel repModel = response.getBody(); assertThat(repModel).isNotNull(); assertThat(repModel.getAttachments()).isNotEmpty(); assertThat(repModel.getAttachments()).isNotNull(); } @Test void should_ChangeValueOfModified_When_UpdatingTask() { ResponseEntity<TaskRepresentationModel> responseGet = template.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID, "TKI:100000000000000000000000000000000000"), HttpMethod.GET, new HttpEntity<>(restHelper.getHeadersTeamlead_1()), TASK_MODEL_TYPE); final TaskRepresentationModel originalTask = responseGet.getBody(); ResponseEntity<TaskRepresentationModel> responseUpdate = template.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID, "TKI:100000000000000000000000000000000000"), HttpMethod.PUT, new HttpEntity<>(originalTask, restHelper.getHeadersTeamlead_1()), TASK_MODEL_TYPE); TaskRepresentationModel updatedTask = responseUpdate.getBody(); assertThat(originalTask).isNotNull(); assertThat(updatedTask).isNotNull(); assertThat(originalTask.getModified()).isBefore(updatedTask.getModified()); } @Test void testCreateAndDeleteTask() { TaskRepresentationModel taskRepresentationModel = getTaskResourceSample(); ResponseEntity<TaskRepresentationModel> responseCreate = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS), HttpMethod.POST, new HttpEntity<>(taskRepresentationModel, restHelper.getHeadersTeamlead_1()), TASK_MODEL_TYPE); assertThat(HttpStatus.CREATED).isEqualTo(responseCreate.getStatusCode()); assertThat(responseCreate.getBody()).isNotNull(); String taskIdOfCreatedTask = responseCreate.getBody().getTaskId(); assertThat(taskIdOfCreatedTask).isNotNull(); assertThat(taskIdOfCreatedTask).startsWith("TKI:"); ResponseEntity<TaskRepresentationModel> responseDeleted = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID, taskIdOfCreatedTask), HttpMethod.DELETE, new HttpEntity<>(restHelper.getHeadersAdmin()), ParameterizedTypeReference.forType(Void.class)); assertThat(responseDeleted.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } /** * TSK-926: If Planned and Due Date is provided to create a task and not matching to service level * throw an exception One is calculated by other other date +- service level. */ @Test void testCreateWithPlannedAndDueDate() { TaskRepresentationModel taskRepresentationModel = getTaskResourceSample(); Instant now = Instant.now(); taskRepresentationModel.setPlanned(now); taskRepresentationModel.setDue(now); ThrowingCallable httpCall = () -> template.exchange( restHelper.toUrl(Mapping.URL_TASKS), HttpMethod.POST, new HttpEntity<>(taskRepresentationModel, restHelper.getHeadersUser_1_1()), TASK_MODEL_TYPE); assertThatThrownBy(httpCall).isInstanceOf(HttpClientErrorException.class); } @Test void testCreateTaskWithInvalidParameter() throws IOException { final String taskToCreateJson = "{\"classificationKey\":\"L11010\"," + "\"workbasketSummaryResource\":" + "{\"workbasketId\":\"WBI:100000000000000000000000000000000004\"}," + "\"primaryObjRef\":{\"company\":\"MyCompany1\",\"system\":\"MySystem1\"," + "\"systemInstance\":\"MyInstance1\",\"type\":\"MyType1\",\"value\":\"00000001\"}}"; URL url = new URL(restHelper.toUrl(Mapping.URL_TASKS)); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setDoOutput(true); con.setRequestProperty("Authorization", RestHelper.AUTHORIZATION_TEAMLEAD_1); con.setRequestProperty("Content-Type", "application/json"); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), UTF_8)); out.write(taskToCreateJson); out.flush(); out.close(); assertThat(con.getResponseCode()).isEqualTo(400); con.disconnect(); final String taskToCreateJson2 = "{\"classificationSummaryResource\":" + "{\"classificationId\":\"CLI:100000000000000000000000000000000004\"}," + "\"workbasketSummaryResource\":{\"workbasketId\":\"\"}," + "\"primaryObjRef\":{\"company\":\"MyCompany1\",\"system\":\"MySystem1\"," + "\"systemInstance\":\"MyInstance1\",\"type\":\"MyType1\",\"value\":\"00000001\"}}"; url = new URL(restHelper.toUrl(Mapping.URL_TASKS)); con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setDoOutput(true); con.setRequestProperty("Authorization", RestHelper.AUTHORIZATION_TEAMLEAD_1); con.setRequestProperty("Content-Type", "application/json"); out = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), UTF_8)); out.write(taskToCreateJson2); out.flush(); out.close(); assertThat(con.getResponseCode()).isEqualTo(400); con.disconnect(); } @Test void testCancelClaimTask() { final String claimed_task_id = "TKI:000000000000000000000000000000000027"; final String user_id_of_claimed_task = "user-1-2"; // retrieve task from Rest Api ResponseEntity<TaskRepresentationModel> getTaskResponse = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID, claimed_task_id), HttpMethod.GET, new HttpEntity<>(restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThat(getTaskResponse.getBody()).isNotNull(); TaskRepresentationModel claimedTaskRepresentationModel = getTaskResponse.getBody(); assertThat(claimedTaskRepresentationModel.getState()).isEqualTo(TaskState.CLAIMED); assertThat(claimedTaskRepresentationModel.getOwner()).isEqualTo(user_id_of_claimed_task); // cancel claim ResponseEntity<TaskRepresentationModel> cancelClaimResponse = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID_CLAIM, claimed_task_id), HttpMethod.DELETE, new HttpEntity<>(restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThat(cancelClaimResponse.getBody()).isNotNull(); assertThat(cancelClaimResponse.getStatusCode().is2xxSuccessful()).isTrue(); TaskRepresentationModel cancelClaimedtaskRepresentationModel = cancelClaimResponse.getBody(); assertThat(cancelClaimedtaskRepresentationModel.getOwner()).isNull(); assertThat(cancelClaimedtaskRepresentationModel.getClaimed()).isNull(); assertThat(cancelClaimedtaskRepresentationModel.getState()).isEqualTo(TaskState.READY); } @Test void testCancelClaimOfClaimedTaskByAnotherUserShouldThrowException() { final String claimed_task_id = "TKI:000000000000000000000000000000000026"; final String user_id_of_claimed_task = "user-1-1"; // retrieve task from Rest Api ResponseEntity<TaskRepresentationModel> responseGet = TEMPLATE.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID, claimed_task_id), HttpMethod.GET, new HttpEntity<>(restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThat(responseGet.getBody()).isNotNull(); TaskRepresentationModel theTaskRepresentationModel = responseGet.getBody(); assertThat(theTaskRepresentationModel.getState()).isEqualTo(TaskState.CLAIMED); assertThat(theTaskRepresentationModel.getOwner()).isEqualTo(user_id_of_claimed_task); // try to cancel claim ThrowingCallable httpCall = () -> template.exchange( restHelper.toUrl(Mapping.URL_TASKS_ID_CLAIM, claimed_task_id), HttpMethod.DELETE, new HttpEntity<>(restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThatThrownBy(httpCall) .extracting(ex -> ((HttpClientErrorException) ex).getStatusCode()) .isEqualTo(HttpStatus.CONFLICT); } @Test void testUpdateTaskOwnerOfReadyTaskSucceeds() { // setup final String taskUrlString = restHelper.toUrl("/api/v1/tasks/TKI:000000000000000000000000000000000025"); // retrieve task from Rest Api ResponseEntity<TaskRepresentationModel> responseGet = TEMPLATE.exchange( taskUrlString, HttpMethod.GET, new HttpEntity<>(restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThat(responseGet.getBody()).isNotNull(); TaskRepresentationModel theTaskRepresentationModel = responseGet.getBody(); assertThat(theTaskRepresentationModel.getState()).isEqualTo(TaskState.READY); assertThat(theTaskRepresentationModel.getOwner()).isNull(); // set Owner and update Task final String anyUserName = "dummyUser"; theTaskRepresentationModel.setOwner(anyUserName); ResponseEntity<TaskRepresentationModel> responseUpdate = TEMPLATE.exchange( taskUrlString, HttpMethod.PUT, new HttpEntity<>(theTaskRepresentationModel, restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThat(responseUpdate.getBody()).isNotNull(); TaskRepresentationModel theUpdatedTaskRepresentationModel = responseUpdate.getBody(); assertThat(theUpdatedTaskRepresentationModel.getState()).isEqualTo(TaskState.READY); assertThat(theUpdatedTaskRepresentationModel.getOwner()).isEqualTo(anyUserName); } @Test void testUpdateTaskOwnerOfClaimedTaskFails() { // setup final String taskUrlString = restHelper.toUrl("/api/v1/tasks/TKI:000000000000000000000000000000000026"); // retrieve task from Rest Api ResponseEntity<TaskRepresentationModel> responseGet = TEMPLATE.exchange( taskUrlString, HttpMethod.GET, new HttpEntity<>(restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThat(responseGet.getBody()).isNotNull(); TaskRepresentationModel theTaskRepresentationModel = responseGet.getBody(); assertThat(theTaskRepresentationModel.getState()).isEqualTo(TaskState.CLAIMED); assertThat(theTaskRepresentationModel.getOwner()).isEqualTo("user-1-1"); // set Owner and update Task final String anyUserName = "dummyuser"; theTaskRepresentationModel.setOwner(anyUserName); ThrowingCallable httpCall = () -> template.exchange( taskUrlString, HttpMethod.PUT, new HttpEntity<>(theTaskRepresentationModel, restHelper.getHeadersUser_1_2()), TASK_MODEL_TYPE); assertThatThrownBy(httpCall) .isInstanceOf(HttpClientErrorException.class) .hasMessageContaining("409"); } private TaskRepresentationModel getTaskResourceSample() { ClassificationSummaryRepresentationModel classificationResource = new ClassificationSummaryRepresentationModel(); classificationResource.setKey("L11010"); WorkbasketSummaryRepresentationModel workbasketSummary = new WorkbasketSummaryRepresentationModel(); workbasketSummary.setWorkbasketId("WBI:100000000000000000000000000000000004"); ObjectReference objectReference = new ObjectReference(); objectReference.setCompany("MyCompany1"); objectReference.setSystem("MySystem1"); objectReference.setSystemInstance("MyInstance1"); objectReference.setType("MyType1"); objectReference.setValue("00000001"); TaskRepresentationModel taskRepresentationModel = new TaskRepresentationModel(); taskRepresentationModel.setClassificationSummary(classificationResource); taskRepresentationModel.setWorkbasketSummary(workbasketSummary); taskRepresentationModel.setPrimaryObjRef(objectReference); return taskRepresentationModel; } }