@@ -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,243 @@ 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+ expect ( result ) . to . deep . equal ( {
1202+ data : {
1203+ fieldWithNullableStringInput : null ,
1204+ } ,
1205+ } ) ;
1206+ } ) ;
1207+
1208+ it ( 'when the definition has a default and is provided' , ( ) => {
1209+ const result = executeQueryWithFragmentArguments ( `
1210+ query {
1211+ ...a(value: "A")
1212+ }
1213+ fragment a($value: String! = "B") on TestType {
1214+ fieldWithNonNullableStringInput(input: $value)
1215+ }
1216+ ` ) ;
1217+ expect ( result ) . to . deep . equal ( {
1218+ data : {
1219+ fieldWithNonNullableStringInput : '"A"' ,
1220+ } ,
1221+ } ) ;
1222+ } ) ;
1223+
1224+ it ( 'when the definition has a default and is not provided' , ( ) => {
1225+ const result = executeQueryWithFragmentArguments ( `
1226+ query {
1227+ ...a
1228+ }
1229+ fragment a($value: String! = "B") on TestType {
1230+ fieldWithNonNullableStringInput(input: $value)
1231+ }
1232+ ` ) ;
1233+ expect ( result ) . to . deep . equal ( {
1234+ data : {
1235+ fieldWithNonNullableStringInput : '"B"' ,
1236+ } ,
1237+ } ) ;
1238+ } ) ;
1239+
1240+ it ( 'when the definition has a non-nullable default and is provided null' , ( ) => {
1241+ const result = executeQueryWithFragmentArguments ( `
1242+ query {
1243+ ...a(value: null)
1244+ }
1245+ fragment a($value: String! = "B") on TestType {
1246+ fieldWithNullableStringInput(input: $value)
1247+ }
1248+ ` ) ;
1249+ expect ( result ) . to . deep . equal ( {
1250+ data : {
1251+ fieldWithNullableStringInput : 'null' ,
1252+ } ,
1253+ } ) ;
1254+ } ) ;
1255+
1256+ it ( 'when the definition has no default and is not provided' , ( ) => {
1257+ const result = executeQueryWithFragmentArguments ( `
1258+ query {
1259+ ...a
1260+ }
1261+ fragment a($value: String) on TestType {
1262+ fieldWithNonNullableStringInputAndDefaultArgumentValue(input: $value)
1263+ }
1264+ ` ) ;
1265+ expect ( result ) . to . deep . equal ( {
1266+ data : {
1267+ fieldWithNonNullableStringInputAndDefaultArgumentValue :
1268+ '"Hello World"' ,
1269+ } ,
1270+ } ) ;
1271+ } ) ;
1272+
1273+ it ( 'when an argument is shadowed by an operation variable' , ( ) => {
1274+ const result = executeQueryWithFragmentArguments ( `
1275+ query($x: String! = "A") {
1276+ ...a(x: "B")
1277+ }
1278+ fragment a($x: String) on TestType {
1279+ fieldWithNullableStringInput(input: $x)
1280+ }
1281+ ` ) ;
1282+ expect ( result ) . to . deep . equal ( {
1283+ data : {
1284+ fieldWithNullableStringInput : '"B"' ,
1285+ } ,
1286+ } ) ;
1287+ } ) ;
1288+
1289+ it ( 'when a nullable argument with a field default is not provided and shadowed by an operation variable' , ( ) => {
1290+ const result = executeQueryWithFragmentArguments ( `
1291+ query($x: String = "A") {
1292+ ...a
1293+ }
1294+ fragment a($x: String) on TestType {
1295+ fieldWithNonNullableStringInputAndDefaultArgumentValue(input: $x)
1296+ }
1297+ ` ) ;
1298+ expect ( result ) . to . deep . equal ( {
1299+ data : {
1300+ fieldWithNonNullableStringInputAndDefaultArgumentValue :
1301+ '"Hello World"' ,
1302+ } ,
1303+ } ) ;
1304+ } ) ;
1305+
1306+ it ( 'when a fragment is used with different args' , ( ) => {
1307+ const result = executeQueryWithFragmentArguments ( `
1308+ query($x: String = "Hello") {
1309+ a: nested {
1310+ ...a(x: "a")
1311+ }
1312+ b: nested {
1313+ ...a(x: "b", b: true)
1314+ }
1315+ hello: nested {
1316+ ...a(x: $x)
1317+ }
1318+ }
1319+ fragment a($x: String, $b: Boolean = false) on NestedType {
1320+ a: echo(input: $x) @skip(if: $b)
1321+ b: echo(input: $x) @include(if: $b)
1322+ }
1323+ ` ) ;
1324+ expect ( result ) . to . deep . equal ( {
1325+ data : {
1326+ a : {
1327+ a : '"a"' ,
1328+ } ,
1329+ b : {
1330+ b : '"b"' ,
1331+ } ,
1332+ hello : {
1333+ a : '"Hello"' ,
1334+ } ,
1335+ } ,
1336+ } ) ;
1337+ } ) ;
1338+
1339+ it ( 'when the argument variable is nested in a complex type' , ( ) => {
1340+ const result = executeQueryWithFragmentArguments ( `
1341+ query {
1342+ ...a(value: "C")
1343+ }
1344+ fragment a($value: String) on TestType {
1345+ list(input: ["A", "B", $value, "D"])
1346+ }
1347+ ` ) ;
1348+ expect ( result ) . to . deep . equal ( {
1349+ data : {
1350+ list : '["A", "B", "C", "D"]' ,
1351+ } ,
1352+ } ) ;
1353+ } ) ;
1354+
1355+ it ( 'when argument variables are used recursively' , ( ) => {
1356+ const result = executeQueryWithFragmentArguments ( `
1357+ query {
1358+ ...a(aValue: "C")
1359+ }
1360+ fragment a($aValue: String) on TestType {
1361+ ...b(bValue: $aValue)
1362+ }
1363+ fragment b($bValue: String) on TestType {
1364+ list(input: ["A", "B", $bValue, "D"])
1365+ }
1366+ ` ) ;
1367+ expect ( result ) . to . deep . equal ( {
1368+ data : {
1369+ list : '["A", "B", "C", "D"]' ,
1370+ } ,
1371+ } ) ;
1372+ } ) ;
1373+
1374+ it ( 'when argument passed in as list' , ( ) => {
1375+ const result = executeQueryWithFragmentArguments ( `
1376+ query Q($opValue: String = "op") {
1377+ ...a(aValue: "A")
1378+ }
1379+ fragment a($aValue: String, $bValue: String) on TestType {
1380+ ...b(aValue: [$aValue, "B"], bValue: [$bValue, $opValue])
1381+ }
1382+ fragment b($aValue: [String], $bValue: [String], $cValue: String) on TestType {
1383+ aList: list(input: $aValue)
1384+ bList: list(input: $bValue)
1385+ cList: list(input: [$cValue])
1386+ }
1387+ ` ) ;
1388+ expect ( result ) . to . deep . equal ( {
1389+ data : {
1390+ aList : '["A", "B"]' ,
1391+ bList : '[null, "op"]' ,
1392+ cList : '[null]' ,
1393+ } ,
1394+ } ) ;
1395+ } ) ;
1396+ } ) ;
11391397} ) ;
0 commit comments