From 680a69c185eab6c539f9b1cc13efab3317e9e816 Mon Sep 17 00:00:00 2001 From: anthony-frage-ouest-france <156292537+anthony-frage-ouest-france@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:18:26 +0100 Subject: [PATCH] fix(pagination) add pagination management (#6) feat(paginate): allow users to retrieve next page and previous pages --- .../querydsl/postgrest/model/Page.java | 7 ++ .../querydsl/postgrest/model/Pageable.java | 30 +++++++- .../PostgrestRepositoryGetMockTest.java | 71 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Page.java b/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Page.java index b81c047..5ddf30c 100644 --- a/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Page.java +++ b/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Page.java @@ -97,4 +97,11 @@ default Iterator iterator() { default Page map(Function converter) { return new PageImpl<>(stream().map(converter).toList(), getPageable(), getTotalElements(), getTotalPages()); } + + default boolean hasNext() { + if(getPageable() == null) { + return false; + } + return getPageable().getPageNumber() + 1 < getTotalPages(); + } } diff --git a/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Pageable.java b/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Pageable.java index 5151efb..b3c0769 100644 --- a/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Pageable.java +++ b/src/main/java/fr/ouestfrance/querydsl/postgrest/model/Pageable.java @@ -7,6 +7,7 @@ public interface Pageable { /** * Create a simple pageRequest with size and no declarative sort + * * @param pageSize number of element in one page * @return pageable object */ @@ -16,16 +17,31 @@ static Pageable ofSize(int pageSize) { /** * Create a simple pageRequest with size and declarative sort + * * @param pageSize number of element in one page - * @param sort sort information + * @param sort sort information * @return pageable object */ static Pageable ofSize(int pageSize, Sort sort) { - return new PageRequest(0, pageSize, sort); + return ofSize(0, pageSize, sort); + } + + + /** + * Create a simple pageRequest with page number and size and declarative sort + * + * @param pageNumber number of the request + * @param pageSize number of element in one page + * @param sort sort information + * @return pageable object + */ + static Pageable ofSize(int pageNumber, int pageSize, Sort sort) { + return new PageRequest(pageNumber, pageSize, sort); } /** * Create an un paged + * * @return pageable object */ static Pageable unPaged() { @@ -34,24 +50,28 @@ static Pageable unPaged() { /** * Request page size + * * @return page size */ int getPageSize(); /** * Request page number + * * @return page number */ int getPageNumber(); /** * Request sort + * * @return sort */ Sort getSort(); /** * Transform a Pageable to range representation + * * @return transform a pagination item to range value */ default String toRange() { @@ -77,5 +97,11 @@ default int pageLimit() { return pageOffset() + getPageSize() - 1; } + default Pageable next() { + return new PageRequest(getPageNumber() + 1, getPageSize(), getSort()); + } + default Pageable previous() { + return getPageNumber() == 0 ? this : new PageRequest(getPageNumber() - 1, getPageSize(), getSort()); + } } diff --git a/src/test/java/fr/ouestfrance/querydsl/postgrest/PostgrestRepositoryGetMockTest.java b/src/test/java/fr/ouestfrance/querydsl/postgrest/PostgrestRepositoryGetMockTest.java index 2e4ae00..094c7ea 100644 --- a/src/test/java/fr/ouestfrance/querydsl/postgrest/PostgrestRepositoryGetMockTest.java +++ b/src/test/java/fr/ouestfrance/querydsl/postgrest/PostgrestRepositoryGetMockTest.java @@ -2,6 +2,7 @@ import fr.ouestfrance.querydsl.postgrest.app.*; import fr.ouestfrance.querydsl.postgrest.model.Page; +import fr.ouestfrance.querydsl.postgrest.model.PageImpl; import fr.ouestfrance.querydsl.postgrest.model.Pageable; import fr.ouestfrance.querydsl.postgrest.model.Sort; import fr.ouestfrance.querydsl.postgrest.model.exceptions.PostgrestRequestException; @@ -43,6 +44,7 @@ void shouldSearchAllPosts() { assertNotNull(search); assertNotNull(search.iterator()); assertEquals(2, search.size()); + assertFalse(search.hasNext()); } private ResponseEntity> ok(List data) { @@ -81,6 +83,75 @@ void shouldSearchWithPaginate() { MultiValueMap value = headerArgs.getValue(); assertEquals("0-9", value.getFirst("Range")); assertEquals("items", value.getFirst("Range-Unit")); + // Assert pagination + assertNotNull(search.getPageable()); + assertEquals(10, search.getPageable().getPageSize()); + assertEquals(0, search.getPageable().getPageNumber()); + assertEquals(2, search.getTotalElements()); + assertEquals(1, search.getTotalPages()); + assertFalse(search.hasNext()); + assertNotNull(search.getPageable().previous()); + assertEquals(0, search.getPageable().previous().getPageNumber()); + } + + @Test + void shouldSearchWithNextPaginate() { + PostRequest request = new PostRequest(); + request.setUserId(1); + request.setId(1); + request.setTitle("Test*"); + request.setCodes(List.of("a", "b", "c")); + request.setExcludes(List.of("z")); + request.setValidDate(LocalDate.of(2023, 11, 10)); + ArgumentCaptor> queryArgs = multiMapCaptor(); + ArgumentCaptor> headerArgs = multiMapCaptor(); + when(webClient.search(anyString(), queryArgs.capture(), headerArgs.capture(), eq(Post.class))).thenReturn(new PageImpl<>(List.of(new Post()), null, 2, 2)); + + Page search = repository.search(request, Pageable.ofSize(1, Sort.by(Sort.Order.asc("id")))); + assertNotNull(search); + assertEquals(1, search.size()); + assertTrue(search.hasNext()); + // Assert pagination + assertNotNull(search.getPageable()); + assertEquals(1, search.getPageable().getPageSize()); + assertEquals(0, search.getPageable().getPageNumber()); + assertEquals(2, search.getTotalElements()); + assertEquals(2, search.getTotalPages()); + // Assert next pagination + assertNotNull(search.getPageable().next()); + assertEquals(1, search.getPageable().next().getPageSize()); + assertEquals(1, search.getPageable().next().getPageNumber()); + assertEquals(search.getPageable().getSort(), search.getPageable().next().getSort()); + + } + + @Test + void shouldSearchWithPreviousPaginate() { + PostRequest request = new PostRequest(); + request.setUserId(1); + request.setId(1); + request.setTitle("Test*"); + request.setCodes(List.of("a", "b", "c")); + request.setExcludes(List.of("z")); + request.setValidDate(LocalDate.of(2023, 11, 10)); + ArgumentCaptor> queryArgs = multiMapCaptor(); + ArgumentCaptor> headerArgs = multiMapCaptor(); + when(webClient.search(anyString(), queryArgs.capture(), headerArgs.capture(), eq(Post.class))).thenReturn(new PageImpl<>(List.of(new Post()), null, 2, 2)); + + Page search = repository.search(request, Pageable.ofSize(1, 1, Sort.by(Sort.Order.asc("id")))); + assertNotNull(search); + assertEquals(1, search.size()); + assertFalse(search.hasNext()); + // Assert pagination + assertNotNull(search.getPageable()); + assertEquals(1, search.getPageable().getPageSize()); + assertEquals(1, search.getPageable().getPageNumber()); + assertEquals(2, search.getTotalElements()); + assertEquals(2, search.getTotalPages()); + // Assert previous pagination + assertNotNull(search.getPageable().previous()); + assertEquals(1, search.getPageable().previous().getPageSize()); + assertEquals(0, search.getPageable().previous().getPageNumber()); } @Test