Skip to content

Commit 9ea9bcc

Browse files
VectorTetraViktor Tochonovxperiandri
authored
Implemented tests for scalar wrappers (#524)
--------- Co-authored-by: Viktor Tochonov <[email protected]> Co-authored-by: Andrii Chebukin <[email protected]>
1 parent 7fd53c2 commit 9ea9bcc

File tree

4 files changed

+152
-3
lines changed

4 files changed

+152
-3
lines changed

Packages.props

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
<PackageReference Update="GraphQL.Server.Ui.Voyager" Version="8.*" />
7676
<PackageReference Update="HotChocolate.AspNetCore" Version="15.*" />
7777
<PackageReference Update="Iced" Version="1.17.*" />
78+
<PackageReference Update="Microsoft.Azure.Cosmos" Version="3.*" />
7879
<PackageReference Update="Microsoft.CodeCoverage" Version="17.3.*" />
7980
<PackageReference Update="Microsoft.Data.Sqlite" Version="$(MicrosoftExtensionsVersion)" />
8081
<PackageReference Update="Microsoft.Diagnostics.NETCore.Client" Version="0.2.*" />

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

+29-3
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@ module ObjectListFilter =
141141
let private StringStartsWithMethod = typeof<string>.GetMethod ("StartsWith", [| typeof<string> |])
142142
let private StringEndsWithMethod = typeof<string>.GetMethod ("EndsWith", [| typeof<string> |])
143143
let private StringContainsMethod = typeof<string>.GetMethod ("Contains", [| typeof<string> |])
144+
let private MemberStartsWithMethod (memberType : Type) =
145+
match memberType.GetMethod ("StartsWith", [| memberType |]) with
146+
| null -> raise (MissingMemberException $"Method 'StartsWith' not found on '{memberType.FullName}'")
147+
| method -> method
148+
let private MemberEndsWithMethod (memberType : Type) =
149+
match memberType.GetMethod ("EndsWith", [| memberType |]) with
150+
| null -> raise (MissingMemberException $"Method 'EndsWith' not found on '{memberType.FullName}'")
151+
| method -> method
152+
let private MemberContainsMethod (memberType : Type) =
153+
match memberType.GetMethod ("Contains", [| memberType |]) with
154+
| null -> raise (MissingMemberException $"Method 'Contains' not found on '{memberType.FullName}'")
155+
| method -> method
144156
let private getEnumerableContainsMethod (memberType : Type) =
145157
match
146158
typeof<Enumerable>
@@ -183,8 +195,18 @@ module ObjectListFilter =
183195
| LessThan f -> Expression.LessThan (Expression.PropertyOrField (param, f.FieldName), Expression.Constant (f.Value))
184196
| GreaterThanOrEqual f -> Expression.GreaterThanOrEqual (Expression.PropertyOrField (param, f.FieldName), Expression.Constant (f.Value))
185197
| LessThanOrEqual f -> Expression.LessThanOrEqual (Expression.PropertyOrField (param, f.FieldName), Expression.Constant (f.Value))
186-
| StartsWith f -> Expression.Call (Expression.PropertyOrField (param, f.FieldName), StringStartsWithMethod, Expression.Constant (f.Value))
187-
| EndsWith f -> Expression.Call (Expression.PropertyOrField (param, f.FieldName), StringEndsWithMethod, Expression.Constant (f.Value))
198+
| StartsWith f ->
199+
let ``member`` = Expression.PropertyOrField (param, f.FieldName)
200+
if ``member``.Type = typeof<string> then
201+
Expression.Call (``member``, StringStartsWithMethod, Expression.Constant (f.Value))
202+
else
203+
Expression.Call (``member``, MemberStartsWithMethod ``member``.Type, Expression.Constant (f.Value))
204+
| EndsWith f ->
205+
let ``member`` = Expression.PropertyOrField (param, f.FieldName)
206+
if ``member``.Type = typeof<string> then
207+
Expression.Call (``member``, StringEndsWithMethod, Expression.Constant (f.Value))
208+
else
209+
Expression.Call (``member``, MemberEndsWithMethod ``member``.Type, Expression.Constant (f.Value))
188210
| Contains f ->
189211
let ``member`` = Expression.PropertyOrField (param, f.FieldName)
190212
let isEnumerable (memberType : Type) =
@@ -214,7 +236,11 @@ module ObjectListFilter =
214236
Expression.PropertyOrField (param, f.FieldName),
215237
Expression.Constant (f.Value)
216238
)
217-
| _ -> Expression.Call (``member``, StringContainsMethod, Expression.Constant (f.Value))
239+
| _ ->
240+
if ``member``.Type = typeof<string> then
241+
Expression.Call (``member``, StringContainsMethod, Expression.Constant (f.Value))
242+
else
243+
Expression.Call (``member``, MemberContainsMethod ``member``.Type, Expression.Constant (f.Value))
218244
| In f ->
219245
let ``member`` = Expression.PropertyOrField (param, f.FieldName)
220246
f.Value

