示例#1
0
        public ExecutionContext(Schema schema, DocumentNode queryDocument,
                                OperationDefinitionNode operation, VariableCollection variables,
                                object rootValue, object userContext)
        {
            Schema = schema
                     ?? throw new ArgumentNullException(nameof(schema));
            QueryDocument = queryDocument
                            ?? throw new ArgumentNullException(nameof(queryDocument));
            Operation = operation
                        ?? throw new ArgumentNullException(nameof(operation));
            Variables = variables
                        ?? throw new ArgumentNullException(nameof(variables));
            RootValue   = rootValue;
            UserContext = userContext;

            Fragments       = new FragmentCollection(schema, queryDocument);
            _fieldCollector = new FieldCollector(schema, variables, Fragments);
        }
示例#2
0
 protected override void VisitOperationDefinition(
     OperationDefinitionNode operation,
     ImmutableStack <ISyntaxNode> path)
 {
     foreach (VariableDefinitionNode variableDefinition in
              operation.VariableDefinitions)
     {
         if (Schema.TryGetTypeFromAst(variableDefinition.Type,
                                      out IType type) &&
             !type.IsInputType())
         {
             Errors.Add(new ValidationError(
                            "The type of variable " +
                            $"`{variableDefinition.Variable.Name.Value}` " +
                            "is not an input type.", variableDefinition));
         }
     }
 }
        public void QueryWithNonNullVariableAndDefaultWhereValueIsNull()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: String! = \"foo\") { a }");
            Dictionary <string, IValueNode> variableValues =
                new Dictionary <string, IValueNode>();

            // act
            VariableValueBuilder resolver =
                new VariableValueBuilder(schema, operation);
            VariableCollection coercedVariableValues =
                resolver.CreateValues(variableValues);

            // assert
            Assert.Equal("foo", coercedVariableValues.GetVariable <string>("test"));
        }
        public void QueryWithNonNullVariableAndDefaultWhereValueWasNotProvided()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: String! = \"foo\") { a }");
            var variableValues = new Dictionary <string, object>
            {
                { "test", NullValueNode.Default }
            };

            // act
            var    resolver = new VariableValueBuilder(schema, operation);
            Action action   = () => resolver.CreateValues(variableValues);

            // assert
            Assert.Throws <QueryException>(action);
        }
示例#5
0
        protected override ISyntaxVisitorAction Leave(
            OperationDefinitionNode node,
            IDocumentValidatorContext context)
        {
            if (context.FieldSets.Count > 0)
            {
                TryMergeFieldsInSet(context, context.FieldSets[node.SelectionSet]);
            }

            if (node.SelectionSet.Selections.Count == 0)
            {
                context.Errors.Add(context.NoSelectionOnRootType(
                                       node,
                                       context.Schema.GetOperationType(node.Operation)));
            }

            return(base.Leave(node, context));
        }
            private DocumentNode RewriteDocument(
                OperationDefinitionNode operation)
            {
                var definitions = new List <IDefinitionNode>();

                var variables = operation.VariableDefinitions.ToList();

                variables.AddRange(_visitor.VariableDeclarations);
                operation = operation.WithVariableDefinitions(variables);
                definitions.Add(operation);

                foreach (var fragmentName in _visitor.TouchedFragments)
                {
                    definitions.Add(_fragments[fragmentName]);
                }

                return(new DocumentNode(definitions));
            }
示例#7
0
        public void MergeFieldsWithFragmentSpreads()
        {
            // arrange
            DocumentNode query = Parser.Default.Parse(
                FileResource.Open("MergeQuery.graphql"));

            OperationDefinitionNode operation =
                query.Definitions.OfType <OperationDefinitionNode>().Single();

            var schema = Schema.Create(
                FileResource.Open("MergeSchema.graphql"),
                c => c.Use(next => context => Task.CompletedTask));

            var fragments = new FragmentCollection(schema, query);

            var variables = new VariableCollection(
                TypeConversion.Default,
                new Dictionary <string, object>());

            // act
            var collector = new FieldCollector(fragments, (f, s) => null);
            IReadOnlyCollection <FieldSelection> selections =
                collector.CollectFields(schema.QueryType,
                                        operation.SelectionSet, Path.New("foo"));

            // assert
            Assert.Collection(selections,
                              selection =>
            {
                Assert.Collection(selection.Selection.SelectionSet.Selections,
                                  selectionNode =>
                {
                    FragmentSpreadNode fragment = Assert.IsType <FragmentSpreadNode>(
                        selectionNode);
                    Assert.Equal("app", fragment.Name.Value);
                },
                                  selectionNode =>
                {
                    FragmentSpreadNode fragment = Assert.IsType <FragmentSpreadNode>(
                        selectionNode);
                    Assert.Equal("parts", fragment.Name.Value);
                });
            });
        }
