Merge branch '1.0.x'
This commit is contained in:
@@ -540,7 +540,8 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
public EntityList<E> contains(E... values) {
|
||||
doAssert(() -> {
|
||||
List<E> expected = Arrays.asList(values);
|
||||
AssertionErrors.assertTrue("List at path '" + getPath() + "' does not contain " + expected,
|
||||
AssertionErrors.assertTrue(
|
||||
"Expecting list " + getEntity() + " at path '" + getPath() + "' to contain " + expected,
|
||||
getEntity().containsAll(expected));
|
||||
});
|
||||
return this;
|
||||
@@ -552,7 +553,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
doAssert(() -> {
|
||||
List<E> expected = Arrays.asList(values);
|
||||
AssertionErrors.assertTrue(
|
||||
"List at path '" + getPath() + "' should not have contained " + expected,
|
||||
"Expecting list " + getEntity() + " at path '" + getPath() + "' to not contain " + expected,
|
||||
!getEntity().containsAll(expected));
|
||||
});
|
||||
return this;
|
||||
@@ -564,7 +565,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
doAssert(() -> {
|
||||
List<E> expected = Arrays.asList(values);
|
||||
AssertionErrors.assertTrue(
|
||||
"List at path '" + getPath() + "' should have contained exactly " + expected,
|
||||
"Expecting list " + getEntity() + " at path '" + getPath() + "' to contain exactly " + expected,
|
||||
getEntity().equals(expected));
|
||||
});
|
||||
return this;
|
||||
@@ -572,7 +573,8 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
|
||||
@Override
|
||||
public EntityList<E> hasSize(int size) {
|
||||
doAssert(() -> AssertionErrors.assertTrue("List at path '" + getPath() + "' should have size " + size,
|
||||
doAssert(() -> AssertionErrors.assertTrue(
|
||||
"Expecting list " + getEntity() + " at path '" + getPath() + "' to have size == " + size,
|
||||
getEntity().size() == size));
|
||||
return this;
|
||||
}
|
||||
@@ -580,7 +582,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
@Override
|
||||
public EntityList<E> hasSizeLessThan(int size) {
|
||||
doAssert(() -> AssertionErrors.assertTrue(
|
||||
"List at path '" + getPath() + "' should have size less than " + size,
|
||||
"Expecting list " + getEntity() + " at path '" + getPath() + "' to have size < " + size,
|
||||
getEntity().size() < size));
|
||||
return this;
|
||||
}
|
||||
@@ -588,7 +590,7 @@ final class DefaultGraphQlTester implements GraphQlTester {
|
||||
@Override
|
||||
public EntityList<E> hasSizeGreaterThan(int size) {
|
||||
doAssert(() -> AssertionErrors.assertTrue(
|
||||
"List at path '" + getPath() + "' should have size greater than " + size,
|
||||
"Expecting list " + getEntity() + " at path '" + getPath() + "' to have size > " + size,
|
||||
getEntity().size() > size));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,11 @@ public class GraphQlTesterTests extends GraphQlTesterTestSupport {
|
||||
|
||||
assertThatThrownBy(() -> entityList.containsExactly(leia, han))
|
||||
.as("Should be exactly the same order")
|
||||
.hasMessageStartingWith("List at path 'me.friends' should have contained exactly");
|
||||
.hasMessage("Expecting list " +
|
||||
"[MovieCharacter[name='Han Solo'], MovieCharacter[name='Leia Organa']] " +
|
||||
"at path 'me.friends' to contain exactly " +
|
||||
"[MovieCharacter[name='Leia Organa'], MovieCharacter[name='Han Solo']]\n" +
|
||||
"Request: document='{me {name, friends}}'");
|
||||
|
||||
response.path("me.friends")
|
||||
.entityList(new ParameterizedTypeReference<MovieCharacter>() {})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -16,6 +16,8 @@
|
||||
package org.springframework.graphql.data.method.annotation.support;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -77,24 +79,33 @@ public class ProjectedPayloadMethodArgumentResolver implements HandlerMethodArgu
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
Class<?> type = parameter.getParameterType();
|
||||
|
||||
if (!type.isInterface()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return AnnotatedElementUtils.findMergedAnnotation(type, ProjectedPayload.class) != null;
|
||||
Class<?> type = parameter.nestedIfOptional().getNestedParameterType();
|
||||
return (type.isInterface() &&
|
||||
AnnotatedElementUtils.findMergedAnnotation(type, ProjectedPayload.class) != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
|
||||
|
||||
String name = (parameter.hasParameterAnnotation(Argument.class) ?
|
||||
ArgumentMethodArgumentResolver.getArgumentName(parameter) : null);
|
||||
|
||||
Class<?> projectionType = parameter.getParameterType();
|
||||
|
||||
boolean isOptional = parameter.isOptional();
|
||||
if (isOptional) {
|
||||
projectionType = parameter.nestedIfOptional().getNestedParameterType();
|
||||
}
|
||||
|
||||
Object projectionSource = (name != null ?
|
||||
environment.getArgument(name) : environment.getArguments());
|
||||
|
||||
return project(parameter.getParameterType(), projectionSource);
|
||||
Object value = null;
|
||||
if (!isOptional || projectionSource != null) {
|
||||
value = project(projectionType, projectionSource);
|
||||
}
|
||||
|
||||
return (isOptional ? Optional.ofNullable(value) : value);
|
||||
}
|
||||
|
||||
protected Object project(Class<?> projectionType, Object projectionSource){
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2020-2022 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.graphql.data.method.annotation.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.web.ProjectedPayload;
|
||||
import org.springframework.graphql.Book;
|
||||
import org.springframework.graphql.data.method.annotation.Argument;
|
||||
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ProjectedPayloadMethodArgumentResolverTests extends ArgumentResolverTestSupport {
|
||||
|
||||
private ProjectedPayloadMethodArgumentResolver resolver;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
this.resolver = new ProjectedPayloadMethodArgumentResolver(context);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void supports() {
|
||||
MethodParameter param = methodParam(BookController.class, "optionalProjection", Optional.class);
|
||||
assertThat(this.resolver.supportsParameter(param)).isTrue();
|
||||
|
||||
param = methodParam(BookController.class, "optionalString", Optional.class);
|
||||
assertThat(this.resolver.supportsParameter(param)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void optionalWrapper() throws Exception {
|
||||
|
||||
Object result = this.resolver.resolveArgument(
|
||||
methodParam(BookController.class, "optionalProjection", Optional.class),
|
||||
environment("{}"));
|
||||
|
||||
assertThat(result).isNotNull().isInstanceOf(Optional.class);
|
||||
assertThat((Optional<?>) result).isNotPresent();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"ConstantConditions", "unused"})
|
||||
@Controller
|
||||
static class BookController {
|
||||
|
||||
@QueryMapping
|
||||
public List<Book> optionalProjection(@Argument(name = "where") Optional<BookProjection> projection) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@QueryMapping
|
||||
public void optionalString(@Argument Optional<String> projection) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ProjectedPayload
|
||||
interface BookProjection {
|
||||
|
||||
String getAuthor();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user