@@ -7,6 +7,7 @@ import { inspect } from '../../jsutils/inspect.js';
77
88import { GraphQLError } from '../../error/GraphQLError.js' ;
99
10+ import { DirectiveLocation } from '../../language/directiveLocation.js' ;
1011import { Kind } from '../../language/kinds.js' ;
1112import { parse } from '../../language/parser.js' ;
1213
@@ -22,10 +23,14 @@ import {
2223 GraphQLObjectType ,
2324 GraphQLScalarType ,
2425} from '../../type/definition.js' ;
25- import { GraphQLString } from '../../type/scalars.js' ;
26+ import {
27+ GraphQLDirective ,
28+ GraphQLIncludeDirective ,
29+ } from '../../type/directives.js' ;
30+ import { GraphQLBoolean , GraphQLString } from '../../type/scalars.js' ;
2631import { GraphQLSchema } from '../../type/schema.js' ;
2732
28- import { executeSync } from '../execute.js' ;
33+ import { executeSync , experimentalExecuteIncrementally } from '../execute.js' ;
2934import { getVariableValues } from '../values.js' ;
3035
3136const TestFaultyScalarGraphQLError = new GraphQLError (
@@ -154,7 +159,30 @@ const TestType = new GraphQLObjectType({
154159 } ,
155160} ) ;
156161
157- const schema = new GraphQLSchema ( { query : TestType } ) ;
162+ const schema = new GraphQLSchema ( {
163+ query : TestType ,
164+ directives : [
165+ new GraphQLDirective ( {
166+ name : 'skip' ,
167+ description :
168+ 'Directs the executor to skip this field or fragment when the `if` argument is true.' ,
169+ locations : [
170+ DirectiveLocation . FIELD ,
171+ DirectiveLocation . FRAGMENT_SPREAD ,
172+ DirectiveLocation . INLINE_FRAGMENT ,
173+ ] ,
174+ args : {
175+ if : {
176+ type : new GraphQLNonNull ( GraphQLBoolean ) ,
177+ description : 'Skipped when true.' ,
178+ // default values will override operation variables in the setting of defined fragment variables that are not provided
179+ defaultValue : true ,
180+ } ,
181+ } ,
182+ } ) ,
183+ GraphQLIncludeDirective ,
184+ ] ,
185+ } ) ;
158186
159187function executeQuery (
160188 query : string ,
@@ -1307,6 +1335,22 @@ describe('Execute: Handles inputs', () => {
13071335 } ) ;
13081336 } ) ;
13091337
1338+ it ( 'when a nullable argument without a field default is not provided and shadowed by an operation variable' , ( ) => {
1339+ const result = executeQueryWithFragmentArguments ( `
1340+ query($x: String = "A") {
1341+ ...a
1342+ }
1343+ fragment a($x: String) on TestType {
1344+ fieldWithNullableStringInput(input: $x)
1345+ }
1346+ ` ) ;
1347+ expect ( result ) . to . deep . equal ( {
1348+ data : {
1349+ fieldWithNullableStringInput : null ,
1350+ } ,
1351+ } ) ;
1352+ } ) ;
1353+
13101354 it ( 'when a nullable argument with a field default is not provided and shadowed by an operation variable' , ( ) => {
13111355 const result = executeQueryWithFragmentArguments ( `
13121356 query($x: String = "A") {
@@ -1412,6 +1456,27 @@ describe('Execute: Handles inputs', () => {
14121456 } ) ;
14131457 } ) ;
14141458
1459+ it ( 'when argument variables with the same name are used directly and recursively' , ( ) => {
1460+ const result = executeQueryWithFragmentArguments ( `
1461+ query {
1462+ ...a(value: "A")
1463+ }
1464+ fragment a($value: String!) on TestType {
1465+ ...b(value: "B")
1466+ fieldInFragmentA: fieldWithNonNullableStringInput(input: $value)
1467+ }
1468+ fragment b($value: String!) on TestType {
1469+ fieldInFragmentB: fieldWithNonNullableStringInput(input: $value)
1470+ }
1471+ ` ) ;
1472+ expect ( result ) . to . deep . equal ( {
1473+ data : {
1474+ fieldInFragmentA : '"A"' ,
1475+ fieldInFragmentB : '"B"' ,
1476+ } ,
1477+ } ) ;
1478+ } ) ;
1479+
14151480 it ( 'when argument passed in as list' , ( ) => {
14161481 const result = executeQueryWithFragmentArguments ( `
14171482 query Q($opValue: String = "op") {
@@ -1434,5 +1499,38 @@ describe('Execute: Handles inputs', () => {
14341499 } ,
14351500 } ) ;
14361501 } ) ;
1502+
1503+ it ( 'when argument passed to a directive' , ( ) => {
1504+ const result = executeQueryWithFragmentArguments ( `
1505+ query {
1506+ ...a(value: true)
1507+ }
1508+ fragment a($value: Boolean!) on TestType {
1509+ fieldWithNonNullableStringInput @skip(if: $value)
1510+ }
1511+ ` ) ;
1512+ expect ( result ) . to . deep . equal ( {
1513+ data : { } ,
1514+ } ) ;
1515+ } ) ;
1516+
1517+ it ( 'when a nullable argument to a directive with a field default is not provided and shadowed by an operation variable' , ( ) => {
1518+ // this test uses the @defer directive and incremental delivery because the `if` argument for skip/include have no field defaults
1519+ const document = parse (
1520+ `
1521+ query($shouldDefer: Boolean = false) {
1522+ ...a
1523+ }
1524+ fragment a($shouldDefer: Boolean) on TestType {
1525+ ... @defer(if: $shouldDefer) {
1526+ fieldWithDefaultArgumentValue
1527+ }
1528+ }
1529+ ` ,
1530+ { experimentalFragmentArguments : true } ,
1531+ ) ;
1532+ const result = experimentalExecuteIncrementally ( { schema, document } ) ;
1533+ expect ( result ) . to . include . keys ( 'initialResult' , 'subsequentResults' ) ;
1534+ } ) ;
14371535 } ) ;
14381536} ) ;
0 commit comments