-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Improving applied directive & directive builders #3825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9f7eb53
b02e379
0c0aeca
677933f
39d451c
276cdea
1be0a4a
df2738b
91c9b74
12eaa86
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,41 +7,52 @@ | |
|
|
||
| import static graphql.Assert.assertNotNull; | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| @Internal | ||
| public abstract class GraphqlDirectivesContainerTypeBuilder<B extends GraphqlDirectivesContainerTypeBuilder<B, BASE>, BASE extends GraphqlTypeBuilder<BASE>> extends GraphqlTypeBuilder<BASE> { | ||
|
|
||
| protected final List<GraphQLAppliedDirective> appliedDirectives = new ArrayList<>(); | ||
| protected final List<GraphQLDirective> directives = new ArrayList<>(); | ||
|
|
||
|
|
||
| public B replaceAppliedDirectives(List<GraphQLAppliedDirective> directives) { | ||
| assertNotNull(directives, () -> "directive can't be null"); | ||
| this.appliedDirectives.clear(); | ||
| this.appliedDirectives.addAll(directives); | ||
| return (B) this; | ||
| } | ||
|
|
||
| /** | ||
| * @param directives the variable args of directives | ||
| * | ||
| * @return this builder | ||
| */ | ||
| public B withAppliedDirectives(GraphQLAppliedDirective... directives) { | ||
| assertNotNull(directives, () -> "directives can't be null"); | ||
| this.appliedDirectives.clear(); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing the unintended "clear" behaviour |
||
| for (GraphQLAppliedDirective directive : directives) { | ||
| withAppliedDirective(directive); | ||
| } | ||
| return (B) this; | ||
| } | ||
|
|
||
| /** | ||
| * @param directive the directive to add | ||
| * | ||
| * @return this builder | ||
| */ | ||
| public B withAppliedDirective(GraphQLAppliedDirective directive) { | ||
| assertNotNull(directive, () -> "directive can't be null"); | ||
| this.appliedDirectives.add(directive); | ||
| return (B) this; | ||
| } | ||
dondonz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * @param builder the directive builder | ||
| * | ||
| * @return this builder | ||
| */ | ||
| public B withAppliedDirective(GraphQLAppliedDirective.Builder builder) { | ||
| return withAppliedDirectives(builder.build()); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems to have been a typo |
||
| return withAppliedDirective(builder.build()); | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * @param directives the list of directives | ||
| * | ||
|
|
@@ -67,7 +78,6 @@ public B replaceDirectives(List<GraphQLDirective> directives) { | |
| @Deprecated(since = "2022-02-24") | ||
| public B withDirectives(GraphQLDirective... directives) { | ||
| assertNotNull(directives, () -> "directives can't be null"); | ||
| this.directives.clear(); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method is deprecated, but let's also remove the unintended clear line from here |
||
| for (GraphQLDirective directive : directives) { | ||
| withDirective(directive); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,6 @@ package graphql.execution | |
|
|
||
| import graphql.Directives | ||
| import graphql.ErrorType | ||
| import graphql.ExecutionInput | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not used |
||
| import graphql.GraphQLContext | ||
| import graphql.GraphQLException | ||
| import graphql.TestUtil | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,16 @@ | ||
| package graphql.schema.validation | ||
|
|
||
| import graphql.TestUtil | ||
| import graphql.schema.FieldCoordinates | ||
| import spock.lang.Specification | ||
|
|
||
| import static graphql.Scalars.GraphQLString | ||
| import static graphql.TestUtil.mkDirective | ||
| import static graphql.introspection.Introspection.DirectiveLocation.FIELD_DEFINITION | ||
| import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition | ||
| import static graphql.schema.GraphQLObjectType.newObject | ||
| import static graphql.schema.GraphQLSchema.newSchema | ||
|
|
||
| class AppliedDirectivesAreValidTest extends Specification { | ||
|
|
||
| def "non repeatable directives cannot be repeated"() { | ||
|
|
@@ -44,11 +52,72 @@ class AppliedDirectivesAreValidTest extends Specification { | |
| then: | ||
| def schemaProblem = thrown(InvalidSchemaException) | ||
| schemaProblem.getErrors().size() == 5 | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLFieldDefinition' called 'fieldC' is a non repeatable directive but has been applied 2 times"); | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLFieldDefinition' called 'fieldD' is a non repeatable directive but has been applied 2 times"); | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLFieldDefinition' called 'fieldA' is a non repeatable directive but has been applied 2 times"); | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLEnumValueDefinition' called 'enumA' is a non repeatable directive but has been applied 2 times"); | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLInputObjectField' called 'inputFieldA' is a non repeatable directive but has been applied 2 times"); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IDEA told me to delete the semi colons, I do what the computer says |
||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLFieldDefinition' called 'fieldC' is a non repeatable directive but has been applied 2 times") | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLFieldDefinition' called 'fieldD' is a non repeatable directive but has been applied 2 times") | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLFieldDefinition' called 'fieldA' is a non repeatable directive but has been applied 2 times") | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLEnumValueDefinition' called 'enumA' is a non repeatable directive but has been applied 2 times") | ||
| hasError(schemaProblem, "The directive 'directiveA' on the 'GraphQLInputObjectField' called 'inputFieldA' is a non repeatable directive but has been applied 2 times") | ||
| } | ||
|
|
||
| def "applied directive builders do not clear any existing applied directives"() { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A new test to lock in the new behaviour |
||
| given: | ||
| def directive1 = mkDirective("myDirectiveName1", FIELD_DEFINITION) | ||
| def directive2 = mkDirective("myDirectiveName2", FIELD_DEFINITION) | ||
| def field = newFieldDefinition() | ||
| .name("hello") | ||
| .type(GraphQLString) | ||
| .withAppliedDirectives(directive1.toAppliedDirective()) | ||
| .withAppliedDirectives(directive2.toAppliedDirective()) | ||
| .build() | ||
|
|
||
| when: | ||
| def schema = newSchema() | ||
| .query( | ||
| newObject() | ||
| .name("Query") | ||
| .field(field) | ||
| .build() | ||
| ) | ||
| .additionalDirective(directive1) | ||
| .additionalDirective(directive2) | ||
| .build() | ||
|
|
||
| then: | ||
| def fieldAppliedDirectives = schema.getFieldDefinition(FieldCoordinates.coordinates("Query", "hello")).getAppliedDirectives() | ||
| fieldAppliedDirectives.size() == 2 | ||
| fieldAppliedDirectives.any { it.name == "myDirectiveName1" } | ||
| fieldAppliedDirectives.any { it.name == "myDirectiveName2" } | ||
| } | ||
|
|
||
| def "replace applied directive builder does clear and replace existing applied directives"() { | ||
| given: | ||
| def directive1 = mkDirective("myDirectiveName1", FIELD_DEFINITION) | ||
| def directive2 = mkDirective("myDirectiveName2", FIELD_DEFINITION) | ||
| def field = newFieldDefinition() | ||
| .name("hello") | ||
| .type(GraphQLString) | ||
| .withAppliedDirective(directive1.toAppliedDirective()) | ||
| .replaceAppliedDirectives(List.of(directive2.toAppliedDirective())) | ||
| .build() | ||
|
|
||
| when: | ||
| def schema = newSchema() | ||
| .query( | ||
| newObject() | ||
| .name("Query") | ||
| .field(field) | ||
| .build() | ||
| ) | ||
| .additionalDirective(directive1) | ||
| .additionalDirective(directive2) | ||
| .build() | ||
|
|
||
| then: | ||
| // As prior applied directives are cleared, there is only 1 applied directive left on the field (directive container) | ||
| def fieldAppliedDirectives = schema.getFieldDefinition(FieldCoordinates.coordinates("Query", "hello")).getAppliedDirectives() | ||
| fieldAppliedDirectives.size() == 1 | ||
| fieldAppliedDirectives.find { it.name == "myDirectiveName1" } == null | ||
| fieldAppliedDirectives.any { it.name == "myDirectiveName2" } | ||
| } | ||
|
|
||
| static boolean hasError(InvalidSchemaException schemaException, String msg) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDEA told me it's no longer needed, I do what the computer says