Refactor paging and sorting unit tests 87/58687/2
authortalig <talig@amdocs.com>
Thu, 2 Aug 2018 11:32:17 +0000 (14:32 +0300)
committertalig <talig@amdocs.com>
Thu, 2 Aug 2018 11:32:17 +0000 (14:32 +0300)
Change-Id: I6c6b1e40d0069b78ef4180b719dbc8107732982d
Issue-ID: SDC-1483
Signed-off-by: talig <talig@amdocs.com>
15 files changed:
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestUtils.java [deleted file]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/Paging.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/Sorting.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionStatesFormatter.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/types/PagingRequest.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/types/Sort.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/RestPath.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowControllerTest.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/PagingTest.java [new file with mode: 0644]
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/SortingTest.java [new file with mode: 0644]
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/VersionStatesFormatterTest.java [new file with mode: 0644]
workflow-designer-be/src/test/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImplTest.java

diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestUtils.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/RestUtils.java
deleted file mode 100644 (file)
index d8577c1..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright © 2018 European Support Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onap.sdc.workflow.api;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-
-public class RestUtils {
-
-    private RestUtils() {
-    }
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(RestUtils.class);
-
-    public static Set<WorkflowVersionState> formatVersionStates(String versionStateFilter) {
-        Set<WorkflowVersionState> filter;
-        try {
-            filter = versionStateFilter == null ? null :
-                             Arrays.stream(versionStateFilter.split(",")).map(WorkflowVersionState::valueOf)
-                                   .collect(Collectors.toSet());
-        } catch (Exception e) {
-            LOGGER.info(
-                    "version state filter value is invalid and cannot be formatted to a set of version states, therefore it is set to empty set");
-            filter = Collections.emptySet();
-        }
-        return filter;
-    }
-}
index 77f6e6d..690b207 100644 (file)
@@ -20,7 +20,6 @@ import static org.onap.sdc.workflow.api.RestParams.LIMIT;
 import static org.onap.sdc.workflow.api.RestParams.OFFSET;
 import static org.onap.sdc.workflow.api.RestParams.SORT;
 import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER;
-import static org.onap.sdc.workflow.api.RestUtils.formatVersionStates;
 import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_LIMIT;
 import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_OFFSET;
 
@@ -31,6 +30,7 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import org.onap.sdc.workflow.api.types.Paging;
 import org.onap.sdc.workflow.api.types.Sorting;
+import org.onap.sdc.workflow.api.types.VersionStatesFormatter;
 import org.onap.sdc.workflow.persistence.types.Workflow;
 import org.onap.sdc.workflow.services.WorkflowManager;
 import org.onap.sdc.workflow.services.WorkflowVersionManager;
@@ -53,6 +53,7 @@ import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
 
 @RequestMapping("/workflows")
 @Api("Workflows")
