Skip to content
Snippets Groups Projects
Commit e100d000 authored by Martin Lowe's avatar Martin Lowe :flag_ca:
Browse files

Iss #31 - Fix pagination calls for common edge case

Current code will fail if the query string starts with the page data.
This should address this issue, and also adds testing to help guard
against regression.
parent c0c94aab
No related branches found
No related tags found
1 merge request!67Iss #31 - Fix pagination calls for common edge case
......@@ -48,7 +48,7 @@ import io.quarkus.arc.Unremovable;
@Unremovable
public class DefaultAPIMiddleware implements APIMiddleware {
public static final Logger LOGGER = LoggerFactory.getLogger(DefaultAPIMiddleware.class);
private static final Pattern PAGE_QUERY_STRING_PARAM_MATCHER = Pattern.compile(".*[\\?&]page=(\\d+).*");
private static final Pattern PAGE_QUERY_STRING_PARAM_MATCHER = Pattern.compile("(?:^page=|.*&page=)(\\d+).*");
@Inject
ObjectMapper objectMapper;
......@@ -129,6 +129,7 @@ public class DefaultAPIMiddleware implements APIMiddleware {
URI lastLink = h.getLinkByRelationship("last").getUri();
Matcher m = PAGE_QUERY_STRING_PARAM_MATCHER.matcher(lastLink.getQuery());
if (m.matches()) {
// page matcher can have either g 1 or 2 as group containing page num depending on format
return Integer.parseInt(m.group(1));
}
}
......
......@@ -22,6 +22,12 @@ import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;
/**
* Partial test to make sure that startup proxy + provider pattern works.
*
* @author Zachary Sabourin
*
*/
@QuarkusTest
@TestProfile(FooBarTestProfiles.BarProfile.class)
class BarServiceTest {
......
......@@ -13,38 +13,59 @@ package org.eclipsefoundation.core.service.impl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import org.eclipsefoundation.core.service.APIMiddleware;
import org.eclipsefoundation.core.service.APIMiddleware.BaseAPIParameters;
import org.eclipsefoundation.core.test.models.TestModel;
import org.jboss.resteasy.spi.LinkHeader;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mockito;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectSpy;
@QuarkusTest
class DefaultAPIMiddlewareTest {
@InjectSpy
TestEndpoint endpoint;
@Inject
APIMiddleware middleware;
@Inject
ObjectMapper objectMapper;
@ParameterizedTest
@ValueSource(strings = { "", "sample=2&", "sample=2&otherpage=10&" })
void getAll_success_pagination(String leadingQueryParams) {
int pages = 5;
// call the sample endpoint
middleware.getAll(params -> endpoint.sample(params, pages, leadingQueryParams), TestModel.class);
// assert that the endpoint sample was called the number of times expected
Mockito
.verify(endpoint, Mockito.times(pages))
.sample(Mockito.any(BaseAPIParameters.class), Mockito.any(Integer.class), Mockito.any(String.class));
}
@Test
void getAll_success_GZIPContent() {
List<TestModel> out = middleware.getAll(
params -> Response.ok(new ByteArrayInputStream(getListAsByteArray())).header("Content-Encoding", "GZIP")
.build(),
TestModel.class);
List<TestModel> out = middleware
.getAll(params -> Response.ok(new ByteArrayInputStream(getListAsByteArray())).header("Content-Encoding", "GZIP").build(),
TestModel.class);
Assertions.assertTrue(out.size() > 0);
}
......@@ -59,11 +80,11 @@ class DefaultAPIMiddlewareTest {
try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream)) {
// Convert list to JSON String before compression
gzipStream.write(objectMapper.writeValueAsString(list).getBytes());
//Explicitly close GZIPStream or it won't fully write.
// Explicitly close GZIPStream or it won't fully write.
gzipStream.close();
compressedData = byteStream.toByteArray();
......@@ -74,4 +95,32 @@ class DefaultAPIMiddlewareTest {
return compressedData;
}
@ApplicationScoped
public static class TestEndpoint {
public Response sample(BaseAPIParameters base, int pageCount, String leadingParams) {
// get current page safely
int currentPage = 1;
if (base.getPage() != null) {
currentPage = base.getPage();
}
// generate link headers
LinkHeader linkHeader = new LinkHeader();
linkHeader
.addLink("this page of results", "self", String.format("https://sample.com/api?%spage=%d", leadingParams, currentPage),
"");
linkHeader.addLink("first page of results", "first", String.format("https://sample.com/api?%spage=%d", leadingParams, 1), "");
linkHeader
.addLink("last page of results", "last", String.format("https://sample.com/api?%spage=%d", leadingParams, pageCount),
"");
if (currentPage < pageCount) {
linkHeader
.addLink("next page of results", "next",
String.format("https://sample.com/api?%spage=%d", leadingParams, currentPage + 1), "");
}
// return basic return with link headers to test
return Response.ok(Collections.emptyList()).header("Link", linkHeader).build();
}
}
}
......@@ -22,6 +22,12 @@ import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;
/**
* Partial test to make sure that startup proxy + provider pattern works.
*
* @author Zachary Sabourin
*
*/
@QuarkusTest
@TestProfile(FooBarTestProfiles.FooProfile.class)
class FooServiceTest {
......@@ -30,7 +36,7 @@ class FooServiceTest {
FooBarService fooService;
@Test
void testBar() {
void testFoo() {
assertTrue(fooService.getName().equalsIgnoreCase("foo"));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment