Skip to content

Commit 8b4a9b0

Browse files
authored
Implemented case-insensitive input object fields and constructor parameters match (#513)
1 parent 645967f commit 8b4a9b0

File tree

3 files changed

+22
-21
lines changed

3 files changed

+22
-21
lines changed

src/FSharp.Data.GraphQL.Server/Values.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ let rec internal compileByType
121121
(fun (allParameters : _ ResizeArray) param ->
122122
match
123123
objDef.Fields
124-
|> Array.tryFind (fun field -> field.Name = param.Name)
124+
// TODO: Improve parameter name matching logic
125+
|> Array.tryFind (fun field -> String.Equals (field.Name, param.Name, StringComparison.InvariantCultureIgnoreCase))
125126
with
126127
| Some field ->
127128
let isParameterSkippable = ReflectionHelper.isParameterSkippable param

tests/FSharp.Data.GraphQL.Tests/Variables and Inputs/InputComplexTests.fs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ let TestComplexScalar =
3838
)
3939

4040
type TestInput =
41-
{ mand : string
42-
opt1 : string option
43-
opt2 : string option
41+
{ Mand : string
42+
Opt : string option
43+
GLCode : string option // for case-insensitive name match test
4444
optSeq : string option seq option
4545
voptSeq : string option seq voption // string voption seq voption is too hard to implement
4646
optArr : string option array option
@@ -53,8 +53,8 @@ let TestInputObject =
5353
name = "TestInputObject",
5454
fields =
5555
[ Define.Input ("mand", StringType)
56-
Define.Input ("opt1", Nullable StringType)
57-
Define.Input ("opt2", Nullable TestComplexScalar)
56+
Define.Input ("opt", Nullable StringType)
57+
Define.Input ("glCode", Nullable TestComplexScalar)
5858
Define.Input ("optSeq", Nullable (ListOf (Nullable StringType)))
5959
Define.Input ("voptSeq", Nullable (ListOf (Nullable StringType)))
6060
Define.Input ("optArr", Nullable (InputArrayOf (Nullable StringType)))
@@ -72,13 +72,13 @@ let schema = Schema (TestType)
7272
[<Fact>]
7373
let ``Execute handles objects and nullability using inline structs with complex input`` () =
7474
let ast =
75-
parse """{ fieldWithObjectInput(input: {mand: "baz", opt1: "foo", optSeq: ["bar"], optArr: ["baf"]}) }"""
75+
parse """{ fieldWithObjectInput(input: {mand: "baz", opt: "foo", optSeq: ["bar"], optArr: ["baf"]}) }"""
7676
let result = sync <| Executor(schema).AsyncExecute (ast)
7777

7878
let expected =
7979
NameValueLookup.ofList
8080
[ "fieldWithObjectInput",
81-
upcast """{"mand":"baz","opt1":"foo","opt2":null,"optSeq":["bar"],"voptSeq":null,"optArr":["baf"],"voptArr":null}""" ]
81+
upcast """{"mand":"baz","opt":"foo","glCode":null,"optSeq":["bar"],"voptSeq":null,"optArr":["baf"],"voptArr":null}""" ]
8282

8383
ensureDirect result <| fun data errors ->
8484
empty errors
@@ -87,22 +87,22 @@ let ``Execute handles objects and nullability using inline structs with complex
8787
// See https://spec.graphql.org/October2021/#sec-List
8888
[<Fact(Skip = "Validation needs to be updated to allow")>]
8989
let ``Execute handles objects and nullability using inline structs and properly parses single value to list`` () =
90-
let ast = parse """{ fieldWithObjectInput(input: {mand:"baz", opt1: "foo", optSeq: "bar"}) }"""
90+
let ast = parse """{ fieldWithObjectInput(input: {mand:"baz", opt: "foo", optSeq: "bar"}) }"""
9191
let result = sync <| Executor(schema).AsyncExecute (ast)
9292
let expected =
93-
NameValueLookup.ofList [ "fieldWithObjectInput", upcast """{"mand":"baz", "opt1":"foo", "optSeq":["bar"], "opt2":null, "optArr":null}""" ]
93+
NameValueLookup.ofList [ "fieldWithObjectInput", upcast """{"mand":"baz", "opt":"foo", "optSeq":["bar"], "glCode":null, "optArr":null}""" ]
9494
ensureDirect result <| fun data errors ->
9595
empty errors
9696
data |> equals (upcast expected)
9797

9898
[<Fact>]
9999
let ``Execute handles objects and nullability using inline structs and properly coerces complex scalar types`` () =
100-
let ast = parse """{ fieldWithObjectInput(input: {mand: "foo", opt2: "SerializedValue"}) }"""
100+
let ast = parse """{ fieldWithObjectInput(input: {mand: "foo", glCode: "SerializedValue"}) }"""
101101
let result = sync <| Executor(schema).AsyncExecute (ast)
102102
let expected =
103103
NameValueLookup.ofList
104104
[ "fieldWithObjectInput",
105-
upcast """{"mand":"foo","opt1":null,"opt2":"DeserializedValue","optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}""" ]
105+
upcast """{"mand":"foo","opt":null,"glCode":"DeserializedValue","optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}""" ]
106106

107107
ensureDirect result <| fun data errors ->
108108
empty errors
@@ -116,7 +116,7 @@ let paramsWithValueInput input =
116116
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions)
117117

118118
let testInputObject =
119-
"""{"mand":"baz","opt1":"foo","opt2":null,"optSeq":["bar"],"voptSeq":["bar"],"optArr":null,"voptArr":null}"""
119+
"""{"mand":"baz","opt":"foo","glCode":null,"optSeq":["bar"],"voptSeq":["bar"],"optArr":null,"voptArr":null}"""
120120

121121
[<Fact>]
122122
let ``Execute handles variables with complex inputs`` () =
@@ -137,7 +137,7 @@ let ``Execute handles variables with complex inputs`` () =
137137
let ``Execute handles variables with default value when no value was provided`` () =
138138
let ast =
139139
parse
140-
"""query q($input: TestInputObject = {mand:"baz", opt1: "foo", optSeq: ["bar"], voptSeq:["bar"]}) {
140+
"""query q($input: TestInputObject = {mand:"baz", opt: "foo", optSeq: ["bar"], voptSeq:["bar"]}) {
141141
fieldWithObjectInput(input: $input)
142142
}"""
143143

@@ -155,7 +155,7 @@ let ``Execute handles variables and errors on null for nested non-nulls`` () =
155155
fieldWithObjectInput(input: $input)
156156
}"""
157157

158-
let testInputObject = """{"mand":null, "opt1":"foo", "optSeq":["bar"], "voptSeq":["bar"]}"""
158+
let testInputObject = """{"mand":null, "opt":"foo", "optSeq":["bar"], "voptSeq":["bar"]}"""
159159
let params' = paramsWithValueInput testInputObject
160160
let result = sync <| Executor(schema).AsyncExecute (ast, variables = params')
161161
ensureRequestError result <| fun [ error ] ->
@@ -185,7 +185,7 @@ let ``Execute handles variables and errors on omission of nested non-nulls`` ()
185185
fieldWithObjectInput(input: $input)
186186
}"""
187187

188-
let testInputObject = """{"opt1":"foo","optSeq":["bar"]}"""
188+
let testInputObject = """{"opt":"foo","optSeq":["bar"]}"""
189189
let params' = paramsWithValueInput testInputObject
190190
let result = sync <| Executor(schema).AsyncExecute (ast, variables = params')
191191
ensureRequestError result <| fun [ error ] ->
@@ -199,7 +199,7 @@ let ``Execute handles list inputs and nullability and does not allow invalid typ
199199
"""query q($input: TestInputObject!) {
200200
fieldWithObjectInput(input: $input)
201201
}"""
202-
// as that kind of an error inside of opt1 query is guaranteed to fail in every call, we're gonna to fail noisy here
202+
// as that kind of an error inside of opt query is guaranteed to fail in every call, we're gonna to fail noisy here
203203
let testInputList = "[\"A\",\"B\"]"
204204
let params' = paramsWithValueInput testInputList
205205
let result = sync <| Executor(schema).AsyncExecute (ast, variables = params')
@@ -217,7 +217,7 @@ let ``Execute handles list inputs and nullability and does not allow unknown typ
217217
"""query q($input: UnknownType!) {
218218
fieldWithObjectInput(input: $input)
219219
}"""
220-
// as that kind of an error inside of opt1 query is guaranteed to fail in every call, we're gonna to fail noisy here
220+
// as that kind of an error inside of opt query is guaranteed to fail in every call, we're gonna to fail noisy here
221221
let testInputValue = "\"whoknows\""
222222
let params' = paramsWithValueInput testInputValue
223223
let result = sync <| Executor(schema).AsyncExecute (ast, variables = params')

tests/FSharp.Data.GraphQL.Tests/Variables and Inputs/InputNestedTests.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ let ``Execute handles nested input objects and nullability using inline structs
110110
NameValueLookup.ofList [
111111
"fieldWithNestedInputObject",
112112
upcast
113-
"""{"n":"optSeq","no":{"mand":"mand","opt1":null,"opt2":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nvo":{"mand":"mand","opt1":null,"opt2":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nl":[],"nlo":null,"nlvo":null}"""
113+
"""{"n":"optSeq","no":{"mand":"mand","opt":null,"glCode":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nvo":{"mand":"mand","opt":null,"glCode":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nl":[],"nlo":null,"nlvo":null}"""
114114
]
115115

116116
ensureDirect result
@@ -127,7 +127,7 @@ let ``Execute handles nested input objects and nullability using inline structs
127127
NameValueLookup.ofList [
128128
"fieldWithNestedInputObject",
129129
upcast
130-
"""{"n":"optSeq","no":{"mand":"mand","opt1":null,"opt2":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nvo":{"mand":"mand","opt1":null,"opt2":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nl":[],"nlo":[],"nlvo":[]}"""
130+
"""{"n":"optSeq","no":{"mand":"mand","opt":null,"glCode":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nvo":{"mand":"mand","opt":null,"glCode":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null},"nl":[],"nlo":[],"nlvo":[]}"""
131131
]
132132

133133
ensureDirect result
@@ -144,7 +144,7 @@ let ``Execute handles nested input objects and nullability using inline structs
144144
NameValueLookup.ofList [
145145
"fieldWithNestedInputObject",
146146
upcast
147-
"""{"n":"optSeq","no":null,"nvo":null,"nl":[{"mand":"mand","opt1":null,"opt2":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}],"nlo":[{"mand":"mand","opt1":null,"opt2":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}],"nlvo":[{"mand":"mand","opt1":null,"opt2":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}]}"""
147+
"""{"n":"optSeq","no":null,"nvo":null,"nl":[{"mand":"mand","opt":null,"glCode":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}],"nlo":[{"mand":"mand","opt":null,"glCode":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}],"nlvo":[{"mand":"mand","opt":null,"glCode":null,"optSeq":null,"voptSeq":null,"optArr":null,"voptArr":null}]}"""
148148
]
149149

150150
ensureDirect result

0 commit comments

Comments
 (0)