Skip to content

Commit 1d0f912

Browse files
author
Viktor Tochonov
committed
Fixed tests for Contains operator on different collection types
1 parent 76071c5 commit 1d0f912

File tree

2 files changed

+58
-24
lines changed

2 files changed

+58
-24
lines changed

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,15 @@ module ObjectListFilter =
129129
let private StringEndsWithMethod = typeof<string>.GetMethod ("EndsWith", [| typeof<string> |])
130130
let private StringContainsMethod = typeof<string>.GetMethod ("Contains", [| typeof<string> |])
131131
let private getEnumerableContainsMethod (memberType : Type) =
132-
match memberType.GetMethods(BindingFlags.Instance &&& BindingFlags.Public).FirstOrDefault(fun m -> m.Name = "Contains" && m.GetParameters().Length = 2) with
133-
| null ->
134-
match typeof<Enumerable>.GetMethods(BindingFlags.Static ||| BindingFlags.Public).FirstOrDefault(fun m -> m.Name = "Contains" && m.GetParameters().Length = 2) with
135-
| null -> raise (MissingMemberException "Static 'Contains' method with 2 parameters not found on 'Enumerable' class")
136-
| containsGenericStaticMethod ->
137-
if memberType.IsGenericType && memberType.GenericTypeArguments.Length = 1 then
138-
containsGenericStaticMethod.MakeGenericMethod(memberType.GenericTypeArguments)
139-
else
140-
let ienumerable = memberType.GetType().GetInterfaces().First(fun i -> i.FullName.StartsWith "System.Collections.Generic.IEnumerable`1")
141-
containsGenericStaticMethod.MakeGenericMethod([| ienumerable.GenericTypeArguments[0] |])
142-
| instanceContainsMethod -> instanceContainsMethod
132+
match typeof<Enumerable>.GetMethods(BindingFlags.Static ||| BindingFlags.Public).FirstOrDefault(fun m -> m.Name = "Contains" && m.GetParameters().Length = 2) with
133+
| null -> raise (MissingMemberException "Static 'Contains' method with 2 parameters not found on 'Enumerable' class")
134+
| containsGenericStaticMethod ->
135+
if memberType.IsGenericType && memberType.GenericTypeArguments.Length = 1 then
136+
containsGenericStaticMethod.MakeGenericMethod(memberType.GenericTypeArguments)
137+
else
138+
let ienumerable = memberType.GetInterfaces().First(fun i -> i.FullName.StartsWith "System.Collections.Generic.IEnumerable`1")
139+
containsGenericStaticMethod.MakeGenericMethod([| ienumerable.GenericTypeArguments[0] |])
140+
143141

144142
let getField (param : ParameterExpression) fieldName = Expression.PropertyOrField (param, fieldName)
145143

@@ -174,7 +172,9 @@ module ObjectListFilter =
174172
&& memberType.GetInterfaces().Any(fun i -> i.FullName.StartsWith "System.Collections.Generic.IEnumerable`1")
175173
match ``member``.Member with
176174
| :? PropertyInfo as prop when prop.PropertyType |> isEnumerable ->
177-
Expression.Call (getEnumerableContainsMethod prop.PropertyType, Expression.PropertyOrField (param, f.FieldName), Expression.Constant (f.Value))
175+
match prop.PropertyType.GetMethods(BindingFlags.Instance ||| BindingFlags.Public).FirstOrDefault(fun m -> m.Name = "Contains" && m.GetParameters().Length = 1) with
176+
| null -> Expression.Call (getEnumerableContainsMethod prop.PropertyType, Expression.PropertyOrField (param, f.FieldName), Expression.Constant (f.Value))
177+
| instanceContainsMethod -> Expression.Call (Expression.PropertyOrField (param, f.FieldName),instanceContainsMethod, Expression.Constant (f.Value))
178178
| :? FieldInfo as field when field.FieldType |> isEnumerable ->
179179
Expression.Call (getEnumerableContainsMethod field.FieldType, Expression.PropertyOrField (param, f.FieldName), Expression.Constant (f.Value))
180180
| _ ->

