TSK-989 Filter Tasks by planned TimeIntervals (REST)
-Added planned, planned-from and planned-until params in filter list -Added due, due-from and due-until params in filter list -Implemented needed methods -Added Test -Updated rest-api.doc -Refactored TaskControllerIntTests to use AssertJ
This commit is contained in:
parent
99e2caadec
commit
b01e5c3de6
|
@ -1,5 +1,6 @@
|
|||
package pro.taskana.rest;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -27,6 +28,7 @@ import pro.taskana.TaskQuery;
|
|||
import pro.taskana.TaskService;
|
||||
import pro.taskana.TaskState;
|
||||
import pro.taskana.TaskSummary;
|
||||
import pro.taskana.TimeInterval;
|
||||
import pro.taskana.exceptions.AttachmentPersistenceException;
|
||||
import pro.taskana.exceptions.ClassificationNotFoundException;
|
||||
import pro.taskana.exceptions.ConcurrencyException;
|
||||
|
@ -70,11 +72,17 @@ public class TaskController extends AbstractPagingController {
|
|||
private static final String POR_SYSTEM = "por.system";
|
||||
private static final String POR_COMPANY = "por.company";
|
||||
private static final String DUE = "due";
|
||||
private static final String DUE_TO = "due-until";
|
||||
private static final String DUE_FROM = "due-from";
|
||||
private static final String PLANNED = "planned";
|
||||
private static final String PLANNED_TO = "planned-until";
|
||||
private static final String PLANNED_FROM = "planned-from";
|
||||
|
||||
private static final String SORT_BY = "sort-by";
|
||||
private static final String SORT_DIRECTION = "order";
|
||||
|
||||
private static final String INDEFINITE = "";
|
||||
|
||||
private TaskService taskService;
|
||||
|
||||
private TaskResourceAssembler taskResourceAssembler;
|
||||
|
@ -248,6 +256,8 @@ public class TaskController extends AbstractPagingController {
|
|||
LOGGER.debug("Entry to applyFilterParams(taskQuery= {}, params= {})", taskQuery, params);
|
||||
}
|
||||
|
||||
checkForIllegalParamCombinations(params);
|
||||
|
||||
// apply filters
|
||||
if (params.containsKey(NAME)) {
|
||||
String[] names = extractCommaSeparatedFields(params.get(NAME));
|
||||
|
@ -280,22 +290,7 @@ public class TaskController extends AbstractPagingController {
|
|||
params.remove(WORKBASKET_ID);
|
||||
}
|
||||
if (params.containsKey(WORKBASKET_KEY)) {
|
||||
String[] domains = null;
|
||||
if (params.get(DOMAIN) != null) {
|
||||
domains = extractCommaSeparatedFields(params.get(DOMAIN));
|
||||
}
|
||||
if (domains == null || domains.length != 1) {
|
||||
throw new InvalidArgumentException(
|
||||
"workbasket-key requires excactly one domain as second parameter.");
|
||||
}
|
||||
String[] workbasketKeys = extractCommaSeparatedFields(params.get(WORKBASKET_KEY));
|
||||
KeyDomain[] keyDomains = new KeyDomain[workbasketKeys.length];
|
||||
for (int i = 0; i < workbasketKeys.length; i++) {
|
||||
keyDomains[i] = new KeyDomain(workbasketKeys[i], domains[0]);
|
||||
}
|
||||
taskQuery.workbasketKeyDomainIn(keyDomains);
|
||||
params.remove(WORKBASKET_KEY);
|
||||
params.remove(DOMAIN);
|
||||
updateTaskQueryWithWorkbasketKey(taskQuery,params);
|
||||
}
|
||||
if (params.containsKey(OWNER)) {
|
||||
String[] owners = extractCommaSeparatedFields(params.get(OWNER));
|
||||
|
@ -330,6 +325,43 @@ public class TaskController extends AbstractPagingController {
|
|||
params.remove(POR_VALUE);
|
||||
}
|
||||
|
||||
if (params.containsKey(PLANNED)) {
|
||||
updateTaskQueryWithPlannedOrDueTimeIntervals(taskQuery, params, PLANNED);
|
||||
}
|
||||
|
||||
if (params.containsKey(DUE)) {
|
||||
updateTaskQueryWithPlannedOrDueTimeIntervals(taskQuery, params, DUE);
|
||||
}
|
||||
|
||||
if (params.containsKey(PLANNED_FROM) && params.containsKey(PLANNED_TO)) {
|
||||
updateTaskQueryWithPlannedOrDueTimeInterval(taskQuery, params, PLANNED_FROM, PLANNED_TO);
|
||||
|
||||
} else if (params.containsKey(PLANNED_FROM) && !params.containsKey(PLANNED_TO)) {
|
||||
|
||||
TimeInterval timeInterval = createIndefiniteTimeIntervalFromParam(params, PLANNED_FROM);
|
||||
updateTaskQueryWithIndefiniteTimeInterval(taskQuery, params, PLANNED_FROM, timeInterval);
|
||||
|
||||
} else if (!params.containsKey(PLANNED_FROM) && params.containsKey(PLANNED_TO)) {
|
||||
|
||||
TimeInterval timeInterval = createIndefiniteTimeIntervalFromParam(params, PLANNED_TO);
|
||||
updateTaskQueryWithIndefiniteTimeInterval(taskQuery, params, PLANNED_TO, timeInterval);
|
||||
}
|
||||
|
||||
if (params.containsKey(DUE_FROM) && params.containsKey(DUE_TO)) {
|
||||
updateTaskQueryWithPlannedOrDueTimeInterval(taskQuery, params, DUE_FROM, DUE_TO);
|
||||
|
||||
} else if (params.containsKey(DUE_FROM) && !params.containsKey(DUE_TO)) {
|
||||
|
||||
TimeInterval indefiniteTimeInterval = createIndefiniteTimeIntervalFromParam(params, DUE_FROM);
|
||||
updateTaskQueryWithIndefiniteTimeInterval(
|
||||
taskQuery, params, DUE_FROM, indefiniteTimeInterval);
|
||||
|
||||
} else if (!params.containsKey(DUE_FROM) && params.containsKey(DUE_TO)) {
|
||||
|
||||
TimeInterval timeInterval = createIndefiniteTimeIntervalFromParam(params, DUE_TO);
|
||||
updateTaskQueryWithIndefiniteTimeInterval(taskQuery, params, DUE_TO, timeInterval);
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Exit from applyFilterParams(), returning {}", taskQuery);
|
||||
}
|
||||
|
@ -337,6 +369,151 @@ public class TaskController extends AbstractPagingController {
|
|||
return taskQuery;
|
||||
}
|
||||
|
||||
private void updateTaskQueryWithWorkbasketKey(TaskQuery taskQuery,
|
||||
MultiValueMap<String, String> params)
|
||||
throws InvalidArgumentException {
|
||||
|
||||
String[] domains = null;
|
||||
if (params.get(DOMAIN) != null) {
|
||||
domains = extractCommaSeparatedFields(params.get(DOMAIN));
|
||||
}
|
||||
if (domains == null || domains.length != 1) {
|
||||
throw new InvalidArgumentException(
|
||||
"workbasket-key requires excactly one domain as second parameter.");
|
||||
}
|
||||
String[] workbasketKeys = extractCommaSeparatedFields(params.get(WORKBASKET_KEY));
|
||||
KeyDomain[] keyDomains = new KeyDomain[workbasketKeys.length];
|
||||
for (int i = 0; i < workbasketKeys.length; i++) {
|
||||
keyDomains[i] = new KeyDomain(workbasketKeys[i], domains[0]);
|
||||
}
|
||||
taskQuery.workbasketKeyDomainIn(keyDomains);
|
||||
params.remove(WORKBASKET_KEY);
|
||||
params.remove(DOMAIN);
|
||||
|
||||
}
|
||||
|
||||
private void checkForIllegalParamCombinations(MultiValueMap<String, String> params) {
|
||||
|
||||
if (params.containsKey(PLANNED)
|
||||
&& (params.containsKey(PLANNED_FROM) || params.containsKey(PLANNED_TO))) {
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"It is prohibited to use the param \""
|
||||
+ PLANNED
|
||||
+ "\" in combination with the params \""
|
||||
+ PLANNED_FROM
|
||||
+ "\" and / or \""
|
||||
+ PLANNED_TO
|
||||
+ "\"");
|
||||
}
|
||||
|
||||
if (params.containsKey(DUE) && (params.containsKey(DUE_FROM) || params.containsKey(DUE_TO))) {
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"It is prohibited to use the param \""
|
||||
+ DUE
|
||||
+ "\" in combination with the params \""
|
||||
+ PLANNED_FROM
|
||||
+ "\" and / or \""
|
||||
+ PLANNED_TO
|
||||
+ "\"");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTaskQueryWithIndefiniteTimeInterval(
|
||||
TaskQuery taskQuery,
|
||||
MultiValueMap<String, String> params,
|
||||
String param,
|
||||
TimeInterval timeInterval) {
|
||||
|
||||
if (param.equals(PLANNED_FROM) || param.equals(PLANNED_TO)) {
|
||||
taskQuery.plannedWithin(timeInterval);
|
||||
|
||||
} else {
|
||||
taskQuery.dueWithin(timeInterval);
|
||||
}
|
||||
params.remove(param);
|
||||
}
|
||||
|
||||
private TimeInterval createIndefiniteTimeIntervalFromParam(
|
||||
MultiValueMap<String, String> params, String param) {
|
||||
|
||||
if (param.equals(PLANNED_FROM) || param.equals(DUE_FROM)) {
|
||||
|
||||
return new TimeInterval(Instant.parse(params.get(param).get(0)), null);
|
||||
|
||||
} else {
|
||||
|
||||
return new TimeInterval(null, Instant.parse(params.get(param).get(0)));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTaskQueryWithPlannedOrDueTimeInterval(
|
||||
TaskQuery taskQuery,
|
||||
MultiValueMap<String, String> params,
|
||||
String plannedFromOrDueFrom,
|
||||
String plannedToOrDueTo) {
|
||||
|
||||
TimeInterval timeInterval =
|
||||
new TimeInterval(
|
||||
Instant.parse(params.get(plannedFromOrDueFrom).get(0)),
|
||||
Instant.parse(params.get(plannedToOrDueTo).get(0)));
|
||||
|
||||
taskQuery.plannedWithin(timeInterval);
|
||||
|
||||
params.remove(plannedToOrDueTo);
|
||||
params.remove(plannedFromOrDueFrom);
|
||||
}
|
||||
|
||||
private void updateTaskQueryWithPlannedOrDueTimeIntervals(
|
||||
TaskQuery taskQuery, MultiValueMap<String, String> params, String plannedOrDue) {
|
||||
|
||||
String[] instants = extractCommaSeparatedFields(params.get(plannedOrDue));
|
||||
|
||||
TimeInterval[] timeIntervals = extractTimeIntervals(instants);
|
||||
|
||||
taskQuery.plannedWithin(timeIntervals);
|
||||
|
||||
params.remove(plannedOrDue);
|
||||
}
|
||||
|
||||
private TimeInterval[] extractTimeIntervals(String[] instants) {
|
||||
|
||||
List<TimeInterval> timeIntervalsList = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < instants.length - 1; i += 2) {
|
||||
|
||||
TimeInterval timeInterval = determineTimeInterval(instants, i);
|
||||
|
||||
if (timeInterval != null) {
|
||||
|
||||
timeIntervalsList.add(timeInterval);
|
||||
}
|
||||
}
|
||||
|
||||
TimeInterval[] timeIntervalArray = new TimeInterval[timeIntervalsList.size()];
|
||||
|
||||
return timeIntervalsList.toArray(timeIntervalArray);
|
||||
}
|
||||
|
||||
private TimeInterval determineTimeInterval(String[] instants, int i) {
|
||||
|
||||
if (!instants[i].equals(INDEFINITE) && !instants[i + 1].equals(INDEFINITE)) {
|
||||
|
||||
return new TimeInterval(Instant.parse(instants[i]), Instant.parse(instants[i + 1]));
|
||||
|
||||
} else if (instants[i].equals(INDEFINITE) && !instants[i + 1].equals(INDEFINITE)) {
|
||||
|
||||
return new TimeInterval(null, Instant.parse(instants[i + 1]));
|
||||
|
||||
} else if (!instants[i].equals(INDEFINITE) && instants[i + 1].equals(INDEFINITE)) {
|
||||
|
||||
return new TimeInterval(Instant.parse(instants[i]), null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private TaskQuery applySortingParams(TaskQuery taskQuery, MultiValueMap<String, String> params)
|
||||
throws InvalidArgumentException {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
package pro.taskana.rest;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
@ -19,7 +14,9 @@ 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.Fail;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -54,6 +51,7 @@ class TaskControllerIntTest {
|
|||
public String schemaName;
|
||||
|
||||
@Autowired RestHelper restHelper;
|
||||
|
||||
@Autowired private DataSource dataSource;
|
||||
|
||||
@BeforeAll
|
||||
|
@ -74,8 +72,8 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertEquals(25, response.getBody().getContent().size());
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(25);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -87,8 +85,188 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertEquals(22, response.getBody().getContent().size());
|
||||
assertThat(response.getBody().getLink(Link.REL_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<TaskSummaryListResource> response =
|
||||
template.exchange(
|
||||
restHelper.toUrl(Mapping.URL_TASKS)
|
||||
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
|
||||
+ "&planned="
|
||||
+ firstInstant
|
||||
+ ",,"
|
||||
+ secondInstant
|
||||
+ ","
|
||||
+ thirdInstant
|
||||
+ ","
|
||||
+ ","
|
||||
+ fourthInstant
|
||||
+ "&sort-by=planned",
|
||||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertThat(response.getBody().getLink(Link.REL_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<TaskSummaryListResource> 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(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAllTasksByWorkbasketIdWithinSingleIndefinitePlannedTimeInterval() {
|
||||
|
||||
Instant plannedFromInstant = Instant.now().minus(6, ChronoUnit.DAYS);
|
||||
|
||||
ResponseEntity<TaskSummaryListResource> response =
|
||||
template.exchange(
|
||||
restHelper.toUrl(Mapping.URL_TASKS)
|
||||
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
|
||||
+ "&planned-from="
|
||||
+ plannedFromInstant
|
||||
+ "&sort-by=planned",
|
||||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAllTasksByWorkbasketIdWithInvalidPlannedParamsCombination() {
|
||||
HttpClientErrorException e =
|
||||
Assertions.assertThrows(
|
||||
HttpClientErrorException.class,
|
||||
() ->
|
||||
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(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class)));
|
||||
assertThat(HttpStatus.BAD_REQUEST).isEqualTo(e.getStatusCode());
|
||||
}
|
||||
|
||||
@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<TaskSummaryListResource> response =
|
||||
template.exchange(
|
||||
restHelper.toUrl(Mapping.URL_TASKS)
|
||||
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
|
||||
+ "&due="
|
||||
+ firstInstant
|
||||
+ ",,"
|
||||
+ secondInstant
|
||||
+ ","
|
||||
+ thirdInstant
|
||||
+ ","
|
||||
+ ","
|
||||
+ fourthInstant
|
||||
+ "&sort-by=due",
|
||||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAllTasksByWorkbasketIdWithinSingleDueTimeInterval() {
|
||||
|
||||
Instant dueFromInstant = Instant.now().minus(8, ChronoUnit.DAYS);
|
||||
Instant dueToInstant = Instant.now().minus(3, ChronoUnit.DAYS);
|
||||
|
||||
ResponseEntity<TaskSummaryListResource> 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(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(9);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAllTasksByWorkbasketIdWithinSingleIndefiniteDueTimeInterval() {
|
||||
|
||||
Instant dueToInstant = Instant.now().minus(1, ChronoUnit.DAYS);
|
||||
|
||||
ResponseEntity<TaskSummaryListResource> response =
|
||||
template.exchange(
|
||||
restHelper.toUrl(Mapping.URL_TASKS)
|
||||
+ "?workbasket-id=WBI:100000000000000000000000000000000001"
|
||||
+ "&due-until="
|
||||
+ dueToInstant
|
||||
+ "&sort-by=due",
|
||||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAllTasksByWorkbasketIdWithInvalidDueParamsCombination() {
|
||||
HttpClientErrorException e =
|
||||
Assertions.assertThrows(
|
||||
HttpClientErrorException.class,
|
||||
() ->
|
||||
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(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class)));
|
||||
assertThat(HttpStatus.BAD_REQUEST).isEqualTo(e.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -102,8 +280,8 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
request,
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertEquals(20, response.getBody().getContent().size());
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(20);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -124,7 +302,7 @@ class TaskControllerIntTest {
|
|||
request,
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
});
|
||||
assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
|
||||
assertThat(HttpStatus.BAD_REQUEST).isEqualTo(e.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -135,8 +313,8 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
new HttpEntity<>(restHelper.getHeadersAdmin()),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertEquals(73, response.getBody().getContent().size());
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(response.getBody().getContent()).hasSize(73);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -148,14 +326,15 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertTrue(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_SELF)
|
||||
.getHref()
|
||||
.endsWith(
|
||||
"/api/v1/tasks?por.type=VNR&por.value=22334455&sort-by=por.value&order=desc"));
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_SELF)
|
||||
.getHref()
|
||||
.endsWith(
|
||||
"/api/v1/tasks?por.type=VNR&por.value=22334455&sort-by=por.value&order=desc"))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -166,10 +345,10 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
restHelper.defaultRequest(),
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
fail();
|
||||
Fail.fail("");
|
||||
} catch (HttpClientErrorException e) {
|
||||
assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
|
||||
assertTrue(e.getResponseBodyAsString().contains("[invalid]"));
|
||||
assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
||||
assertThat(e.getResponseBodyAsString().contains("[invalid]")).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,23 +363,25 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
request,
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertEquals(1, response.getBody().getContent().size());
|
||||
assertTrue(response.getBody().getLink(Link.REL_LAST).getHref().contains("page=14"));
|
||||
assertEquals(
|
||||
"TKI:100000000000000000000000000000000000",
|
||||
response.getBody().getContent().iterator().next().getTaskId());
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertTrue(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_SELF)
|
||||
.getHref()
|
||||
.endsWith(
|
||||
"/api/v1/tasks?"
|
||||
+ "state=READY,CLAIMED&sort-by=por.value&order=desc&page=15&page-size=5"));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_FIRST));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_LAST));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_PREVIOUS));
|
||||
assertThat(response.getBody().getContent()).hasSize(1);
|
||||
assertThat(response.getBody().getLink(Link.REL_LAST).getHref().contains("page=14")).isTrue();
|
||||
assertThat("TKI:100000000000000000000000000000000000")
|
||||
.isEqualTo(response.getBody().getContent().iterator().next().getTaskId());
|
||||
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_SELF)
|
||||
.getHref()
|
||||
.endsWith(
|
||||
"/api/v1/tasks?"
|
||||
+ "state=READY,CLAIMED&sort-by=por.value&order=desc&page=15&page-size=5"))
|
||||
.isTrue();
|
||||
|
||||
assertThat(response.getBody().getLink(Link.REL_FIRST)).isNotNull();
|
||||
assertThat(response.getBody().getLink(Link.REL_LAST)).isNotNull();
|
||||
assertThat(response.getBody().getLink(Link.REL_PREVIOUS)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -220,7 +401,7 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
request,
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertEquals(25, response.getBody().getContent().size());
|
||||
assertThat(response.getBody().getContent()).hasSize(25);
|
||||
|
||||
response =
|
||||
template.exchange(
|
||||
|
@ -228,21 +409,23 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
request,
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertEquals(5, response.getBody().getContent().size());
|
||||
assertTrue(response.getBody().getLink(Link.REL_LAST).getHref().contains("page=5"));
|
||||
assertEquals(
|
||||
"TKI:000000000000000000000000000000000023",
|
||||
response.getBody().getContent().iterator().next().getTaskId());
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertTrue(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_SELF)
|
||||
.getHref()
|
||||
.endsWith("/api/v1/tasks?sort-by=due&order=desc&page=5&page-size=5"));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_FIRST));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_LAST));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_PREVIOUS));
|
||||
assertThat(response.getBody().getContent()).hasSize(5);
|
||||
assertThat(response.getBody().getLink(Link.REL_LAST).getHref().contains("page=5")).isTrue();
|
||||
assertThat("TKI:000000000000000000000000000000000023")
|
||||
.isEqualTo(response.getBody().getContent().iterator().next().getTaskId());
|
||||
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
assertThat(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_SELF)
|
||||
.getHref()
|
||||
.endsWith("/api/v1/tasks?sort-by=due&order=desc&page=5&page-size=5"))
|
||||
.isTrue();
|
||||
|
||||
assertThat(response.getBody().getLink(Link.REL_FIRST)).isNotNull();
|
||||
assertThat(response.getBody().getLink(Link.REL_LAST)).isNotNull();
|
||||
assertThat(response.getBody().getLink(Link.REL_PREVIOUS)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -263,23 +446,26 @@ class TaskControllerIntTest {
|
|||
HttpMethod.GET,
|
||||
request,
|
||||
ParameterizedTypeReference.forType(TaskSummaryListResource.class));
|
||||
assertEquals(1, response.getBody().getContent().size());
|
||||
assertEquals(
|
||||
"TKI:000000000000000000000000000000000013",
|
||||
response.getBody().getContent().iterator().next().getTaskId());
|
||||
assertNotNull(response.getBody().getLink(Link.REL_SELF));
|
||||
assertTrue(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_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=2&page-size=5"));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_FIRST));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_LAST));
|
||||
assertNotNull(response.getBody().getLink(Link.REL_PREVIOUS));
|
||||
assertThat(response.getBody().getContent()).hasSize(1);
|
||||
assertThat("TKI:000000000000000000000000000000000013")
|
||||
.isEqualTo(response.getBody().getContent().iterator().next().getTaskId());
|
||||
|
||||
assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull();
|
||||
|
||||
assertThat(
|
||||
response
|
||||
.getBody()
|
||||
.getLink(Link.REL_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=2&page-size=5"))
|
||||
.isTrue();
|
||||
|
||||
assertThat(response.getBody().getLink(Link.REL_FIRST)).isNotNull();
|
||||
assertThat(response.getBody().getLink(Link.REL_LAST)).isNotNull();
|
||||
assertThat(response.getBody().getLink(Link.REL_PREVIOUS)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -289,7 +475,7 @@ class TaskControllerIntTest {
|
|||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
con.setRequestProperty("Authorization", "Basic YWRtaW46YWRtaW4=");
|
||||
assertEquals(200, con.getResponseCode());
|
||||
assertThat(con.getResponseCode()).isEqualTo(200);
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), UTF_8));
|
||||
|
@ -303,8 +489,8 @@ class TaskControllerIntTest {
|
|||
String response = content.toString();
|
||||
JsonNode jsonNode = objectMapper.readTree(response);
|
||||
String created = jsonNode.get("created").asText();
|
||||
assertFalse(response.contains("\"attachments\":[]"));
|
||||
assertTrue(created.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z"));
|
||||
assertThat(response.contains("\"attachments\":[]")).isFalse();
|
||||
assertThat(created.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -313,7 +499,7 @@ class TaskControllerIntTest {
|
|||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
con.setRequestProperty("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x");
|
||||
assertEquals(200, con.getResponseCode());
|
||||
assertThat(con.getResponseCode()).isEqualTo(200);
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), UTF_8));
|
||||
String inputLine;
|
||||
|
@ -334,14 +520,15 @@ class TaskControllerIntTest {
|
|||
out.write(content.toString());
|
||||
out.flush();
|
||||
out.close();
|
||||
assertEquals(200, con.getResponseCode());
|
||||
assertThat(con.getResponseCode()).isEqualTo(200);
|
||||
|
||||
con.disconnect();
|
||||
|
||||
url = new URL(restHelper.toUrl("/api/v1/tasks/TKI:100000000000000000000000000000000000"));
|
||||
con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
con.setRequestProperty("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x");
|
||||
assertEquals(200, con.getResponseCode());
|
||||
assertThat(con.getResponseCode()).isEqualTo(200);
|
||||
|
||||
in = new BufferedReader(new InputStreamReader(con.getInputStream(), UTF_8));
|
||||
content = new StringBuffer();
|
||||
|
@ -356,7 +543,7 @@ class TaskControllerIntTest {
|
|||
TaskResource originalTaskObject = mapper.readValue(originalTask, TaskResource.class);
|
||||
TaskResource updatedTaskObject = mapper.readValue(updatedTask, TaskResource.class);
|
||||
|
||||
assertNotEquals(originalTaskObject.getModified(), updatedTaskObject.getModified());
|
||||
assertThat(updatedTaskObject.getModified()).isNotEqualTo(originalTaskObject.getModified());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -369,12 +556,13 @@ class TaskControllerIntTest {
|
|||
HttpMethod.POST,
|
||||
new HttpEntity<>(taskResource, restHelper.getHeaders()),
|
||||
ParameterizedTypeReference.forType(TaskResource.class));
|
||||
assertEquals(responseCreate.getStatusCode(), HttpStatus.CREATED);
|
||||
assertNotNull(responseCreate.getBody());
|
||||
assertThat(HttpStatus.CREATED).isEqualTo(responseCreate.getStatusCode());
|
||||
assertThat(responseCreate.getBody()).isNotNull();
|
||||
|
||||
String taskIdOfCreatedTask = responseCreate.getBody().getTaskId();
|
||||
assertNotNull(taskIdOfCreatedTask);
|
||||
assertTrue(taskIdOfCreatedTask.startsWith("TKI:"));
|
||||
|
||||
assertThat(taskIdOfCreatedTask).isNotNull();
|
||||
assertThat(taskIdOfCreatedTask.startsWith("TKI:")).isTrue();
|
||||
|
||||
ResponseEntity<TaskResource> responseDeleted =
|
||||
template.exchange(
|
||||
|
@ -383,7 +571,7 @@ class TaskControllerIntTest {
|
|||
new HttpEntity<>(restHelper.getHeadersAdmin()),
|
||||
ParameterizedTypeReference.forType(Void.class));
|
||||
|
||||
assertEquals(HttpStatus.NO_CONTENT, responseDeleted.getStatusCode());
|
||||
assertThat(responseDeleted.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -426,7 +614,8 @@ class TaskControllerIntTest {
|
|||
out.write(taskToCreateJson);
|
||||
out.flush();
|
||||
out.close();
|
||||
assertEquals(400, con.getResponseCode());
|
||||
assertThat(con.getResponseCode()).isEqualTo(400);
|
||||
|
||||
con.disconnect();
|
||||
|
||||
final String taskToCreateJson2 =
|
||||
|
@ -446,7 +635,8 @@ class TaskControllerIntTest {
|
|||
out.write(taskToCreateJson2);
|
||||
out.flush();
|
||||
out.close();
|
||||
assertEquals(400, con.getResponseCode());
|
||||
assertThat(con.getResponseCode()).isEqualTo(400);
|
||||
|
||||
con.disconnect();
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,26 @@ include::{snippets}/GetAllTasksDocTest/response-fields.adoc[]
|
|||
The list generated in the response can be filtered using following parameters in the uri: +
|
||||
name | priority | state | classification.key | workbasket-id | {workbasket-key , domain} | +
|
||||
owner | por.company | por.system | por.instance | por.type | por.value +
|
||||
planned | planned-from | planned-until | due | due-from | due-until +
|
||||
|
||||
If it is sufficient to filter the list with a single time interval, use the parameters +
|
||||
planned-from/due-from and planned-until/due-until. +
|
||||
Leave one of them out of the request, if you want to have an open interval. +
|
||||
|
||||
If it is required to filter the list with multiple planned or due time intervals, the parameters +
|
||||
planned / due can be used as follows instead: +
|
||||
|
||||
- provide a string with an even number of instants separated by a ",". Time intervals will be +
|
||||
determined in pairs of those instants. +
|
||||
|
||||
- in case of a required open interval, just give one of the arguments of the pair an empty string +
|
||||
like this: +
|
||||
|
||||
planned = {Instant1},{Instant2},,{Instant3} this will create two intervals, one between Instant1 +
|
||||
and Instant2 as well as an open interval between the beginning of time and Instant3 +
|
||||
|
||||
Note that it is prohibited to use the planned / due parameter in combination with the +
|
||||
planned-from/due-from and/or planned-until/due-until parameters +
|
||||
|
||||
It can also be sorted by using this set of parameters: +
|
||||
sortBy = { classification.key | por.type | por.value | state | name| due | planned | priority } | order={ desc | asc }
|
||||
|
|
Loading…
Reference in New Issue