public OutputTypeModel AnalyzeOperation(
            IDocumentAnalyzerContext context,
            SelectionSetVariants selectionSetVariants)
        {
            Path rootSelectionPath = Path.Root.Append(context.OperationName);

            FragmentNode returnTypeFragment =
                FragmentHelper.CreateFragmentNode(
                    context.OperationType,
                    rootSelectionPath,
                    selectionSetVariants.ReturnType);

            returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment);

            OutputTypeModel returnType =
                FragmentHelper.CreateInterface(
                    context,
                    returnTypeFragment,
                    rootSelectionPath);

            FragmentHelper.CreateClass(
                context,
                returnTypeFragment,
                selectionSetVariants.ReturnType,
                returnType);

            return(returnType);
        }
Пример #2
0
        public async Task GetFragment_From_FragmentTree_Found()
        {
            // arrange
            var schema =
                await new ServiceCollection()
                .AddStarWarsRepositories()
                .AddGraphQL()
                .AddStarWars()
                .BuildSchemaAsync();

            var document =
                Utf8GraphQLParser.Parse(@"
                    query GetHero {
                        hero(episode: NEW_HOPE) @returns(fragment: ""Hero"") {
                            ... Characters
                        }
                    }

                    fragment Characters on Character @remove {
                        ... Human
                        ... Droid
                    }

                    fragment Hero on Character {
                        name
                    }

                    fragment Human on Human {
                        ... Hero
                        homePlanet
                    }

                    fragment Droid on Droid {
                        ... Hero
                        primaryFunction
                    }");

            var context = new DocumentAnalyzerContext(schema, document);
            var selectionSetVariants = context.CollectFields();
            var fieldSelection       = selectionSetVariants.ReturnType.Fields.First();

            selectionSetVariants = context.CollectFields(fieldSelection);

            // act
            var returnTypeFragmentName = FragmentHelper.GetReturnTypeName(fieldSelection);
            var returnTypeFragment     = FragmentHelper.CreateFragmentNode(
                selectionSetVariants.Variants[0],
                fieldSelection.Path,
                appendTypeName: true);

            returnTypeFragment = FragmentHelper.GetFragment(
                returnTypeFragment,
                returnTypeFragmentName !);

            // assert
            Assert.NotNull(returnTypeFragment);
            Assert.Equal("Hero", returnTypeFragment?.Fragment.Name);
        }
        private OutputTypeModel AnalyzeWithDefaults(
            IDocumentAnalyzerContext context,
            FieldSelection fieldSelection,
            SelectionSetVariants selectionVariants)
        {
            FragmentNode returnTypeFragment =
                FragmentHelper.CreateFragmentNode(
                    selectionVariants.ReturnType,
                    fieldSelection.Path);

            OutputTypeModel returnType =
                FragmentHelper.CreateInterface(
                    context,
                    returnTypeFragment,
                    fieldSelection.Path);

            context.RegisterSelectionSet(
                returnType.Type,
                selectionVariants.ReturnType.SyntaxNode,
                returnType.SelectionSet);

            foreach (SelectionSet selectionSet in selectionVariants.Variants)
            {
                returnTypeFragment = FragmentHelper.CreateFragmentNode(
                    selectionSet,
                    fieldSelection.Path,
                    appendTypeName: true);

                returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment);

                OutputTypeModel @interface =
                    FragmentHelper.CreateInterface(
                        context,
                        returnTypeFragment,
                        fieldSelection.Path,
                        new[] { returnType });

                OutputTypeModel @class =
                    FragmentHelper.CreateClass(
                        context,
                        returnTypeFragment,
                        selectionSet,
                        @interface);

                context.RegisterSelectionSet(
                    selectionSet.Type,
                    selectionSet.SyntaxNode,
                    @class.SelectionSet);
            }

            return(returnType);
        }
