@@ -59,6 +59,13 @@ const TestComplexScalar = new GraphQLScalarType({
5959  } , 
6060} ) ; 
6161
62+ const  NestedType : GraphQLObjectType  =  new  GraphQLObjectType ( { 
63+   name : 'NestedType' , 
64+   fields : { 
65+     echo : fieldWithInputArg ( {  type : GraphQLString  } ) , 
66+   } , 
67+ } ) ; 
68+ 
6269const  TestInputObject  =  new  GraphQLInputObjectType ( { 
6370  name : 'TestInputObject' , 
6471  fields : { 
@@ -129,6 +136,10 @@ const TestType = new GraphQLObjectType({
129136      defaultValue : 'Hello World' , 
130137    } ) , 
131138    list : fieldWithInputArg ( {  type : new  GraphQLList ( GraphQLString )  } ) , 
139+     nested : { 
140+       type : NestedType , 
141+       resolve : ( )  =>  ( { } ) , 
142+     } , 
132143    nnList : fieldWithInputArg ( { 
133144      type : new  GraphQLNonNull ( new  GraphQLList ( GraphQLString ) ) , 
134145    } ) , 
@@ -153,6 +164,14 @@ function executeQuery(
153164  return  executeSync ( {  schema,  document,  variableValues } ) ; 
154165} 
155166
167+ function  executeQueryWithFragmentArguments ( 
168+   query : string , 
169+   variableValues ?: {  [ variable : string ] : unknown  } , 
170+ )  { 
171+   const  document  =  parse ( query ,  {  experimentalFragmentArguments : true  } ) ; 
172+   return  executeSync ( {  schema,  document,  variableValues } ) ; 
173+ } 
174+ 
156175describe ( 'Execute: Handles inputs' ,  ( )  =>  { 
157176  describe ( 'Handles objects and nullability' ,  ( )  =>  { 
158177    describe ( 'using inline structs' ,  ( )  =>  { 
@@ -1136,4 +1155,284 @@ describe('Execute: Handles inputs', () => {
11361155      } ) ; 
11371156    } ) ; 
11381157  } ) ; 
1158+ 
1159+   describe ( 'using fragment arguments' ,  ( )  =>  { 
1160+     it ( 'when there are no fragment arguments' ,  ( )  =>  { 
1161+       const  result  =  executeQueryWithFragmentArguments ( ` 
1162+         query { 
1163+           ...a 
1164+         } 
1165+         fragment a on TestType { 
1166+           fieldWithNonNullableStringInput(input: "A") 
1167+         } 
1168+       ` ) ; 
1169+       expect ( result ) . to . deep . equal ( { 
1170+         data : { 
1171+           fieldWithNonNullableStringInput : '"A"' , 
1172+         } , 
1173+       } ) ; 
1174+     } ) ; 
1175+ 
1176+     it ( 'when a value is required and provided' ,  ( )  =>  { 
1177+       const  result  =  executeQueryWithFragmentArguments ( ` 
1178+         query { 
1179+           ...a(value: "A") 
1180+         } 
1181+         fragment a($value: String!) on TestType { 
1182+           fieldWithNonNullableStringInput(input: $value) 
1183+         } 
1184+       ` ) ; 
1185+       expect ( result ) . to . deep . equal ( { 
1186+         data : { 
1187+           fieldWithNonNullableStringInput : '"A"' , 
1188+         } , 
1189+       } ) ; 
1190+     } ) ; 
1191+ 
1192+     it ( 'when a value is required and not provided' ,  ( )  =>  { 
1193+       const  result  =  executeQueryWithFragmentArguments ( ` 
1194+         query { 
1195+           ...a 
1196+         } 
1197+         fragment a($value: String!) on TestType { 
1198+           fieldWithNullableStringInput(input: $value) 
1199+         } 
1200+       ` ) ; 
1201+ 
1202+       expect ( result ) . to . have . property ( 'errors' ) ; 
1203+       expect ( result . errors ) . to . have . length ( 1 ) ; 
1204+       expect ( result . errors ?. at ( 0 ) ?. message ) . to . match ( 
1205+         / A r g u m e n t   " v a l u e "   o f   r e q u i r e d   t y p e   " S t r i n g ! " / , 
1206+       ) ; 
1207+     } ) ; 
1208+ 
1209+     it ( 'when the definition has a default and is provided' ,  ( )  =>  { 
1210+       const  result  =  executeQueryWithFragmentArguments ( ` 
1211+         query { 
1212+           ...a(value: "A") 
1213+         } 
1214+         fragment a($value: String! = "B") on TestType { 
1215+           fieldWithNonNullableStringInput(input: $value) 
1216+         } 
1217+       ` ) ; 
1218+       expect ( result ) . to . deep . equal ( { 
1219+         data : { 
1220+           fieldWithNonNullableStringInput : '"A"' , 
1221+         } , 
1222+       } ) ; 
1223+     } ) ; 
1224+ 
1225+     it ( 'when the definition has a default and is not provided' ,  ( )  =>  { 
1226+       const  result  =  executeQueryWithFragmentArguments ( ` 
1227+         query { 
1228+           ...a 
1229+         } 
1230+         fragment a($value: String! = "B") on TestType { 
1231+           fieldWithNonNullableStringInput(input: $value) 
1232+         } 
1233+       ` ) ; 
1234+       expect ( result ) . to . deep . equal ( { 
1235+         data : { 
1236+           fieldWithNonNullableStringInput : '"B"' , 
1237+         } , 
1238+       } ) ; 
1239+     } ) ; 
1240+ 
1241+     it ( 'when a definition has a default, is not provided, and spreads another fragment' ,  ( )  =>  { 
1242+       const  result  =  executeQueryWithFragmentArguments ( ` 
1243+         query { 
1244+           ...a 
1245+         } 
1246+         fragment a($a: String! = "B") on TestType { 
1247+           ...b(b: $a) 
1248+         } 
1249+         fragment b($b: String!) on TestType { 
1250+           fieldWithNonNullableStringInput(input: $b) 
1251+         } 
1252+       ` ) ; 
1253+       expect ( result ) . to . deep . equal ( { 
1254+         data : { 
1255+           fieldWithNonNullableStringInput : '"B"' , 
1256+         } , 
1257+       } ) ; 
1258+     } ) ; 
1259+ 
1260+     it ( 'when the definition has a non-nullable default and is provided null' ,  ( )  =>  { 
1261+       const  result  =  executeQueryWithFragmentArguments ( ` 
1262+         query { 
1263+           ...a(value: null) 
1264+         } 
1265+         fragment a($value: String! = "B") on TestType { 
1266+           fieldWithNullableStringInput(input: $value) 
1267+         } 
1268+       ` ) ; 
1269+ 
1270+       expect ( result ) . to . have . property ( 'errors' ) ; 
1271+       expect ( result . errors ) . to . have . length ( 1 ) ; 
1272+       expect ( result . errors ?. at ( 0 ) ?. message ) . to . match ( 
1273+         / A r g u m e n t   " v a l u e "   o f   n o n - n u l l   t y p e   " S t r i n g ! " / , 
1274+       ) ; 
1275+     } ) ; 
1276+ 
1277+     it ( 'when the definition has no default and is not provided' ,  ( )  =>  { 
1278+       const  result  =  executeQueryWithFragmentArguments ( ` 
1279+         query { 
1280+           ...a 
1281+         } 
1282+         fragment a($value: String) on TestType { 
1283+           fieldWithNonNullableStringInputAndDefaultArgumentValue(input: $value) 
1284+         } 
1285+       ` ) ; 
1286+       expect ( result ) . to . deep . equal ( { 
1287+         data : { 
1288+           fieldWithNonNullableStringInputAndDefaultArgumentValue :
1289+             '"Hello World"' , 
1290+         } , 
1291+       } ) ; 
1292+     } ) ; 
1293+ 
1294+     it ( 'when an argument is shadowed by an operation variable' ,  ( )  =>  { 
1295+       const  result  =  executeQueryWithFragmentArguments ( ` 
1296+         query($x: String! = "A") { 
1297+           ...a(x: "B") 
1298+         } 
1299+         fragment a($x: String) on TestType { 
1300+           fieldWithNullableStringInput(input: $x) 
1301+         } 
1302+       ` ) ; 
1303+       expect ( result ) . to . deep . equal ( { 
1304+         data : { 
1305+           fieldWithNullableStringInput : '"B"' , 
1306+         } , 
1307+       } ) ; 
1308+     } ) ; 
1309+ 
1310+     it ( 'when a nullable argument with a field default is not provided and shadowed by an operation variable' ,  ( )  =>  { 
1311+       const  result  =  executeQueryWithFragmentArguments ( ` 
1312+         query($x: String = "A") { 
1313+           ...a 
1314+         } 
1315+         fragment a($x: String) on TestType { 
1316+           fieldWithNonNullableStringInputAndDefaultArgumentValue(input: $x) 
1317+         } 
1318+       ` ) ; 
1319+       expect ( result ) . to . deep . equal ( { 
1320+         data : { 
1321+           fieldWithNonNullableStringInputAndDefaultArgumentValue :
1322+             '"Hello World"' , 
1323+         } , 
1324+       } ) ; 
1325+     } ) ; 
1326+ 
1327+     it ( 'when a fragment-variable is shadowed by an intermediate fragment-spread but defined in the operation-variables' ,  ( )  =>  { 
1328+       const  result  =  executeQueryWithFragmentArguments ( ` 
1329+         query($x: String = "A") { 
1330+           ...a 
1331+         } 
1332+         fragment a($x: String) on TestType { 
1333+           ...b 
1334+         } 
1335+ 
1336+         fragment b on TestType { 
1337+           fieldWithNullableStringInput(input: $x) 
1338+         } 
1339+       ` ) ; 
1340+       expect ( result ) . to . deep . equal ( { 
1341+         data : { 
1342+           fieldWithNullableStringInput : '"A"' , 
1343+         } , 
1344+       } ) ; 
1345+     } ) ; 
1346+ 
1347+     it ( 'when a fragment is used with different args' ,  ( )  =>  { 
1348+       const  result  =  executeQueryWithFragmentArguments ( ` 
1349+         query($x: String = "Hello") { 
1350+           a: nested { 
1351+             ...a(x: "a") 
1352+           } 
1353+           b: nested { 
1354+             ...a(x: "b", b: true) 
1355+           } 
1356+           hello: nested { 
1357+             ...a(x: $x) 
1358+           } 
1359+         } 
1360+         fragment a($x: String, $b: Boolean = false) on NestedType { 
1361+           a: echo(input: $x) @skip(if: $b) 
1362+           b: echo(input: $x) @include(if: $b) 
1363+         } 
1364+       ` ) ; 
1365+       expect ( result ) . to . deep . equal ( { 
1366+         data : { 
1367+           a : { 
1368+             a : '"a"' , 
1369+           } , 
1370+           b : { 
1371+             b : '"b"' , 
1372+           } , 
1373+           hello : { 
1374+             a : '"Hello"' , 
1375+           } , 
1376+         } , 
1377+       } ) ; 
1378+     } ) ; 
1379+ 
1380+     it ( 'when the argument variable is nested in a complex type' ,  ( )  =>  { 
1381+       const  result  =  executeQueryWithFragmentArguments ( ` 
1382+         query { 
1383+           ...a(value: "C") 
1384+         } 
1385+         fragment a($value: String) on TestType { 
1386+           list(input: ["A", "B", $value, "D"]) 
1387+         } 
1388+       ` ) ; 
1389+       expect ( result ) . to . deep . equal ( { 
1390+         data : { 
1391+           list : '["A", "B", "C", "D"]' , 
1392+         } , 
1393+       } ) ; 
1394+     } ) ; 
1395+ 
1396+     it ( 'when argument variables are used recursively' ,  ( )  =>  { 
1397+       const  result  =  executeQueryWithFragmentArguments ( ` 
1398+         query { 
1399+           ...a(aValue: "C") 
1400+         } 
1401+         fragment a($aValue: String) on TestType { 
1402+           ...b(bValue: $aValue) 
1403+         } 
1404+         fragment b($bValue: String) on TestType { 
1405+           list(input: ["A", "B", $bValue, "D"]) 
1406+         } 
1407+       ` ) ; 
1408+       expect ( result ) . to . deep . equal ( { 
1409+         data : { 
1410+           list : '["A", "B", "C", "D"]' , 
1411+         } , 
1412+       } ) ; 
1413+     } ) ; 
1414+ 
1415+     it ( 'when argument passed in as list' ,  ( )  =>  { 
1416+       const  result  =  executeQueryWithFragmentArguments ( ` 
1417+         query Q($opValue: String = "op") { 
1418+           ...a(aValue: "A") 
1419+         } 
1420+         fragment a($aValue: String, $bValue: String) on TestType { 
1421+           ...b(aValue: [$aValue, "B"], bValue: [$bValue, $opValue]) 
1422+         } 
1423+         fragment b($aValue: [String], $bValue: [String], $cValue: String) on TestType { 
1424+           aList: list(input: $aValue) 
1425+           bList: list(input: $bValue) 
1426+           cList: list(input: [$cValue]) 
1427+         } 
1428+       ` ) ; 
1429+       expect ( result ) . to . deep . equal ( { 
1430+         data : { 
1431+           aList : '["A", "B"]' , 
1432+           bList : '[null, "op"]' , 
1433+           cList : '[null]' , 
1434+         } , 
1435+       } ) ; 
1436+     } ) ; 
1437+   } ) ; 
11391438} ) ; 
0 commit comments