-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathvalues_test.go
More file actions
144 lines (135 loc) · 4.31 KB
/
Copy pathvalues_test.go
File metadata and controls
144 lines (135 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package graphql
import (
"math"
"reflect"
"testing"
)
func TestIsIterable(t *testing.T) {
if !isIterable([]int{}) {
t.Fatal("expected isIterable to return true for a slice, got false")
}
if !isIterable([]int{}) {
t.Fatal("expected isIterable to return true for an array, got false")
}
if isIterable(1) {
t.Fatal("expected isIterable to return false for an int, got true")
}
if isIterable(nil) {
t.Fatal("expected isIterable to return false for nil, got true")
}
}
func Test_coerceValue(t *testing.T) {
t.Parallel()
type input struct {
ttype Input
value any
}
testCases := map[string]struct {
input input
expected any
}{
"null Input Object is coerced to nil": {
input: input{
ttype: NewInputObject(InputObjectConfig{
Name: "InputObject",
}),
value: nil,
},
expected: nil,
},
"null field in Input Object is not omitted, and coerced to nil": {
input: input{
ttype: NewInputObject(InputObjectConfig{
Name: "InputObject",
Fields: InputObjectConfigFieldMap{
"string": &InputObjectFieldConfig{
Type: String,
},
},
}),
value: map[string]any{"string": nil},
},
expected: map[string]any{"string": nil},
},
}
// None of these cases involve a default value, so both coercion modes must
// agree on all of them.
for name, tc := range testCases {
name, tc := name, tc
for _, nonSpec := range []bool{false, true} {
nonSpec := nonSpec
mode := "spec"
if nonSpec {
mode = "nonSpec"
}
t.Run(name+"/"+mode, func(t *testing.T) {
t.Parallel()
got := coerceValue(tc.input.ttype, tc.input.value, nonSpec)
if !reflect.DeepEqual(tc.expected, got) {
t.Errorf("unexpected result, expected: %v, got: %v", tc.expected, got)
}
})
}
}
}
// Spec §3.10 / §5.6.4: an input field is required only when its type is non-null
// AND it declares no default value. Pinned at the function level so the three
// states stay distinct: absent-with-default, absent-without-default, explicit null.
func Test_isValidInputValue_NonNullFieldWithDefault(t *testing.T) {
withDefault := NewInputObject(InputObjectConfig{
Name: "WithDefault",
Fields: InputObjectConfigFieldMap{
"a": &InputObjectFieldConfig{Type: NewNonNull(String), DefaultValue: "FIELDDEF"},
},
})
withoutDefault := NewInputObject(InputObjectConfig{
Name: "WithoutDefault",
Fields: InputObjectConfigFieldMap{
"a": &InputObjectFieldConfig{Type: NewNonNull(String)},
},
})
if isValid, messages := isValidInputValue(map[string]interface{}{}, withDefault, false); !isValid {
t.Errorf("spec mode: expected an omitted field with a default to be valid, got: %v", messages)
}
if isValid, _ := isValidInputValue(map[string]interface{}{}, withDefault, true); isValid {
t.Error("non-spec mode: expected an omitted non-null field to be invalid")
}
for _, nonSpec := range []bool{false, true} {
if isValid, _ := isValidInputValue(map[string]interface{}{"a": nil}, withDefault, nonSpec); isValid {
t.Errorf("expected an explicit null to be invalid (nonSpec=%v)", nonSpec)
}
if isValid, _ := isValidInputValue(map[string]interface{}{}, withoutDefault, nonSpec); isValid {
t.Errorf("expected an omitted field without a default to be invalid (nonSpec=%v)", nonSpec)
}
}
}
// A default that is nullish but not nil — a typed nil pointer, say — is not a
// default coercion can substitute: coerceValue and valueFromAST both skip it
// under isNullish. Validation has to agree, otherwise a non-null field passes
// validation and then goes missing from the coerced map.
func Test_isValidInputValue_NullishDefaultIsNotADefault(t *testing.T) {
var nilString *string
for _, tc := range []struct {
name string
defaultVal interface{}
wantValid bool
}{
{"usable default", "FIELDDEF", true},
{"no default", nil, false},
{"typed nil pointer", nilString, false},
{"NaN", math.NaN(), false},
} {
t.Run(tc.name, func(t *testing.T) {
in := NewInputObject(InputObjectConfig{
Name: "NullishDefault" + tc.name,
Fields: InputObjectConfigFieldMap{
"a": &InputObjectFieldConfig{Type: NewNonNull(String), DefaultValue: tc.defaultVal},
},
})
isValid, messages := isValidInputValue(map[string]interface{}{}, in, false)
if isValid != tc.wantValid {
t.Errorf("isValid = %v, want %v (messages: %v)", isValid, tc.wantValid, messages)
}
})
}
}