Пример #4
0
        public async Task GetReturnTypeName_Not_Found()
        {
            // arrange
            var schema =
                await new ServiceCollection()
                .AddStarWarsRepositories()
                .AddGraphQL()
                .AddStarWars()
                .BuildSchemaAsync();

            var document =
                Utf8GraphQLParser.Parse(@"
                    query GetHero {
                        hero(episode: NEW_HOPE) {
                            ... Characters
                        }
                    }

                    fragment Characters on Character {
                        ... Human
                        ... Droid
                    }

                    fragment Hero on Character {
                        name
                    }

                    fragment Human on Human {
                        ... Hero
                        homePlanet
                    }

                    fragment Droid on Droid {
                        ... Hero
                        primaryFunction
                    }");

            var context = new DocumentAnalyzerContext(schema, document);
            var selectionSetVariants = context.CollectFields();
            var fieldSelection       = selectionSetVariants.ReturnType.Fields.First();

            // act
            var returnTypeFragmentName = FragmentHelper.GetReturnTypeName(fieldSelection);

            // assert
            Assert.Null(returnTypeFragmentName);
        }
        public override OutputTypeModel Analyze(
            IDocumentAnalyzerContext context,
            FieldSelection fieldSelection,
            SelectionSetVariants selectionVariants)
        {
            var returnTypeFragmentName = FragmentHelper.GetReturnTypeName(fieldSelection);

            if (returnTypeFragmentName is null)
            {
                return(AnalyzeWithDefaults(
                           context,
                           fieldSelection,
                           selectionVariants));
            }

            return(AnalyzeWithHoistedFragment(
                       context,
                       fieldSelection,
                       selectionVariants,
                       returnTypeFragmentName));
        }
Пример #6
0
        public async Task Create_TypeModels_Infer_From_Fragments_With_HoistedFragment()
        {
            // arrange
            var schema =
                await new ServiceCollection()
                .AddStarWarsRepositories()
                .AddGraphQL()
                .AddStarWars()
                .BuildSchemaAsync();

            var document =
                Utf8GraphQLParser.Parse(@"
                    query GetHero {
                        hero(episode: NEW_HOPE) @returns(fragment: ""Hero"") {
                            ... Characters
                        }
                    }

                    fragment Characters on Character {
                        ... Human
                        ... Droid
                    }

                    fragment Hero on Character {
                        name
                    }

                    fragment Human on Human {
                        ... Hero
                        homePlanet
                    }

                    fragment Droid on Droid {
                        ... Hero
                        primaryFunction
                    }");

            var context = new DocumentAnalyzerContext(schema, document);
            var selectionSetVariants = context.CollectFields();
            var fieldSelection       = selectionSetVariants.ReturnType.Fields.First();

            selectionSetVariants = context.CollectFields(fieldSelection);

            // act
            var list = new List <OutputTypeModel>();
            var returnTypeFragmentName = FragmentHelper.GetReturnTypeName(fieldSelection);
            var returnTypeFragment     = FragmentHelper.CreateFragmentNode(
                selectionSetVariants.Variants[0],
                fieldSelection.Path,
                appendTypeName: true);

            returnTypeFragment = FragmentHelper.GetFragment(
                returnTypeFragment,
                returnTypeFragmentName !);
            list.Add(FragmentHelper.CreateInterface(
                         context,
                         returnTypeFragment !,
                         fieldSelection.Path));

            foreach (SelectionSet selectionSet in
                     selectionSetVariants.Variants.OrderBy(t => t.Type.Name.Value))
            {
                returnTypeFragment = FragmentHelper.CreateFragmentNode(
                    selectionSet,
                    fieldSelection.Path,
                    appendTypeName: true);

                returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment);

                OutputTypeModel @interface = FragmentHelper.CreateInterface(
                    context,
                    returnTypeFragment,
                    fieldSelection.Path,
                    new [] { list[0] });

                OutputTypeModel @class = FragmentHelper.CreateClass(
                    context,
                    returnTypeFragment,
                    selectionSet,
                    @interface);

                list.Add(@interface);
                list.Add(@class);
            }

            // assert
            Assert.Collection(
                list,
                type =>
            {
                Assert.Equal("IHero", type.Name);

                Assert.Empty(type.Implements);

                Assert.Collection(
                    type.Fields,
                    field => Assert.Equal("Name", field.Name));
            },
                type =>
            {
                Assert.Equal("IGetHero_Hero_Droid", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("ICharacters_Droid", impl.Name));

                Assert.Empty(type.Fields);
            },
                type =>
            {
                Assert.Equal("GetHero_Hero_Droid", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("IGetHero_Hero_Droid", impl.Name));

                Assert.Collection(
                    type.Fields,
                    field => Assert.Equal("Name", field.Name),
                    field => Assert.Equal("PrimaryFunction", field.Name));
            },
                type =>
            {
                Assert.Equal("IGetHero_Hero_Human", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("ICharacters_Human", impl.Name));

                Assert.Empty(type.Fields);
            },
                type =>
            {
                Assert.Equal("GetHero_Hero_Human", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("IGetHero_Hero_Human", impl.Name));

                Assert.Collection(
                    type.Fields,
                    field => Assert.Equal("Name", field.Name),
                    field => Assert.Equal("HomePlanet", field.Name));
            });
        }
Пример #7
0
        public async Task Create_TypeModels_Infer_TypeStructure()
        {
            // arrange
            var schema =
                await new ServiceCollection()
                .AddStarWarsRepositories()
                .AddGraphQL()
                .AddStarWars()
                .BuildSchemaAsync();

            var document =
                Utf8GraphQLParser.Parse(@"
                    query GetHero {
                        hero(episode: NEW_HOPE) {
                            name
                        }
                    }");

            var context = new DocumentAnalyzerContext(schema, document);
            var selectionSetVariants = context.CollectFields();
            var fieldSelection       = selectionSetVariants.ReturnType.Fields.First();

            selectionSetVariants = context.CollectFields(fieldSelection);

            // act
            var list = new List <OutputTypeModel>();
            var returnTypeFragment = FragmentHelper.CreateFragmentNode(
                selectionSetVariants.ReturnType,
                fieldSelection.Path);

            list.Add(FragmentHelper.CreateInterface(
                         context,
                         returnTypeFragment,
                         fieldSelection.Path));

            foreach (SelectionSet selectionSet in
                     selectionSetVariants.Variants.OrderBy(t => t.Type.Name.Value))
            {
                returnTypeFragment = FragmentHelper.CreateFragmentNode(
                    selectionSet,
                    fieldSelection.Path,
                    appendTypeName: true);

                OutputTypeModel @interface = FragmentHelper.CreateInterface(
                    context,
                    returnTypeFragment,
                    fieldSelection.Path,
                    new [] { list[0] });

                OutputTypeModel @class = FragmentHelper.CreateClass(
                    context,
                    returnTypeFragment,
                    selectionSet,
                    @interface);

                list.Add(@interface);
                list.Add(@class);
            }

            // assert
            Assert.Collection(
                list,
                type =>
            {
                Assert.Equal("IGetHero_Hero", type.Name);

                Assert.Empty(type.Implements);

                Assert.Collection(
                    type.Fields,
                    field => Assert.Equal("Name", field.Name));
            },
                type =>
            {
                Assert.Equal("IGetHero_Hero_Droid", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("IGetHero_Hero", impl.Name));

                Assert.Empty(type.Fields);
            },
                type =>
            {
                Assert.Equal("GetHero_Hero_Droid", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("IGetHero_Hero_Droid", impl.Name));

                Assert.Collection(
                    type.Fields,
                    field => Assert.Equal("Name", field.Name));
            },
                type =>
            {
                Assert.Equal("IGetHero_Hero_Human", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("IGetHero_Hero", impl.Name));

                Assert.Empty(type.Fields);
            },
                type =>
            {
                Assert.Equal("GetHero_Hero_Human", type.Name);

                Assert.Collection(
                    type.Implements,
                    impl => Assert.Equal("IGetHero_Hero_Human", impl.Name));

                Assert.Collection(
                    type.Fields,
                    field => Assert.Equal("Name", field.Name));
            });
        }
        private OutputTypeModel AnalyzeWithHoistedFragment(
            IDocumentAnalyzerContext context,
            FieldSelection fieldSelection,
            SelectionSetVariants selectionVariants,
            string fragmentName)
        {
            FragmentNode?returnTypeFragment =
                FragmentHelper.CreateFragmentNode(
                    selectionVariants.Variants[0],
                    fieldSelection.Path,
                    appendTypeName: true);

            returnTypeFragment = FragmentHelper.GetFragment(returnTypeFragment, fragmentName);

            if (returnTypeFragment is null)
            {
                // TODO : throw helper
                throw new GraphQLException(
                          "The specified return fragment does not exist.");
            }

            OutputTypeModel returnType =
                FragmentHelper.CreateInterface(context, returnTypeFragment, fieldSelection.Path);

            context.RegisterSelectionSet(
                returnType.Type,
                selectionVariants.ReturnType.SyntaxNode,
                returnType.SelectionSet);

            foreach (SelectionSet selectionSet in selectionVariants.Variants)
            {
                returnTypeFragment = FragmentHelper.CreateFragmentNode(
                    selectionSet,
                    fieldSelection.Path,
                    appendTypeName: true);

                returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment);

                if (FragmentHelper.GetFragment(returnTypeFragment, fragmentName) is null)
                {
                    // TODO : throw helper
                    throw new GraphQLException(
                              "The specified return fragment must be implement by all type fragments.");
                }

                OutputTypeModel @interface =
                    FragmentHelper.CreateInterface(
                        context,
                        returnTypeFragment,
                        fieldSelection.Path,
                        new[] { returnType });

                OutputTypeModel @class =
                    FragmentHelper.CreateClass(
                        context,
                        returnTypeFragment,
                        selectionSet,
                        @interface);

                context.RegisterSelectionSet(
                    selectionSet.Type,
                    selectionSet.SyntaxNode,
                    @class.SelectionSet);
            }

            return(returnType);
        }
        private OutputTypeModel AnalyzeWithHoistedFragment(
            IDocumentAnalyzerContext context,
            FieldSelection fieldSelection,
            SelectionSetVariants selectionVariants,
            string fragmentName)
        {
            FragmentNode?returnTypeFragment =
                FragmentHelper.CreateFragmentNode(
                    selectionVariants.Variants[0],
                    fieldSelection.Path,
                    appendTypeName: true);

            returnTypeFragment = FragmentHelper.GetFragment(returnTypeFragment, fragmentName);

            if (returnTypeFragment is null)
            {
                throw ThrowHelper.ReturnFragmentDoesNotExist();
            }

            OutputTypeModel returnType =
                FragmentHelper.CreateInterface(context, returnTypeFragment, fieldSelection.Path);

            context.RegisterSelectionSet(
                returnType.Type,
                selectionVariants.ReturnType.SyntaxNode,
                returnType.SelectionSet);

            foreach (SelectionSet selectionSet in selectionVariants.Variants)
            {
                returnTypeFragment = FragmentHelper.CreateFragmentNode(
                    selectionSet,
                    fieldSelection.Path,
                    appendTypeName: true);

                returnTypeFragment = FragmentHelper.RewriteForConcreteType(returnTypeFragment);

                if (FragmentHelper.GetFragment(returnTypeFragment, fragmentName) is null)
                {
                    throw ThrowHelper.FragmentMustBeImplementedByAllTypeFragments();
                }

                OutputTypeModel @interface =
                    FragmentHelper.CreateInterface(
                        context,
                        returnTypeFragment,
                        fieldSelection.Path,
                        new[] { returnType });

                OutputTypeModel @class =
                    FragmentHelper.CreateClass(
                        context,
                        returnTypeFragment,
                        selectionSet,
                        @interface);

                context.RegisterSelectionSet(
                    selectionSet.Type,
                    selectionSet.SyntaxNode,
                    @class.SelectionSet);
            }

            return(returnType);
        }