示例#1
0
        public ClientModel Analyze()
        {
            if (_schema is null)
            {
                throw new InvalidOperationException(
                          "You must provide a schema.");
            }

            if (_documents.Count == 0)
            {
                throw new InvalidOperationException(
                          "You must at least provide one document.");
            }

            if (_hashProvider is null)
            {
                throw new InvalidOperationException(
                          "You must specify a hash provider.");
            }

            var context = new DocumentAnalyzerContext(_schema, _reservedName);

            CollectEnumTypes(context, _documents.Values);
            CollectInputObjectTypes(context, _documents.Values);
            CollectOutputTypes(context, _documents.Values);

            return(new ClientModel(
                       _documents.Select(d =>
                                         CreateDocumentModel(context, d.Key, d.Value, _hashProvider))
                       .ToArray(),
                       context.Types.ToArray()));
        }
        public async Task Union_With_Fragment_Definition_Two_Models()
        {
            // arrange
            var schema =
                await new ServiceCollection()
                .AddStarWarsRepositories()
                .AddGraphQL()
                .AddStarWars()
                .BuildSchemaAsync();

            var document =
                Utf8GraphQLParser.Parse(@"
                    query GetHero {
                        search(text: ""hello"") {
                            ... Hero
                            ... Starship
                        }
                    }

                    fragment Hero on Character {
                        name
                        ... Human
                        ... Droid
                    }

                    fragment Human on Human {
                        homePlanet
                    }

                    fragment Droid on Droid {
                        primaryFunction
                    }

                    fragment Starship on Starship {
                        length
                    }");

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

            selectionSetVariants = context.CollectFields(fieldSelection);

            // act
            var analyzer = new InterfaceTypeSelectionSetAnalyzer();
            var result   = analyzer.Analyze(context, fieldSelection, selectionSetVariants);

            // assert
            Assert.Equal("IGetHero_Search", result.Name);

            Assert.Collection(
                context.GetImplementations(result),
                model => Assert.Equal("IGetHero_Search_Starship", model.Name),
                model => Assert.Equal("IGetHero_Search_Human", model.Name),
                model => Assert.Equal("IGetHero_Search_Droid", model.Name));

            Assert.Empty(result.Fields);
        }
        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);
        }
        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 async Task Interface_With_Default_Names_Two_Models()
        {
            // arrange
            var schema =
                await new ServiceCollection()
                .AddStarWarsRepositories()
                .AddGraphQL()
                .AddStarWars()
                .BuildSchemaAsync();

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

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

            selectionSetVariants = context.CollectFields(fieldSelection);

            // act
            var analyzer = new InterfaceTypeSelectionSetAnalyzer();
            var result   = analyzer.Analyze(context, fieldSelection, selectionSetVariants);

            // assert
            Assert.Equal("IGetHero_Hero", result.Name);

            Assert.Collection(
                context.GetImplementations(result),
                model => Assert.Equal("IGetHero_Hero_Human", model.Name),
                model => Assert.Equal("IGetHero_Hero_Droid", model.Name));

            Assert.Collection(
                result.Fields,
                field => Assert.Equal("Name", field.Name));
        }
        public async Task Interface_With_Fragment_Definition_One_Model()
        {
            // arrange
            var schema =
                await new ServiceCollection()
                .AddStarWarsRepositories()
                .AddGraphQL()
                .AddStarWars()
                .BuildSchemaAsync();

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

                    fragment Hero on Character {
                        name
                    }");

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

            selectionSetVariants = context.CollectFields(fieldSelection);

            // act
            var analyzer = new InterfaceTypeSelectionSetAnalyzer();
            var result   = analyzer.Analyze(context, fieldSelection, selectionSetVariants);

            // assert
            Assert.Equal("IGetHero_Hero", result.Name);

            Assert.Collection(
                context.GetImplementations(result).OrderBy(t => t.Name),
                model => Assert.Equal("IGetHero_Hero_Droid", model.Name),
                model => Assert.Equal("IGetHero_Hero_Human", model.Name));

            Assert.Empty(result.Fields);
        }
