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); }
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); * }); * }); */ }
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); }); }); }
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)); }); }
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)); }); }