@@ -56,6 +56,8 @@ const QueryRootType = new GraphQLObjectType({
56
56
} ) ;
57
57
58
58
const TestSchema = new GraphQLSchema ( {
59
+ experimentalDefer : true ,
60
+ experimentalStream : true ,
59
61
query : QueryRootType ,
60
62
mutation : new GraphQLObjectType ( {
61
63
name : 'MutationRoot' ,
@@ -1022,6 +1024,54 @@ function runTests(server: Server) {
1022
1024
errors : [ { message : 'Must provide query string.' } ] ,
1023
1025
} ) ;
1024
1026
} ) ;
1027
+
1028
+ it ( 'allows for streaming results with @defer' , async ( ) => {
1029
+ const app = server ( ) ;
1030
+
1031
+ app . post (
1032
+ urlString ( ) ,
1033
+ graphqlHTTP ( {
1034
+ schema : TestSchema ,
1035
+ } ) ,
1036
+ ) ;
1037
+
1038
+ const req = app
1039
+ . request ( )
1040
+ . post ( urlString ( ) )
1041
+ . send ( {
1042
+ query :
1043
+ '{ ...frag @defer(label: "deferLabel") } fragment frag on QueryRoot { test(who: "World") }' ,
1044
+ } )
1045
+ . parse ( ( res , cb ) => {
1046
+ res . on ( 'data' , ( data ) => {
1047
+ res . text = `${ res . text || '' } ${ data . toString ( 'utf8' ) as string } ` ;
1048
+ } ) ;
1049
+ res . on ( 'end' , ( err ) => {
1050
+ cb ( err , null ) ;
1051
+ } ) ;
1052
+ } ) ;
1053
+
1054
+ const response = await req ;
1055
+ expect ( response . text ) . to . equal (
1056
+ [
1057
+ '' ,
1058
+ '---' ,
1059
+ 'Content-Type: application/json; charset=utf-8' ,
1060
+ 'Content-Length: 26' ,
1061
+ '' ,
1062
+ '{"data":{},"hasNext":true}' ,
1063
+ '' ,
1064
+ '---' ,
1065
+ 'Content-Type: application/json; charset=utf-8' ,
1066
+ 'Content-Length: 78' ,
1067
+ '' ,
1068
+ '{"data":{"test":"Hello World"},"path":[],"label":"deferLabel","hasNext":false}' ,
1069
+ '' ,
1070
+ '-----' ,
1071
+ '' ,
1072
+ ] . join ( '\r\n' ) ,
1073
+ ) ;
1074
+ } ) ;
1025
1075
} ) ;
1026
1076
1027
1077
describe ( 'Pretty printing' , ( ) => {
@@ -1104,6 +1154,62 @@ function runTests(server: Server) {
1104
1154
1105
1155
expect ( unprettyResponse . text ) . to . equal ( '{"data":{"test":"Hello World"}}' ) ;
1106
1156
} ) ;
1157
+ it ( 'supports pretty printing async iterable requests' , async ( ) => {
1158
+ const app = server ( ) ;
1159
+
1160
+ app . post (
1161
+ urlString ( ) ,
1162
+ graphqlHTTP ( {
1163
+ schema : TestSchema ,
1164
+ pretty : true ,
1165
+ } ) ,
1166
+ ) ;
1167
+
1168
+ const req = app
1169
+ . request ( )
1170
+ . post ( urlString ( ) )
1171
+ . send ( {
1172
+ query :
1173
+ '{ ...frag @defer } fragment frag on QueryRoot { test(who: "World") }' ,
1174
+ } )
1175
+ . parse ( ( res , cb ) => {
1176
+ res . on ( 'data' , ( data ) => {
1177
+ res . text = `${ res . text || '' } ${ data . toString ( 'utf8' ) as string } ` ;
1178
+ } ) ;
1179
+ res . on ( 'end' , ( err ) => {
1180
+ cb ( err , null ) ;
1181
+ } ) ;
1182
+ } ) ;
1183
+
1184
+ const response = await req ;
1185
+ expect ( response . text ) . to . equal (
1186
+ [
1187
+ '' ,
1188
+ '---' ,
1189
+ 'Content-Type: application/json; charset=utf-8' ,
1190
+ 'Content-Length: 35' ,
1191
+ '' ,
1192
+ [ '{' , ' "data": {},' , ' "hasNext": true' , '}' ] . join ( '\n' ) ,
1193
+ '' ,
1194
+ '---' ,
1195
+ 'Content-Type: application/json; charset=utf-8' ,
1196
+ 'Content-Length: 79' ,
1197
+ '' ,
1198
+ [
1199
+ '{' ,
1200
+ ' "data": {' ,
1201
+ ' "test": "Hello World"' ,
1202
+ ' },' ,
1203
+ ' "path": [],' ,
1204
+ ' "hasNext": false' ,
1205
+ '}' ,
1206
+ ] . join ( '\n' ) ,
1207
+ '' ,
1208
+ '-----' ,
1209
+ '' ,
1210
+ ] . join ( '\r\n' ) ,
1211
+ ) ;
1212
+ } ) ;
1107
1213
} ) ;
1108
1214
1109
1215
it ( 'will send request and response when using thunk' , async ( ) => {
@@ -1224,6 +1330,108 @@ function runTests(server: Server) {
1224
1330
} ) ;
1225
1331
} ) ;
1226
1332
1333
+ it ( 'allows for custom error formatting in initial payload of async iterator' , async ( ) => {
1334
+ const app = server ( ) ;
1335
+
1336
+ app . post (
1337
+ urlString ( ) ,
1338
+ graphqlHTTP ( {
1339
+ schema : TestSchema ,
1340
+ customFormatErrorFn ( error ) {
1341
+ return { message : 'Custom error format: ' + error . message } ;
1342
+ } ,
1343
+ } ) ,
1344
+ ) ;
1345
+
1346
+ const req = app
1347
+ . request ( )
1348
+ . post ( urlString ( ) )
1349
+ . send ( {
1350
+ query :
1351
+ '{ thrower, ...frag @defer } fragment frag on QueryRoot { test(who: "World") }' ,
1352
+ } )
1353
+ . parse ( ( res , cb ) => {
1354
+ res . on ( 'data' , ( data ) => {
1355
+ res . text = `${ res . text || '' } ${ data . toString ( 'utf8' ) as string } ` ;
1356
+ } ) ;
1357
+ res . on ( 'end' , ( err ) => {
1358
+ cb ( err , null ) ;
1359
+ } ) ;
1360
+ } ) ;
1361
+
1362
+ const response = await req ;
1363
+ expect ( response . text ) . to . equal (
1364
+ [
1365
+ '' ,
1366
+ '---' ,
1367
+ 'Content-Type: application/json; charset=utf-8' ,
1368
+ 'Content-Length: 94' ,
1369
+ '' ,
1370
+ '{"errors":[{"message":"Custom error format: Throws!"}],"data":{"thrower":null},"hasNext":true}' ,
1371
+ '' ,
1372
+ '---' ,
1373
+ 'Content-Type: application/json; charset=utf-8' ,
1374
+ 'Content-Length: 57' ,
1375
+ '' ,
1376
+ '{"data":{"test":"Hello World"},"path":[],"hasNext":false}' ,
1377
+ '' ,
1378
+ '-----' ,
1379
+ '' ,
1380
+ ] . join ( '\r\n' ) ,
1381
+ ) ;
1382
+ } ) ;
1383
+
1384
+ it ( 'allows for custom error formatting in subsequent payloads of async iterator' , async ( ) => {
1385
+ const app = server ( ) ;
1386
+
1387
+ app . post (
1388
+ urlString ( ) ,
1389
+ graphqlHTTP ( {
1390
+ schema : TestSchema ,
1391
+ customFormatErrorFn ( error ) {
1392
+ return { message : 'Custom error format: ' + error . message } ;
1393
+ } ,
1394
+ } ) ,
1395
+ ) ;
1396
+
1397
+ const req = app
1398
+ . request ( )
1399
+ . post ( urlString ( ) )
1400
+ . send ( {
1401
+ query :
1402
+ '{ test(who: "World"), ...frag @defer } fragment frag on QueryRoot { thrower }' ,
1403
+ } )
1404
+ . parse ( ( res , cb ) => {
1405
+ res . on ( 'data' , ( data ) => {
1406
+ res . text = `${ res . text || '' } ${ data . toString ( 'utf8' ) as string } ` ;
1407
+ } ) ;
1408
+ res . on ( 'end' , ( err ) => {
1409
+ cb ( err , null ) ;
1410
+ } ) ;
1411
+ } ) ;
1412
+
1413
+ const response = await req ;
1414
+ expect ( response . text ) . to . equal (
1415
+ [
1416
+ '' ,
1417
+ '---' ,
1418
+ 'Content-Type: application/json; charset=utf-8' ,
1419
+ 'Content-Length: 46' ,
1420
+ '' ,
1421
+ '{"data":{"test":"Hello World"},"hasNext":true}' ,
1422
+ '' ,
1423
+ '---' ,
1424
+ 'Content-Type: application/json; charset=utf-8' ,
1425
+ 'Content-Length: 105' ,
1426
+ '' ,
1427
+ '{"data":{"thrower":null},"path":[],"errors":[{"message":"Custom error format: Throws!"}],"hasNext":false}' ,
1428
+ '' ,
1429
+ '-----' ,
1430
+ '' ,
1431
+ ] . join ( '\r\n' ) ,
1432
+ ) ;
1433
+ } ) ;
1434
+
1227
1435
it ( 'allows for custom error formatting to elaborate' , async ( ) => {
1228
1436
const app = server ( ) ;
1229
1437
@@ -2215,6 +2423,57 @@ function runTests(server: Server) {
2215
2423
} ) ;
2216
2424
} ) ;
2217
2425
2426
+ it ( 'allows for custom extensions in initial and subsequent payloads of async iterator' , async ( ) => {
2427
+ const app = server ( ) ;
2428
+
2429
+ app . post (
2430
+ urlString ( ) ,
2431
+ graphqlHTTP ( {
2432
+ schema : TestSchema ,
2433
+ extensions ( { result } ) {
2434
+ return { preservedResult : { ...result } } ;
2435
+ } ,
2436
+ } ) ,
2437
+ ) ;
2438
+
2439
+ const req = app
2440
+ . request ( )
2441
+ . post ( urlString ( ) )
2442
+ . send ( {
2443
+ query :
2444
+ '{ hello: test(who: "Rob"), ...frag @defer } fragment frag on QueryRoot { test(who: "World") }' ,
2445
+ } )
2446
+ . parse ( ( res , cb ) => {
2447
+ res . on ( 'data' , ( data ) => {
2448
+ res . text = `${ res . text || '' } ${ data . toString ( 'utf8' ) as string } ` ;
2449
+ } ) ;
2450
+ res . on ( 'end' , ( err ) => {
2451
+ cb ( err , null ) ;
2452
+ } ) ;
2453
+ } ) ;
2454
+
2455
+ const response = await req ;
2456
+ expect ( response . text ) . to . equal (
2457
+ [
2458
+ '' ,
2459
+ '---' ,
2460
+ 'Content-Type: application/json; charset=utf-8' ,
2461
+ 'Content-Length: 124' ,
2462
+ '' ,
2463
+ '{"data":{"hello":"Hello Rob"},"hasNext":true,"extensions":{"preservedResult":{"data":{"hello":"Hello Rob"},"hasNext":true}}}' ,
2464
+ '' ,
2465
+ '---' ,
2466
+ 'Content-Type: application/json; charset=utf-8' ,
2467
+ 'Content-Length: 148' ,
2468
+ '' ,
2469
+ '{"data":{"test":"Hello World"},"path":[],"hasNext":false,"extensions":{"preservedResult":{"data":{"test":"Hello World"},"path":[],"hasNext":false}}}' ,
2470
+ '' ,
2471
+ '-----' ,
2472
+ '' ,
2473
+ ] . join ( '\r\n' ) ,
2474
+ ) ;
2475
+ } ) ;
2476
+
2218
2477
it ( 'extension function may be async' , async ( ) => {
2219
2478
const app = server ( ) ;
2220
2479
0 commit comments