示例#8
0
        private void CreateClassModels(
            IModelGeneratorContext context,
            OperationDefinitionNode operation,
            IType fieldType,
            FieldNode fieldSelection,
            PossibleSelections possibleSelections,
            IFragmentNode returnType,
            IInterfaceDescriptor interfaceDescriptor,
            Path path)
        {
            var resultParserTypes = new List <ResultParserTypeDescriptor>();
            IReadOnlyCollection <SelectionInfo> selections = possibleSelections.Variants;

            if (selections.Count == 1)
            {
                CreateClassModel(
                    context,
                    returnType,
                    interfaceDescriptor,
                    selections.Single(),
                    resultParserTypes);
            }
            else
            {
                CreateClassModels(
                    context,
                    fieldSelection,
                    returnType,
                    interfaceDescriptor,
                    selections,
                    resultParserTypes,
                    path);
            }

            context.Register(
                new ResultParserMethodDescriptor(
                    GetPathName(path),
                    operation,
                    fieldType,
                    fieldSelection,
                    path,
                    interfaceDescriptor,
                    resultParserTypes));
        }
示例#9
0
        public void FieldsAndInlineFragments()
        {
            // arrange
            Schema       schema = CreateSchema();
            DocumentNode query  = Parser.Default.Parse(@"
                {
                    a
                    ... on Foo {
                        z:a
                    }
                    ... on Fa {
                        x:a
                    }
                }
            ");

            VariableCollection variables = new VariableCollection(
                new Dictionary <string, object>());
            FragmentCollection fragments = new FragmentCollection(schema, query);

            OperationDefinitionNode operation = query.Definitions
                                                .OfType <OperationDefinitionNode>().First();

            // act
            FieldResolver fieldResolver = new FieldResolver(schema, variables, fragments);
            IReadOnlyCollection <FieldSelection> fields = fieldResolver
                                                          .CollectFields(schema.GetType <ObjectType>("Foo"),
                                                                         operation.SelectionSet, e => { });

            // assert
            Assert.Collection(fields,
                              f =>
            {
                Assert.Equal("a", f.ResponseName);
                Assert.Equal("a", f.Field.Name);
                Assert.Equal("String", f.Field.Type.TypeName());
            },
                              f =>
            {
                Assert.Equal("z", f.ResponseName);
                Assert.Equal("a", f.Field.Name);
                Assert.Equal("String", f.Field.Type.TypeName());
            });
        }
示例#10
0
        public void Fields()
        {
            // arrange
            var          errorRaised = false;
            Schema       schema      = CreateSchema();
            DocumentNode query       = Parser.Default.Parse(@"
                {
                    a
                    x:c
                }
            ");

            var variables = new VariableCollection(
                TypeConversion.Default,
                new Dictionary <string, object>());
            var fragments = new FragmentCollection(schema, query);

            OperationDefinitionNode operation = query.Definitions
                                                .OfType <OperationDefinitionNode>().First();

            // act
            var fieldResolver = new FieldCollector(fragments, (f, s) => null);
            IReadOnlyCollection <FieldSelection> fields = fieldResolver
                                                          .CollectFields(
                schema.GetType <ObjectType>("Foo"),
                operation.SelectionSet,
                null);

            // assert
            Assert.Collection(fields.Where(t => t.IsVisible(variables)),
                              f =>
            {
                Assert.Equal("a", f.ResponseName);
                Assert.Equal("a", f.Field.Name);
                Assert.Equal("String", f.Field.Type.TypeName());
            },
                              f =>
            {
                Assert.Equal("x", f.ResponseName);
                Assert.Equal("c", f.Field.Name);
                Assert.Equal("String", f.Field.Type.TypeName());
            });
            Assert.False(errorRaised);
        }
示例#11
0
        public void Prepare_Fragment_Definition()
        {
            // arrange
            ISchema schema = SchemaBuilder.New()
                             .AddStarWarsTypes()
                             .Create();

            DocumentNode document = Utf8GraphQLParser.Parse(
                @"{
                hero(episode: EMPIRE) {
                    name
                    ... abc
                    ... def
                }
              }

              fragment abc on Droid {
                  primaryFunction
              }

              fragment def on Human {
                  homePlanet
              }
             ");

            OperationDefinitionNode operation =
                document.Definitions.OfType <OperationDefinitionNode>().Single();

            var fragments = new FragmentCollection(schema, document);

            // act
            IReadOnlyDictionary <SelectionSetNode, SelectionVariants> selectionSets =
                OperationCompiler.Compile(schema, fragments, operation);

            // assert
            var op = new Operation(
                "abc",
                document,
                operation,
                schema.QueryType,
                selectionSets);

            op.Print().MatchSnapshot();
        }
示例#12
0
        public void Object_Field_Visibility_Is_Correctly_Inherited_3()
        {
            // arrange
            var variables = new Mock <IVariableValueCollection>();

            variables.Setup(t => t.GetVariable <bool>(It.IsAny <NameString>()))
            .Returns((NameString name) => name.Equals("v"));

            ISchema schema = SchemaBuilder.New()
                             .AddStarWarsTypes()
                             .Create();

            ObjectType droid = schema.GetType <ObjectType>("Droid");

            DocumentNode document = Utf8GraphQLParser.Parse(
                @"query foo($v: Boolean, $q: Boolean) {
                    hero(episode: EMPIRE) @include(if: $v) {
                        name @include(if: $q)
                    }
                }");

            OperationDefinitionNode operationDefinition =
                document.Definitions.OfType <OperationDefinitionNode>().Single();

            // act
            var operation =
                (Operation)OperationCompiler.Compile(
                    "a",
                    document,
                    operationDefinition,
                    schema,
                    schema.QueryType);

            // assert
            ISelectionSet rootSelections =
                operation.RootSelectionVariants.GetSelectionSet(
                    operation.RootSelectionVariants.GetPossibleTypes().First());
            ISelectionSet droidSelections =
                operation.GetSelectionSet(rootSelections.Selections[0].SelectionSet !, droid);

            Assert.Empty(droidSelections.Selections.Where(t => t.IsIncluded(variables.Object)));

            operation.Print().MatchSnapshot();
        }
示例#13
0
        private ObjectType GetOperationType(
            Schema schema, OperationDefinitionNode operation)
        {
            switch (operation.Operation)
            {
            case OperationType.Query:
                return(schema.QueryType);

            case OperationType.Mutation:
                return(schema.MutationType);

            case OperationType.Subscription:
                return(schema.SubscriptionType);

            default:
                throw new NotSupportedException(
                          "The specified operation type is not supported.");
            }
        }
示例#14
0
        public ResultParserDescriptor(
            string name,
            string ns,
            OperationDefinitionNode operation,
            ICodeDescriptor resultDescriptor,
            IReadOnlyList <IResultParserMethodDescriptor> parseMethods)
        {
            Name = name
                   ?? throw new ArgumentNullException(nameof(name));
            Namespace = ns ?? throw new ArgumentNullException(nameof(ns));
            Operation = operation
                        ?? throw new ArgumentNullException(nameof(operation));
            ResultDescriptor = resultDescriptor
                               ?? throw new ArgumentNullException(nameof(resultDescriptor));
            ParseMethods = parseMethods
                           ?? throw new ArgumentNullException(nameof(parseMethods));

            InvolvedLeafTypes = CollectLeafTypes(parseMethods);
        }
示例#15
0
        public ExecutionContext(Schema schema, DocumentNode queryDocument,
                                OperationDefinitionNode operation, VariableCollection variables,
                                IServiceProvider services, object rootValue, object userContext)
        {
            if (schema == null)
            {
                throw new ArgumentNullException(nameof(schema));
            }

            if (queryDocument == null)
            {
                throw new ArgumentNullException(nameof(queryDocument));
            }

            if (operation == null)
            {
                throw new ArgumentNullException(nameof(operation));
            }

            if (variables == null)
            {
                throw new ArgumentNullException(nameof(variables));
            }

            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            Schema        = schema;
            QueryDocument = queryDocument;
            Operation     = operation;
            Variables     = variables;
            RootValue     = rootValue;
            UserContext   = userContext;
            _services     = services;

            Data          = new OrderedDictionary();
            Fragments     = new FragmentCollection(schema, queryDocument);
            FieldResolver = new FieldResolver(schema, variables, Fragments);
            Errors        = new List <IQueryError>();
            NextBatch     = new List <FieldResolverTask>();
        }
示例#16
0
        protected virtual void VisitOperationDefinition(
            OperationDefinitionNode operation,
            ImmutableStack <ISyntaxNode> path)
        {
            IType operationType = Schema.GetOperationType(operation.Operation);

            if (operationType != null)
            {
                ImmutableStack <ISyntaxNode> newPath = path.Push(operation);

                VisitSelectionSet(
                    operation.SelectionSet,
                    operationType,
                    newPath);

                VisitDirectives(operation.Directives, newPath);
            }
            _visitedFragments.Clear();
        }
示例#17
0
        public void QueryWithNonNullVariableAndDefaultWhereValueWasNotProvided()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: String! = \"foo\") { a }");
            Dictionary <string, IValueNode> variableValues =
                new Dictionary <string, IValueNode>();

            variableValues.Add("test", new NullValueNode(null));

            // act
            VariableValueResolver resolver = new VariableValueResolver();
            Action action = () =>
                            resolver.CoerceVariableValues(schema, operation, variableValues);

            // assert
            Assert.Throws <QueryException>(action);
        }
示例#18
0
        private ICodeDescriptor GenerateOperationSelectionSet(
            ObjectType operationType,
            OperationDefinitionNode operation,
            Path path,
            Queue <FieldSelection> backlog)
        {
            PossibleSelections possibleSelections =
                _fieldCollector.CollectFields(
                    operationType,
                    operation.SelectionSet,
                    path);

            EnqueueFields(backlog, possibleSelections.ReturnType.Fields, path);

            ICodeDescriptor resultDescriptor = _objectModelGenerator.Generate(
                _context,
                operation,
                operationType,
                new NonNullType(operationType),
                new FieldNode(
                    null,
                    new NameNode(operation.Name !.Value),
                    null,
                    new[]
            {
                new DirectiveNode(
                    GeneratorDirectives.Type,
                    new ArgumentNode("name", operation.Name.Value)),
                new DirectiveNode(GeneratorDirectives.Operation)
            },
                    Array.Empty <ArgumentNode>(),
                    null),
                possibleSelections,
                path);

            _operationModelGenerator.Generate(
                _context,
                operationType,
                operation,
                resultDescriptor);

            return(resultDescriptor);
        }
示例#19
0
        public void QueryWithNonNullVariableAndDefaultWhereValueIsNull()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: String! = \"foo\") { a }");
            Dictionary <string, IValueNode> variableValues =
                new Dictionary <string, IValueNode>();

            // act
            VariableValueResolver       resolver = new VariableValueResolver();
            Dictionary <string, object> coercedVariableValues =
                resolver.CoerceVariableValues(schema, operation, variableValues);

            // assert
            Assert.True(coercedVariableValues.ContainsKey("test"));
            Assert.IsType <string>(coercedVariableValues["test"]);
            Assert.Equal("foo", coercedVariableValues["test"]);
        }
        public void FindUndeclaredVariablesInlineFragment()
        {
            // arrange
            ISchema schema = SchemaBuilder.New()
                             .AddStarWarsTypes()
                             .Create();

            DocumentNode document = Utf8GraphQLParser.Parse(
                @"
                query getHero {
                    ... on Query {
                        hero(episode: $ep) {
                            name
                        }
                    }
                }");

            OperationDefinitionNode operation = document.Definitions
                                                .OfType <OperationDefinitionNode>()
                                                .First();

            var visitor       = new CollectVariablesVisitor(schema);
            var visitationMap = new CollectVariablesVisitationMap();

            // act
            operation.Accept(
                visitor,
                visitationMap,
                node => VisitorAction.Continue);

            // assert
            var variables = operation.VariableDefinitions.ToList();

            variables.AddRange(visitor.VariableDeclarations);
            operation = operation.WithVariableDefinitions(variables);

            QuerySyntaxSerializer.Serialize(
                new DocumentNode(
                    new IDefinitionNode[]
            {
                operation
            })).MatchSnapshot();
        }
示例#21
0
        protected override ISyntaxVisitorAction Leave(
            OperationDefinitionNode node,
            IDocumentValidatorContext context)
        {
            context.Unused.ExceptWith(context.Used);
            context.Used.ExceptWith(context.Declared);

            if (context.Unused.Count > 0)
            {
                context.Errors.Add(context.VariableNotUsed(node));
            }

            if (context.Used.Count > 0)
            {
                context.Errors.Add(context.VariableNotDeclared(node));
            }

            return(base.Leave(node, context));
        }
        public void QueryWithNullableVariableAndNoDefaultWhereNoValueWasProvided()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: String) { a }");
            var variableValues = new Dictionary <string, object>();

            variableValues.Add("test", NullValueNode.Default);

            var resolver = new VariableValueBuilder(schema, operation);

            // act
            VariableCollection coercedVariableValues =
                resolver.CreateValues(variableValues);

            // assert
            Assert.Null(coercedVariableValues.GetVariable <string>("test"));
        }
