9 changed files with 699 additions and 1 deletions
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
/* |
||||
* Copyright 2016-2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.data.web; |
||||
|
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.data.domain.OffsetScrollPosition; |
||||
import org.springframework.lang.NonNull; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.web.bind.WebDataBinder; |
||||
import org.springframework.web.bind.support.WebDataBinderFactory; |
||||
import org.springframework.web.context.request.NativeWebRequest; |
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
||||
import org.springframework.web.method.support.ModelAndViewContainer; |
||||
|
||||
/** |
||||
* Argument resolver to extract a {@link OffsetScrollPosition} object from a {@link NativeWebRequest} for a particular |
||||
* {@link MethodParameter}. A {@link OffsetScrollPositionArgumentResolver} can either resolve {@link OffsetScrollPosition} itself or wrap another |
||||
* {@link OffsetScrollPositionArgumentResolver} to post-process {@link OffsetScrollPosition}. |
||||
* |
||||
* @since 3.2 |
||||
* @author Yanming Zhou |
||||
* @see HandlerMethodArgumentResolver |
||||
*/ |
||||
public interface OffsetScrollPositionArgumentResolver extends HandlerMethodArgumentResolver { |
||||
|
||||
/** |
||||
* Resolves a {@link OffsetScrollPosition} method parameter into an argument value from a given request. |
||||
* |
||||
* @param parameter the method parameter to resolve. This parameter must have previously been passed to |
||||
* {@link #supportsParameter} which must have returned {@code true}. |
||||
* @param mavContainer the ModelAndViewContainer for the current request |
||||
* @param webRequest the current request |
||||
* @param binderFactory a factory for creating {@link WebDataBinder} instances |
||||
* @return the resolved argument value |
||||
*/ |
||||
@NonNull |
||||
@Override |
||||
OffsetScrollPosition resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, |
||||
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory); |
||||
} |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
/* |
||||
* Copyright 2013-2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.data.web; |
||||
|
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.data.domain.OffsetScrollPosition; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.web.bind.support.WebDataBinderFactory; |
||||
import org.springframework.web.context.request.NativeWebRequest; |
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
||||
import org.springframework.web.method.support.ModelAndViewContainer; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* {@link HandlerMethodArgumentResolver} to automatically create {@link OffsetScrollPosition} instances from request parameters. |
||||
* |
||||
* @since 3.2 |
||||
* @author Yanming Zhou |
||||
*/ |
||||
public class OffsetScrollPositionHandlerMethodArgumentResolver extends OffsetScrollPositionHandlerMethodArgumentResolverSupport |
||||
implements OffsetScrollPositionArgumentResolver { |
||||
|
||||
@Override |
||||
public boolean supportsParameter(MethodParameter parameter) { |
||||
return OffsetScrollPosition.class.equals(parameter.getParameterType()); |
||||
} |
||||
|
||||
@Override |
||||
public OffsetScrollPosition resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, |
||||
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) { |
||||
|
||||
String[] offsetParameter = webRequest.getParameterValues(getOffsetParameter(parameter)); |
||||
return parseParameterIntoOffsetScrollPosition(offsetParameter != null ? Arrays.asList(offsetParameter) : null); |
||||
} |
||||
} |
||||
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
/* |
||||
* Copyright 2017-2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.data.web; |
||||
|
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.data.domain.OffsetScrollPosition; |
||||
import org.springframework.data.domain.ScrollPosition; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
import java.util.List; |
||||
import java.util.Objects; |
||||
|
||||
/** |
||||
* Base class providing methods for handler method argument resolvers to create {@link OffsetScrollPosition} instances from request |
||||
* parameters. |
||||
* |
||||
* @since 3.2 |
||||
* @author Yanming Zhou |
||||
* @see OffsetScrollPositionHandlerMethodArgumentResolver |
||||
* @see ReactiveOffsetScrollPositionHandlerMethodArgumentResolver |
||||
*/ |
||||
public abstract class OffsetScrollPositionHandlerMethodArgumentResolverSupport { |
||||
|
||||
private static final String DEFAULT_PARAMETER = "offset"; |
||||
|
||||
private static final String DEFAULT_QUALIFIER_DELIMITER = "_"; |
||||
|
||||
private String offsetParameter = DEFAULT_PARAMETER; |
||||
|
||||
private String qualifierDelimiter = DEFAULT_QUALIFIER_DELIMITER; |
||||
|
||||
/** |
||||
* Configure the request parameter to lookup offset information from. Defaults to {@code offset}. |
||||
* |
||||
* @param offsetParameter must not be {@literal null} or empty. |
||||
*/ |
||||
public void setOffsetParameter(String offsetParameter) { |
||||
|
||||
Assert.hasText(offsetParameter, "offsetParameter must not be null nor empty"); |
||||
this.offsetParameter = offsetParameter; |
||||
} |
||||
|
||||
/** |
||||
* Configures the delimiter used to separate the qualifier from the offset parameter. Defaults to {@code _}, so a |
||||
* qualified offset property would look like {@code qualifier_offset}. |
||||
* |
||||
* @param qualifierDelimiter the qualifier delimiter to be used or {@literal null} to reset to the default. |
||||
*/ |
||||
public void setQualifierDelimiter(@Nullable String qualifierDelimiter) { |
||||
this.qualifierDelimiter = qualifierDelimiter == null ? DEFAULT_QUALIFIER_DELIMITER : qualifierDelimiter; |
||||
} |
||||
|
||||
/** |
||||
* Returns the offset parameter to be looked up from the request. Potentially applies qualifiers to it. |
||||
* |
||||
* @param parameter can be {@literal null}. |
||||
* @return the offset parameter |
||||
*/ |
||||
protected String getOffsetParameter(@Nullable MethodParameter parameter) { |
||||
|
||||
StringBuilder builder = new StringBuilder(); |
||||
|
||||
String value = SpringDataAnnotationUtils.getQualifier(parameter); |
||||
|
||||
if (StringUtils.hasLength(value)) { |
||||
builder.append(value); |
||||
builder.append(qualifierDelimiter); |
||||
} |
||||
|
||||
return builder.append(offsetParameter).toString(); |
||||
} |
||||
|
||||
/** |
||||
* Parses the given source into a {@link OffsetScrollPosition} instance. |
||||
* |
||||
* @param source could be {@literal null} or empty. |
||||
* @return parsed OffsetScrollPosition |
||||
*/ |
||||
OffsetScrollPosition parseParameterIntoOffsetScrollPosition(@Nullable List<String> source) { |
||||
// No parameter or Single empty parameter, e.g "offset="
|
||||
if (source == null || source.size() == 1 && !StringUtils.hasText(source.get(0))) { |
||||
return ScrollPosition.offset(); |
||||
} |
||||
try { |
||||
long offset = Long.parseLong(source.get(0)); |
||||
return ScrollPosition.offset(offset); |
||||
} catch (NumberFormatException ex) { |
||||
return ScrollPosition.offset(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
/* |
||||
* Copyright 2017-2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.data.web; |
||||
|
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.data.domain.OffsetScrollPosition; |
||||
import org.springframework.lang.NonNull; |
||||
import org.springframework.web.reactive.BindingContext; |
||||
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; |
||||
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver; |
||||
import org.springframework.web.server.ServerWebExchange; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Reactive {@link HandlerMethodArgumentResolver} to create {@link OffsetScrollPosition} instances from query string parameters. |
||||
* |
||||
* @since 3.2 |
||||
* @author Yanming Zhou |
||||
*/ |
||||
public class ReactiveOffsetScrollPositionHandlerMethodArgumentResolver extends OffsetScrollPositionHandlerMethodArgumentResolverSupport |
||||
implements SyncHandlerMethodArgumentResolver { |
||||
|
||||
@Override |
||||
public boolean supportsParameter(MethodParameter parameter) { |
||||
return OffsetScrollPosition.class.equals(parameter.getParameterType()); |
||||
} |
||||
|
||||
@NonNull |
||||
@Override |
||||
public OffsetScrollPosition resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext, |
||||
ServerWebExchange exchange) { |
||||
|
||||
List<String> offsetParameter = exchange.getRequest().getQueryParams().get(getOffsetParameter(parameter)); |
||||
|
||||
return parseParameterIntoOffsetScrollPosition(offsetParameter); |
||||
} |
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
/* |
||||
* Copyright 2017-2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.data.web.config; |
||||
|
||||
import org.springframework.data.web.OffsetScrollPositionHandlerMethodArgumentResolver; |
||||
|
||||
/** |
||||
* Callback interface that can be implemented by beans wishing to customize the |
||||
* {@link OffsetScrollPositionHandlerMethodArgumentResolver} configuration. |
||||
* |
||||
* @since 2.0 |
||||
* @author Yanming Zhou |
||||
*/ |
||||
public interface OffsetScrollPositionHandlerMethodArgumentResolverCustomizer { |
||||
|
||||
/** |
||||
* Customize the given {@link OffsetScrollPositionHandlerMethodArgumentResolver}. |
||||
* |
||||
* @param offsetResolver the {@link OffsetScrollPositionHandlerMethodArgumentResolver} to customize, will never be {@literal null}. |
||||
*/ |
||||
void customize(OffsetScrollPositionHandlerMethodArgumentResolver offsetResolver); |
||||
} |
||||
@ -0,0 +1,185 @@
@@ -0,0 +1,185 @@
|
||||
/* |
||||
* Copyright 2013-2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.data.web; |
||||
|
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import org.junit.jupiter.api.BeforeAll; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.springframework.beans.factory.annotation.Qualifier; |
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.data.domain.OffsetScrollPosition; |
||||
import org.springframework.data.domain.ScrollPosition; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.mock.web.MockHttpServletRequest; |
||||
import org.springframework.util.StringUtils; |
||||
import org.springframework.web.context.request.NativeWebRequest; |
||||
import org.springframework.web.context.request.ServletWebRequest; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Unit tests for {@link OffsetScrollPositionHandlerMethodArgumentResolver}. |
||||
* |
||||
* @since 3.2 |
||||
* @author Yanming Zhou |
||||
*/ |
||||
class OffsetScrollPositionHandlerMethodArgumentResolverUnitTests { |
||||
|
||||
static MethodParameter PARAMETER; |
||||
|
||||
@BeforeAll |
||||
static void setUp() throws Exception { |
||||
PARAMETER = getParameterOfMethod("supportedMethod"); |
||||
} |
||||
|
||||
@Test |
||||
void supportsSortParameter() { |
||||
|
||||
var resolver = new OffsetScrollPositionHandlerMethodArgumentResolver(); |
||||
|
||||
assertThat(resolver.supportsParameter(PARAMETER)).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
void fallbackToDefaultOffset() { |
||||
|
||||
var parameter = TestUtils.getParameterOfMethod(Controller.class, "unsupportedMethod", String.class); |
||||
var position = resolveOffset(new MockHttpServletRequest(), parameter); |
||||
assertThat(position).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void discoversOffsetFromRequest() { |
||||
|
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, null), PARAMETER, reference); |
||||
} |
||||
|
||||
@Test |
||||
void discoversOffsetFromRequestWithMultipleParams() { |
||||
|
||||
var request = new MockHttpServletRequest(); |
||||
request.addParameter("offset", "5"); |
||||
request.addParameter("offset", "6"); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset(5)); |
||||
} |
||||
|
||||
@Test |
||||
void discoversQualifiedOffsetFromRequest() { |
||||
|
||||
var parameter = getParameterOfMethod("qualifiedOffset"); |
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "qual"), parameter, reference); |
||||
} |
||||
|
||||
@Test |
||||
void returnsDefaultForOffsetParamSetToNothing() { |
||||
|
||||
var request = new MockHttpServletRequest(); |
||||
request.addParameter("offset", (String) null); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void returnsDefaultForEmptyOffsetParam() { |
||||
|
||||
var request = new MockHttpServletRequest(); |
||||
request.addParameter("offset", ""); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void returnsDefaultForOffsetParamIsInvalidProperty() { |
||||
|
||||
var request = new MockHttpServletRequest(); |
||||
request.addParameter("offset", "invalid_number"); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void emptyQualifierIsUsedInParameterLookup() { |
||||
|
||||
var parameter = getParameterOfMethod("emptyQualifier"); |
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, ""), parameter, reference); |
||||
} |
||||
|
||||
@Test |
||||
void mergedQualifierIsUsedInParameterLookup() { |
||||
|
||||
var parameter = getParameterOfMethod("mergedQualifier"); |
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "merged"), parameter, reference); |
||||
} |
||||
|
||||
private static OffsetScrollPosition resolveOffset(HttpServletRequest request, MethodParameter parameter) { |
||||
|
||||
var resolver = new OffsetScrollPositionHandlerMethodArgumentResolver(); |
||||
return resolver.resolveArgument(parameter, null, new ServletWebRequest(request), null); |
||||
} |
||||
|
||||
private static void assertSupportedAndResolvedTo(NativeWebRequest request, MethodParameter parameter, OffsetScrollPosition position) { |
||||
|
||||
var resolver = new OffsetScrollPositionHandlerMethodArgumentResolver(); |
||||
assertThat(resolver.supportsParameter(parameter)).isTrue(); |
||||
|
||||
try { |
||||
assertThat(resolver.resolveArgument(parameter, null, request, null)).isEqualTo(position); |
||||
} catch (Exception e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
|
||||
private static MethodParameter getParameterOfMethod(String name) { |
||||
return TestUtils.getParameterOfMethod(Controller.class, name, OffsetScrollPosition.class); |
||||
} |
||||
|
||||
private static NativeWebRequest getRequestWithOffset(@Nullable OffsetScrollPosition position, @Nullable String qualifier) { |
||||
|
||||
var request = new MockHttpServletRequest(); |
||||
|
||||
if (position == null) { |
||||
return new ServletWebRequest(request); |
||||
} |
||||
|
||||
String parameterName = StringUtils.hasLength(qualifier) ? qualifier + "_offset" : "offset"; |
||||
request.addParameter(parameterName, String.valueOf(position.getOffset())); |
||||
|
||||
return new ServletWebRequest(request); |
||||
} |
||||
|
||||
interface Controller { |
||||
|
||||
void supportedMethod(OffsetScrollPosition offset); |
||||
|
||||
void unsupportedMethod(String string); |
||||
|
||||
void qualifiedOffset(@Qualifier("qual") OffsetScrollPosition offset); |
||||
|
||||
void emptyQualifier(@Qualifier OffsetScrollPosition offset); |
||||
|
||||
void mergedQualifier(@TestQualifier OffsetScrollPosition offset); |
||||
} |
||||
} |
||||
@ -0,0 +1,176 @@
@@ -0,0 +1,176 @@
|
||||
/* |
||||
* Copyright 2017-2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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.springframework.data.web; |
||||
|
||||
import org.junit.jupiter.api.BeforeAll; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.springframework.beans.factory.annotation.Qualifier; |
||||
import org.springframework.core.MethodParameter; |
||||
import org.springframework.data.domain.OffsetScrollPosition; |
||||
import org.springframework.data.domain.ScrollPosition; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest; |
||||
import org.springframework.mock.web.server.MockServerWebExchange; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Unit tests for {@link ReactiveOffsetScrollPositionHandlerMethodArgumentResolver}. |
||||
* |
||||
* @since 3.2 |
||||
* @author Yanming Zhou |
||||
*/ |
||||
class ReactiveOffsetScrollPositionHandlerMethodArgumentResolverUnitTests { |
||||
|
||||
static MethodParameter PARAMETER; |
||||
|
||||
@BeforeAll |
||||
static void setUp() throws Exception { |
||||
PARAMETER = getParameterOfMethod("supportedMethod"); |
||||
} |
||||
|
||||
@Test |
||||
void supportsSortParameter() { |
||||
|
||||
var resolver = new ReactiveOffsetScrollPositionHandlerMethodArgumentResolver(); |
||||
|
||||
assertThat(resolver.supportsParameter(PARAMETER)).isTrue(); |
||||
} |
||||
|
||||
@Test |
||||
void fallbackToDefaultOffset() { |
||||
|
||||
var parameter = TestUtils.getParameterOfMethod(Controller.class, "unsupportedMethod", String.class); |
||||
var request = MockServerHttpRequest.get("/foo").build(); |
||||
var position = resolveOffset(request, parameter); |
||||
assertThat(position).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void discoversOffsetFromRequest() { |
||||
|
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, null), PARAMETER, reference); |
||||
} |
||||
|
||||
@Test |
||||
void discoversOffsetFromRequestWithMultipleParams() { |
||||
|
||||
var request = MockServerHttpRequest.get("/foo?offset=5&offset=6").build(); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset(5)); |
||||
} |
||||
|
||||
@Test |
||||
void discoversQualifiedOffsetFromRequest() { |
||||
|
||||
var parameter = getParameterOfMethod("qualifiedOffset"); |
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "qual"), parameter, reference); |
||||
} |
||||
|
||||
@Test |
||||
void returnsDefaultForOffsetParamSetToNothing() { |
||||
|
||||
var request = MockServerHttpRequest.get("/foo").build(); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void returnsDefaultForEmptyOffsetParam() { |
||||
|
||||
var request = MockServerHttpRequest.get("/foo?offset=").build(); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void returnsDefaultForOffsetParamIsInvalidProperty() { |
||||
|
||||
var request = MockServerHttpRequest.get("/foo?offset=invalid_number").build(); |
||||
|
||||
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset()); |
||||
} |
||||
|
||||
@Test |
||||
void emptyQualifierIsUsedInParameterLookup() { |
||||
|
||||
var parameter = getParameterOfMethod("emptyQualifier"); |
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, ""), parameter, reference); |
||||
} |
||||
|
||||
@Test |
||||
void mergedQualifierIsUsedInParameterLookup() { |
||||
|
||||
var parameter = getParameterOfMethod("mergedQualifier"); |
||||
var reference = ScrollPosition.offset(5); |
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "merged"), parameter, reference); |
||||
} |
||||
|
||||
private static OffsetScrollPosition resolveOffset(MockServerHttpRequest request, MethodParameter parameter) { |
||||
|
||||
var resolver = new ReactiveOffsetScrollPositionHandlerMethodArgumentResolver(); |
||||
return resolver.resolveArgumentValue(parameter, null, MockServerWebExchange.from(request)); |
||||
} |
||||
|
||||
private static void assertSupportedAndResolvedTo(MockServerHttpRequest request, MethodParameter parameter, OffsetScrollPosition position) { |
||||
|
||||
var resolver = new ReactiveOffsetScrollPositionHandlerMethodArgumentResolver(); |
||||
assertThat(resolver.supportsParameter(parameter)).isTrue(); |
||||
|
||||
try { |
||||
var resolved = resolveOffset(request, parameter); |
||||
assertThat(resolved).isEqualTo(position); |
||||
} catch (Exception e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
|
||||
private static MethodParameter getParameterOfMethod(String name) { |
||||
return TestUtils.getParameterOfMethod(Controller.class, name, OffsetScrollPosition.class); |
||||
} |
||||
|
||||
private static MockServerHttpRequest getRequestWithOffset(@Nullable OffsetScrollPosition position, @Nullable String qualifier) { |
||||
|
||||
if (position == null) { |
||||
return TestUtils.getWebfluxRequest(); |
||||
} |
||||
|
||||
String parameterName = StringUtils.hasLength(qualifier) ? qualifier + "_offset" : "offset"; |
||||
return MockServerHttpRequest.get(String.format("foo?%s=%s", parameterName, String.valueOf(position.getOffset()))).build(); |
||||
} |
||||
|
||||
interface Controller { |
||||
|
||||
void supportedMethod(OffsetScrollPosition offset); |
||||
|
||||
void unsupportedMethod(String string); |
||||
|
||||
void qualifiedOffset(@Qualifier("qual") OffsetScrollPosition offset); |
||||
|
||||
void emptyQualifier(@Qualifier OffsetScrollPosition offset); |
||||
|
||||
void mergedQualifier(@TestQualifier OffsetScrollPosition offset); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue