Skip to content

Commit d5eaddb

Browse files
committed
add tests for annotation definition
1 parent edeb801 commit d5eaddb

File tree

4 files changed

+262
-35
lines changed

4 files changed

+262
-35
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,8 @@ public String name() {
572572
We now wired the field "name" - so it will turn upper case when calling the field.
573573
The ``Directive`` annotations requires the name of the directive, the wiring class (the ``UpperWiring`` class defined earlier), and the values of the arguments. If an argument has a default value, you don't have to supply a value in the arguments values.
574574

575+
Notice that in any way, the directives are sequential, so the first annotated directive will happen before the second one.
576+
575577
## Relay support
576578

577579
### Mutations

src/main/java/graphql/annotations/processor/retrievers/fieldBuilders/DirectivesBuilder.java

+3
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
*/
1515
package graphql.annotations.processor.retrievers.fieldBuilders;
1616

17+
import com.sun.deploy.util.ReflectionUtil;
1718
import graphql.annotations.annotationTypes.directives.activation.GraphQLDirectives;
1819
import graphql.annotations.processor.ProcessingElementsContainer;
1920
import graphql.annotations.processor.exceptions.GraphQLAnnotationsException;
2021
import graphql.annotations.processor.util.DirectiveJavaAnnotationUtil;
2122
import graphql.schema.GraphQLArgument;
2223
import graphql.schema.GraphQLDirective;
2324
import graphql.schema.GraphQLScalarType;
25+
import javafx.scene.effect.Reflection;
2426

2527
import java.lang.annotation.Annotation;
2628
import java.lang.reflect.AnnotatedElement;
@@ -92,6 +94,7 @@ private void transformArgument(Annotation annotation, GraphQLDirective.Builder d
9294
directiveBuilder.argument(graphQLArgument.transform(builder -> {
9395
if (graphQLArgument.getType() instanceof GraphQLScalarType) {
9496
try {
97+
methods[finalI].setAccessible(true);
9598
Object argumentValue = methods[finalI].invoke(annotation);
9699
Object value = ((GraphQLScalarType) graphQLArgument.getType()).getCoercing().parseValue(argumentValue);
97100
builder.value(value);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
package graphql.annotations;
2+
3+
import graphql.ExecutionResult;
4+
import graphql.GraphQL;
5+
import graphql.annotations.annotationTypes.GraphQLDataFetcher;
6+
import graphql.annotations.annotationTypes.GraphQLField;
7+
import graphql.annotations.annotationTypes.GraphQLName;
8+
import graphql.annotations.annotationTypes.directives.activation.Directive;
9+
import graphql.annotations.annotationTypes.directives.activation.GraphQLDirectives;
10+
import graphql.annotations.annotationTypes.directives.definition.DirectiveLocations;
11+
import graphql.annotations.annotationTypes.directives.definition.GraphQLDirectiveDefinition;
12+
import graphql.annotations.directives.AnnotationsDirectiveWiring;
13+
import graphql.annotations.directives.AnnotationsWiringEnvironment;
14+
import graphql.annotations.processor.GraphQLAnnotations;
15+
import graphql.annotations.processor.util.CodeRegistryUtil;
16+
import graphql.introspection.Introspection;
17+
import graphql.schema.*;
18+
import org.testng.annotations.BeforeMethod;
19+
import org.testng.annotations.Test;
20+
21+
import java.lang.annotation.ElementType;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
25+
import java.util.Map;
26+
27+
import static graphql.schema.GraphQLSchema.newSchema;
28+
import static org.testng.Assert.assertEquals;
29+
import static org.testng.Assert.assertNotNull;
30+
import static org.testng.Assert.assertTrue;
31+
32+
public class GraphQLDirectivesViaAnnotationDefinitionTest {
33+
private GraphQLAnnotations graphQLAnnotations;
34+
private GraphQLSchema schema;
35+
36+
@BeforeMethod
37+
public void setUp() {
38+
this.graphQLAnnotations = new GraphQLAnnotations();
39+
this.graphQLAnnotations.directiveViaAnnotation(Upper.class);
40+
this.graphQLAnnotations.directiveViaAnnotation(Suffix.class);
41+
GraphQLObjectType object = this.graphQLAnnotations.object(Query.class);
42+
GraphQLCodeRegistry codeRegistry = graphQLAnnotations.getContainer().getCodeRegistryBuilder().build();
43+
this.schema = newSchema().query(object).codeRegistry(codeRegistry).build();
44+
45+
46+
}
47+
48+
/**
49+
* Definitions
50+
*/
51+
52+
public static class UpperWiring implements AnnotationsDirectiveWiring {
53+
@Override
54+
public GraphQLFieldDefinition onField(AnnotationsWiringEnvironment environment) {
55+
GraphQLFieldDefinition field = (GraphQLFieldDefinition) environment.getElement();
56+
boolean isActive = (boolean) environment.getDirective().getArgument("isActive").getValue();
57+
CodeRegistryUtil.wrapDataFetcher(field, environment, (((dataFetchingEnvironment, value) -> {
58+
if (value instanceof String && isActive) {
59+
return ((String) value).toUpperCase();
60+
}
61+
return value;
62+
})));
63+
64+
return field;
65+
}
66+
}
67+
68+
public static class SuffixWiring implements AnnotationsDirectiveWiring {
69+
@Override
70+
public GraphQLInputObjectField onInputObjectField(AnnotationsWiringEnvironment environment) {
71+
GraphQLInputObjectField field = (GraphQLInputObjectField) environment.getElement();
72+
boolean isActive = (boolean) environment.getDirective().getArgument("isActive").getValue();
73+
if (!isActive) return field;
74+
String suffix = (String) environment.getDirective().getArgument("suffix").getValue();
75+
return field.transform(builder -> builder.name(field.getName() + suffix));
76+
}
77+
78+
@Override
79+
public GraphQLFieldDefinition onField(AnnotationsWiringEnvironment environment) {
80+
GraphQLFieldDefinition field = (GraphQLFieldDefinition) environment.getElement();
81+
String suffix = (String) environment.getDirective().getArgument("suffix").getValue();
82+
boolean isActive = (boolean) environment.getDirective().getArgument("isActive").getValue();
83+
if (!isActive) return field;
84+
CodeRegistryUtil.wrapDataFetcher(field, environment, (dataFetchingEnvironment, value) -> {
85+
if (value instanceof String) {
86+
return value + suffix;
87+
}
88+
return value;
89+
});
90+
91+
return field;
92+
}
93+
94+
@Override
95+
public GraphQLArgument onArgument(AnnotationsWiringEnvironment environment) {
96+
GraphQLArgument element = (GraphQLArgument) environment.getElement();
97+
String suffix = (String) environment.getDirective().getArgument("suffix").getValue();
98+
boolean isActive = (boolean) environment.getDirective().getArgument("isActive").getValue();
99+
if (!isActive) return element;
100+
return element.transform(builder -> builder.name(element.getName() + suffix));
101+
}
102+
103+
@Override
104+
public GraphQLInputObjectType onInputObjectType(AnnotationsWiringEnvironment environment) {
105+
GraphQLInputObjectType element = (GraphQLInputObjectType) environment.getElement();
106+
boolean isActive = (boolean) environment.getDirective().getArgument("isActive").getValue();
107+
if (!isActive) return element;
108+
String suffix = (String) environment.getDirective().getArgument("suffix").getValue();
109+
return element;
110+
}
111+
}
112+
113+
114+
@GraphQLDirectiveDefinition(wiring = UpperWiring.class)
115+
@GraphQLName("upper")
116+
@Target(ElementType.METHOD)
117+
@Retention(RetentionPolicy.RUNTIME)
118+
@DirectiveLocations(Introspection.DirectiveLocation.FIELD_DEFINITION)
119+
@interface Upper{
120+
boolean isActive() default true;
121+
}
122+
123+
@GraphQLDirectiveDefinition(wiring = SuffixWiring.class)
124+
@GraphQLName("suffix")
125+
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.METHOD})
126+
@Retention(RetentionPolicy.RUNTIME)
127+
@DirectiveLocations({Introspection.DirectiveLocation.FIELD_DEFINITION, Introspection.DirectiveLocation.ARGUMENT_DEFINITION, Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION})
128+
@interface Suffix{
129+
@GraphQLName("suffix")
130+
String suffixToAdd();
131+
boolean isActive();
132+
}
133+
134+
public static class Query{
135+
@GraphQLField
136+
@Upper
137+
public static String goodAnnotatedNameWithDefaultValue(){return "yarin";}
138+
139+
@GraphQLField
140+
@Upper(isActive = true)
141+
public static String goodAnnotatedNameWithTrueValue(){return "yarin";}
142+
143+
@GraphQLField
144+
@Upper(isActive = false)
145+
public static String goodAnnotatedNameWithFalseValue(){return "yarin";}
146+
147+
@GraphQLField
148+
@Suffix(isActive = true, suffixToAdd = " is cool")
149+
public static String goodAnnotatedNameWithUnOrderedValues() {return "yarin";}
150+
151+
@GraphQLField
152+
@GraphQLDataFetcher(NameWithArgument.class)
153+
public static String nameWithArgument(@Suffix(isActive = true, suffixToAdd = "x") @GraphQLName("extensionArg") String extensionArg) {
154+
return "yarin" + extensionArg;
155+
}
156+
157+
@GraphQLField
158+
public static String nameWithInputObject(@GraphQLName("inputObject") InputObject input) {
159+
return "yarin";
160+
}
161+
162+
@GraphQLField
163+
@Upper
164+
@Suffix(isActive = true, suffixToAdd = " is cool")
165+
public static String nameWithMultipleDirectives(){
166+
return "yarin";
167+
}
168+
169+
170+
public static class NameWithArgument implements DataFetcher {
171+
@Override
172+
public Object get(DataFetchingEnvironment environment) throws Exception {
173+
String value = environment.getArgument("extensionArgx");
174+
return "yarin"+value;
175+
}
176+
}
177+
178+
public static class InputObject {
179+
@GraphQLField
180+
@Suffix(isActive = true, suffixToAdd = "coolSuffix")
181+
private String a;
182+
183+
@GraphQLField
184+
private int b;
185+
186+
public InputObject(@GraphQLName("a") String a, @GraphQLName("b") int b) {
187+
this.a = a;
188+
this.b = b;
189+
}
190+
}
191+
192+
}
193+
194+
@Test
195+
public void usingAnnotationDirective_goodAnnotatedFieldWithDefaultValue_wiringHappens() {
196+
// Act
197+
ExecutionResult result = GraphQL.newGraphQL(schema).build().execute("query { goodAnnotatedNameWithDefaultValue }");
198+
199+
// Assert
200+
assertTrue(result.getErrors().isEmpty());
201+
assertEquals(((Map<String, String>) result.getData()).get("goodAnnotatedNameWithDefaultValue").toString(), "YARIN");
202+
}
203+
204+
@Test
205+
public void usingAnnotationDirective_goodAnnotatedFieldWithCustomValue_wiringHappens() {
206+
// Act
207+
ExecutionResult result1 = GraphQL.newGraphQL(schema).build().execute("query { goodAnnotatedNameWithTrueValue }");
208+
ExecutionResult result2 = GraphQL.newGraphQL(schema).build().execute("query { goodAnnotatedNameWithFalseValue }");
209+
210+
// Assert
211+
assertTrue(result1.getErrors().isEmpty());
212+
assertEquals(((Map<String, String>) result1.getData()).get("goodAnnotatedNameWithTrueValue").toString(), "YARIN");
213+
assertTrue(result2.getErrors().isEmpty());
214+
assertEquals(((Map<String, String>) result2.getData()).get("goodAnnotatedNameWithFalseValue").toString(), "yarin");
215+
}
216+
217+
@Test
218+
public void usingAnnotationDirective_goodAnnotatedFieldWithUnOrderedValues_wiringHappens() {
219+
// Act
220+
ExecutionResult result1 = GraphQL.newGraphQL(schema).build().execute("query { goodAnnotatedNameWithUnOrderedValues }");
221+
222+
// Assert
223+
assertTrue(result1.getErrors().isEmpty());
224+
assertEquals(((Map<String, String>) result1.getData()).get("goodAnnotatedNameWithUnOrderedValues").toString(), "yarin is cool");
225+
}
226+
227+
@Test
228+
public void usingAnnotationDirective_annotatedParam_wiringHappens(){
229+
// Act
230+
ExecutionResult result1 = GraphQL.newGraphQL(schema).build().execute("query { nameWithArgument(extensionArgx: \" is cool\") }");
231+
232+
// Assert
233+
assertTrue(result1.getErrors().isEmpty());
234+
assertEquals(((Map<String, String>) result1.getData()).get("nameWithArgument").toString(), "yarin is cool");
235+
}
236+
237+
@Test
238+
public void usingAnnotationDirective_inputObject_wiringHappens(){
239+
// Act
240+
GraphQLFieldDefinition nameWithInputObject = schema.getQueryType().getFieldDefinition("nameWithInputObject");
241+
GraphQLInputObjectField field = ((GraphQLInputObjectType) nameWithInputObject.getArgument("inputObject").getType()).getField("acoolSuffix");
242+
// Assert
243+
assertNotNull(field);
244+
}
245+
246+
@Test
247+
public void usingAnnotationDirective_multipleDirectivesOnField_wiringHappensInOrder(){
248+
// Act
249+
ExecutionResult result1 = GraphQL.newGraphQL(schema).build().execute("query { nameWithMultipleDirectives }");
250+
251+
// Assert
252+
assertTrue(result1.getErrors().isEmpty());
253+
assertEquals(((Map<String, String>) result1.getData()).get("nameWithMultipleDirectives").toString(), "YARIN is cool");
254+
}
255+
256+
}

src/test/java/graphql/annotations/GraphQLDirectivesTest.java renamed to src/test/java/graphql/annotations/GraphQLDirectivesViaClassDefinitionTest.java

+1-35
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import static graphql.schema.GraphQLSchema.newSchema;
4646
import static org.testng.Assert.*;
4747

48-
public class GraphQLDirectivesTest {
48+
public class GraphQLDirectivesViaClassDefinitionTest {
4949

5050
private GraphQLAnnotations graphQLAnnotations;
5151

@@ -185,40 +185,6 @@ public static String name() {
185185
}
186186

187187

188-
@Target({ElementType.TYPE, ElementType.METHOD})
189-
@Retention(RetentionPolicy.RUNTIME)
190-
@GraphQLDirectiveDefinition(wiring = UpperWiring.class)
191-
@DirectiveLocations(Introspection.DirectiveLocation.FIELD_DEFINITION)
192-
@GraphQLName("upper")
193-
public @interface ToUpperCase{
194-
boolean isActive() default true;
195-
}
196-
197-
198-
public static class QueryAnnotation {
199-
@GraphQLField
200-
@ToUpperCase
201-
public static String name() {
202-
return "yarin";
203-
}
204-
}
205-
206-
207-
@Test
208-
public void queryName_javaAnnotationDirective_wiringIsActivated() throws Exception {
209-
this.graphQLAnnotations.directiveViaAnnotation(ToUpperCase.class);
210-
GraphQLObjectType object = this.graphQLAnnotations.object(QueryAnnotation.class);
211-
GraphQLCodeRegistry codeRegistry = graphQLAnnotations.getContainer().getCodeRegistryBuilder().build();
212-
213-
GraphQLSchema schema = newSchema().query(object).codeRegistry(codeRegistry).build();
214-
215-
ExecutionResult result = GraphQL.newGraphQL(schema).build().execute("query { name }");
216-
assertTrue(result.getErrors().isEmpty());
217-
assertEquals(((Map<String, String>) result.getData()).get("name").toString(), "YARIN");
218-
}
219-
220-
221-
222188
@Test
223189
public void queryName_directivesInAlternativeWayCreation_wiringIsActivated() throws Exception {
224190
this.graphQLAnnotations.directives(QueryAlternative.class);

0 commit comments

Comments
 (0)