|
| 1 | +// The MIT License (MIT) |
| 2 | + |
| 3 | +module FSharp.Data.GraphQL.Tests.InputRecordListTests |
| 4 | + |
| 5 | +#nowarn "25" |
| 6 | + |
| 7 | +open Xunit |
| 8 | +open System.Collections.Immutable |
| 9 | +open System.Text.Json |
| 10 | +open System.Text.Json.Serialization |
| 11 | + |
| 12 | +open FSharp.Data.GraphQL |
| 13 | +open FSharp.Data.GraphQL.Types |
| 14 | +open FSharp.Data.GraphQL.Parser |
| 15 | +open FSharp.Data.GraphQL.Tests.InputRecordTests |
| 16 | + |
| 17 | +let schema verify = |
| 18 | + let schema = |
| 19 | + Schema ( |
| 20 | + query = |
| 21 | + Define.Object ( |
| 22 | + "Query", |
| 23 | + [ Define.Field ( |
| 24 | + "recordInputs", |
| 25 | + StringType, |
| 26 | + [ Define.Input ("records", ListOf InputRecordType) |
| 27 | + Define.Input ("recordsOptional", Nullable (ListOf (Nullable InputRecordOptionalType))) |
| 28 | + Define.Input ("recordsNested", ListOf (Nullable InputRecordNestedType)) ], |
| 29 | + (fun ctx name -> |
| 30 | + let _ = ctx.Arg<InputRecord list> "records" |
| 31 | + let _ = ctx.TryArg<list<InputRecordOptional option>> "recordsOptional" |
| 32 | + let recordNested = |
| 33 | + ctx.Arg<list<InputRecordNested option>> "recordsNested" |
| 34 | + |> List.tryHead |
| 35 | + |> Option.flatten |
| 36 | + match verify, recordNested with |
| 37 | + | Nothing, _ -> () |
| 38 | + | AllInclude, Some recordNested -> recordNested.s |> ValueOption.iter _.VerifyAllInclude |
| 39 | + | AllSkip, Some recordNested -> recordNested.s |> ValueOption.iter _.VerifyAllSkip |
| 40 | + | SkipAndIncludeNull, Some recordNested -> recordNested.s |> ValueOption.iter _.VerifySkipAndIncludeNull |
| 41 | + | _ -> () |
| 42 | + stringifyInput ctx name |
| 43 | + ) |
| 44 | + ) // TODO: add all args stringificaiton |
| 45 | + Define.Field ( |
| 46 | + "objectInputs", |
| 47 | + StringType, |
| 48 | + [ Define.Input ("object", InputObjectType) |
| 49 | + Define.Input ("objectOptional", Nullable InputObjectOptionalType) ], |
| 50 | + stringifyInput |
| 51 | + ) ] // TODO: add all args stringificaiton |
| 52 | + ) |
| 53 | + ) |
| 54 | + |
| 55 | + Executor schema |
| 56 | + |
| 57 | +[<Fact>] |
| 58 | +let ``Execute handles creation of inline empty input records list`` () = |
| 59 | + let query = |
| 60 | + """{ |
| 61 | + recordInputs( |
| 62 | + records: [], |
| 63 | + recordsOptional: [], |
| 64 | + recordsNested: [] |
| 65 | + ) |
| 66 | + }""" |
| 67 | + let result = sync <| (schema AllInclude).AsyncExecute(parse query) |
| 68 | + ensureDirect result <| fun data errors -> empty errors |
| 69 | + |
| 70 | +[<Fact>] |
| 71 | +let ``Execute handles creation of inline input records list with all fields`` () = |
| 72 | + let query = |
| 73 | + """{ |
| 74 | + recordInputs( |
| 75 | + records: [{ a: "a", b: "b", c: "c" }], |
| 76 | + recordsOptional: [{ a: "a", b: "b", c: "c" }], |
| 77 | + recordsNested: [{ |
| 78 | + a: { a: "a", b: "b", c: "c" }, |
| 79 | + b: { a: "a", b: "b", c: "c" }, |
| 80 | + c: { a: "a", b: "b", c: "c" }, |
| 81 | + s: { a: "a", b: "b", c: "c" }, |
| 82 | + l: [{ a: "a", b: "b", c: "c" }] |
| 83 | + }] |
| 84 | + ) |
| 85 | + }""" |
| 86 | + let result = sync <| (schema AllInclude).AsyncExecute(parse query) |
| 87 | + ensureDirect result <| fun data errors -> empty errors |
| 88 | + |
| 89 | +[<Fact>] |
| 90 | +let ``Execute handles creation of inline input records list with optional null fields`` () = |
| 91 | + let query = |
| 92 | + """{ |
| 93 | + recordInputs( |
| 94 | + records: [{ a: "a", b: "b", c: "c" }], |
| 95 | + recordsOptional: [null], |
| 96 | + recordsNested: [{ a: { a: "a", b: "b", c: "c" }, b: null, c: null, s: null, l: [] }] |
| 97 | + ) |
| 98 | + }""" |
| 99 | + let result = sync <| (schema Nothing).AsyncExecute(parse query) |
| 100 | + ensureDirect result <| fun data errors -> empty errors |
| 101 | + |
| 102 | +[<Fact>] |
| 103 | +let ``Execute handles creation of inline input records list with mandatory only fields`` () = |
| 104 | + let query = |
| 105 | + """{ |
| 106 | + recordInputs( |
| 107 | + records: [{ a: "a", b: "b", c: "c" }], |
| 108 | + recordsNested: [{ a: { a: "a", b: "b", c: "c" }, l: [{ a: "a", b: "b", c: "c" }] }] |
| 109 | + ) |
| 110 | + }""" |
| 111 | + let result = sync <| (schema Nothing).AsyncExecute(parse query) |
| 112 | + ensureDirect result <| fun data errors -> empty errors |
| 113 | + |
| 114 | +let variablesWithAllInputs (record, optRecord, skippable) = |
| 115 | + $""" |
| 116 | + {{ |
| 117 | + "records":[%s{record}], |
| 118 | + "optRecords":[%s{optRecord}], |
| 119 | + "nestedRecords":[ {{ "a": {record}, "b": {optRecord}, "c": {optRecord}, "s": {skippable}, "l": [{record}] }}] |
| 120 | + }} |
| 121 | +""" |
| 122 | + |
| 123 | +let paramsWithValues variables = |
| 124 | + JsonDocument |
| 125 | + .Parse(variables : string) |
| 126 | + .RootElement.Deserialize<ImmutableDictionary<string, JsonElement>> (serializerOptions) |
| 127 | + |
| 128 | +[<Fact>] |
| 129 | +let ``Execute handles creation of input records list from variables with all fields`` () = |
| 130 | + let query = |
| 131 | + """query ( |
| 132 | + $records: [InputRecord!]!, |
| 133 | + $optRecords: [InputRecordOptional], |
| 134 | + $nestedRecords: [InputRecordNested]! |
| 135 | + ) { |
| 136 | + recordInputs( |
| 137 | + records: $records, |
| 138 | + recordsOptional: $optRecords, |
| 139 | + recordsNested: $nestedRecords |
| 140 | + ) |
| 141 | + }""" |
| 142 | + let testInputObject = """{"a":"a","b":"b","c":"c"}""" |
| 143 | + let params' = |
| 144 | + variablesWithAllInputs(testInputObject, testInputObject, testInputObject) |> paramsWithValues |
| 145 | + let result = sync <| (schema AllInclude).AsyncExecute(parse query, variables = params') |
| 146 | + //let expected = NameValueLookup.ofList [ "recordInputs", upcast testInputObject ] |
| 147 | + ensureDirect result <| fun data errors -> |
| 148 | + empty errors |
| 149 | + //data |> equals (upcast expected) |
| 150 | + |
| 151 | +[<Fact>] |
| 152 | +let ``Execute handles creation of input records list from variables with optional null fields`` () = |
| 153 | + let query = |
| 154 | + """query ( |
| 155 | + $records: [InputRecord!]!, |
| 156 | + $optRecords: [InputRecordOptional], |
| 157 | + $nestedRecords: [InputRecordNested]! |
| 158 | + ) { |
| 159 | + recordInputs( |
| 160 | + records: $records, |
| 161 | + recordsOptional: $optRecords, |
| 162 | + recordsNested: $nestedRecords |
| 163 | + ) |
| 164 | + }""" |
| 165 | + let testInputObject = """{"a":"a","b":"b","c":"c"}""" |
| 166 | + let testInputSkippable = """{ "a": null, "b": null, "c": null }""" |
| 167 | + let params' = variablesWithAllInputs(testInputObject, "null", testInputSkippable) |> paramsWithValues |
| 168 | + let result = sync <| (schema SkipAndIncludeNull).AsyncExecute(parse query, variables = params') |
| 169 | + ensureDirect result <| fun data errors -> empty errors |
| 170 | + |
| 171 | +[<Fact>] |
| 172 | +let ``Execute handles creation of input records from variables with mandatory only fields`` () = |
| 173 | + let variablesWithAllInputs (record) = |
| 174 | + $""" |
| 175 | + {{ |
| 176 | + "record":%s{record}, |
| 177 | + "list":[%s{record}] |
| 178 | + }} |
| 179 | + """ |
| 180 | + |
| 181 | + let query = |
| 182 | + """query ($record: InputRecord!, $list: [InputRecord!]!){ |
| 183 | + recordInputs( |
| 184 | + records: [$record], |
| 185 | + recordsNested: [{ a: $record, l: $list }] |
| 186 | + ) |
| 187 | + }""" |
| 188 | + let testInputObject = """{"a":"a","b":"b","c":"c"}""" |
| 189 | + let params' = variablesWithAllInputs testInputObject |> paramsWithValues |
| 190 | + let result = sync <| (schema AllSkip).AsyncExecute(parse query, variables = params') |
| 191 | + ensureDirect result <| fun data errors -> empty errors |
0 commit comments