@@ -71,6 +72,8 @@ public class WorkflowController {
     @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation("List workflows")
     @ApiImplicitParams({
+            @ApiImplicitParam(name = "versionState", dataType = "string", paramType = "query",
+                    allowableValues = "DRAFT,CERTIFIED", value = "Filter by version state"),
             @ApiImplicitParam(name = OFFSET, dataType = "string", paramType = "query", defaultValue = "0",
                     value = "Index of the starting item"),
             @ApiImplicitParam(name = LIMIT, dataType = "string", paramType = "query", defaultValue = "200",
@@ -78,12 +81,11 @@ public class WorkflowController {
             @ApiImplicitParam(name = SORT, dataType = "string", paramType = "query", defaultValue = "name:asc",
                     value = "Sorting criteria in the format: property:(asc|desc). Default sort order is ascending.",
                     allowableValues = "name:asc,name:desc")})
-    public Page<Workflow> list(@ApiParam(value = "Filter by version state", allowableValues = "DRAFT,CERTIFIED")
-            @RequestParam(name = "versionState", required = false) String versionStateFilter,
-            @ApiParam(hidden = true) Paging paging,
-            @ApiParam(hidden = true) Sorting sorting,
+    public Page<Workflow> list(@ApiIgnore VersionStatesFormatter versionStateFilter,
+            @ApiIgnore Paging paging,
+            @ApiIgnore Sorting sorting,
             @RequestHeader(USER_ID_HEADER) String user) {
-        return workflowManager.list(formatVersionStates(versionStateFilter), initRequestSpec(paging, sorting));
+        return workflowManager.list(versionStateFilter.getVersionStates(), initRequestSpec(paging, sorting));
     }
 
     @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
index ba15f9f..df4c9fe 100644 (file)
 
 package org.onap.sdc.workflow.api;
 
-import static org.onap.sdc.workflow.api.RestUtils.formatVersionStates;
 import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER;
 
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
 import org.onap.sdc.workflow.api.types.CollectionResponse;
 import org.onap.sdc.workflow.api.types.VersionStateDto;
+import org.onap.sdc.workflow.api.types.VersionStatesFormatter;
 import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
 import org.onap.sdc.workflow.persistence.types.WorkflowVersion;
 import org.onap.sdc.workflow.services.WorkflowVersionManager;
@@ -50,6 +50,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
+import springfox.documentation.annotations.ApiIgnore;
 
 @RequestMapping("/workflows/{workflowId}/versions")
 @Api("Workflow versions")
@@ -71,13 +72,14 @@ public class WorkflowVersionController {
         this.validator = validator;
     }
 
+    @ApiImplicitParam(name = "state", dataType = "string", paramType = "query",
+            allowableValues = "DRAFT,CERTIFIED", value = "Filter by state")
     @GetMapping
     @ApiOperation("List workflow versions")
     public CollectionResponse<WorkflowVersion> list(@PathVariable("workflowId") String workflowId,
-            @ApiParam(value = "Filter by state", allowableValues = "DRAFT,CERTIFIED")
-            @RequestParam(value = "state", required = false) String stateFilter,
+            @ApiIgnore VersionStatesFormatter stateFilter,
             @RequestHeader(USER_ID_HEADER) String user) {
-        return new CollectionResponse<>(workflowVersionManager.list(workflowId, formatVersionStates(stateFilter)));
+        return new CollectionResponse<>(workflowVersionManager.list(workflowId, stateFilter.getVersionStates()));
     }
 
     @PostMapping
index 3d91c8e..0a27e1e 100644 (file)
@@ -16,14 +16,16 @@ public class Paging {
     }
 
     public void setLimit(String limit) {
-        getIntValue(limit).map(integer -> integer > MAX_LIMIT ? MAX_LIMIT : integer)
-                          .ifPresent(integer -> this.limit = integer);
+        getIntValue(limit).map(integer -> integer > MAX_LIMIT ? MAX_LIMIT : integer).ifPresent(integer -> {
+            if (integer != 0) {
+                this.limit = integer;
+            }
+        });
     }
 
-    private Optional<Integer> getIntValue(String value) {
-        int intValue;
+    private static Optional<Integer> getIntValue(String value) {
         try {
-            intValue = Integer.parseInt(value);
+            int intValue = Integer.parseInt(value);
             return intValue < 0 ? Optional.empty() : Optional.of(intValue);
         } catch (NumberFormatException e) {
             return Optional.empty();
index 7bb43d0..f02a05f 100644 (file)
@@ -18,11 +18,11 @@ public class Sorting {
     private List<Sort> sorts = Collections.emptyList();
 
     public void setSort(String sortString) {
-        this.sorts = Arrays.stream(sortString.split(SORTS_DELIMITER)).map(this::formatSort).filter(Objects::nonNull)
+        this.sorts = Arrays.stream(sortString.split(SORTS_DELIMITER)).map(Sorting::formatSort).filter(Objects::nonNull)
                            .collect(Collectors.toList());
     }
 
-    private Sort formatSort(String sort) {
+    private static Sort formatSort(String sort) {
         String[] tokens = sort.split(DIRECTION_DELIMITER);
         try {
             return new Sort(tokens[0], ASCENDING_ORDER.equalsIgnoreCase(tokens[1]));
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionStatesFormatter.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/types/VersionStatesFormatter.java
new file mode 100644 (file)
index 0000000..5467dee
--- /dev/null
@@ -0,0 +1,36 @@
+package org.onap.sdc.workflow.api.types;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+import lombok.Getter;
+import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+
+@Getter
+public class VersionStatesFormatter {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(VersionStatesFormatter.class);
+
+    private Set<WorkflowVersionState> versionStates = null;
+
+    public void setVersionState(String value) {
+        this.versionStates = formatString(value);
+    }
+
+    public void setState(String value) {
+        this.versionStates = formatString(value);
+    }
+
+    private static Set<WorkflowVersionState> formatString(String value) {
+        try {
+            return value == null ? null : Arrays.stream(value.split(",")).map(WorkflowVersionState::valueOf)
+                                                .collect(Collectors.toSet());
+        } catch (Exception ignore) {
+            LOGGER.info(
+                    "value is invalid and cannot be formatted to a set of version states, therefore it set to null");
+            return null;
+        }
+    }
+}
index 23979a5..a309204 100644 (file)
@@ -135,14 +135,14 @@ public class WorkflowManagerImpl implements WorkflowManager {
         itemManager.update(item);
     }
 
-    private RequestSpec getRequestSpec(RequestSpec requestSpec) {
+    private static RequestSpec getRequestSpec(RequestSpec requestSpec) {
         if (requestSpec == null) {
             return WORKSPACES_DEFAULT_REQUEST_SPEC;
         }
         if (requestSpec.getPaging() == null) {
             requestSpec.setPaging(WORKSPACES_DEFAULT_REQUEST_SPEC.getPaging());
-        } else if (requestSpec.getPaging().getLimit() > MAX_LIMIT) {
-            requestSpec.getPaging().setLimit(MAX_LIMIT);
+        } else {
+            handlePagingRequestValues(requestSpec.getPaging());
         }
         if (requestSpec.getSorting() == null) {
             requestSpec.setSorting(WORKSPACES_DEFAULT_REQUEST_SPEC.getSorting());
@@ -150,7 +150,18 @@ public class WorkflowManagerImpl implements WorkflowManager {
         return requestSpec;
     }
 
-    private Comparator<Workflow> getWorkflowComparator(SortingRequest sorting) {
+    private static void handlePagingRequestValues(PagingRequest paging) {
+        if (paging.getOffset() == null) {
+            paging.setOffset(DEFAULT_OFFSET);
+        }
+        if (paging.getLimit() == null) {
+            paging.setLimit(DEFAULT_LIMIT);
+        } else if (paging.getLimit() > MAX_LIMIT) {
+            paging.setLimit(MAX_LIMIT);
+        }
+    }
+
+    private static Comparator<Workflow> getWorkflowComparator(SortingRequest sorting) {
         Boolean byNameAscending = sorting.getSorts().stream()
                                   .filter(sort -> WORKSPACES_SORT_PROPERTY.equalsIgnoreCase(sort.getProperty()))
                                   .findFirst().map(Sort::isAscendingOrder).orElse(true);
index f06822f..da46cc2 100644 (file)
@@ -1,15 +1,23 @@
 package org.onap.sdc.workflow.services.types;
 
-import lombok.Data;
+import lombok.Getter;
 
-@Data
+@Getter
 public class PagingRequest {
 
-    private int offset;
-    private int limit;
+    private Integer offset;
+    private Integer limit;
 
     public PagingRequest(int offset, int limit) {
-        this.offset = offset;
-        this.limit = limit;
+        setOffset(offset);
+        setLimit(limit);
+    }
+
+    public void setOffset(int offset) {
+        this.offset = offset < 0 ? null : offset;
+    }
+
+    public void setLimit(int limit) {
+        this.limit = limit <= 0 ? null : limit;
     }
 }
index 563c9ad..88151a0 100644 (file)
@@ -1,8 +1,10 @@
 package org.onap.sdc.workflow.services.types;
 
+import lombok.EqualsAndHashCode;
 import lombok.Getter;
 
 @Getter
+@EqualsAndHashCode
 public class Sort {
 
     private String property;
index a9408f1..4301feb 100644 (file)
@@ -48,10 +48,6 @@ public class RestPath {
         return WORKFLOWS_URL;
     }
 
-    public static String getWorkflowsWithVersionStateFilterPath(String versionState) {
-        return String.format(WORKFLOWS_WITH_VERSION_STATE_FILTER_URL, versionState);
-    }
-
     public static String getWorkflowPath(String workflowId) {
         return String.format(WORKFLOW_URL_FORMATTER, workflowId);
     }
index 95f7fff..f8d2aec 100644 (file)
@@ -4,7 +4,6 @@ import static org.hamcrest.Matchers.is;
 import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 import static org.onap.sdc.workflow.TestUtil.createWorkflow;
@@ -21,25 +20,29 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import com.amdocs.zusammen.datatypes.Id;
 import com.amdocs.zusammen.datatypes.item.Item;
 import com.google.gson.Gson;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.onap.sdc.workflow.RestPath;
 import org.onap.sdc.workflow.api.exceptionshandlers.CustomizedResponseEntityExceptionHandler;
 import org.onap.sdc.workflow.persistence.types.Workflow;
-import org.onap.sdc.workflow.persistence.types.WorkflowVersionState;
 import org.onap.sdc.workflow.services.WorkflowManager;
 import org.onap.sdc.workflow.services.types.Page;
 import org.onap.sdc.workflow.services.types.PagingRequest;
+import org.onap.sdc.workflow.services.types.RequestSpec;
+import org.onap.sdc.workflow.services.types.Sort;
 import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -55,11 +58,13 @@ public class WorkflowControllerTest {
     private MockMvc mockMvc;
 
 
+    @Mock
+    private WorkflowManager workflowManagerMock;
+    @Captor
+    private ArgumentCaptor<RequestSpec> requestSpecArg;
     @InjectMocks
     private WorkflowController workflowController;
 
-    @Mock
-    private WorkflowManager workflowManagerMock;
 
     @Before
     public void setUp() {
@@ -99,109 +104,92 @@ public class WorkflowControllerTest {
     }
 
     @Test
-    public void shouldReturn5WorkflowWhen5WorkflowsExists() throws Exception {
-        int numOfWorkflows = 5;
-        Page<Workflow> workflowMocks = createWorkflows(numOfWorkflows);
-        doReturn(workflowMocks).when(workflowManagerMock).list(any(), any());
-        mockMvc.perform(get(RestPath.getWorkflowsPath()).header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON))
-               .andDo(print()).andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(numOfWorkflows)));
-    }
-
-    @Test
-    public void listWithValidVersionStateFilter() throws Exception {
-        int numOfWorkflows = 3;
-        Page<Workflow> workflows = createWorkflows(numOfWorkflows);
-        doReturn(workflows).when(workflowManagerMock)
-                           .list(eq(Collections.singleton(WorkflowVersionState.CERTIFIED)), any());
-        mockMvc.perform(
-                get(RestPath.getWorkflowsWithVersionStateFilterPath("CERTIFIED")).header(USER_ID_HEADER, USER_ID)
-                                                                                 .contentType(APPLICATION_JSON))
-               .andDo(print()).andExpect(status().isOk()).andExpect(jsonPath("$.paging.total", is(numOfWorkflows)))
-               .andExpect(jsonPath("$.items", hasSize(numOfWorkflows)));
-    }
-
-    @Test
-    public void listWithInvalidVersionStateFilter() throws Exception {
-        int numOfWorkflows = 0;
-        Page<Workflow> workflows = createWorkflows(numOfWorkflows);
-        doReturn(workflows).when(workflowManagerMock).list(eq(Collections.emptySet()), any());
+    public void listWhenExist() throws Exception {
+        mockManagerList3();
+        ResultActions result = mockMvc.perform(
+                get(RestPath.getWorkflowsPath()).header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON))
+                                      .andDo(print()).andExpect(status().isOk())
+                                      .andExpect(jsonPath("$.items", hasSize(3)));
+        for (int i = 0; i < 3; i++) {
+            result.andExpect(jsonPath(String.format("$.items[%s].id", i), is(String.valueOf(i + 1))));
+        }
 
-        mockMvc.perform(
-                get(RestPath.getWorkflowsWithVersionStateFilterPath("gibberish")).header(USER_ID_HEADER, USER_ID)
-                                                                                 .contentType(APPLICATION_JSON))
-               .andDo(print()).andExpect(status().isOk()).andExpect(jsonPath("$.paging.total", is(numOfWorkflows)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, DEFAULT_LIMIT, Collections.emptyList());
     }
 
     @Test
-    public void shouldReturnSortedLimitOffsetAppliedWorkflows() throws Exception {
-        Page<Workflow> workflowMocks = createLimit2AndOffset1For5WorkflowList();
-        doReturn(workflowMocks).when(workflowManagerMock).list(any(), any());
+    public void listWhenPagingAndSortingAreSet() throws Exception {
+        mockManagerList3();
         mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "1"))
                                 .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
-               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(2)));
+               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), 1, 2, Collections.singletonList(new Sort("name", true)));
     }
 
-/*    @Test
+    @Test
     public void shouldReturnResultsWithDefaultWhenLimitIsNegative() throws Exception {
-        Page<Workflow> workflowMocks = createLimit2AndOffset1For5WorkflowList();
-        doReturn(workflowMocks).when(workflowManagerMock).list(any(), any());
+        mockManagerList3();
         mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "-2", "1"))
                                 .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
-               .andExpect(status().isOk())
-               .andExpect(jsonPath("$.paging.offset", is(1)))
-               .andExpect(jsonPath("$.paging.limit", is(DEFAULT_LIMIT)))
-               .andExpect(jsonPath("$.paging.total", is(2)));
-    }*/
+               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), 1, DEFAULT_LIMIT,
+                Collections.singletonList(new Sort("name", true)));
+    }
 
-/*    @Test
+    @Test
     public void shouldFallbackOnDefaultOffsetWhenOffsetIsNegative() throws Exception {
-        mockMvc.perform(
-                get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "-1"))
-                        .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
-                                                  .andExpect(status().isOk())
-               .andExpect(jsonPath("$.paging.offset", is(DEFAULT_OFFSET)))
-               .andExpect(jsonPath("$.paging.limit", is(2)))
-               .andExpect(jsonPath("$.paging.total", is(0)));
-    }*/
-
-/*    @Test
+        mockManagerList3();
+        mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "-1"))
+                                .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
+               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, 2,
+                Collections.singletonList(new Sort("name", true)));
+    }
+
+    @Test
     public void shouldFallbackOnDefaultLimitWhenLimitIsNotAnInteger() throws Exception {
-        mockMvc.perform(
-                get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "abc", "0"))
-                        .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
-                                                  .andExpect(status().isOk())
-                                                  .andExpect(jsonPath("$.paging.offset", is(0)))
-                                                  .andExpect(jsonPath("$.paging.limit", is(DEFAULT_LIMIT)))
-                                                  .andExpect(jsonPath("$.paging.total", is(0)));
-    }*/
-
-/*    @Test
+        mockManagerList3();
+        mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "abc", "0"))
+                                .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
+               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), 0, DEFAULT_LIMIT,
+                Collections.singletonList(new Sort("name", true)));
+    }
+
+    @Test
     public void shouldFallbackOnDefaultOffsetWhenOffsetIsNotAnInteger() throws Exception {
-        mockMvc.perform(
-                get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "abc"))
-                        .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
-                                                  .andExpect(status().isOk())
-                                                  .andExpect(jsonPath("$.paging.offset", is(DEFAULT_OFFSET)))
-                                                  .andExpect(jsonPath("$.paging.limit", is(2)))
-                                                  .andExpect(jsonPath("$.paging.total", is(0)));
-    }*/
+        mockManagerList3();
+        mockMvc.perform(get(RestPath.getWorkflowsPathAllQueryParams(DEFAULT_SORT_VALUE, "2", "abc"))
+                                .header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)).andDo(print())
+               .andExpect(jsonPath("$.items", hasSize(3)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, 2,
+                Collections.singletonList(new Sort("name", true)));
+    }
 
     @Test
     public void shouldReturnDefaultLimitOffsetAppliedWorkflowsWhenLimitIsNotSpecified() throws Exception {
-        Page<Workflow> workflowMocks = createLimit2AndOffset1For5WorkflowList();
-        doReturn(workflowMocks).when(workflowManagerMock).list(any(), any());
+        mockManagerList3();
         mockMvc.perform(get(RestPath.getWorkflowsPathNoSortAndLimit("1")).header(USER_ID_HEADER, USER_ID)
                                                                          .contentType(APPLICATION_JSON)).andDo(print())
-               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(2)));
+               .andExpect(jsonPath("$.items", hasSize(3)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), 1, DEFAULT_LIMIT, Collections.emptyList());
     }
 
     @Test
     public void shouldReturnDefaultOffsetAppliedWorkflowsWhenOffsetIsNotSpecified() throws Exception {
-        Page<Workflow> workflowMocks = createLimit1WorkflowList();
-        doReturn(workflowMocks).when(workflowManagerMock).list(any(), any());
+        mockManagerList3();
         mockMvc.perform(get(RestPath.getWorkflowsPathNoSortAndOffset("1")).header(USER_ID_HEADER, USER_ID)
                                                                           .contentType(APPLICATION_JSON)).andDo(print())
-               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(1)));
+               .andExpect(status().isOk()).andExpect(jsonPath("$.items", hasSize(3)));
+        verify(workflowManagerMock).list(any(), requestSpecArg.capture());
+        assertRequestSpec(requestSpecArg.getValue(), DEFAULT_OFFSET, 1, Collections.emptyList());
     }
 
     @Test
@@ -227,24 +215,25 @@ public class WorkflowControllerTest {
         assertEquals("Workflow name must contain only letters, digits and underscores", response.getContentAsString());
     }
 
-    private Page<Workflow> createWorkflows(int numOfWorkflows) {
-        List<Workflow> workflows = new ArrayList<>(numOfWorkflows);
-        for (int i = 0; i < numOfWorkflows; i++) {
-            workflows.add(createWorkflow(i, true));
-        }
-        return new Page<>(workflows, new PagingRequest(0, 200), numOfWorkflows);
+    private void mockManagerList3() {
+        doReturn(new Page<>(Arrays.asList(
+                createWorkflow(1, true),
+                createWorkflow(2, true),
+                createWorkflow(3, true)),
+                new PagingRequest(DEFAULT_OFFSET, DEFAULT_LIMIT), 3))
+                .when(workflowManagerMock).list(any(), any());
     }
 
-    private Page<Workflow> createLimit2AndOffset1For5WorkflowList() {
-        List<Workflow> workflows = new ArrayList<>();
-        workflows.add(createWorkflow(2, true));
-        workflows.add(createWorkflow(3, true));
-        return new Page<>(workflows, new PagingRequest(1, 200), 5);
-    }
-
-    private Page<Workflow> createLimit1WorkflowList() {
-        List<Workflow> workflows = new ArrayList<>();
-        workflows.add(createWorkflow(0, true));
-        return new Page<>(workflows, new PagingRequest(0, 1), 1);
+    private static void assertRequestSpec(RequestSpec actual, int expectedOffset, int expectedLimit,
+            List<Sort> expectedSorts) {
+        assertEquals(Integer.valueOf(expectedOffset), actual.getPaging().getOffset());
+        assertEquals(Integer.valueOf(expectedLimit), actual.getPaging().getLimit());
+        if (expectedSorts.isEmpty()) {
+            assertEquals(expectedSorts, actual.getSorting().getSorts());
+        } else {
+            for (int i = 0; i < expectedSorts.size(); i++) {
+                assertEquals(expectedSorts.get(i), actual.getSorting().getSorts().get(i));
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/PagingTest.java b/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/PagingTest.java
new file mode 100644 (file)
index 0000000..c2b6cef
--- /dev/null
@@ -0,0 +1,71 @@
+package org.onap.sdc.workflow.api.types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.onap.sdc.workflow.services.types.PagingConstants.MAX_LIMIT;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class PagingTest {
+
+    @InjectMocks
+    private Paging paging;
+
+    @Test
+    public void setOffsetNotNumber() {
+        paging.setOffset("aaa");
+        assertNull(paging.getOffset());
+    }
+
+    @Test
+    public void setOffsetNegative() {
+        paging.setOffset("-5");
+        assertNull(paging.getOffset());
+    }
+
+    @Test
+    public void setOffsetZero() {
+        paging.setOffset("0");
+        assertEquals(Integer.valueOf(0), paging.getOffset());
+    }
+
+    @Test
+    public void setOffsetPositive() {
+        paging.setOffset("8");
+        assertEquals(Integer.valueOf(8), paging.getOffset());
+    }
+
+    @Test
+    public void setLimitNotNumber() {
+        paging.setLimit("aaa");
+        assertNull(paging.getLimit());
+    }
+
+    @Test
+    public void setLimitNegative() {
+        paging.setLimit("-5");
+        assertNull(paging.getLimit());
+    }
+
+    @Test
+    public void setLimitZero() {
+        paging.setLimit("0");
+        assertNull(paging.getLimit());
+    }
+
+    @Test
+    public void setLimitPositive() {
+        paging.setLimit("8");
+        assertEquals(Integer.valueOf(8), paging.getLimit());
+    }
+
+    @Test
+    public void setLimitGreaterThanMax() {
+        paging.setLimit("7000");
+        assertEquals(Integer.valueOf(MAX_LIMIT), paging.getLimit());
+    }
+}
\ No newline at end of file
diff --git a/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/SortingTest.java b/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/SortingTest.java
new file mode 100644 (file)
index 0000000..2943644
--- /dev/null
@@ -0,0 +1,42 @@
+package org.onap.sdc.workflow.api.types;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.onap.sdc.workflow.services.types.Sort;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SortingTest {
+
+    @InjectMocks
+    private Sorting sorting;
+
+    @Test
+    public void setSortInvalid() {
+        sorting.setSort("a");
+        assertEquals(Collections.emptyList(), sorting.getSorts());
+    }
+
+    @Test
+    public void setSortAsc() {
+        sorting.setSort("name:asc");
+        assertEquals(Collections.singletonList(new Sort("name", true)), sorting.getSorts());
+    }
+
+    @Test
+    public void setSortDesc() {
+        sorting.setSort("name:desc");
+        assertEquals(Collections.singletonList(new Sort("name", false)), sorting.getSorts());
+    }
+
+    @Test
+    public void setSortMoreThanOne() {
+        sorting.setSort("name:asc,date:desc");
+        assertEquals(Arrays.asList(new Sort("name", true), new Sort("date", false)), sorting.getSorts());
+    }
+}
\ No newline at end of file
diff --git a/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/VersionStatesFormatterTest.java b/workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/types/VersionStatesFormatterTest.java
new file mode 100644 (file)
index 0000000..c57bd9c
--- /dev/null
@@ -0,0 +1,45 @@
+package org.onap.sdc.workflow.api.types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.onap.sdc.workflow.persistence.types.WorkflowVersionState.CERTIFIED;
+import static org.onap.sdc.workflow.persistence.types.WorkflowVersionState.DRAFT;
+
+import java.util.Collections;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class VersionStatesFormatterTest {
+
+    @InjectMocks
+    private VersionStatesFormatter versionStateSet;
+
+    @Test
+    public void setVersionStateInvalid() {
+        versionStateSet.setVersionState("aaa");
+        assertNull(versionStateSet.getVersionStates());
+    }
+
+    @Test
+    public void setVersionStateDraft() {
+        versionStateSet.setVersionState("DRAFT");
+        assertEquals(Collections.singleton(DRAFT), versionStateSet.getVersionStates());
+    }
+
+    @Test
+    public void setVersionStateCertified() {
+        versionStateSet.setVersionState("CERTIFIED");
+        assertEquals(Collections.singleton(CERTIFIED), versionStateSet.getVersionStates());
+    }
+
+    @Test
+    public void setVersionStateBoth() {
+        versionStateSet.setVersionState("DRAFT,CERTIFIED");
+        assertEquals(Stream.of(DRAFT, CERTIFIED).collect(Collectors.toSet()), versionStateSet.getVersionStates());
+    }
+}
\ No newline at end of file
index 0797b64..de17a04 100644 (file)
@@ -8,6 +8,9 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.onap.sdc.workflow.TestUtil.createItem;
 import static org.onap.sdc.workflow.TestUtil.createWorkflow;
+import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_LIMIT;
+import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_OFFSET;
+import static org.onap.sdc.workflow.services.types.PagingConstants.MAX_LIMIT;
 import static org.openecomp.sdc.versioning.dao.types.VersionStatus.Certified;
 
 import java.util.ArrayList;
@@ -18,7 +21,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
@@ -30,6 +32,7 @@ import org.onap.sdc.workflow.services.exceptions.EntityNotFoundException;
 import org.onap.sdc.workflow.services.impl.mappers.VersionStateMapper;
 import org.onap.sdc.workflow.services.impl.mappers.WorkflowMapper;
 import org.onap.sdc.workflow.services.types.Page;
+import org.onap.sdc.workflow.services.types.Paging;
 import org.onap.sdc.workflow.services.types.PagingRequest;
 import org.onap.sdc.workflow.services.types.RequestSpec;
 import org.onap.sdc.workflow.services.types.Sort;
@@ -53,7 +56,7 @@ public class WorkflowManagerImplTest {
     static {
         List<Item> items = new ArrayList<>();
         List<Workflow> mappedWorkflows = new ArrayList<>();
-        for (int i = 1; i < 6; i++) {
+        for (int i = 0; i < 5; i++) {
             items.add(createItem(i, true, true));
             mappedWorkflows.add(createWorkflow(i, true));
         }
@@ -75,17 +78,18 @@ public class WorkflowManagerImplTest {
     @Test
     public void shouldReturnWorkflowVersionList() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
-        for (int i = 0; i < ITEMS.size(); i++) {
-            doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
-        }
-        Page<Workflow> workflows = workflowManager.list(null, createRequestSpec(20, 0, true, SORT_FIELD_NAME));
+        mockItemToWorkflowMaps();
+        RequestSpec requestSpec = createRequestSpec(0, 20, true);
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
 
         Map<String, Workflow> workflowById =
                 workflows.getItems().stream().collect(Collectors.toMap(Workflow::getId, Function.identity()));
         assertEquals(ITEMS.size(), workflows.getItems().size());
-        for (int i = 1; i < ITEMS.size() + 1; i++) {
+        for (int i = 0; i < ITEMS.size(); i++) {
             assertTrue(workflowById.containsKey(String.valueOf(i)));
         }
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
     }
 
     @Test
@@ -96,14 +100,17 @@ public class WorkflowManagerImplTest {
         doReturn(MAPPED_WORKFLOWS.get(0)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(0));
         doReturn(MAPPED_WORKFLOWS.get(2)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(2));
 
-        Page<Workflow> workflows = workflowManager.list(Collections.singleton(WorkflowVersionState.CERTIFIED),
-                createRequestSpec(20, 0, true, SORT_FIELD_NAME));
+        RequestSpec requestSpec = createRequestSpec(0, 20, true);
+        Page<Workflow> workflows =
+                workflowManager.list(Collections.singleton(WorkflowVersionState.CERTIFIED), requestSpec);
 
         Map<String, Workflow> workflowById =
                 workflows.getItems().stream().collect(Collectors.toMap(Workflow::getId, Function.identity()));
         assertEquals(2, workflows.getItems().size());
-        assertTrue(workflowById.containsKey("1"));
-        assertTrue(workflowById.containsKey("3"));
+        assertTrue(workflowById.containsKey("0"));
+        assertTrue(workflowById.containsKey("2"));
+
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(), 2);
     }
 
     @Test(expected = EntityNotFoundException.class)
@@ -162,81 +169,183 @@ public class WorkflowManagerImplTest {
     }
 
     @Test
-    public void shouldListAllWorkflowsWhenLimitAndOffsetAreValid() {
-        RequestSpec requestSpec = createRequestSpec(5, 0, true, SORT_FIELD_NAME);
+    public void listWhenRequestSpecIsNull() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
-        for (int i = 0; i < ITEMS.size(); i++) {
-            doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, null);
+
+        assertEquals(ITEMS.size(), workflows.getItems().size());
+        assertPaging(workflows.getPaging(), DEFAULT_OFFSET, DEFAULT_LIMIT, ITEMS.size());
+
+        // verify sorted ascending by name
+        for (int i = DEFAULT_OFFSET; i < ITEMS.size(); i++) {
+            assertEquals("Workflow_" + i, workflows.getItems().get(i).getName());
         }
-        Assert.assertEquals(5, workflowManager.list(null, requestSpec).getItems().size());
     }
 
     @Test
-    public void shouldListLimitFilteredWorkflowsInFirstOffsetRange() {
-        RequestSpec requestSpec = createRequestSpec(3, 0, true, SORT_FIELD_NAME);
+    public void listWhenPagingIsNull() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
-        for (int i = 0; i < ITEMS.size(); i++) {
-            doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
-        }
-        Assert.assertEquals(3, workflowManager.list(null, requestSpec).getItems().size());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, new RequestSpec(null,
+                SortingRequest.builder().sort(new Sort(SORT_FIELD_NAME, true)).build()));
+
+        assertEquals(ITEMS.size(), workflows.getItems().size());
+        assertPaging(workflows.getPaging(), DEFAULT_OFFSET, DEFAULT_LIMIT, ITEMS.size());
     }
 
-/*    @Test
-    public void shouldListLimitFilteredWorkflowsInSecondOffsetRange() {
-        RequestSpec requestSpec = createRequestSpec(3, 1, true, SORT_FIELD_NAME);
+    @Test
+    public void listWhenOffsetAndLimitAreNull() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
-        for (int i = 0; i < ITEMS.size(); i++) {
-            doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
-        }
-        Assert.assertEquals(2, workflowManager.list(null, requestSpec).getItems().size());
-    }*/
+        mockItemToWorkflowMaps();
+        RequestSpec requestSpec = new RequestSpec(new PagingRequest(-2, -8),
+                SortingRequest.builder().sort(new Sort(SORT_FIELD_NAME, true)).build());
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+
+        assertEquals(ITEMS.size(), workflows.getItems().size());
+        assertPaging(workflows.getPaging(), DEFAULT_OFFSET, DEFAULT_LIMIT, ITEMS.size());
+    }
 
     @Test
-    public void shouldListAllWorkflowsWhenLimitGreaterThanTotalRecordsAndOffsetInRange() {
-        RequestSpec requestSpec = createRequestSpec(10, 0, true, SORT_FIELD_NAME);
+    public void listWhenSortingIsNull() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
-        for (int i = 0; i < ITEMS.size(); i++) {
-            doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
-        }
-        Assert.assertEquals(5, workflowManager.list(null, requestSpec).getItems().size());
+        mockItemToWorkflowMaps();
+        RequestSpec requestSpec = new RequestSpec(new PagingRequest(2, 8), null);
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+
+        assertEquals(3, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+
+        // verify sorted ascending by name
+        assertEquals("Workflow_2", workflows.getItems().get(0).getName());
+        assertEquals("Workflow_3", workflows.getItems().get(1).getName());
+        assertEquals("Workflow_4", workflows.getItems().get(2).getName());
     }
 
     @Test
-    public void shouldNotListWorkflowsIfOffsetGreaterThanTotalRecords() {
-        RequestSpec requestSpec = createRequestSpec(3, 6, true, SORT_FIELD_NAME);
+    public void listWhenSortingIsEmpty() {
         doReturn(ITEMS).when(itemManagerMock).list(any());
-        for (int i = 0; i < ITEMS.size(); i++) {
-            doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
-        }
-        Assert.assertEquals(0, workflowManager.list(null, requestSpec).getItems().size());
+        mockItemToWorkflowMaps();
+        RequestSpec requestSpec = new RequestSpec(new PagingRequest(2, 8), SortingRequest.builder().build());
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+
+        assertEquals(3, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+
+        // verify sorted ascending by name
+        assertEquals("Workflow_2", workflows.getItems().get(0).getName());
+        assertEquals("Workflow_3", workflows.getItems().get(1).getName());
+        assertEquals("Workflow_4", workflows.getItems().get(2).getName());
     }
 
     @Test
-    public void shouldNotListWorkflowsBothLimitAndOffsetGreaterThanTotalRecords() {
-        RequestSpec requestSpec = createRequestSpec(10, 10, true, SORT_FIELD_NAME);
+    public void listWhenRequestSpecIsValid() {
+        RequestSpec requestSpec = createRequestSpec(0, 5, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
-        for (int i = 0; i < ITEMS.size(); i++) {
-            doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
-        }
-        Assert.assertEquals(0, workflowManager.list(null, requestSpec).getItems().size());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+
+        assertEquals(5, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+    }
+
+    @Test
+    public void listWhenLimitIsLessThanTotal() {
+        RequestSpec requestSpec = createRequestSpec(0, 3, true);
+        doReturn(ITEMS).when(itemManagerMock).list(any());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+        assertEquals(3, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+    }
+
+
+    @Test
+    public void listWhenOffsetIsNotFirst() {
+        RequestSpec requestSpec = createRequestSpec(3, 1, true);
+        doReturn(ITEMS).when(itemManagerMock).list(any());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+        assertEquals(1, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+    }
+
+    @Test
+    public void listWhenLimitIsMoreThanTotal() {
+        RequestSpec requestSpec = createRequestSpec(0, 10, true);
+        doReturn(ITEMS).when(itemManagerMock).list(any());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+        assertEquals(5, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+    }
+
+    @Test
+    public void listWhenOffsetIsMoreThanTotal() {
+        RequestSpec requestSpec = createRequestSpec(6, 3, true);
+        doReturn(ITEMS).when(itemManagerMock).list(any());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+        assertEquals(0, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+    }
+
+    @Test
+    public void listWhenOffsetIsMoreThanMax() {
+        doReturn(ITEMS).when(itemManagerMock).list(any());
+        mockItemToWorkflowMaps();
+        RequestSpec requestSpec = createRequestSpec(0, 5555, true);
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+
+        assertEquals(ITEMS.size(), workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), MAX_LIMIT, ITEMS.size());
     }
 
-/*    @Test
-    public void shouldListLimitOffsetAppliedWorkflowsSortedInDescOrder() {
-        RequestSpec requestSpec = createRequestSpec(2, 1, false, SORT_FIELD_NAME);
+    @Test
+    public void listWhenOffsetAndLimitAreMoreThanTotal() {
+        RequestSpec requestSpec = createRequestSpec(10, 10, true);
         doReturn(ITEMS).when(itemManagerMock).list(any());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+        assertEquals(0, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+    }
+
+    @Test
+    public void listWhenSortedDesc() {
+        RequestSpec requestSpec = createRequestSpec(2, 1, false);
+        doReturn(ITEMS).when(itemManagerMock).list(any());
+        mockItemToWorkflowMaps();
+        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
+        assertEquals(1, workflows.getItems().size());
+        assertPaging(workflows.getPaging(), requestSpec.getPaging().getOffset(), requestSpec.getPaging().getLimit(),
+                ITEMS.size());
+        Iterator<Workflow> workflowIterator = workflows.getItems().iterator();
+        assertEquals("Workflow_2", workflowIterator.next().getName());
+    }
+
+    private void mockItemToWorkflowMaps() {
         for (int i = 0; i < ITEMS.size(); i++) {
             doReturn(MAPPED_WORKFLOWS.get(i)).when(workflowMapperMock).itemToWorkflow(ITEMS.get(i));
         }
-        Page<Workflow> workflows = workflowManager.list(null, requestSpec);
-        Assert.assertEquals(2, workflows.getItems().size());
-        Iterator<Workflow> workflowIterator = workflows.getItems().iterator();
-        Assert.assertEquals("Workflow_3", workflowIterator.next().getName());
-        Assert.assertEquals("Workflow_2", workflowIterator.next().getName());
-    }*/
+    }
 
-    private RequestSpec createRequestSpec(int limit, int offset, boolean isAscending, String sortField) {
+    private static RequestSpec createRequestSpec(int offset, int limit, boolean isAscending) {
         return new RequestSpec(new PagingRequest(offset, limit),
-                SortingRequest.builder().sort(new Sort(sortField, isAscending)).build());
+                SortingRequest.builder().sort(new Sort(SORT_FIELD_NAME, isAscending)).build());
+    }
+
+    private static void assertPaging(Paging paging, int expectedOffset, int expectedLimit, int expectedTotal) {
+        assertEquals(expectedOffset, paging.getOffset());
+        assertEquals(expectedLimit, paging.getLimit());
+        assertEquals(expectedTotal, paging.getTotal());
     }
 }
\ No newline at end of file