示例#7
0
        public void Interface_With_2_Selections_Per_Type()
        {
            // arrange
            ISchema schema =
                SchemaBuilder.New()
                .Use(next => context => Task.CompletedTask)
                .AddDocumentFromString(@"
                    type Query {
                      foo: Foo
                    }

                    interface Foo {
                      id: String
                      name: String
                    }

                    type Bar implements Foo {
                      id: String
                      name: String
                      bar: String
                      bar2: String
                    }

                    type Baz implements Foo {
                      id: String
                      name: String
                      baz: String
                      baz2: String
                    }")
                .Create();

            DocumentNode document =
                Utf8GraphQLParser.Parse(@"
                {
                  foo {
                    id
                    name
                    ... on Bar {
                      bar
                    }
                    ... on Bar {
                      bar2
                    }
                    ... on Baz {
                      baz
                    }
                    ... on Baz {
                      baz2
                    }
                  }
                }");

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

            FieldNode field =
                operation.SelectionSet.Selections.OfType <FieldNode>().Single();

            var context = new DocumentAnalyzerContext(schema);

            context.SetDocument(document);

            InterfaceType fooType  = schema.GetType <InterfaceType>("Foo");
            Path          rootPath = Path.New("foo");

            PossibleSelections possibleSelections =
                context.CollectFields(
                    fooType,
                    field.SelectionSet,
                    rootPath);

            // act
            var analyzer = new InterfaceTypeSelectionSetAnalyzer();

            analyzer.Analyze(
                context,
                operation,
                field,
                possibleSelections,
                schema.QueryType.Fields["foo"].Type,
                fooType,
                rootPath);

            // assert

            /*
             * Assert.Collection(context.Types.OfType<ComplexOutputTypeModel>(),
             *  type =>
             *  {
             *      Assert.Equal("Foo", type.Name);
             *      Assert.Null(type.Description);
             *      Assert.Equal(fooType, type.Type);
             *      Assert.Equal(field.SelectionSet, type.SelectionSet);
             *      Assert.Empty(type.Types);
             *      Assert.Collection(type.Fields,
             *          field =>
             *          {
             *              Assert.Equal("Bar", field.Name);
             *              Assert.Null(field.Description);
             *              Assert.Equal(fooType.Fields["bar"], field.Field);
             *              Assert.Equal(fooType.Fields["bar"].Type, field.Type);
             *              Assert.Equal(rootPath.Append("bar"), field.Path);
             *          });
             *  });
             */
        }
示例#8
0
        public void Interface_Two_Types_One_Inline_Fragment_Per_Type()
        {
            // arrange
            ISchema schema =
                SchemaBuilder.New()
                .Use(next => context => Task.CompletedTask)
                .AddDocumentFromString(@"
                    type Query {
                      foo: Foo
                    }

                    interface Foo {
                      id: String
                      name: String
                    }

                    type Bar implements Foo {
                      id: String
                      name: String
                      bar: String
                    }

                    type Baz implements Foo {
                      id: String
                      name: String
                      baz: String
                    }")
                .Create();

            DocumentNode document =
                Utf8GraphQLParser.Parse(@"
                {
                  foo {
                    id
                    name
                    ... on Bar {
                      bar
                    }
                    ... on Baz {
                      baz
                    }
                  }
                }");

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

            FieldNode field =
                operation.SelectionSet.Selections.OfType <FieldNode>().Single();

            var context = new DocumentAnalyzerContext(schema);

            context.SetDocument(document);

            InterfaceType fooType  = schema.GetType <InterfaceType>("Foo");
            Path          rootPath = Path.New("foo");

            PossibleSelections possibleSelections =
                context.CollectFields(
                    fooType,
                    field.SelectionSet,
                    rootPath);

            // act
            var analyzer = new InterfaceTypeSelectionSetAnalyzer();

            analyzer.Analyze(
                context,
                operation,
                field,
                possibleSelections,
                schema.QueryType.Fields["foo"].Type,
                fooType,
                rootPath);

            // assert
        }
        public void Simple_Object_Selection_With_Alias()
        {
            // arrange
            ISchema schema =
                SchemaBuilder.New()
                .AddQueryType <Query>()
                .Create();

            DocumentNode document =
                Utf8GraphQLParser.Parse("{ foo { b: bar { baz } } }");

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

            FieldNode field =
                operation.SelectionSet.Selections.OfType <FieldNode>().Single();

            var context = new DocumentAnalyzerContext(schema);

            context.SetDocument(document);

            ObjectType fooType  = schema.GetType <ObjectType>("Foo");
            Path       rootPath = Path.New("foo");

            PossibleSelections possibleSelections =
                context.CollectFields(
                    fooType,
                    field.SelectionSet,
                    rootPath);

            // act
            var analyzer = new ObjectTypeSelectionSetAnalyzer();

            analyzer.Analyze(
                context,
                operation,
                field,
                possibleSelections,
                schema.QueryType.Fields["foo"].Type,
                fooType,
                rootPath);

            // assert
            Assert.Collection(context.Types.OfType <ComplexOutputTypeModel>(),
                              type =>
            {
                Assert.Equal("Foo", type.Name);
                Assert.Null(type.Description);
                Assert.Equal(fooType, type.Type);
                Assert.Equal(field.SelectionSet, type.SelectionSet);
                Assert.Empty(type.Types);
                Assert.Collection(type.Fields,
                                  field =>
                {
                    Assert.Equal("B", field.Name);
                    Assert.Null(field.Description);
                    Assert.Equal(fooType.Fields["bar"], field.Field);
                    Assert.Equal(fooType.Fields["bar"].Type, field.Type);
                    Assert.Equal(rootPath.Append("b"), field.Path);
                });
            });
        }
示例#10
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));
            });
        }
示例#11
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));
            });
        }