Skip to content

Commit e26affc

Browse files
feature: Adds VariablesAreInputTypesRule
1 parent 073718b commit e26affc

File tree

3 files changed

+89
-1
lines changed

3 files changed

+89
-1
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
/**
3+
* Variables are input types
4+
*
5+
* A GraphQL operation is only valid if all the variables it defines are of
6+
* input types (scalar, enum, or input object).
7+
*
8+
* See https://spec.graphql.org/draft/#sec-Variables-Are-Input-Types
9+
*/
10+
func VariablesAreInputTypesRule(context: ValidationContext) -> Visitor {
11+
return Visitor(
12+
enter: { node, _, _, _, _ in
13+
if let variableDefinition = node as? VariableDefinition {
14+
let variableType = variableDefinition.type
15+
if let type = typeFromAST(schema: context.schema, inputTypeAST: variableType) {
16+
guard !isInputType(type: type) else {
17+
return .continue
18+
}
19+
20+
let variableName = variableDefinition.variable.name.value
21+
let typeName = print(ast: variableType)
22+
context.report(
23+
error: GraphQLError(
24+
message: "Variable \"$\(variableName)\" cannot be non-input type \"\(typeName)\".",
25+
nodes: [variableType]
26+
)
27+
)
28+
}
29+
}
30+
return .continue
31+
}
32+
)
33+
}

Sources/GraphQL/Validation/SpecifiedRules.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public let specifiedRules: [(ValidationContext) -> Visitor] = [
88
// SingleFieldSubscriptionsRule,
99
KnownTypeNamesRule,
1010
FragmentsOnCompositeTypesRule,
11-
// VariablesAreInputTypesRule,
11+
VariablesAreInputTypesRule,
1212
ScalarLeafsRule,
1313
FieldsOnCorrectTypeRule,
1414
// UniqueFragmentNamesRule,
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
@testable import GraphQL
2+
import XCTest
3+
4+
class VariablesAreInputTypesRuleTests: ValidationTestCase {
5+
override func setUp() {
6+
rule = VariablesAreInputTypesRule
7+
}
8+
9+
func testUnknownTypesAreIgnored() throws {
10+
try assertValid(
11+
"""
12+
query Foo($a: Unknown, $b: [[Unknown!]]!) {
13+
field(a: $a, b: $b)
14+
}
15+
"""
16+
)
17+
}
18+
19+
func testInputTypesAreValid() throws {
20+
try assertValid(
21+
"""
22+
query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) {
23+
field(a: $a, b: $b, c: $c)
24+
}
25+
"""
26+
)
27+
}
28+
29+
func testOutputTypesAreInvalid() throws {
30+
let errors = try assertInvalid(
31+
errorCount: 3,
32+
query:
33+
"""
34+
query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) {
35+
field(a: $a, b: $b, c: $c)
36+
}
37+
"""
38+
)
39+
try assertValidationError(
40+
error: errors[0],
41+
locations: [(line: 1, column: 15)],
42+
message: "Variable \"$a\" cannot be non-input type \"Dog\"."
43+
)
44+
try assertValidationError(
45+
error: errors[1],
46+
locations: [(line: 1, column: 24)],
47+
message: "Variable \"$b\" cannot be non-input type \"[[CatOrDog!]]!\"."
48+
)
49+
try assertValidationError(
50+
error: errors[2],
51+
locations: [(line: 1, column: 44)],
52+
message: "Variable \"$c\" cannot be non-input type \"Pet\"."
53+
)
54+
}
55+
}

0 commit comments

Comments
 (0)