-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added tests for input records list and fixed missing
ExecuteInput
o…
…n input objects (#509) * Added tests for input records list * Fixed crash of input objects list creation from variables --------- Co-authored-by: Andrii Chebukin <XperiAndri@Outlook.com>
- Loading branch information
1 parent
c184046
commit 859c99c
Showing
3 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
191 changes: 191 additions & 0 deletions
191
tests/FSharp.Data.GraphQL.Tests/Variables and Inputs/InputRecordListTests.fs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
// The MIT License (MIT) | ||
|
||
module FSharp.Data.GraphQL.Tests.InputRecordListTests | ||
|
||
#nowarn "25" | ||
|
||
open Xunit | ||
open System.Collections.Immutable | ||
open System.Text.Json | ||
open System.Text.Json.Serialization | ||
|
||
open FSharp.Data.GraphQL | ||
open FSharp.Data.GraphQL.Types | ||
open FSharp.Data.GraphQL.Parser | ||
open FSharp.Data.GraphQL.Tests.InputRecordTests | ||
|
||
let schema verify = | ||
let schema = | ||
Schema ( | ||
query = | ||
Define.Object ( | ||
"Query", | ||
[ Define.Field ( | ||
"recordInputs", | ||
StringType, | ||
[ Define.Input ("records", ListOf InputRecordType) | ||
Define.Input ("recordsOptional", Nullable (ListOf (Nullable InputRecordOptionalType))) | ||
Define.Input ("recordsNested", ListOf (Nullable InputRecordNestedType)) ], | ||
(fun ctx name -> | ||
let _ = ctx.Arg<InputRecord list> "records" | ||
let _ = ctx.TryArg<list<InputRecordOptional option>> "recordsOptional" | ||
let recordNested = | ||
ctx.Arg<list<InputRecordNested option>> "recordsNested" | ||
|> List.tryHead | ||
|> Option.flatten | ||
match verify, recordNested with | ||
| Nothing, _ -> () | ||
| AllInclude, Some recordNested -> recordNested.s |> ValueOption.iter _.VerifyAllInclude | ||
| AllSkip, Some recordNested -> recordNested.s |> ValueOption.iter _.VerifyAllSkip | ||
| SkipAndIncludeNull, Some recordNested -> recordNested.s |> ValueOption.iter _.VerifySkipAndIncludeNull | ||
| _ -> () | ||
stringifyInput ctx name | ||
) | ||
) // TODO: add all args stringificaiton | ||
Define.Field ( | ||
"objectInputs", | ||
StringType, | ||
[ Define.Input ("object", InputObjectType) | ||
Define.Input ("objectOptional", Nullable InputObjectOptionalType) ], | ||
stringifyInput | ||
) ] // TODO: add all args stringificaiton | ||
) | ||
) | ||
|
||
Executor schema | ||
|
||
[<Fact>] | ||
let ``Execute handles creation of inline empty input records list`` () = | ||
let query = | ||
"""{ | ||
recordInputs( | ||
records: [], | ||
recordsOptional: [], | ||
recordsNested: [] | ||
) | ||
}""" | ||
let result = sync <| (schema AllInclude).AsyncExecute(parse query) | ||
ensureDirect result <| fun data errors -> empty errors | ||
|
||
[<Fact>] | ||
let ``Execute handles creation of inline input records list with all fields`` () = | ||
let query = | ||
"""{ | ||
recordInputs( | ||
records: [{ a: "a", b: "b", c: "c" }], | ||
recordsOptional: [{ a: "a", b: "b", c: "c" }], | ||
recordsNested: [{ | ||
a: { a: "a", b: "b", c: "c" }, | ||
b: { a: "a", b: "b", c: "c" }, | ||
c: { a: "a", b: "b", c: "c" }, | ||
s: { a: "a", b: "b", c: "c" }, | ||
l: [{ a: "a", b: "b", c: "c" }] | ||
}] | ||
) | ||
}""" | ||
let result = sync <| (schema AllInclude).AsyncExecute(parse query) | ||
ensureDirect result <| fun data errors -> empty errors | ||
|
||
[<Fact>] | ||
let ``Execute handles creation of inline input records list with optional null fields`` () = | ||
let query = | ||
"""{ | ||
recordInputs( | ||
records: [{ a: "a", b: "b", c: "c" }], | ||
recordsOptional: [null], | ||
recordsNested: [{ a: { a: "a", b: "b", c: "c" }, b: null, c: null, s: null, l: [] }] | ||
) | ||
}""" | ||
let result = sync <| (schema Nothing).AsyncExecute(parse query) | ||
ensureDirect result <| fun data errors -> empty errors | ||
|
||
[<Fact>] | ||
let ``Execute handles creation of inline input records list with mandatory only fields`` () = | ||
let query = | ||
"""{ | ||
recordInputs( | ||
records: [{ a: "a", b: "b", c: "c" }], | ||
recordsNested: [{ a: { a: "a", b: "b", c: "c" }, l: [{ a: "a", b: "b", c: "c" }] }] | ||
) | ||
}""" | ||
let result = sync <| (schema Nothing).AsyncExecute(parse query) | ||
ensureDirect result <| fun data errors -> empty errors | ||
|
||
let variablesWithAllInputs (record, optRecord, skippable) = | ||
$""" | ||
{{ | ||
"records":[%s{record}], | ||
"optRecords":[%s{optRecord}], | ||
"nestedRecords":[ {{ "a": {record}, "b": {optRecord}, "c": {optRecord}, "s": {skippable}, "l": [{record}] }}] | ||
}} | ||
""" | ||
|
||
let paramsWithValues variables = | ||
JsonDocument | ||
.Parse(variables : string) | ||
.RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions) | ||
|
||
[<Fact>] | ||
let ``Execute handles creation of input records list from variables with all fields`` () = | ||
let query = | ||
"""query ( | ||
$records: [InputRecord!]!, | ||
$optRecords: [InputRecordOptional], | ||
$nestedRecords: [InputRecordNested]! | ||
) { | ||
recordInputs( | ||
records: $records, | ||
recordsOptional: $optRecords, | ||
recordsNested: $nestedRecords | ||
) | ||
}""" | ||
let testInputObject = """{"a":"a","b":"b","c":"c"}""" | ||
let params' = | ||
variablesWithAllInputs(testInputObject, testInputObject, testInputObject) |> paramsWithValues | ||
let result = sync <| (schema AllInclude).AsyncExecute(parse query, variables = params') | ||
//let expected = NameValueLookup.ofList [ "recordInputs", upcast testInputObject ] | ||
ensureDirect result <| fun data errors -> | ||
empty errors | ||
//data |> equals (upcast expected) | ||
|
||
[<Fact>] | ||
let ``Execute handles creation of input records list from variables with optional null fields`` () = | ||
let query = | ||
"""query ( | ||
$records: [InputRecord!]!, | ||
$optRecords: [InputRecordOptional], | ||
$nestedRecords: [InputRecordNested]! | ||
) { | ||
recordInputs( | ||
records: $records, | ||
recordsOptional: $optRecords, | ||
recordsNested: $nestedRecords | ||
) | ||
}""" | ||
let testInputObject = """{"a":"a","b":"b","c":"c"}""" | ||
let testInputSkippable = """{ "a": null, "b": null, "c": null }""" | ||
let params' = variablesWithAllInputs(testInputObject, "null", testInputSkippable) |> paramsWithValues | ||
let result = sync <| (schema SkipAndIncludeNull).AsyncExecute(parse query, variables = params') | ||
ensureDirect result <| fun data errors -> empty errors | ||
|
||
[<Fact>] | ||
let ``Execute handles creation of input records from variables with mandatory only fields`` () = | ||
let variablesWithAllInputs (record) = | ||
$""" | ||
{{ | ||
"record":%s{record}, | ||
"list":[%s{record}] | ||
}} | ||
""" | ||
|
||
let query = | ||
"""query ($record: InputRecord!, $list: [InputRecord!]!){ | ||
recordInputs( | ||
records: [$record], | ||
recordsNested: [{ a: $record, l: $list }] | ||
) | ||
}""" | ||
let testInputObject = """{"a":"a","b":"b","c":"c"}""" | ||
let params' = variablesWithAllInputs testInputObject |> paramsWithValues | ||
let result = sync <| (schema AllSkip).AsyncExecute(parse query, variables = params') | ||
ensureDirect result <| fun data errors -> empty errors |