示例#23
0
        public void InvalidFieldError()
        {
            // arrange
            bool         errorRaised = false;
            Schema       schema      = CreateSchema();
            DocumentNode query       = Parser.Default.Parse(@"
                {
                    a
                    x:c
                    xyz
                }
            ");

            VariableCollection variables = new VariableCollection(
                new Dictionary <string, object>());
            FragmentCollection fragments = new FragmentCollection(schema, query);

            OperationDefinitionNode operation = query.Definitions
                                                .OfType <OperationDefinitionNode>().First();

            // act
            FieldResolver fieldResolver = new FieldResolver(schema, variables, fragments);
            IReadOnlyCollection <FieldSelection> fields = fieldResolver
                                                          .CollectFields(schema.GetType <ObjectType>("Foo"),
                                                                         operation.SelectionSet, e => { errorRaised = true; });

            // assert
            Assert.Collection(fields,
                              f =>
            {
                Assert.Equal("a", f.ResponseName);
                Assert.Equal("a", f.Field.Name);
                Assert.Equal("String", f.Field.Type.TypeName());
            },
                              f =>
            {
                Assert.Equal("x", f.ResponseName);
                Assert.Equal("c", f.Field.Name);
                Assert.Equal("String", f.Field.Type.TypeName());
            });
            Assert.True(errorRaised);
        }
        private static void AddVariables(
            IQueryRequestBuilder builder,
            DocumentNode query,
            IEnumerable <Delegation.VariableValue> variableValues)
        {
            OperationDefinitionNode operation =
                query.Definitions.OfType <OperationDefinitionNode>().First();

            var usedVariables = new HashSet <string>(
                operation.VariableDefinitions.Select(t =>
                                                     t.Variable.Name.Value));

            foreach (Delegation.VariableValue variableValue in variableValues)
            {
                if (usedVariables.Contains(variableValue.Name))
                {
                    builder.AddVariableValue(variableValue.Name, variableValue.Value);
                }
            }
        }
示例#25
0
        public void QueryWithNullableVariableAndNoDefaultWhereNoValueWasProvided()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: String) { a }");
            Dictionary <string, IValueNode> variableValues =
                new Dictionary <string, IValueNode>();

            variableValues.Add("test", new NullValueNode(null));

            // act
            VariableValueResolver       resolver = new VariableValueResolver();
            Dictionary <string, object> coercedVariableValues =
                resolver.CoerceVariableValues(schema, operation, variableValues);

            // assert
            Assert.True(coercedVariableValues.ContainsKey("test"));
            Assert.Equal(null, coercedVariableValues["test"]);
        }
        public void Variable_InputObjectAsClrType_NonNullFieldNull()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: BazInput) { a }");
            var variableValues = new Dictionary <string, object>
            {
                { "test", new Baz {
                      Bar = "bar"
                  } }
            };

            // act
            var    resolver = new VariableValueBuilder(schema, operation);
            Action action   = () => resolver.CreateValues(variableValues);

            // assert
            Assert.Throws <QueryException>(action);
        }
        public void Variable_List_NonNullListItemNull()
        {
            // arrange
            Schema schema = CreateSchema();
            OperationDefinitionNode operation = CreateQuery(
                "query test($test: [String!]) { a }");
            var variableValues = new Dictionary <string, object>
            {
                { "test", new List <string> {
                      null
                  } }
            };

            // act
            var    resolver = new VariableValueBuilder(schema, operation);
            Action action   = () => resolver.CreateValues(variableValues);

            // assert
            Assert.Throws <QueryException>(action);
        }