tests/FSharp.Data.GraphQL.Tests/FSharp.Data.GraphQL.Tests.fsproj

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
</PropertyGroup>
1616

1717
<ItemGroup>
18+
<PackageReference Include="Microsoft.Azure.Cosmos" />
1819
<PackageReference Include="Microsoft.NET.Test.Sdk" />
1920
<PackageReference Include="BenchmarkDotNet" />
2021
<PackageReference Include="Validus" />
@@ -65,6 +66,7 @@
6566
<Compile Include="Variables and Inputs\InputListTests.fs" />
6667
<Compile Include="SelectLinqTests.fs" />
6768
<Compile Include="ObjectListFilterLinqTests.fs" />
69+
<Compile Include="ObjectListFilterLinqGenerateTests.fs" />
6870
<Compile Include="DeferredTests.fs" />
6971
<Compile Include="SubscriptionTests.fs" />
7072
<Compile Include="MiddlewareTests.fs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
module FSharp.Data.GraphQL.Tests.ObjectListFilterLinqGenerateTests
2+
3+
open Xunit
4+
open System
5+
open System.Numerics
6+
open Microsoft.Azure.Cosmos.Linq
7+
open Microsoft.Azure.Cosmos
8+
open FSharp.Data.GraphQL.Shared
9+
open FSharp.Data.GraphQL.Server.Middleware
10+
11+
[<Struct>]
12+
type ValidStringStruct =
13+
internal
14+
| ValidStringStruct of string
15+
static member internal op_Equality (ValidStringStruct left, ValidStringStruct right) = left = right
16+
static member internal op_Inequality (ValidStringStruct left, ValidStringStruct right) = left <> right
17+
18+
static member internal op_Equality (ValidStringStruct left, right) = left = right
19+
static member internal op_Inequality (ValidStringStruct left, right) = left <> right
20+
static member internal op_GreaterThan (ValidStringStruct left, right) = left > right
21+
static member internal op_GreaterThanOrEqual (ValidStringStruct left, right) = left >= right
22+
static member internal op_LessThan (ValidStringStruct left, right) = left < right
23+
static member internal op_LessThanOrEqual (ValidStringStruct left, right) = left <= right
24+
25+
// Just for demo purposes
26+
interface IEqualityOperators<ValidStringStruct, ValidStringStruct, bool> with
27+
static member op_Equality (ValidStringStruct left, ValidStringStruct right) = left = right
28+
static member op_Inequality (ValidStringStruct left, ValidStringStruct right) = left <> right
29+
interface IComparisonOperators<ValidStringStruct, ValidStringStruct, bool> with
30+
static member op_GreaterThan (ValidStringStruct left, ValidStringStruct right) = left > right
31+
static member op_GreaterThanOrEqual (ValidStringStruct left, ValidStringStruct right) = left >= right
32+
static member op_LessThan (ValidStringStruct left, ValidStringStruct right) = left < right
33+
static member op_LessThanOrEqual (ValidStringStruct left, ValidStringStruct right) = left <= right
34+
35+
type ValidStringObject =
36+
internal
37+
| ValidStringObject of string
38+
static member internal op_Equality (ValidStringObject left, ValidStringObject right) = left = right
39+
static member internal op_Inequality (ValidStringObject left, ValidStringObject right) = left <> right
40+
static member internal op_Equality (ValidStringObject left, right) = left = right
41+
static member internal op_Inequality (ValidStringObject left, right) = left <> right
42+
static member internal op_GreaterThan (ValidStringObject left, right) = left > right
43+
static member internal op_GreaterThanOrEqual (ValidStringObject left, right) = left >= right
44+
static member internal op_LessThan (ValidStringObject left, right) = left < right
45+
static member internal op_LessThanOrEqual (ValidStringObject left, right) = left <= right
46+
47+
// Just for demo purposes
48+
interface IEqualityOperators<ValidStringObject, ValidStringObject, bool> with
49+
static member op_Equality (ValidStringObject left, ValidStringObject right) = left = right
50+
static member op_Inequality (ValidStringObject left, ValidStringObject right) = left <> right
51+
interface IComparisonOperators<ValidStringObject, ValidStringObject, bool> with
52+
static member op_GreaterThan (ValidStringObject left, ValidStringObject right) = left > right
53+
static member op_GreaterThanOrEqual (ValidStringObject left, ValidStringObject right) = left >= right
54+
static member op_LessThan (ValidStringObject left, ValidStringObject right) = left < right
55+
static member op_LessThanOrEqual (ValidStringObject left, ValidStringObject right) = left <= right
56+
57+
[<Struct>]
58+
type ValidIntStruct =
59+
internal
60+
| ValidIntStruct of Int64
61+
static member internal op_Equality (ValidIntStruct left, ValidIntStruct right) = left = right
62+
static member internal op_Inequality (ValidIntStruct left, ValidIntStruct right) = left <> right
63+
static member internal op_GreaterThan (ValidIntStruct left, right : Int64) = left > right
64+
65+
type ValidIntObject =
66+
internal
67+
| ValidIntObject of Int64
68+
static member internal op_Equality (ValidIntObject left, ValidIntObject right) = left = right
69+
static member internal op_Inequality (ValidIntObject left, ValidIntObject right) = left <> right
70+
static member internal op_GreaterThan (ValidIntObject left, right : Int64) = left > right
71+
72+
type FakeEntity = {
73+
ValidStringStruct : ValidStringStruct
74+
ValidStringObject : ValidStringObject
75+
string : string
76+
ValidIntStruct : ValidIntStruct
77+
ValidIntObject : ValidIntObject
78+
int : Int64
79+
}
80+
81+
let jsonOptions = Json.getSerializerOptions Seq.empty
82+
let cosmosClient =
83+
let options = CosmosClientOptions(UseSystemTextJsonSerializerWithOptions = jsonOptions)
84+
new CosmosClient ("https://localhost:8081/", "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", options)
85+
let container = cosmosClient.GetContainer("database", "container")
86+
let filterOptions =
87+
ObjectListFilterLinqOptions<FakeEntity, obj>.None
88+
89+
[<Fact>]
90+
let ``ObjectListFilter works with Equals operator for ValidStringStruct`` () =
91+
let queryable = container.GetItemLinqQueryable<FakeEntity> ()
92+
let filter = Equals { FieldName = "validStringStruct"; Value = "Jonathan"}
93+
let filterQuery = queryable.Apply (filter, filterOptions)
94+
let queryDefinition = CosmosLinqExtensions.ToQueryDefinition filterQuery
95+
equals queryDefinition.QueryText """SELECT VALUE root FROM root WHERE (root["validStringStruct"] = "Jonathan")"""
96+
97+
[<Fact>]
98+
let ``ObjectListFilter works with Equals operator for ValidStringObject`` () =
99+
let filter = Equals { FieldName = "validStringObject"; Value = ValidStringObject "Jonathan" }
100+
let queryable = container.GetItemLinqQueryable<FakeEntity> ()
101+
let filterQuery = queryable.Apply (filter)
102+
let queryDefinition = CosmosLinqExtensions.ToQueryDefinition filterQuery
103+
equals queryDefinition.QueryText, """SELECT VALUE root FROM root WHERE (root["validStringObject"] = "Jonathan")"""
104+
105+
[<Fact>]
106+
let ``ObjectListFilter works with GreaterThan operator for ValidIntStruct`` () =
107+
let queryable = container.GetItemLinqQueryable<FakeEntity> ()
108+
let filter = GreaterThan { FieldName = "validIntStruct"; Value = 6L }
109+
let filterQuery = queryable.Apply (filter, filterOptions)
110+
let queryDefinition = CosmosLinqExtensions.ToQueryDefinition filterQuery
111+
equals queryDefinition.QueryText, """SELECT VALUE root FROM root WHERE (root["validIntStruct"] > 6)"""
112+
113+
[<Fact>]
114+
let ``ObjectListFilter works with GreaterThan operator for ValidIntObject`` () =
115+
let filter = GreaterThan { FieldName = "validIntObject"; Value = 6L }
116+
let queryable = container.GetItemLinqQueryable<FakeEntity> ()
117+
let filterQuery = queryable.Apply (filter)
118+
let queryDefinition = CosmosLinqExtensions.ToQueryDefinition filterQuery
119+
equals queryDefinition.QueryText, """SELECT VALUE root FROM root WHERE (root["validIntObject"] > 6)"""
120+

0 commit comments

Comments
 (0)