Merge branch '1.0.x'

This commit is contained in:
rstoyanchev
2022-10-17 17:44:19 +01:00
4 changed files with 126 additions and 16 deletions

View File

@@ -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;
}

View File

@@ -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>() {})

View File

@@ -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){

View File

@@ -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();
}
}