tests/FSharp.Data.GraphQL.Tests/ObjectListFilterLinqTests.fs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -324,22 +324,20 @@ let ``ObjectListFilter works with getDiscriminatorValue startsWith for Horse and
324324
c.ID |> equals 5
325325
c.Name |> equals "Hamster E"
326326

327-
type Product = {
327+
type ListTagsProduct = {
328328
Name : string
329329
Tags : string list
330330
}
331331

332-
let productList =
333-
[
334-
{ Name = "Product A"; Tags = ["Tag1"; "Tag2"] }
335-
{ Name = "Product B"; Tags = ["Tag2"; "Tag3"] }
336-
{ Name = "Product C"; Tags = ["Tag3"; "Tag4"] }
337-
{ Name = "Product D"; Tags = ["Tag4"; "Tag5"] }
338-
]
339-
let productArray = productList.ToArray()
340-
341332
[<Fact>]
342-
let ``ObjectListFilter works with Contains operator collection type properties``() =
333+
let ``ObjectListFilter works with Contains operator on list collection properties``() =
334+
let productList =
335+
[
336+
{ Name = "Product A"; Tags = ["Tag1"; "Tag2"] }
337+
{ Name = "Product B"; Tags = ["Tag2"; "Tag3"] }
338+
{ Name = "Product C"; Tags = ["Tag3"; "Tag4"] }
339+
{ Name = "Product D"; Tags = ["Tag4"; "Tag5"] }
340+
]
343341
let queryable = productList.AsQueryable()
344342
let filter = Contains { FieldName = "Tags"; Value = "Tag3" }
345343
let filteredData = queryable.Apply(filter) |> Seq.toList
@@ -349,9 +347,45 @@ let ``ObjectListFilter works with Contains operator collection type properties``
349347
let result2 = List.last filteredData
350348
result2.Name |> equals "Product C"
351349

350+
type ArrayTagsProduct = {
351+
Name : string
352+
Tags : string array
353+
}
354+
355+
[<Fact>]
356+
let ``ObjectListFilter works with Contains operator on array collection properties``() =
357+
358+
let productArray =
359+
[
360+
{ Name = "Product A"; Tags = [|"Tag1"; "Tag2"|] }
361+
{ Name = "Product B"; Tags = [|"Tag2"; "Tag3"|] }
362+
{ Name = "Product C"; Tags = [|"Tag3"; "Tag4"|] }
363+
{ Name = "Product D"; Tags = [|"Tag4"; "Tag5"|] }
364+
]
365+
let queryable = productArray.AsQueryable()
366+
let filter = Contains { FieldName = "Tags"; Value = "Tag3" }
367+
let filteredData = queryable.Apply(filter) |> Seq.toList
368+
List.length filteredData |> equals 2
369+
let result1 = List.head filteredData
370+
result1.Name |> equals "Product B"
371+
let result2 = List.last filteredData
372+
result2.Name |> equals "Product C"
373+
374+
type SetTagsProduct = {
375+
Name : string
376+
Tags : string Set
377+
}
352378

353379
[<Fact>]
354-
let ``ObjectListFilter works with Contains operator collection type properties with array``() =
380+
let ``ObjectListFilter works with Contains operator on set collection properties``() =
381+
382+
let productArray =
383+
[
384+
{ Name = "Product A"; Tags = [|"Tag1"; "Tag2"|] |> Set.ofArray}
385+
{ Name = "Product B"; Tags = [|"Tag2"; "Tag3"|] |> Set.ofArray}
386+
{ Name = "Product C"; Tags = [|"Tag3"; "Tag4"|] |> Set.ofArray}
387+
{ Name = "Product D"; Tags = [|"Tag4"; "Tag5"|] |> Set.ofArray}
388+
]
355389
let queryable = productArray.AsQueryable()
356390
let filter = Contains { FieldName = "Tags"; Value = "Tag3" }
357391
let filteredData = queryable.Apply(filter) |> Seq.toList

0 commit comments

Comments
 (0)