Skip to content

Commit 0bf272a

Browse files
committed
Implement KnownArgumentNames validation rule
1 parent be0b950 commit 0bf272a

File tree

3 files changed

+42
-16
lines changed

3 files changed

+42
-16
lines changed

graphql/core/validation/rules.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from ..utils import type_from_ast
22
from ..error import GraphQLError
33
from ..type.definition import is_composite_type, is_input_type, is_leaf_type
4-
from ..language.ast import OperationDefinition
4+
from ..language import ast
55
from ..language.visitor import Visitor
66
from ..language.printer import print_ast
77

@@ -39,7 +39,7 @@ def __init__(self, context):
3939
def enter_Document(self, node, *args):
4040
n = 0
4141
for definition in node.definitions:
42-
if isinstance(definition, OperationDefinition):
42+
if isinstance(definition, ast.OperationDefinition):
4343
n += 1
4444
self._op_count = n
4545

@@ -180,7 +180,44 @@ class KnownDirectives(ValidationRule):
180180

181181

182182
class KnownArgumentNames(ValidationRule):
183-
pass
183+
def enter_Argument(self, node, key, parent, path, ancestors):
184+
argument_of = ancestors[-1]
185+
if isinstance(argument_of, ast.Field):
186+
field_def = self.context.get_field_def()
187+
if field_def:
188+
field_arg_def = None
189+
for arg in field_def.args:
190+
if arg.name == node.name.value:
191+
field_arg_def = arg
192+
break
193+
if not field_arg_def:
194+
parent_type = self.context.get_parent_type()
195+
assert parent_type
196+
return GraphQLError(
197+
self.message(node.name.value, field_def.name, parent_type.name),
198+
[node]
199+
)
200+
elif isinstance(argument_of, ast.Directive):
201+
directive = self.context.get_directive()
202+
if directive:
203+
directive_arg_def = None
204+
for arg in directive.args:
205+
if arg.name == node.name.value:
206+
directive_arg_def = arg
207+
break
208+
if not directive_arg_def:
209+
return GraphQLError(
210+
self.directive_message(node.name.value, directive.name),
211+
[node]
212+
)
213+
214+
@staticmethod
215+
def message(arg_name, field_name, type):
216+
return 'Unknown argument "{}" on field "{}" of type "{}".'.format(arg_name, field_name, type)
217+
218+
@staticmethod
219+
def directive_message(arg_name, directive_name):
220+
return 'Unknown argument "{}" on directive "@{}".'.format(arg_name, directive_name)
184221

185222

186223
class UniqueArgumentNames(ValidationRule):

tests/core_validation/test_known_argument_names.py

Lines changed: 1 addition & 13 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 KnownArgumentNames
53
from utils import expect_passes_rule, expect_fails_rule
@@ -14,7 +12,7 @@ def unknown_arg(arg_name, field_name, type_name, line, column):
1412

1513
def unknown_directive_arg(arg_name, directive_name, line, column):
1614
return {
17-
'message': KnownArgumentNames.unknown_directive_message(
15+
'message': KnownArgumentNames.directive_message(
1816
arg_name, directive_name),
1917
'locations': [SourceLocation(line, column)]
2018
}
@@ -85,10 +83,6 @@ def test_directive_args_are_known():
8583
''')
8684

8785

88-
@pytest.mark.skipif(not hasattr(KnownArgumentNames,
89-
"unknown_directive_message"),
90-
reason=("KnownDirectives.unknown_directive_message not "
91-
"yet implemented"))
9286
def test_undirective_args_are_invalid():
9387
expect_fails_rule(KnownArgumentNames, '''
9488
{
@@ -97,8 +91,6 @@ def test_undirective_args_are_invalid():
9791
''', [unknown_directive_arg('unless', 'skip', 3, 19)])
9892

9993

100-
@pytest.mark.skipif(not hasattr(KnownArgumentNames, "message"),
101-
reason="KnownArgumentNames.message not yet implemented")
10294
def test_invalid_arg_name():
10395
expect_fails_rule(KnownArgumentNames, '''
10496
fragment invalidArgName on Dog {
@@ -107,8 +99,6 @@ def test_invalid_arg_name():
10799
''', [unknown_arg('unknown', 'doesKnowCommand', 'Dog', 3, 25)])
108100

109101

110-
@pytest.mark.skipif(not hasattr(KnownArgumentNames, "message"),
111-
reason="KnownArgumentNames.message not yet implemented")
112102
def test_unknown_args_amongst_known_args():
113103
expect_fails_rule(KnownArgumentNames, '''
114104
fragment oneGoodArgOneInvalidArg on Dog {
@@ -118,8 +108,6 @@ def test_unknown_args_amongst_known_args():
118108
unknown_arg('unknown', 'doesKnowCommand', 'Dog', 3, 55)])
119109

120110

121-
@pytest.mark.skipif(not hasattr(KnownArgumentNames, "message"),
122-
reason="KnownArgumentNames.message not yet implemented")
123111
def test_unknown_args_deeply():
124112
expect_fails_rule(KnownArgumentNames, '''
125113
{

tests/core_validation/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
'human': GraphQLField(Human, {
7474
'id': GraphQLArgument(GraphQLID),
7575
}),
76+
'dog': GraphQLField(Dog),
7677
'pet': GraphQLField(Pet),
7778
'catOrDog': GraphQLField(CatOrDog),
7879
'complicatedArgs': GraphQLField(ComplicatedArgs),

0 commit comments

Comments
 (0)