Skip to content

Commit 47cf92e

Browse files
committed
Fix ObjectListFilter IN coercion behavior and add converter/no-converter tests
1 parent af5eeb2 commit 47cf92e

2 files changed

Lines changed: 32 additions & 4 deletions

File tree

src/FSharp.Data.GraphQL.Server.Middleware/TypeCoercion.fs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,28 @@ module TypeCoercion =
200200
| null -> filter
201201
| prop ->
202202
let unwrapped = unwrapOption prop.PropertyType
203-
let coercedList = ff.Value |> List.vchoose (tryCoerceValue jsonOptions unwrapped)
204-
In { ff with Value = coercedList }
203+
204+
let struct (coercedValues, failedValues) =
205+
ff.Value
206+
|> List.fold
207+
(fun struct (coerced, failed) value ->
208+
match tryCoerceValue jsonOptions unwrapped value with
209+
| ValueSome coercedValue -> (coercedValue :: coerced, failed)
210+
| ValueNone -> struct (coerced, value :: failed))
211+
([], [])
212+
213+
match failedValues with
214+
| [] -> In { ff with Value = List.rev coercedValues }
215+
| _ ->
216+
let failedValuesText =
217+
failedValues
218+
|> Seq.rev
219+
|> Seq.map (sprintf "%A")
220+
|> String.concat ", "
221+
222+
invalidArg
223+
(nameof filter)
224+
($"Unable to coerce one or more values for '{ff.FieldName}' to '{unwrapped.FullName}'. Uncoerced values: [{failedValuesText}]")
205225
| StartsWith (ff, cmp)
206226
| EndsWith (ff, cmp) as originalFilter ->
207227
match entityType.GetProperty (stripOperatorSuffix ff.FieldName, propertyBindFlags) with

tests/FSharp.Data.GraphQL.Tests/ObjectListFilter/ObjectListFilterLinqGenerateTests.fs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ let cosmosClient =
101101
new CosmosClient ("https://localhost:8081/", "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", options)
102102
let container = cosmosClient.GetContainer ("database", "container")
103103
let filterOptions = ObjectListFilterLinqOptions<FakeEntity, obj>.None
104+
let filterOptionsWithConverters = ObjectListFilterLinqOptions<FakeEntity, obj> (jsonOptions)
104105

105106
[<Fact>]
106107
let ``ObjectListFilter works with Equals operator for ValidStringStruct`` () =
@@ -247,13 +248,20 @@ let ``ObjectListFilter works with Contains operator for ValidStringStruct list``
247248
equals queryDefinition.QueryText, """SELECT VALUE root FROM root WHERE ARRAY_CONTAINS(root["validStringStructList"], "athan")"""
248249

249250
[<Fact>]
250-
let ``ObjectListFilter works with In operator for ValidStringStruct list`` () =
251+
let ``ObjectListFilter works with In operator for ValidStringStruct list when converters are provided`` () =
251252
let queryable = container.GetItemLinqQueryable<FakeEntity> ()
252253
let filter = In { FieldName = "validStringStruct"; Value = [ "athan"; "gaja" ] }
253-
let filterQuery = queryable.Apply (filter, filterOptions)
254+
let filterQuery = queryable.Apply (filter, filterOptionsWithConverters)
254255
let queryDefinition = CosmosLinqExtensions.ToQueryDefinition filterQuery
255256
equals queryDefinition.QueryText, """SELECT VALUE root FROM root WHERE ARRAY_CONTAINS([ "athan", "gaja" ], root["validStringStruct"])"""
256257

258+
[<Fact>]
259+
let ``ObjectListFilter works with In operator for ValidStringStruct list when converters are not provided`` () =
260+
let queryable = container.GetItemLinqQueryable<FakeEntity> ()
261+
let filter = In { FieldName = "validStringStruct"; Value = [ "athan"; "gaja" ] }
262+
let ex = Assert.Throws<ArgumentException>(fun () -> queryable.Apply (filter, filterOptions) |> ignore)
263+
Assert.Contains ("Uncoerced values", ex.Message)
264+
257265
[<Fact>]
258266
let ``ObjectListFilter works with In operator for empty ValidStringStruct list`` () =
259267
let queryable = container.GetItemLinqQueryable<FakeEntity> ()

0 commit comments

Comments
 (0)