diff --git a/src/Service.GraphQLBuilder/Queries/InputTypeBuilder.cs b/src/Service.GraphQLBuilder/Queries/InputTypeBuilder.cs index 9679db4748..e1342992d6 100644 --- a/src/Service.GraphQLBuilder/Queries/InputTypeBuilder.cs +++ b/src/Service.GraphQLBuilder/Queries/InputTypeBuilder.cs @@ -24,8 +24,7 @@ IDictionary inputTypes { List inputFields = GenerateFilterInputFieldsForBuiltInFields(node, inputTypes); string filterInputName = GenerateObjectInputFilterName(node); - - GenerateInputTypeFromInputFields(inputTypes, inputFields, filterInputName, $"Filter input for {node.Name} GraphQL type"); + GenerateFilterInputTypeFromInputFields(inputTypes, inputFields, filterInputName, $"Filter input for {node.Name} GraphQL type"); } internal static void GenerateOrderByInputTypeForObjectType(ObjectTypeDefinitionNode node, IDictionary inputTypes) @@ -33,7 +32,17 @@ internal static void GenerateOrderByInputTypeForObjectType(ObjectTypeDefinitionN List inputFields = GenerateOrderByInputFieldsForBuiltInFields(node); string orderByInputName = GenerateObjectInputOrderByName(node); - GenerateInputTypeFromInputFields(inputTypes, inputFields, orderByInputName, $"Order by input for {node.Name} GraphQL type"); + // OrderBy does not include "and" and "or" input types so we add only the orderByInputName here. + inputTypes.Add( + orderByInputName, + new( + location: null, + new NameNode(orderByInputName), + new StringValueNode($"Order by input for {node.Name} GraphQL type"), + new List(), + inputFields + ) + ); } private static List GenerateOrderByInputFieldsForBuiltInFields(ObjectTypeDefinitionNode node) @@ -53,27 +62,12 @@ private static List GenerateOrderByInputFieldsForBuilt new List()) ); } - else - { - string targetEntityName = RelationshipDirectiveType.Target(field); - - inputFields.Add( - new( - location: null, - field.Name, - new StringValueNode($"Order by options for {field.Name}"), - new NamedTypeNode(GenerateObjectInputOrderByName(targetEntityName)), - defaultValue: null, - new List()) - ); - } - } return inputFields; } - private static void GenerateInputTypeFromInputFields( + private static void GenerateFilterInputTypeFromInputFields( IDictionary inputTypes, List inputFields, string inputTypeName, diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs index 600ea32c71..056cc6aad2 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/GraphQLQueryTestBase.cs @@ -2146,6 +2146,62 @@ public virtual async Task TestInvalidFilterParamQuery() SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString()); } + [TestMethod] + public virtual async Task TestInvalidOrderByQueryUsingAnd() + { + string graphQLQueryName = "publishers"; + string graphQLQuery = @"{ + books(orderBy: { and: { id: ASC, title: ASC } }) { + items { + id + } + } + }"; + + JsonElement result = await ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: false); + SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString()); + } + + [TestMethod] + public virtual async Task TestInvalidOrderByQueryUsingOr() + { + string graphQLQueryName = "publishers"; + string graphQLQuery = @"{ + books(orderBy: { or: { id: ASC, title: ASC } }) { + items { + id + } + } + }"; + + JsonElement result = await ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: false); + SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString()); + } + + [TestMethod] + public virtual async Task TestInvalidOrderByQueryUsingRelationship() + { + string graphQLQueryName = "publishers"; + string graphQLQuery = @"{ + publishers (first: 5 orderBy: {books: { + title: DESC + } + }){ + items { + id + books { + items { + title + } + } + } + } + }"; + + JsonElement result = await ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: false); + SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString()); + } + /// /// Test to check that sourceFields and targetFields for relationship provided in the config /// overrides relationship fields defined in DB.