Skip to content

Commit

Permalink
fix variables validation: (#685)
Browse files Browse the repository at this point in the history
- do not traverse list value in case it is null
- continue after validating list value

---------

Co-authored-by: spetrunin <neyasut@gmail.com>
  • Loading branch information
jensneuse and devsergiy authored Nov 29, 2023
1 parent ad6fd15 commit eefd234
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
11 changes: 9 additions & 2 deletions v2/pkg/variablesvalidation/variablesvalidation.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,19 @@ func (v *variablesVisitor) traverseNode(jsonNodeRef int, typeName []byte) {
v.renderVariableRequiredNotProvidedError(fieldName, fieldType)
return
}

if !v.variables.NodeIsDefined(fieldVariablesJsonNodeRef) {
continue
}

if v.definition.TypeIsList(fieldType) {
if v.variables.Nodes[fieldVariablesJsonNodeRef].Kind != astjson.NodeKindArray {
v.renderVariableInvalidNestedTypeError(fieldVariablesJsonNodeRef, fieldTypeDefinitionNode.Kind, typeName)
return
}
if len(v.variables.Nodes[fieldVariablesJsonNodeRef].ArrayValues) == 0 {
continue
}
fieldTypeName := v.definition.ResolveTypeNameBytes(fieldType)
v.pushObjectPath(fieldName)
for i, arrayValue := range v.variables.Nodes[fieldVariablesJsonNodeRef].ArrayValues {
Expand All @@ -332,10 +340,9 @@ func (v *variablesVisitor) traverseNode(jsonNodeRef int, typeName []byte) {
continue
}
v.popPath()
}
if !v.variables.NodeIsDefined(fieldVariablesJsonNodeRef) {
continue
}

v.pushObjectPath(fieldName)
v.traverseNode(fieldVariablesJsonNodeRef, v.definition.ResolveTypeNameBytes(fieldType))
v.popPath()
Expand Down
42 changes: 42 additions & 0 deletions v2/pkg/variablesvalidation/variablesvalidation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,48 @@ func TestVariablesValidation(t *testing.T) {
require.Error(t, err)
assert.Equal(t, `Variable "$bar" got invalid value 123 at "bar.[0]"; String cannot represent a non string value: 123`, err.Error())
})

t.Run("optional nested list argument provided with null", func(t *testing.T) {
tc := testCase{
schema: `input Foo { bars : [String] bat: Int! } type Query { hello(arg: Foo): String }`,
operation: `query Foo($input: Foo) { hello(arg: $input) }`,
variables: `{"input":{"bars":null,"bat":1}}`,
}
err := runTest(t, tc)
require.NoError(t, err)
})

t.Run("optional nested list argument provided with empty list", func(t *testing.T) {
tc := testCase{
schema: `input Foo { bars : [String] bat: Int! } type Query { hello(arg: Foo): String }`,
operation: `query Foo($input: Foo) { hello(arg: $input) }`,
variables: `{"input":{"bars":[],"bat":1}}`,
}
err := runTest(t, tc)
require.NoError(t, err)
})

t.Run("optional nested list argument provided with empty list and missing Int", func(t *testing.T) {
tc := testCase{
schema: `input Foo { bars : [String] bat: Int! } type Query { hello(arg: Foo): String }`,
operation: `query Foo($input: Foo) { hello(arg: $input) }`,
variables: `{"input":{"bars":[]}}`,
}
err := runTest(t, tc)
require.Error(t, err)
assert.Equal(t, `Variable "$input" got invalid value {"bars":[]}; Field "bat" of required type "Int!" was not provided.`, err.Error())
})

t.Run("optional nested field is null followed by required nested field of wrong type", func(t *testing.T) {
tc := testCase{
schema: `input Foo { bar: String! } input Bar { foo: Foo bat: Int! } type Query { hello(arg: Bar): String }`,
operation: `query Foo($input: Bar) { hello(arg: $input) }`,
variables: `{"input":{"foo":null,"bat":"hello"}}`,
}
err := runTest(t, tc)
require.Error(t, err)
assert.Equal(t, `Variable "$input" got invalid value "hello" at "input.bat"; Int cannot represent non-integer value: "hello"`, err.Error())
})
}

type testCase struct {
Expand Down

0 comments on commit eefd234

Please sign in to comment.