示例#28
0
        public void Prepare_Fragment_Definition()
        {
            // arrange
            ISchema schema = SchemaBuilder.New()
                             .AddStarWarsTypes()
                             .Create();

            DocumentNode document = Utf8GraphQLParser.Parse(
                @"{
                hero(episode: EMPIRE) {
                    name
                    ... abc
                    ... def
                }
              }

              fragment abc on Droid {
                  primaryFunction
              }

              fragment def on Human {
                  homePlanet
              }
             ");

            OperationDefinitionNode operationDefinition =
                document.Definitions.OfType <OperationDefinitionNode>().Single();

            // act
            IPreparedOperation operation =
                OperationCompiler.Compile(
                    "a",
                    document,
                    operationDefinition,
                    schema,
                    schema.QueryType,
                    new(new DefaultTypeConverter()));

            // assert
            operation.Print().MatchSnapshot();
        }
示例#29
0
        public override ICodeDescriptor Generate(
            IModelGeneratorContext context,
            OperationDefinitionNode operation,
            ObjectType namedType,
            IType fieldType,
            FieldNode fieldSelection,
            PossibleSelections possibleSelections,
            Path path)
        {
            IFragmentNode returnType = ResolveReturnType(
                context,
                namedType,
                fieldSelection,
                possibleSelections.ReturnType);

            IInterfaceDescriptor interfaceDescriptor = CreateInterfaceModel(
                context, returnType, path);

            context.Register(fieldSelection, interfaceDescriptor);

            var resultParserTypes = new List <ResultParserTypeDescriptor>();

            CreateClassModel(
                context,
                returnType,
                interfaceDescriptor,
                possibleSelections.ReturnType,
                resultParserTypes);

            context.Register(
                new ResultParserMethodDescriptor(
                    GetPathName(path),
                    operation,
                    fieldType,
                    fieldSelection,
                    path,
                    interfaceDescriptor,
                    resultParserTypes));

            return(interfaceDescriptor);
        }
