Skip to content

Commit 14cc288

Browse files
committed
Implement KnownDirectives validation rule
1 parent 3bd04e7 commit 14cc288

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

graphql/core/validation/rules.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,42 @@ class NoUnusedVariables(ValidationRule):
176176

177177

178178
class KnownDirectives(ValidationRule):
179-
pass
179+
def enter_Directive(self, node, key, parent, path, ancestors):
180+
directive_def = None
181+
for definition in self.context.get_schema().get_directives():
182+
if definition.name == node.name.value:
183+
directive_def = definition
184+
break
185+
if not directive_def:
186+
return GraphQLError(
187+
self.message(node.name.value),
188+
[node]
189+
)
190+
applied_to = ancestors[-1]
191+
if isinstance(applied_to, ast.OperationDefinition) and not directive_def.on_operation:
192+
return GraphQLError(
193+
self.misplaced_directive_message(node.name.value, 'operation'),
194+
[node]
195+
)
196+
if isinstance(applied_to, ast.Field) and not directive_def.on_field:
197+
return GraphQLError(
198+
self.misplaced_directive_message(node.name.value, 'field'),
199+
[node]
200+
)
201+
if (isinstance(applied_to, (ast.FragmentSpread, ast.InlineFragment, ast.FragmentDefinition)) and
202+
not directive_def.on_fragment):
203+
return GraphQLError(
204+
self.misplaced_directive_message(node.name.value, 'fragment'),
205+
[node]
206+
)
207+
208+
@staticmethod
209+
def message(directive_name):
210+
return 'Unknown directive "{}".'.format(directive_name)
211+
212+
@staticmethod
213+
def misplaced_directive_message(directive_name, placement):
214+
return 'Directive "{}" may not be used on "{}".'.format(directive_name, placement)
180215

181216

182217
class KnownArgumentNames(ValidationRule):

tests/core_validation/test_known_directives.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import pytest
2-
31
from graphql.core.language.location import SourceLocation
42
from graphql.core.validation.rules import KnownDirectives
53
from utils import expect_passes_rule, expect_fails_rule
@@ -46,9 +44,6 @@ def test_with_known_directives():
4644
''')
4745

4846

49-
@pytest.mark.skipif(not hasattr(KnownDirectives, "message"),
50-
reason=("KnownDirectives.message has not yet been "
51-
"implemented"))
5247
def test_with_unknown_directive():
5348
expect_fails_rule(KnownDirectives, '''
5449
{
@@ -59,9 +54,6 @@ def test_with_unknown_directive():
5954
''', [unknown_directive('unknown', 3, 13)])
6055

6156

62-
@pytest.mark.skipif(not hasattr(KnownDirectives, "message"),
63-
reason=("KnownDirectives.message has not yet been "
64-
"implemented"))
6557
def test_with_many_unknown_directives():
6658
expect_fails_rule(KnownDirectives, '''
6759
{
@@ -91,10 +83,6 @@ def test_with_well_placed_directives():
9183
''')
9284

9385

94-
@pytest.mark.skipif(not hasattr(KnownDirectives,
95-
"misplaced_directive_message"),
96-
reason=("KnownDirectives.misplaced_directive_message has "
97-
"not yet been implemented"))
9886
def test_with_misplaced_directives():
9987
expect_fails_rule(KnownDirectives, '''
10088
query Foo @include(if: true) {

0 commit comments

Comments
 (0)