Skip to content

Commit ea8fed8

Browse files
committed
Merge branch '1.0.x'
2 parents 30b1689 + 13683ee commit ea8fed8

File tree

4 files changed

+126
-16
lines changed

4 files changed

+126
-16
lines changed

spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/DefaultGraphQlTester.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,8 @@ private DefaultEntityList(List<E> entity, String path, ResponseDelegate delegate
540540
public EntityList<E> contains(E... values) {
541541
doAssert(() -> {
542542
List<E> expected = Arrays.asList(values);
543-
AssertionErrors.assertTrue("List at path '" + getPath() + "' does not contain " + expected,
543+
AssertionErrors.assertTrue(
544+
"Expecting list " + getEntity() + " at path '" + getPath() + "' to contain " + expected,
544545
getEntity().containsAll(expected));
545546
});
546547
return this;
@@ -552,7 +553,7 @@ public EntityList<E> doesNotContain(E... values) {
552553
doAssert(() -> {
553554
List<E> expected = Arrays.asList(values);
554555
AssertionErrors.assertTrue(
555-
"List at path '" + getPath() + "' should not have contained " + expected,
556+
"Expecting list " + getEntity() + " at path '" + getPath() + "' to not contain " + expected,
556557
!getEntity().containsAll(expected));
557558
});
558559
return this;
@@ -564,31 +565,32 @@ public EntityList<E> containsExactly(E... values) {
564565
doAssert(() -> {
565566
List<E> expected = Arrays.asList(values);
566567
AssertionErrors.assertTrue(
567-
"List at path '" + getPath() + "' should have contained exactly " + expected,
568+
"Expecting list " + getEntity() + " at path '" + getPath() + "' to contain exactly " + expected,
568569
getEntity().equals(expected));
569570
});
570571
return this;
571572
}
572573

573574
@Override
574575
public EntityList<E> hasSize(int size) {
575-
doAssert(() -> AssertionErrors.assertTrue("List at path '" + getPath() + "' should have size " + size,
576+
doAssert(() -> AssertionErrors.assertTrue(
577+
"Expecting list " + getEntity() + " at path '" + getPath() + "' to have size == " + size,
576578
getEntity().size() == size));
577579
return this;
578580
}
579581

580582
@Override
581583
public EntityList<E> hasSizeLessThan(int size) {
582584
doAssert(() -> AssertionErrors.assertTrue(
583-
"List at path '" + getPath() + "' should have size less than " + size,
585+
"Expecting list " + getEntity() + " at path '" + getPath() + "' to have size < " + size,
584586
getEntity().size() < size));
585587
return this;
586588
}
587589

588590
@Override
589591
public EntityList<E> hasSizeGreaterThan(int size) {
590592
doAssert(() -> AssertionErrors.assertTrue(
591-
"List at path '" + getPath() + "' should have size greater than " + size,
593+
"Expecting list " + getEntity() + " at path '" + getPath() + "' to have size > " + size,
592594
getEntity().size() > size));
593595
return this;
594596
}

spring-graphql-test/src/test/java/org/springframework/graphql/test/tester/GraphQlTesterTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,11 @@ void entityList() {
179179

180180
assertThatThrownBy(() -> entityList.containsExactly(leia, han))
181181
.as("Should be exactly the same order")
182-
.hasMessageStartingWith("List at path 'me.friends' should have contained exactly");
182+
.hasMessage("Expecting list " +
183+
"[MovieCharacter[name='Han Solo'], MovieCharacter[name='Leia Organa']] " +
184+
"at path 'me.friends' to contain exactly " +
185+
"[MovieCharacter[name='Leia Organa'], MovieCharacter[name='Han Solo']]\n" +
186+
"Request: document='{me {name, friends}}'");
183187

184188
response.path("me.friends")
185189
.entityList(new ParameterizedTypeReference<MovieCharacter>() {})

spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/ProjectedPayloadMethodArgumentResolver.java

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616
package org.springframework.graphql.data.method.annotation.support;
1717

1818

19+
import java.util.Optional;
20+
1921
import graphql.schema.DataFetchingEnvironment;
2022

2123
import org.springframework.context.ApplicationContext;
@@ -77,24 +79,33 @@ public ProjectedPayloadMethodArgumentResolver(ApplicationContext applicationCont
7779

7880
@Override
7981
public boolean supportsParameter(MethodParameter parameter) {
80-
Class<?> type = parameter.getParameterType();
81-
82-
if (!type.isInterface()) {
83-
return false;
84-
}
85-
86-
return AnnotatedElementUtils.findMergedAnnotation(type, ProjectedPayload.class) != null;
82+
Class<?> type = parameter.nestedIfOptional().getNestedParameterType();
83+
return (type.isInterface() &&
84+
AnnotatedElementUtils.findMergedAnnotation(type, ProjectedPayload.class) != null);
8785
}
8886

8987
@Override
9088
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception {
89+
9190
String name = (parameter.hasParameterAnnotation(Argument.class) ?
9291
ArgumentMethodArgumentResolver.getArgumentName(parameter) : null);
9392

93+
Class<?> projectionType = parameter.getParameterType();
94+
95+
boolean isOptional = parameter.isOptional();
96+
if (isOptional) {
97+
projectionType = parameter.nestedIfOptional().getNestedParameterType();
98+
}
99+
94100
Object projectionSource = (name != null ?
95101
environment.getArgument(name) : environment.getArguments());
96102

97-
return project(parameter.getParameterType(), projectionSource);
103+
Object value = null;
104+
if (!isOptional || projectionSource != null) {
105+
value = project(projectionType, projectionSource);
106+
}
107+
108+
return (isOptional ? Optional.ofNullable(value) : value);
98109
}
99110

100111
protected Object project(Class<?> projectionType, Object projectionSource){
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2020-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.graphql.data.method.annotation.support;
17+
18+
import java.util.List;
19+
import java.util.Optional;
20+
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
24+
import org.springframework.context.support.StaticApplicationContext;
25+
import org.springframework.core.MethodParameter;
26+
import org.springframework.data.web.ProjectedPayload;
27+
import org.springframework.graphql.Book;
28+
import org.springframework.graphql.data.method.annotation.Argument;
29+
import org.springframework.graphql.data.method.annotation.QueryMapping;
30+
import org.springframework.stereotype.Controller;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
/**
35+
*
36+
*/
37+
public class ProjectedPayloadMethodArgumentResolverTests extends ArgumentResolverTestSupport {
38+
39+
private ProjectedPayloadMethodArgumentResolver resolver;
40+
41+
42+
@BeforeEach
43+
void setUp() {
44+
StaticApplicationContext context = new StaticApplicationContext();
45+
this.resolver = new ProjectedPayloadMethodArgumentResolver(context);
46+
}
47+
48+
49+
@Test
50+
void supports() {
51+
MethodParameter param = methodParam(BookController.class, "optionalProjection", Optional.class);
52+
assertThat(this.resolver.supportsParameter(param)).isTrue();
53+
54+
param = methodParam(BookController.class, "optionalString", Optional.class);
55+
assertThat(this.resolver.supportsParameter(param)).isFalse();
56+
}
57+
58+
@Test
59+
void optionalWrapper() throws Exception {
60+
61+
Object result = this.resolver.resolveArgument(
62+
methodParam(BookController.class, "optionalProjection", Optional.class),
63+
environment("{}"));
64+
65+
assertThat(result).isNotNull().isInstanceOf(Optional.class);
66+
assertThat((Optional<?>) result).isNotPresent();
67+
}
68+
69+
70+
@SuppressWarnings({"ConstantConditions", "unused"})
71+
@Controller
72+
static class BookController {
73+
74+
@QueryMapping
75+
public List<Book> optionalProjection(@Argument(name = "where") Optional<BookProjection> projection) {
76+
return null;
77+
}
78+
79+
@QueryMapping
80+
public void optionalString(@Argument Optional<String> projection) {
81+
}
82+
83+
}
84+
85+
86+
@ProjectedPayload
87+
interface BookProjection {
88+
89+
String getAuthor();
90+
91+
}
92+
93+
}

0 commit comments

Comments
 (0)