示例#30
0
        public void MergeMerged()
        {
            // arrange
            DocumentNode query = Utf8GraphQLParser.Parse(
                FileResource.Open("MergeQuery.graphql"));

            OperationDefinitionNode operation =
                query.Definitions.OfType <OperationDefinitionNode>().Single();

            var schema = Schema.Create(
                FileResource.Open("MergeSchema.graphql"),
                c => c.Use(next => context => Task.CompletedTask));

            var fragments = new FragmentCollection(schema, query);

            var variables = new VariableValueCollection(
                TypeConversion.Default,
                new Dictionary <string, object>());

            var collector = new FieldCollector(
                fragments,
                (f, s) => null,
                TypeConversion.Default,
                Array.Empty <IArgumentCoercionHandler>());

            IReadOnlyCollection <FieldSelection> selections =
                collector.CollectFields(schema.QueryType,
                                        operation.SelectionSet, Path.New("foo"));

            // act
            selections = collector.CollectFields(
                schema.GetType <ObjectType>("Application"),
                selections.Single().Selection.SelectionSet,
                Path.New("bat"));

            // assert
            Assert.Collection(selections,
                              selection => Assert.Equal("id", selection.ResponseName),
                              selection => Assert.Equal("name", selection.ResponseName),
                              selection => Assert.Equal("parts", selection.ResponseName));
        }