diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/DefaultHttpMethod.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/DefaultHttpMethod.cs index 4cbb2b624bc..fbc1de92891 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/DefaultHttpMethod.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/DefaultHttpMethod.cs @@ -1,7 +1,17 @@ namespace HotChocolate.AspNetCore; +/// +/// The default HTTP fetch method for Banana Cake Pop. +/// public enum DefaultHttpMethod { + /// + /// Use a GraphQL HTTP GET request. + /// Get, + + /// + /// Use a GraphQL HTTP Post request. + /// Post } diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/Serialization/DefaultHttpResponseFormatter.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/Serialization/DefaultHttpResponseFormatter.cs index 8179a994093..9bf82ba44e0 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/Serialization/DefaultHttpResponseFormatter.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/Serialization/DefaultHttpResponseFormatter.cs @@ -299,7 +299,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter var mediaType = acceptMediaTypes[0]; if (resultKind is ResultKind.Single && - mediaType.Kind is ApplicationGraphQL or AllApplication or All) + mediaType.Kind is ApplicationGraphQL or AllApplication) { formatInfo = new FormatInfo( ContentType.GraphQLResponse, @@ -309,7 +309,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter } if (resultKind is ResultKind.Single && - mediaType.Kind is ApplicationJson) + mediaType.Kind is ApplicationJson or All) { formatInfo = new FormatInfo( ContentType.Json, @@ -350,7 +350,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter var mediaType = Unsafe.Add(ref searchSpace, i); if (resultKind is ResultKind.Single && - mediaType.Kind is ApplicationGraphQL or AllApplication or All) + mediaType.Kind is ApplicationGraphQL or AllApplication) { formatInfo = new FormatInfo( ContentType.GraphQLResponse, @@ -360,7 +360,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter } if (resultKind is ResultKind.Single && - mediaType.Kind is ApplicationJson) + mediaType.Kind is ApplicationJson or All) { // application/json is a legacy response content-type. // We will create a formatInfo but keep on validating for diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/QueryExtension.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/QueryExtension.cs index 3e31cc3d692..1582547fd36 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/QueryExtension.cs +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests.Utilities/QueryExtension.cs @@ -16,4 +16,10 @@ public bool Evict([FromServices] IRequestExecutorResolver executorResolver, ISch executorResolver.EvictRequestExecutor(schema.Name); return true; } + + public async Task Wait(int m, CancellationToken ct) + { + await Task.Delay(m, ct); + return true; + } } diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs index 94bf09c2680..d4db3293ced 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/GraphQLOverHttpSpecTests.cs @@ -385,7 +385,7 @@ public async Task New_Query_No_Streams_4() /// /// This request specifies the */* accept header. - /// expected response content-type: application/graphql-response+json; charset=utf-8 + /// expected response content-type: application/json; charset=utf-8 /// expected status code: 200 /// [Fact] @@ -412,14 +412,14 @@ public async Task New_Query_No_Streams_5() using var response = await client.SendAsync(request); // assert - // expected response content-type: application/graphql-response+json; charset=utf-8 + // expected response content-type: application/json; charset=utf-8 // expected status code: 200 Snapshot .Create() .Add(response) .MatchInline( @"Headers: - Content-Type: application/graphql-response+json; charset=utf-8 + Content-Type: application/json; charset=utf-8 --------------------------> Status Code: OK --------------------------> @@ -862,7 +862,8 @@ public async Task New_Query_With_Streams_3() Status Code: OK --------------------------> {""event"":""next"",""data"":{""data"":{},""hasNext"":true}} - {""event"":""next"",""data"":{""path"":[],""data"":{""__typename"":""Query""},""hasNext"":false}} + {""event"":""next"",""data"":{""incremental"":[{""data"":{" + + @"""__typename"":""Query""},""path"":[]}],""hasNext"":false}} {""event"":""complete""} "); } diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpPostMiddlewareTests.cs b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpPostMiddlewareTests.cs index 9f739b8cb56..303359fa87c 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpPostMiddlewareTests.cs +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/HttpPostMiddlewareTests.cs @@ -240,6 +240,9 @@ public async Task SingleRequest_Defer_Results() { Query = @" { + ... @defer { + wait(m: 300) + } hero(episode: NEW_HOPE) { name @@ -271,6 +274,9 @@ public async Task Single_Diagnostic_Listener_Is_Triggered() { Query = @" { + ... @defer { + wait(m: 300) + } hero(episode: NEW_HOPE) { name @@ -304,6 +310,9 @@ public async Task Aggregate_Diagnostic_All_Listeners_Are_Triggered() { Query = @" { + ... @defer { + wait(m: 300) + } hero(episode: NEW_HOPE) { name @@ -332,6 +341,9 @@ public async Task Ensure_Multipart_Format_Is_Correct_With_Defer() { Query = @" { + ... @defer { + wait(m: 300) + } hero(episode: NEW_HOPE) { name @@ -359,6 +371,9 @@ public async Task Ensure_Multipart_Format_Is_Correct_With_Defer_If_Condition_Tru { Query = @" query ($if: Boolean!){ + ... @defer { + wait(m: 300) + } hero(episode: NEW_HOPE) { name @@ -421,6 +436,9 @@ public async Task Ensure_Multipart_Format_Is_Correct_With_Stream() { Query = @" { + ... @defer { + wait(m: 300) + } hero(episode: NEW_HOPE) { name diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap index 80807c57733..e32912bb51a 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL.snap @@ -74,6 +74,7 @@ type Query { droid(id: String): Droid time: Long! evict: Boolean! + wait(m: Int!): Boolean! } type Review { diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap index 80807c57733..e32912bb51a 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route.snap @@ -74,6 +74,7 @@ type Query { droid(id: String): Droid time: Long! evict: Boolean! + wait(m: Int!): Boolean! } type Review { diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap index 80807c57733..e32912bb51a 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_SDL_Explicit_Route_Explicit_Pattern.snap @@ -74,6 +74,7 @@ type Query { droid(id: String): Droid time: Long! evict: Boolean! + wait(m: Int!): Boolean! } type Review { diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL.snap index 17147636b80..6c224e62101 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL.snap @@ -7,4 +7,5 @@ type Query { droid(id: String): Droid time: Long! evict: Boolean! + wait(m: Int!): Boolean! } \ No newline at end of file diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL_Character_and_Query.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL_Character_and_Query.snap index 3c873505da1..2a79a63d9e1 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL_Character_and_Query.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpGetSchemaMiddlewareTests.Download_GraphQL_Types_SDL_Character_and_Query.snap @@ -15,4 +15,5 @@ type Query { droid(id: String): Droid time: Long! evict: Boolean! + wait(m: Int!): Boolean! } \ No newline at end of file diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer.snap index df8d19e76af..0f0c4e7f9ce 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer.snap @@ -6,5 +6,9 @@ Content-Type: application/json; charset=utf-8 --- Content-Type: application/json; charset=utf-8 -{"incremental":[{"data":{"id":"2001"},"label":"my_id","path":["hero"]}],"hasNext":false} +{"incremental":[{"data":{"id":"2001"},"label":"my_id","path":["hero"]}],"hasNext":true} +--- +Content-Type: application/json; charset=utf-8 + +{"incremental":[{"data":{"wait":true},"path":[]}],"hasNext":false} ----- diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer_If_Condition_True.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer_If_Condition_True.snap index df8d19e76af..0f0c4e7f9ce 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer_If_Condition_True.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Defer_If_Condition_True.snap @@ -6,5 +6,9 @@ Content-Type: application/json; charset=utf-8 --- Content-Type: application/json; charset=utf-8 -{"incremental":[{"data":{"id":"2001"},"label":"my_id","path":["hero"]}],"hasNext":false} +{"incremental":[{"data":{"id":"2001"},"label":"my_id","path":["hero"]}],"hasNext":true} +--- +Content-Type: application/json; charset=utf-8 + +{"incremental":[{"data":{"wait":true},"path":[]}],"hasNext":false} ----- diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Stream.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Stream.snap index 97dfd3e47e9..fe8822d442a 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Stream.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.Ensure_Multipart_Format_Is_Correct_With_Stream.snap @@ -6,9 +6,9 @@ Content-Type: application/json; charset=utf-8 --- Content-Type: application/json; charset=utf-8 -{"incremental":[{"data":{"name":"Han Solo"},"label":"foo","path":["hero","friends","nodes",1]},{"data":{"name":"Leia Organa"},"label":"foo","path":["hero","friends","nodes",2]}],"hasNext":true} +{"incremental":[{"items":[{"name":"Han Solo"}],"label":"foo","path":["hero","friends","nodes",1]},{"items":[{"name":"Leia Organa"}],"label":"foo","path":["hero","friends","nodes",2]}],"hasNext":true} --- Content-Type: application/json; charset=utf-8 -{"hasNext":false} +{"incremental":[{"data":{"wait":true},"path":[]}],"hasNext":false} ----- diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.SingleRequest_Defer_Results.snap b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.SingleRequest_Defer_Results.snap index 098c281a900..77d47381062 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.SingleRequest_Defer_Results.snap +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Tests/__snapshots__/HttpPostMiddlewareTests.SingleRequest_Defer_Results.snap @@ -1,5 +1,5 @@ { "ContentType": "multipart/mixed; boundary=\"-\"; charset=utf-8", "StatusCode": "OK", - "Content": "\r\n---\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{\"data\":{\"hero\":{\"name\":\"R2-D2\"}},\"hasNext\":true}\r\n---\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{\"incremental\":[{\"data\":{\"id\":\"2001\"},\"label\":\"my_id\",\"path\":[\"hero\"]}],\"hasNext\":false}\r\n-----\r\n" + "Content": "\r\n---\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{\"data\":{\"hero\":{\"name\":\"R2-D2\"}},\"hasNext\":true}\r\n---\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{\"incremental\":[{\"data\":{\"id\":\"2001\"},\"label\":\"my_id\",\"path\":[\"hero\"]}],\"hasNext\":true}\r\n---\r\nContent-Type: application/json; charset=utf-8\r\n\r\n{\"incremental\":[{\"data\":{\"wait\":true},\"path\":[]}],\"hasNext\":false}\r\n-----\r\n" } \ No newline at end of file diff --git a/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResult.cs b/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResult.cs index d7489d31f64..7a8643ea654 100644 --- a/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResult.cs +++ b/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResult.cs @@ -29,6 +29,15 @@ public interface IQueryResult : IExecutionResult /// IReadOnlyDictionary? Data { get; } + /// + /// The `items` entry in a stream payload is a list of results from the execution of + /// the associated @stream directive. This output will be a list of the same type of + /// the field with the associated `@stream` directive. If `items` is set to `null`, + /// it indicates that an error has caused a `null` to bubble up to a field higher + /// than the list field with the associated `@stream` directive. + /// + IReadOnlyList? Items { get; } + /// /// Gets the GraphQL errors of the result. /// diff --git a/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResultBuilder.cs b/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResultBuilder.cs index 24e58a95def..77edef027fb 100644 --- a/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResultBuilder.cs +++ b/src/HotChocolate/Core/src/Abstractions/Execution/IQueryResultBuilder.cs @@ -10,6 +10,8 @@ public interface IQueryResultBuilder { IQueryResultBuilder SetData(IReadOnlyDictionary? data); + IQueryResultBuilder SetItems(IReadOnlyList? items); + IQueryResultBuilder AddError(IError error); IQueryResultBuilder AddErrors(IEnumerable errors); diff --git a/src/HotChocolate/Core/src/Abstractions/Execution/QueryResult.cs b/src/HotChocolate/Core/src/Abstractions/Execution/QueryResult.cs index 4b82a5369e4..0e42a4e1375 100644 --- a/src/HotChocolate/Core/src/Abstractions/Execution/QueryResult.cs +++ b/src/HotChocolate/Core/src/Abstractions/Execution/QueryResult.cs @@ -17,6 +17,7 @@ public sealed class QueryResult : ExecutionResult, IQueryResult IReadOnlyList? errors, IReadOnlyDictionary? extension, IReadOnlyDictionary? contextData, + IReadOnlyList? items, IReadOnlyList? incremental, string? label, Path? path, @@ -24,7 +25,11 @@ public sealed class QueryResult : ExecutionResult, IQueryResult Func[] cleanupTasks) : base(cleanupTasks) { - if (data is null && errors is null && incremental is null && hasNext is not false) + if (data is null && + items is null && + errors is null && + incremental is null && + hasNext is not false) { throw new ArgumentException( AbstractionResources.QueryResult_DataAndResultAreNull, @@ -32,6 +37,7 @@ public sealed class QueryResult : ExecutionResult, IQueryResult } Data = data; + Items = items; Errors = errors; Extensions = extension; ContextData = contextData; @@ -49,12 +55,17 @@ public sealed class QueryResult : ExecutionResult, IQueryResult IReadOnlyList? errors = null, IReadOnlyDictionary? extension = null, IReadOnlyDictionary? contextData = null, + IReadOnlyList? items = null, IReadOnlyList? incremental = null, string? label = null, Path? path = null, bool? hasNext = null) { - if (data is null && errors is null && incremental is null && hasNext is not false) + if (data is null && + items is null && + errors is null && + incremental is null && + hasNext is not false) { throw new ArgumentException( AbstractionResources.QueryResult_DataAndResultAreNull, @@ -62,6 +73,7 @@ public sealed class QueryResult : ExecutionResult, IQueryResult } Data = data; + Items = items; Errors = errors; Extensions = extension; ContextData = contextData; @@ -83,6 +95,9 @@ public sealed class QueryResult : ExecutionResult, IQueryResult /// public IReadOnlyDictionary? Data { get; } + /// + public IReadOnlyList? Items { get; } + /// public IReadOnlyList? Errors { get; } diff --git a/src/HotChocolate/Core/src/Abstractions/Execution/QueryResultBuilder.cs b/src/HotChocolate/Core/src/Abstractions/Execution/QueryResultBuilder.cs index 34c43056791..ded585362c2 100644 --- a/src/HotChocolate/Core/src/Abstractions/Execution/QueryResultBuilder.cs +++ b/src/HotChocolate/Core/src/Abstractions/Execution/QueryResultBuilder.cs @@ -9,6 +9,7 @@ namespace HotChocolate.Execution; public class QueryResultBuilder : IQueryResultBuilder { private IReadOnlyDictionary? _data; + private IReadOnlyList? _items; private List? _errors; private ExtensionData? _extensionData; private ExtensionData? _contextData; @@ -21,6 +22,19 @@ public class QueryResultBuilder : IQueryResultBuilder public IQueryResultBuilder SetData(IReadOnlyDictionary? data) { _data = data; + _items = null; + return this; + } + + public IQueryResultBuilder SetItems(IReadOnlyList? items) + { + _items = items; + + if (items is not null) + { + _data = null; + } + return this; } @@ -159,6 +173,7 @@ public IQueryResult Create() _errors?.Count > 0 ? _errors : null, _extensionData?.Count > 0 ? _extensionData : null, _contextData?.Count > 0 ? _contextData : null, + _items, _incremental, _label, _path, diff --git a/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs b/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs index 859f025967b..ca682fc8576 100644 --- a/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs +++ b/src/HotChocolate/Core/src/Abstractions/Properties/AbstractionResources.Designer.cs @@ -9,21 +9,21 @@ namespace HotChocolate.Properties { using System; - - + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [System.Diagnostics.DebuggerNonUserCodeAttribute()] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class AbstractionResources { - + private static System.Resources.ResourceManager resourceMan; - + private static System.Globalization.CultureInfo resourceCulture; - + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal AbstractionResources() { } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Resources.ResourceManager ResourceManager { get { @@ -34,7 +34,7 @@ internal class AbstractionResources { return resourceMan; } } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Globalization.CultureInfo Culture { get { @@ -44,215 +44,203 @@ internal class AbstractionResources { resourceCulture = value; } } - + internal static string DataLoader_KeyMustNotBeNullOrEmpty { get { return ResourceManager.GetString("DataLoader_KeyMustNotBeNullOrEmpty", resourceCulture); } } - + internal static string DirectiveArgument_NameMustNotBeNullOrempty { get { return ResourceManager.GetString("DirectiveArgument_NameMustNotBeNullOrempty", resourceCulture); } } - + internal static string Name_MustNotBeEmpty { get { return ResourceManager.GetString("Name_MustNotBeEmpty", resourceCulture); } } - + internal static string QueryRequestBuilder_QueryIsNull { get { return ResourceManager.GetString("QueryRequestBuilder_QueryIsNull", resourceCulture); } } - + internal static string QueryRequestBuilder_QueryIsNullOrEmpty { get { return ResourceManager.GetString("QueryRequestBuilder_QueryIsNullOrEmpty", resourceCulture); } } - + internal static string State_KeyMustNotBeNullOrEmpty { get { return ResourceManager.GetString("State_KeyMustNotBeNullOrEmpty", resourceCulture); } } - + internal static string Type_NameIsNotValid { get { return ResourceManager.GetString("Type_NameIsNotValid", resourceCulture); } } - + internal static string Error_Unknown_Error { get { return ResourceManager.GetString("Error_Unknown_Error", resourceCulture); } } - + internal static string Error_Message_Mustnt_Be_Null { get { return ResourceManager.GetString("Error_Message_Mustnt_Be_Null", resourceCulture); } } - + internal static string Error_WithMessage_Message_Cannot_Be_Empty { get { return ResourceManager.GetString("Error_WithMessage_Message_Cannot_Be_Empty", resourceCulture); } } - + internal static string Path_WithPath_Path_Value_NotSupported { get { return ResourceManager.GetString("Path_WithPath_Path_Value_NotSupported", resourceCulture); } } - + internal static string Error_SetExtension_Key_Cannot_Be_Empty { get { return ResourceManager.GetString("Error_SetExtension_Key_Cannot_Be_Empty", resourceCulture); } } - + internal static string Location_Line_Is_1_Based { get { return ResourceManager.GetString("Location_Line_Is_1_Based", resourceCulture); } } - + internal static string Location_Column_Is_1_Based { get { return ResourceManager.GetString("Location_Column_Is_1_Based", resourceCulture); } } - + internal static string SubscriptionResult_ResultHasErrors { get { return ResourceManager.GetString("SubscriptionResult_ResultHasErrors", resourceCulture); } } - + internal static string SubscriptionResult_ReadOnlyOnce { get { return ResourceManager.GetString("SubscriptionResult_ReadOnlyOnce", resourceCulture); } } - + internal static string SingleValueExtensionData_KeyNotFound { get { return ResourceManager.GetString("SingleValueExtensionData_KeyNotFound", resourceCulture); } } - + internal static string ExtensionDataKeyCollection_CopyTo_ArrayNotBigEnough { get { return ResourceManager.GetString("ExtensionDataKeyCollection_CopyTo_ArrayNotBigEnough", resourceCulture); } } - + internal static string ExtensionDataCollection_CollectionIsReadOnly { get { return ResourceManager.GetString("ExtensionDataCollection_CollectionIsReadOnly", resourceCulture); } } - + internal static string SingleValueExtensionData_KeyIsEmpty { get { return ResourceManager.GetString("SingleValueExtensionData_KeyIsEmpty", resourceCulture); } } - + internal static string FieldCoordinate_Parse_InvalidComponentCount { get { return ResourceManager.GetString("FieldCoordinate_Parse_InvalidComponentCount", resourceCulture); } } - + internal static string FieldCoordinate_Parse_InvalidFieldComponentCount { get { return ResourceManager.GetString("FieldCoordinate_Parse_InvalidFieldComponentCount", resourceCulture); } } - + internal static string FieldCoordinate_Parse_InvalidFormat { get { return ResourceManager.GetString("FieldCoordinate_Parse_InvalidFormat", resourceCulture); } } - + internal static string AggregateError_Message { get { return ResourceManager.GetString("AggregateError_Message", resourceCulture); } } - + internal static string ResultValue_NameIsNullOrEmpty { get { return ResourceManager.GetString("ResultValue_NameIsNullOrEmpty", resourceCulture); } } - + internal static string QueryResult_DataAndResultAreNull { get { return ResourceManager.GetString("QueryResult_DataAndResultAreNull", resourceCulture); } } - + internal static string ThrowHelper_TryRewriteNullability_InvalidNullabilityStructure { get { return ResourceManager.GetString("ThrowHelper_TryRewriteNullability_InvalidNullabilityStructure", resourceCulture); } } - + internal static string ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName { get { return ResourceManager.GetString("ThrowHelper_SchemaCoordinate_ArgumentNameCannotBeSetWithoutMemberName", resourceCulture); } } - + internal static string ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate { get { return ResourceManager.GetString("ThrowHelper_SchemaCoordinate_MemberNameCannotBeSetOnADirectiveCoordinate", resourceCulture); } } - + internal static string ResponseStream_InvalidResultKind { get { return ResourceManager.GetString("ResponseStream_InvalidResultKind", resourceCulture); } } - + internal static string ExecutionResultExtensions_ExpectResponseStream_NotResponseStream { get { return ResourceManager.GetString("ExecutionResultExtensions_ExpectResponseStream_NotResponseStream", resourceCulture); } } - + internal static string ExecutionResultExtensions_ExpectQueryResult_NotQueryResult { get { return ResourceManager.GetString("ExecutionResultExtensions_ExpectQueryResult_NotQueryResult", resourceCulture); } } - + internal static string NameUtils_InvalidGraphQLName { get { return ResourceManager.GetString("NameUtils_InvalidGraphQLName", resourceCulture); } } - - internal static string ThrowHelper_Operation_NoSelectionSet { - get { - return ResourceManager.GetString("ThrowHelper_Operation_NoSelectionSet", resourceCulture); - } - } - - internal static string ThrowHelper_JsonFormatter_ResultNotSupported { - get { - return ResourceManager.GetString("ThrowHelper_JsonFormatter_ResultNotSupported", resourceCulture); - } - } } } diff --git a/src/HotChocolate/Core/src/Execution/Configuration/IApplicationServiceProvider.cs b/src/HotChocolate/Core/src/Execution/Configuration/IApplicationServiceProvider.cs index 53e7a3715e3..e9218b1fbc5 100644 --- a/src/HotChocolate/Core/src/Execution/Configuration/IApplicationServiceProvider.cs +++ b/src/HotChocolate/Core/src/Execution/Configuration/IApplicationServiceProvider.cs @@ -2,7 +2,6 @@ namespace HotChocolate.Execution.Configuration; -public interface IApplicationServiceProvider - : IServiceProvider +public interface IApplicationServiceProvider : IServiceProvider { } diff --git a/src/HotChocolate/Core/src/Execution/Extensions/OperationContextExtensions.cs b/src/HotChocolate/Core/src/Execution/Extensions/OperationContextExtensions.cs index 36472233baf..172d7cf1780 100644 --- a/src/HotChocolate/Core/src/Execution/Extensions/OperationContextExtensions.cs +++ b/src/HotChocolate/Core/src/Execution/Extensions/OperationContextExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using HotChocolate.Execution.Processing; // ReSharper disable once CheckNamespace @@ -113,6 +114,14 @@ internal static class OperationContextExtensions return context; } + public static OperationContext SetItems( + this OperationContext context, + IReadOnlyList items) + { + context.Result.SetItems(items); + return context; + } + public static OperationContext SetPatchId( this OperationContext context, uint patchId) @@ -131,8 +140,4 @@ internal static class OperationContextExtensions public static IQueryResult BuildResult( this OperationContext context) => context.Result.BuildResult(); - - public static IQueryResultBuilder BuildResultBuilder( - this OperationContext context) => - context.Result.BuildResultBuilder(); } diff --git a/src/HotChocolate/Core/src/Execution/HotChocolate.Execution.csproj b/src/HotChocolate/Core/src/Execution/HotChocolate.Execution.csproj index 09e37d4b625..9c9efc2c24f 100644 --- a/src/HotChocolate/Core/src/Execution/HotChocolate.Execution.csproj +++ b/src/HotChocolate/Core/src/Execution/HotChocolate.Execution.csproj @@ -179,6 +179,9 @@ OperationContext.cs + + JsonResultFormatter.cs + diff --git a/src/HotChocolate/Core/src/Execution/Processing/DeferredFragment.cs b/src/HotChocolate/Core/src/Execution/Processing/DeferredFragment.cs index 5e76c09b292..1e6374e05e6 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/DeferredFragment.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/DeferredFragment.cs @@ -82,7 +82,7 @@ internal sealed class DeferredFragment : DeferredExecutionTask .SetPath(Path) .SetData(parentResult) .SetPatchId(patchId) - .BuildResultBuilder(); + .BuildResult(); // complete the task and provide the result operationContext.DeferredScheduler.Complete(new(resultId, parentResultId, result)); diff --git a/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs b/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs index df1ab4b706c..181b2d506c3 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; @@ -94,12 +95,14 @@ internal sealed class DeferredStream : DeferredExecutionTask return; } + var item = _task.ChildTask.ParentResult[0].Value!; + var result = operationContext .SetLabel(Label) .SetPath(operationContext.PathFactory.Append(Path, Index)) - .SetData((ObjectResult)_task.ChildTask.ParentResult[0].Value!) + .SetItems(new[] { item }) .SetPatchId(patchId) - .BuildResultBuilder(); + .BuildResult(); await _task.ChildTask.CompleteUnsafeAsync().ConfigureAwait(false); @@ -107,8 +110,11 @@ internal sealed class DeferredStream : DeferredExecutionTask operationContext.DeferredScheduler.Register(this, patchId); operationContext.DeferredScheduler.Complete(new(resultId, parentResultId, result)); } - catch + catch(Exception ex) { + var builder = operationContext.ErrorHandler.CreateUnexpectedError(ex); + var result = QueryResultBuilder.CreateError(builder.Build()); + operationContext.DeferredScheduler.Complete(new(resultId, parentResultId, result)); error = true; } finally diff --git a/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkScheduler.cs b/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkScheduler.cs index c95ef43f062..41ced2c0d50 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkScheduler.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkScheduler.cs @@ -129,7 +129,7 @@ private class DeferResultStream : IAsyncEnumerable hasNext = result.HasNext ?? false; yield return result; } - else + else if (_stateOwner.State.IsCompleted) { if (hasNext) { diff --git a/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkState.cs b/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkState.cs index 39d76d46a1b..0297f1bcb51 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkState.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkState.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using static HotChocolate.WellKnownContextData; @@ -13,20 +14,24 @@ internal sealed class DeferredWorkState private readonly object _patchSync = new(); private readonly List _ready = new(); - private readonly Queue _deliverable = new(); + private readonly Queue _deliverable = new(); private readonly HashSet _completed = new(); private readonly HashSet _notPatchable = new(); private SemaphoreSlim _semaphore = new(0); private uint _taskId; private uint _delivered; + private uint _work; private uint _patchId; public bool HasResults => _taskId > 0; + public bool IsCompleted => _work is 0; + public uint CreateId() { lock (_deliverSync) { + _work++; return ++_taskId; } } @@ -51,55 +56,72 @@ public uint AssignPatchId(ResultData resultData) public void Complete(DeferredExecutionTaskResult result) { - lock (_completeSync) + var update = true; + + try { - if (result.ParentTaskId is 0 || _completed.Contains(result.ParentTaskId)) + lock (_completeSync) { - _completed.Add(result.TaskId); - EnqueueResult(result.Result); - - var evaluateDeferredResults = _ready.Count > 0; - - while (evaluateDeferredResults) + if (result.ParentTaskId is 0 || _completed.Contains(result.ParentTaskId)) { - var i = 0; - evaluateDeferredResults = false; + _completed.Add(result.TaskId); + EnqueueResult(result.Result); + + var evaluateDeferredResults = _ready.Count > 0; - while (_ready.Count > 0 && i < _ready.Count) + while (evaluateDeferredResults) { - var current = _ready[i]; + var i = 0; + evaluateDeferredResults = false; - if (_completed.Contains(current.ParentTaskId)) + while (_ready.Count > 0 && i < _ready.Count) { - _completed.Add(current.TaskId); - _ready.RemoveAt(i); - EnqueueResult(current.Result); - evaluateDeferredResults = true; - } - else - { - i++; + var current = _ready[i]; + + if (_completed.Contains(current.ParentTaskId)) + { + _completed.Add(current.TaskId); + _ready.RemoveAt(i); + EnqueueResult(current.Result); + evaluateDeferredResults = true; + } + else + { + i++; + } } } } + else + { + _ready.Add(result); + update = false; + } } - else + } + finally + { + if (update) { - _ready.Add(result); + _semaphore.Release(); } } } - private void EnqueueResult(IQueryResultBuilder? queryResult) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void EnqueueResult(IQueryResult? queryResult) { - if (queryResult is not null) + lock (_deliverSync) { - lock (_deliverSync) + if (queryResult is not null) { _deliverable.Enqueue(queryResult); } + else + { + _work--; + } } - _semaphore.Release(); } public async ValueTask TryDequeueResultsAsync( @@ -117,16 +139,14 @@ private void EnqueueResult(IQueryResultBuilder? queryResult) for (var i = 0; i < result.Length; i++) { - var builder = _deliverable.Dequeue(); + var deliverable = _deliverable.Dequeue(); - if (++_delivered == _taskId) + if (--_work is 0) { _semaphore.Release(); hasNext = false; } - var deliverable = builder.Create(); - // if the deferred result can still be patched into the result set from which // it was being spawned of we will add it to the result batch. if ((deliverable.ContextData?.TryGetValue(PatchId, out var value) ?? false) && @@ -193,6 +213,7 @@ public void Reset() _deliverable.Clear(); _taskId = 0; _delivered = 0; + _work = 0; _patchId = 0; } } diff --git a/src/HotChocolate/Core/src/Execution/Processing/DirectiveCollectionExtensions.cs b/src/HotChocolate/Core/src/Execution/Processing/DirectiveCollectionExtensions.cs deleted file mode 100644 index 6dc6156eb82..00000000000 --- a/src/HotChocolate/Core/src/Execution/Processing/DirectiveCollectionExtensions.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System; -using System.Collections.Generic; -using HotChocolate.Language; -using HotChocolate.Types; -using HotChocolate.Utilities; -using IHasDirectives = HotChocolate.Language.IHasDirectives; - -namespace HotChocolate.Execution.Processing; - -internal static class DirectiveCollectionExtensions -{ - public static IValueNode? SkipValue(this IReadOnlyList directives) - { - var directive = directives.GetSkipDirective(); - return directive is null ? null : GetIfArgumentValue(directive); - } - - public static IValueNode? IncludeValue(this IReadOnlyList directives) - { - var directive = directives.GetIncludeDirective(); - return directive is null ? null : GetIfArgumentValue(directive); - } - - public static bool IsDeferrable(this InlineFragmentNode fragmentNode) => - fragmentNode.Directives.IsDeferrable(); - - public static bool IsDeferrable(this FragmentSpreadNode fragmentSpreadNode) => - fragmentSpreadNode.Directives.IsDeferrable(); - - public static bool IsDeferrable(this IReadOnlyList directives) - { - var directive = directives.GetDeferDirective(); - var ifValue = directive?.GetIfArgumentValueOrDefault(); - - // a fragment is not deferrable if we do not find a defer directive or - // if the `if` of the defer directive is a bool literal with a false value. - return directive is not null && ifValue is not BooleanValueNode { Value: false }; - } - - public static bool IsStreamable(this FieldNode field) => - field.Directives.GetStreamDirective() is not null; - - private static IValueNode GetIfArgumentValue(DirectiveNode directive) - { - if (directive.Arguments.Count == 1) - { - var argument = directive.Arguments[0]; - if (string.Equals( - argument.Name.Value, - WellKnownDirectives.IfArgument, - StringComparison.Ordinal)) - { - return argument.Value; - } - } - - throw ThrowHelper.MissingIfArgument(directive); - } - - private static DirectiveNode? GetSkipDirective( - this IReadOnlyList directives) => - GetDirective(directives, WellKnownDirectives.Skip); - - private static DirectiveNode? GetIncludeDirective( - this IReadOnlyList directives) => - GetDirective(directives, WellKnownDirectives.Include); - - internal static DirectiveNode? GetDeferDirective( - this IHasDirectives container) => - GetDirective(container.Directives, WellKnownDirectives.Defer); - - internal static DeferDirective? GetDeferDirective( - this IReadOnlyList directives, - IVariableValueCollection variables) - { - var directiveNode = - GetDirective(directives, WellKnownDirectives.Defer); - - if (directiveNode is not null) - { - var @if = true; - string? label = null; - - foreach (var argument in directiveNode.Arguments) - { - switch (argument.Name.Value) - { - case WellKnownDirectives.IfArgument: - @if = argument.Value switch - { - VariableNode variable - => variables.GetVariable(variable.Name.Value), - BooleanValueNode b => b.Value, - _ => @if - }; - break; - - case WellKnownDirectives.LabelArgument: - label = argument.Value switch - { - VariableNode variable - => variables.GetVariable(variable.Name.Value), - StringValueNode b => b.Value, - _ => label - }; - break; - } - } - - return new DeferDirective(@if, label); - } - - return null; - } - - internal static StreamDirective? GetStreamDirective( - this ISelection selection, - IVariableValueCollection variables) => - selection.SyntaxNode.Directives.GetStreamDirective(variables); - - internal static StreamDirective? GetStreamDirective( - this IReadOnlyList directives, - IVariableValueCollection variables) - { - var directiveNode = GetDirective(directives, WellKnownDirectives.Stream); - - if (directiveNode is not null) - { - var @if = true; - string? label = null; - var initialCount = 0; - - foreach (var argument in directiveNode.Arguments) - { - switch (argument.Name.Value) - { - case WellKnownDirectives.IfArgument: - @if = argument.Value switch - { - VariableNode variable - => variables.GetVariable(variable.Name.Value), - BooleanValueNode b => b.Value, - _ => @if - }; - break; - - case WellKnownDirectives.LabelArgument: - label = argument.Value switch - { - VariableNode variable - => variables.GetVariable(variable.Name.Value), - StringValueNode b => b.Value, - _ => label - }; - break; - - case WellKnownDirectives.InitialCount: - initialCount = argument.Value switch - { - VariableNode variable - => variables.GetVariable(variable.Name.Value), - IntValueNode b => b.ToInt32(), - _ => initialCount - }; - break; - } - } - - return new StreamDirective(@if, initialCount, label); - } - - return null; - } - - internal static IValueNode? GetIfArgumentValueOrDefault(this DirectiveNode directive) - { - for (var i = 0; i < directive.Arguments.Count; i++) - { - var argument = directive.Arguments[i]; - - if (argument.Name.Value.EqualsOrdinal(WellKnownDirectives.IfArgument)) - { - return argument.Value; - } - } - - return null; - } - - internal static DirectiveNode? GetDeferDirective( - this IReadOnlyList directives) => - GetDirective(directives, WellKnownDirectives.Defer); - - internal static DirectiveNode? GetStreamDirective( - this FieldNode selection) => - GetDirective(selection.Directives, WellKnownDirectives.Stream); - - internal static DirectiveNode? GetStreamDirective( - this IReadOnlyList directives) => - GetDirective(directives, WellKnownDirectives.Stream); - - private static DirectiveNode? GetDirective( - this IReadOnlyList directives, - string name) - { - if (directives.Count == 0) - { - return null; - } - - for (var i = 0; i < directives.Count; i++) - { - var directive = directives[i]; - if (directive.Name.Value.EqualsOrdinal(name)) - { - return directive; - } - } - return null; - } -} diff --git a/src/HotChocolate/Core/src/Execution/Processing/IDeferredWorkScheduler.cs b/src/HotChocolate/Core/src/Execution/Processing/IDeferredWorkScheduler.cs index 6f437e78de6..0cfcfa48578 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/IDeferredWorkScheduler.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/IDeferredWorkScheduler.cs @@ -16,7 +16,7 @@ internal interface IDeferredWorkScheduler /// Registers deferred work /// /// - /// + /// void Register(DeferredExecutionTask task, ResultData parentResult); void Register(DeferredExecutionTask task, uint patchId); @@ -31,7 +31,7 @@ internal interface IDeferredWorkScheduler public DeferredExecutionTaskResult( uint taskId, uint parentTaskId, - IQueryResultBuilder? result = null) + IQueryResult? result = null) { TaskId = taskId; ParentTaskId = parentTaskId; @@ -42,5 +42,5 @@ internal interface IDeferredWorkScheduler public uint ParentTaskId { get; } - public IQueryResultBuilder? Result { get; } + public IQueryResult? Result { get; } } diff --git a/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.cs b/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.cs index cc8d35ca944..f52ffe79189 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using HotChocolate.Language; using HotChocolate.Types; using HotChocolate.Utilities; +using static System.Runtime.InteropServices.MemoryMarshal; using static System.StringComparer; using static HotChocolate.Execution.Properties.Resources; using static HotChocolate.Execution.ThrowHelper; @@ -185,16 +188,27 @@ public OperationCompiler(InputParser parser) variants[item.Key] = item.Value; } +#if NET5_0_OR_GREATER + ref var optSpace = ref GetReference(CollectionsMarshal.AsSpan(_operationOptimizers)); + + for (var i = 0; i < _operationOptimizers.Count; i++) + { + Unsafe.Add(ref optSpace, i).OptimizeOperation(context); + } +#else for (var i = 0; i < _operationOptimizers.Count; i++) { _operationOptimizers[i].OptimizeOperation(context); } +#endif CompleteResolvers(schema); - for (var i = 0; i < variants.Length; i++) + ref var varSpace = ref GetReference(variants.AsSpan()); + + for (var i = 0; i < _operationOptimizers.Count; i++) { - variants[i].Seal(); + Unsafe.Add(ref varSpace, i).Seal(); } } @@ -211,6 +225,24 @@ public OperationCompiler(InputParser parser) private void CompleteResolvers(ISchema schema) { +#if NET5_0_OR_GREATER + ref var searchSpace = ref GetReference(CollectionsMarshal.AsSpan(_selections)); + + for (var i = 0; i < _selections.Count; i++) + { + var selection = Unsafe.Add(ref searchSpace, i); + + if (selection.ResolverPipeline is null && selection.PureResolver is null) + { + var field = selection.Field; + var syntaxNode = selection.SyntaxNode; + var resolver = CreateFieldMiddleware(schema, field, syntaxNode); + var pureResolver = TryCreatePureField(field, syntaxNode); + selection.SetResolvers(resolver, pureResolver); + } + } + +#else foreach (var selection in _selections) { if (selection.ResolverPipeline is null && selection.PureResolver is null) @@ -222,6 +254,7 @@ private void CompleteResolvers(ISchema schema) selection.SetResolvers(resolver, pureResolver); } } +#endif } private void CompileSelectionSet(CompilerContext context) @@ -295,7 +328,7 @@ private void CompleteSelectionSet(CompilerContext context) // For now we only allow streams on lists of composite types. if (selection.SyntaxNode.IsStreamable()) { - var streamDirective = selection.SyntaxNode.GetStreamDirective(); + var streamDirective = selection.SyntaxNode.GetStreamDirectiveNode(); var nullValue = NullValueNode.Default; var ifValue = streamDirective?.GetIfArgumentValueOrDefault() ?? nullValue; long ifConditionFlags = 0; @@ -498,7 +531,7 @@ private void CollectFields(CompilerContext context) if (directives.IsDeferrable()) { - var deferDirective = directives.GetDeferDirective(); + var deferDirective = directives.GetDeferDirectiveNode(); var nullValue = NullValueNode.Default; var ifValue = deferDirective?.GetIfArgumentValueOrDefault() ?? nullValue; diff --git a/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.Pooling.cs b/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.Pooling.cs index 1e2d571f947..989c8baaf80 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.Pooling.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.Pooling.cs @@ -41,6 +41,7 @@ public void Clear() _errorHandler = default!; _diagnosticEvents = default!; _data = null; + _items = null; _path = null; _label = null; _hasNext = null; diff --git a/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs b/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs index 142886ab0e9..ec628bc49bc 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs @@ -23,6 +23,7 @@ internal sealed partial class ResultBuilder private ResultMemoryOwner _resultOwner = default!; private ObjectResult? _data; + private IReadOnlyList? _items; private Path? _path; private string? _label; private bool? _hasNext; @@ -30,7 +31,26 @@ internal sealed partial class ResultBuilder public IReadOnlyList Errors => _errors; public void SetData(ObjectResult data) - => _data = data; + { + if (_items is not null) + { + throw new InvalidOperationException( + Resources.ResultBuilder_DataAndItemsNotAllowed); + } + + _data = data; + } + + public void SetItems(IReadOnlyList items) + { + if (_data is not null) + { + throw new InvalidOperationException( + Resources.ResultBuilder_DataAndItemsNotAllowed); + } + + _items = items; + } public void SetExtension(string key, object? value) { @@ -127,7 +147,7 @@ public IQueryResult BuildResult() _resultOwner.Dispose(); } - if (_data is null && _errors.Count == 0 && _hasNext is not false) + if (_data is null && _items is null && _errors.Count == 0 && _hasNext is not false) { throw new InvalidOperationException( Resources.ResultHelper_BuildResult_InvalidResult); @@ -150,17 +170,19 @@ public IQueryResult BuildResult() _contextData.Add(WellKnownContextData.ExpectedPatches, _patchIds.ToArray()); } - var result = new QueryResult - ( + var result = new QueryResult( _data, - _errors.Count == 0 ? null : new List(_errors), + _errors.Count == 0 + ? null + : new List(_errors), CreateExtensionData(_extensions), CreateExtensionData(_contextData), - null, - _label, - _path, - _hasNext, - _cleanupTasks.Count > 0 + incremental: null, + items: _items, + label: _label, + path: _path, + hasNext: _hasNext, + cleanupTasks: _cleanupTasks.Count > 0 ? _cleanupTasks.ToArray() : Array.Empty>() ); @@ -173,50 +195,6 @@ public IQueryResult BuildResult() return result; } - public IQueryResultBuilder BuildResultBuilder() - { - if (!ApplyNonNullViolations(_errors, _nonNullViolations, _fieldErrors)) - { - // The non-null violation cased the whole result being deleted. - _data = null; - _resultOwner.Dispose(); - } - - if (_data is null && _errors.Count == 0 && _hasNext is not false) - { - throw new InvalidOperationException( - Resources.ResultHelper_BuildResult_InvalidResult); - } - - var builder = QueryResultBuilder.New(); - - builder.SetData(_data); - - if (_errors.Count > 0) - { - _errors.Sort(ErrorComparer.Default); - builder.AddErrors(_errors); - } - - _removedResults.Remove(0); - if (_removedResults.Count > 0) - { - _contextData.Add(WellKnownContextData.RemovedResults, _removedResults.ToArray()); - } - - builder.SetExtensions(CreateExtensionData(_extensions)); - builder.SetContextData(CreateExtensionData(_contextData)); - builder.SetLabel(_label); - builder.SetPath(_path); - - if (_data is not null) - { - builder.RegisterForCleanup(_resultOwner); - } - - return builder; - } - private static IReadOnlyDictionary? CreateExtensionData( Dictionary data) { diff --git a/src/HotChocolate/Core/src/Execution/Processing/Tasks/ResolverTask.Execute.cs b/src/HotChocolate/Core/src/Execution/Processing/Tasks/ResolverTask.Execute.cs index 9b4772038c1..b2f5b87d2e5 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/Tasks/ResolverTask.Execute.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/Tasks/ResolverTask.Execute.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using HotChocolate.Execution.Internal; +using HotChocolate.Types; namespace HotChocolate.Execution.Processing.Tasks; diff --git a/src/HotChocolate/Core/src/Execution/Properties/Resources.Designer.cs b/src/HotChocolate/Core/src/Execution/Properties/Resources.Designer.cs index 8d08e758ffa..85dba57cb8c 100644 --- a/src/HotChocolate/Core/src/Execution/Properties/Resources.Designer.cs +++ b/src/HotChocolate/Core/src/Execution/Properties/Resources.Designer.cs @@ -45,12 +45,6 @@ internal class Resources { } } - internal static string ThrowHelper_MissingDirectiveIfArgument { - get { - return ResourceManager.GetString("ThrowHelper_MissingDirectiveIfArgument", resourceCulture); - } - } - internal static string ThrowHelper_FieldDoesNotExistOnType { get { return ResourceManager.GetString("ThrowHelper_FieldDoesNotExistOnType", resourceCulture); @@ -428,5 +422,11 @@ internal class Resources { return ResourceManager.GetString("ThrowHelper_JsonFormatter_ResultNotSupported", resourceCulture); } } + + internal static string ResultBuilder_DataAndItemsNotAllowed { + get { + return ResourceManager.GetString("ResultBuilder_DataAndItemsNotAllowed", resourceCulture); + } + } } } diff --git a/src/HotChocolate/Core/src/Execution/Properties/Resources.resx b/src/HotChocolate/Core/src/Execution/Properties/Resources.resx index 3e41d28d07c..61b1175a771 100644 --- a/src/HotChocolate/Core/src/Execution/Properties/Resources.resx +++ b/src/HotChocolate/Core/src/Execution/Properties/Resources.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - The {0}-directive is missing the if-argument. - Field `{0}` does not exist on type `{1}`. @@ -309,4 +306,7 @@ The {0} only supports formatting `IQueryResult`. + + Its not allowed to set `items` and `data` at the same time. + diff --git a/src/HotChocolate/Core/src/Execution/Serialization/JsonConstants.cs b/src/HotChocolate/Core/src/Execution/Serialization/JsonConstants.cs deleted file mode 100644 index 97318f11f24..00000000000 --- a/src/HotChocolate/Core/src/Execution/Serialization/JsonConstants.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace HotChocolate.Execution.Serialization; - -internal static class JsonConstants -{ - public const string Data = "data"; - public const string Errors = "errors"; - public const string Extensions = "extensions"; - public const string Message = "message"; - public const string Locations = "locations"; - public const string Path = "path"; - public const string Line = "line"; - public const string Column = "column"; - public const string Incremental = "incremental"; -} diff --git a/src/HotChocolate/Core/src/Execution/Serialization/JsonResultFormatter.FieldNames.cs b/src/HotChocolate/Core/src/Execution/Serialization/JsonResultFormatter.FieldNames.cs new file mode 100644 index 00000000000..7274612d9e1 --- /dev/null +++ b/src/HotChocolate/Core/src/Execution/Serialization/JsonResultFormatter.FieldNames.cs @@ -0,0 +1,51 @@ +using System; + +namespace HotChocolate.Execution.Serialization; + +public sealed partial class JsonResultFormatter +{ + private static ReadOnlySpan Data + => new[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a' }; + + private static ReadOnlySpan Items + => new[] { (byte)'i', (byte)'t', (byte)'e', (byte)'m', (byte)'s' }; + + private static ReadOnlySpan Errors + => new[] { (byte)'e', (byte)'r', (byte)'r', (byte)'o', (byte)'r', (byte)'s' }; + + private static ReadOnlySpan Extensions + => new[] + { + (byte)'e', (byte)'x', (byte)'t', (byte)'e', (byte)'n', (byte)'s', (byte)'i', + (byte)'o', (byte)'n', (byte)'s' + }; + + private static ReadOnlySpan Message + => new[] + { + (byte)'m', (byte)'e', (byte)'s', (byte)'s', (byte)'a', (byte)'g', (byte)'e' + }; + + private static ReadOnlySpan Locations + => new[] + { + (byte)'l', (byte)'o', (byte)'c', (byte)'a', (byte)'t', (byte)'i', (byte)'o', + (byte)'n', (byte)'s' + }; + + private static ReadOnlySpan Path + => new[] { (byte)'p', (byte)'a', (byte)'t', (byte)'h' }; + + private static ReadOnlySpan Line + => new[] { (byte)'l', (byte)'i', (byte)'n', (byte)'e' }; + + private static ReadOnlySpan Column + => new[] { (byte)'c', (byte)'o', (byte)'l', (byte)'u', (byte)'m', (byte)'n' }; + + private static ReadOnlySpan Incremental + => new[] + { + (byte)'i', (byte)'n', (byte)'c', (byte)'r', (byte)'e', (byte)'m', (byte)'e', + (byte)'n', (byte)'t', (byte)'a', (byte)'l' + }; +} diff --git a/src/HotChocolate/Core/src/Execution/Serialization/JsonResultFormatter.cs b/src/HotChocolate/Core/src/Execution/Serialization/JsonResultFormatter.cs index 37b68e38481..19b22502dfd 100644 --- a/src/HotChocolate/Core/src/Execution/Serialization/JsonResultFormatter.cs +++ b/src/HotChocolate/Core/src/Execution/Serialization/JsonResultFormatter.cs @@ -11,7 +11,6 @@ using System.Threading.Tasks; using HotChocolate.Execution.Processing; using HotChocolate.Utilities; -using static HotChocolate.Execution.Serialization.JsonConstants; using static HotChocolate.Execution.ThrowHelper; namespace HotChocolate.Execution.Serialization; @@ -19,7 +18,7 @@ namespace HotChocolate.Execution.Serialization; /// /// The default JSON formatter for . /// -public sealed class JsonResultFormatter : IQueryResultFormatter, IExecutionResultFormatter +public sealed partial class JsonResultFormatter : IQueryResultFormatter, IExecutionResultFormatter { private readonly JsonWriterOptions _options; @@ -229,6 +228,7 @@ private void WriteResult(Utf8JsonWriter writer, IQueryResult result) WriteErrors(writer, result.Errors); WriteData(writer, result.Data); + WriteItems(writer, result.Items); WriteIncremental(writer, result.Incremental); WriteExtensions(writer, result.Extensions); WritePatchInfo(writer, result); @@ -281,11 +281,28 @@ private void WriteResult(Utf8JsonWriter writer, IQueryResult result) } } + private void WriteItems(Utf8JsonWriter writer, IReadOnlyList? items) + { + if (items is { Count: > 0 }) + { + writer.WritePropertyName(Items); + + writer.WriteStartArray(); + + for (var i = 0; i < items.Count; i++) + { + WriteFieldValue(writer, items[i]); + } + + writer.WriteEndArray(); + } + } + private void WriteErrors(Utf8JsonWriter writer, IReadOnlyList? errors) { if (errors is { Count: > 0 }) { - writer.WritePropertyName(JsonConstants.Errors); + writer.WritePropertyName(Errors); writer.WriteStartArray(); @@ -340,7 +357,7 @@ private static void WritePath(Utf8JsonWriter writer, Path? path) { if (path is not null) { - writer.WritePropertyName(JsonConstants.Path); + writer.WritePropertyName(Path); WritePathValue(writer, path); } } diff --git a/src/HotChocolate/Core/src/Execution/Serialization/MultiPartResultFormatter.cs b/src/HotChocolate/Core/src/Execution/Serialization/MultiPartResultFormatter.cs index 48d6520028c..bb0aa2d8495 100644 --- a/src/HotChocolate/Core/src/Execution/Serialization/MultiPartResultFormatter.cs +++ b/src/HotChocolate/Core/src/Execution/Serialization/MultiPartResultFormatter.cs @@ -168,10 +168,7 @@ public sealed partial class MultiPartResultFormatter : IExecutionResultFormatter Stream outputStream, CancellationToken ct = default) { - // first we write a leading CRLF - await outputStream.WriteAsync(CrLf, 0, CrLf.Length, ct).ConfigureAwait(false); - - // Before each part of the multi-part response, a boundary (---, CRLF) + // Before each part of the multi-part response, a boundary (CRLF, ---, CRLF) // is sent. await WriteNextAsync(outputStream, ct).ConfigureAwait(false); @@ -179,9 +176,6 @@ public sealed partial class MultiPartResultFormatter : IExecutionResultFormatter { // Now we can write the header and body of the part. await WriteResultAsync(queryResult, outputStream, ct).ConfigureAwait(false); - - // after each result we write a CRLF signaling the next or final part. - await outputStream.WriteAsync(CrLf, 0, CrLf.Length, ct).ConfigureAwait(false); } finally { diff --git a/src/HotChocolate/Core/src/Execution/ThrowHelper.cs b/src/HotChocolate/Core/src/Execution/ThrowHelper.cs index 82d7d46a28c..fe021132eb0 100644 --- a/src/HotChocolate/Core/src/Execution/ThrowHelper.cs +++ b/src/HotChocolate/Core/src/Execution/ThrowHelper.cs @@ -66,18 +66,6 @@ internal static class ThrowHelper return new GraphQLException(errorBuilder.Build()); } - public static GraphQLException MissingIfArgument( - DirectiveNode directive) - { - return new( - ErrorBuilder.New() - .SetMessage( - ThrowHelper_MissingDirectiveIfArgument, - directive.Name.Value) - .AddLocation(directive) - .Build()); - } - public static GraphQLException FieldDoesNotExistOnType( FieldNode selection, string typeName) { diff --git a/src/HotChocolate/Core/src/Types/HotChocolate.Types.csproj b/src/HotChocolate/Core/src/Types/HotChocolate.Types.csproj index d8643115285..d2c29442f26 100644 --- a/src/HotChocolate/Core/src/Types/HotChocolate.Types.csproj +++ b/src/HotChocolate/Core/src/Types/HotChocolate.Types.csproj @@ -12,12 +12,14 @@ + + diff --git a/src/HotChocolate/Core/src/Types/Properties/TypeResources.Designer.cs b/src/HotChocolate/Core/src/Types/Properties/TypeResources.Designer.cs index 752ae46c9bf..ba1a29940a5 100644 --- a/src/HotChocolate/Core/src/Types/Properties/TypeResources.Designer.cs +++ b/src/HotChocolate/Core/src/Types/Properties/TypeResources.Designer.cs @@ -9,21 +9,21 @@ namespace HotChocolate.Properties { using System; - - + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [System.Diagnostics.DebuggerNonUserCodeAttribute()] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class TypeResources { - + private static System.Resources.ResourceManager resourceMan; - + private static System.Globalization.CultureInfo resourceCulture; - + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal TypeResources() { } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Resources.ResourceManager ResourceManager { get { @@ -34,7 +34,7 @@ internal class TypeResources { return resourceMan; } } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Globalization.CultureInfo Culture { get { @@ -44,1858 +44,1861 @@ internal class TypeResources { resourceCulture = value; } } - + + internal static string ThrowHelper_MissingDirectiveIfArgument { + get { + return ResourceManager.GetString("ThrowHelper_MissingDirectiveIfArgument", resourceCulture); + } + } + internal static string ArgumentDescriptor_InputTypeViolation { get { return ResourceManager.GetString("ArgumentDescriptor_InputTypeViolation", resourceCulture); } } - + internal static string ArgumentValueBuilder_NonNull { get { return ResourceManager.GetString("ArgumentValueBuilder_NonNull", resourceCulture); } } - + internal static string BooleanType_Description { get { return ResourceManager.GetString("BooleanType_Description", resourceCulture); } } - + internal static string ByteType_Description { get { return ResourceManager.GetString("ByteType_Description", resourceCulture); } } - + internal static string ComplexTypeBindingBuilder_FieldBuilderNotSupported { get { return ResourceManager.GetString("ComplexTypeBindingBuilder_FieldBuilderNotSupported", resourceCulture); } } - + internal static string ComplexTypeBindingBuilder_FieldNotComplete { get { return ResourceManager.GetString("ComplexTypeBindingBuilder_FieldNotComplete", resourceCulture); } } - + internal static string DataLoaderRegistry_KeyNullOrEmpty { get { return ResourceManager.GetString("DataLoaderRegistry_KeyNullOrEmpty", resourceCulture); } } - + internal static string DataLoaderResolverContextExtensions_RegistryIsNull { get { return ResourceManager.GetString("DataLoaderResolverContextExtensions_RegistryIsNull", resourceCulture); } } - + internal static string DataLoaderResolverContextExtensions_UnableToRegister { get { return ResourceManager.GetString("DataLoaderResolverContextExtensions_UnableToRegister", resourceCulture); } } - + internal static string DateTimeType_Description { get { return ResourceManager.GetString("DateTimeType_Description", resourceCulture); } } - + internal static string DateType_Description { get { return ResourceManager.GetString("DateType_Description", resourceCulture); } } - + internal static string DecimalType_Description { get { return ResourceManager.GetString("DecimalType_Description", resourceCulture); } } - + internal static string DefaultTypeInspector_MemberInvalid { get { return ResourceManager.GetString("DefaultTypeInspector_MemberInvalid", resourceCulture); } } - + internal static string DependencyDescriptorBase_OnlyTsoIsAllowed { get { return ResourceManager.GetString("DependencyDescriptorBase_OnlyTsoIsAllowed", resourceCulture); } } - + internal static string DirectiveCollection_DirectiveIsUnique { get { return ResourceManager.GetString("DirectiveCollection_DirectiveIsUnique", resourceCulture); } } - + internal static string DirectiveCollection_LocationNotAllowed { get { return ResourceManager.GetString("DirectiveCollection_LocationNotAllowed", resourceCulture); } } - + internal static string DirectiveLocation_ArgumentDefinition { get { return ResourceManager.GetString("DirectiveLocation_ArgumentDefinition", resourceCulture); } } - + internal static string DirectiveLocation_Description { get { return ResourceManager.GetString("DirectiveLocation_Description", resourceCulture); } } - + internal static string DirectiveLocation_Enum { get { return ResourceManager.GetString("DirectiveLocation_Enum", resourceCulture); } } - + internal static string DirectiveLocation_EnumValue { get { return ResourceManager.GetString("DirectiveLocation_EnumValue", resourceCulture); } } - + internal static string DirectiveLocation_Field { get { return ResourceManager.GetString("DirectiveLocation_Field", resourceCulture); } } - + internal static string DirectiveLocation_FieldDefinition { get { return ResourceManager.GetString("DirectiveLocation_FieldDefinition", resourceCulture); } } - + internal static string DirectiveLocation_FragmentDefinition { get { return ResourceManager.GetString("DirectiveLocation_FragmentDefinition", resourceCulture); } } - + internal static string DirectiveLocation_FragmentSpread { get { return ResourceManager.GetString("DirectiveLocation_FragmentSpread", resourceCulture); } } - + internal static string DirectiveLocation_InlineFragment { get { return ResourceManager.GetString("DirectiveLocation_InlineFragment", resourceCulture); } } - + internal static string DirectiveLocation_InputFieldDefinition { get { return ResourceManager.GetString("DirectiveLocation_InputFieldDefinition", resourceCulture); } } - + internal static string DirectiveLocation_InputObject { get { return ResourceManager.GetString("DirectiveLocation_InputObject", resourceCulture); } } - + internal static string DirectiveLocation_Interface { get { return ResourceManager.GetString("DirectiveLocation_Interface", resourceCulture); } } - + internal static string DirectiveLocation_Mutation { get { return ResourceManager.GetString("DirectiveLocation_Mutation", resourceCulture); } } - + internal static string DirectiveLocation_Object { get { return ResourceManager.GetString("DirectiveLocation_Object", resourceCulture); } } - + internal static string DirectiveLocation_Query { get { return ResourceManager.GetString("DirectiveLocation_Query", resourceCulture); } } - + internal static string DirectiveLocation_Scalar { get { return ResourceManager.GetString("DirectiveLocation_Scalar", resourceCulture); } } - + internal static string DirectiveLocation_Schema { get { return ResourceManager.GetString("DirectiveLocation_Schema", resourceCulture); } } - + internal static string DirectiveLocation_Subscription { get { return ResourceManager.GetString("DirectiveLocation_Subscription", resourceCulture); } } - + internal static string DirectiveLocation_Union { get { return ResourceManager.GetString("DirectiveLocation_Union", resourceCulture); } } - + internal static string DirectiveTypeDescriptor_OnlyProperties { get { return ResourceManager.GetString("DirectiveTypeDescriptor_OnlyProperties", resourceCulture); } } - + internal static string DirectiveTypeFactory_LocationNotSupported { get { return ResourceManager.GetString("DirectiveTypeFactory_LocationNotSupported", resourceCulture); } } - + internal static string DirectiveType_NoLocations { get { return ResourceManager.GetString("DirectiveType_NoLocations", resourceCulture); } } - + internal static string DirectiveType_ReplaceWithUse { get { return ResourceManager.GetString("DirectiveType_ReplaceWithUse", resourceCulture); } } - + internal static string DirectiveType_UnableToConvert { get { return ResourceManager.GetString("DirectiveType_UnableToConvert", resourceCulture); } } - + internal static string Directive_Description { get { return ResourceManager.GetString("Directive_Description", resourceCulture); } } - + internal static string Directive_UseLocation { get { return ResourceManager.GetString("Directive_UseLocation", resourceCulture); } } - + internal static string EnumTypeExtension_CannotMerge { get { return ResourceManager.GetString("EnumTypeExtension_CannotMerge", resourceCulture); } } - + internal static string EnumTypeExtension_ValueTypeInvalid { get { return ResourceManager.GetString("EnumTypeExtension_ValueTypeInvalid", resourceCulture); } } - + internal static string EnumType_NoValues { get { return ResourceManager.GetString("EnumType_NoValues", resourceCulture); } } - + internal static string EnumValue_Description { get { return ResourceManager.GetString("EnumValue_Description", resourceCulture); } } - + internal static string EnumValue_ValueIsNull { get { return ResourceManager.GetString("EnumValue_ValueIsNull", resourceCulture); } } - + internal static string FieldInitHelper_InvalidDefaultValue { get { return ResourceManager.GetString("FieldInitHelper_InvalidDefaultValue", resourceCulture); } } - + internal static string FieldInitHelper_NoFields { get { return ResourceManager.GetString("FieldInitHelper_NoFields", resourceCulture); } } - + internal static string Field_Description { get { return ResourceManager.GetString("Field_Description", resourceCulture); } } - + internal static string FloatType_Description { get { return ResourceManager.GetString("FloatType_Description", resourceCulture); } } - + internal static string IdType_Description { get { return ResourceManager.GetString("IdType_Description", resourceCulture); } } - + internal static string InputField_CannotSetValue { get { return ResourceManager.GetString("InputField_CannotSetValue", resourceCulture); } } - + internal static string InputObjectTypeExtension_CannotMerge { get { return ResourceManager.GetString("InputObjectTypeExtension_CannotMerge", resourceCulture); } } - + internal static string InputObjectType_CannotParseLiteral { get { return ResourceManager.GetString("InputObjectType_CannotParseLiteral", resourceCulture); } } - + internal static string InputObjectType_NoFields { get { return ResourceManager.GetString("InputObjectType_NoFields", resourceCulture); } } - + internal static string InputTypeNonNullCheck_ValueIsNull { get { return ResourceManager.GetString("InputTypeNonNullCheck_ValueIsNull", resourceCulture); } } - + internal static string InputValue_DefaultValue { get { return ResourceManager.GetString("InputValue_DefaultValue", resourceCulture); } } - + internal static string InputValue_Description { get { return ResourceManager.GetString("InputValue_Description", resourceCulture); } } - + internal static string InterfaceImplRule_ArgumentsDontMatch { get { return ResourceManager.GetString("InterfaceImplRule_ArgumentsDontMatch", resourceCulture); } } - + internal static string InterfaceImplRule_ArgumentsNotImpl { get { return ResourceManager.GetString("InterfaceImplRule_ArgumentsNotImpl", resourceCulture); } } - + internal static string InterfaceImplRule_FieldNotImpl { get { return ResourceManager.GetString("InterfaceImplRule_FieldNotImpl", resourceCulture); } } - + internal static string InterfaceImplRule_FieldTypeInvalid { get { return ResourceManager.GetString("InterfaceImplRule_FieldTypeInvalid", resourceCulture); } } - + internal static string InterfaceImplRule_ReturnTypeInvalid { get { return ResourceManager.GetString("InterfaceImplRule_ReturnTypeInvalid", resourceCulture); } } - + internal static string InterfaceTypeExtension_CannotMerge { get { return ResourceManager.GetString("InterfaceTypeExtension_CannotMerge", resourceCulture); } } - + internal static string IntType_Description { get { return ResourceManager.GetString("IntType_Description", resourceCulture); } } - + internal static string LongType_Description { get { return ResourceManager.GetString("LongType_Description", resourceCulture); } } - + internal static string MultiplierPathType_Description { get { return ResourceManager.GetString("MultiplierPathType_Description", resourceCulture); } } - + internal static string NameType_Description { get { return ResourceManager.GetString("NameType_Description", resourceCulture); } } - + internal static string Name_Cannot_BeEmpty { get { return ResourceManager.GetString("Name_Cannot_BeEmpty", resourceCulture); } } - + internal static string ObjectFieldDescriptorBase_FieldType { get { return ResourceManager.GetString("ObjectFieldDescriptorBase_FieldType", resourceCulture); } } - + internal static string ObjectTypeDescriptor_InterfaceBaseClass { get { return ResourceManager.GetString("ObjectTypeDescriptor_InterfaceBaseClass", resourceCulture); } } - + internal static string InterfaceTypeDescriptor_InterfaceBaseClass { get { return ResourceManager.GetString("InterfaceTypeDescriptor_InterfaceBaseClass", resourceCulture); } } - + internal static string ObjectTypeDescriptor_MustBePropertyOrMethod { get { return ResourceManager.GetString("ObjectTypeDescriptor_MustBePropertyOrMethod", resourceCulture); } } - + internal static string NodeDescriptor_MustBeMethod { get { return ResourceManager.GetString("NodeDescriptor_MustBeMethod", resourceCulture); } } - + internal static string NodeDescriptor_IdMember { get { return ResourceManager.GetString("NodeDescriptor_IdMember", resourceCulture); } } - + internal static string ObjectTypeDescriptor_Resolver_SchemaType { get { return ResourceManager.GetString("ObjectTypeDescriptor_Resolver_SchemaType", resourceCulture); } } - + internal static string Reflection_MemberMust_BeMethodOrProperty { get { return ResourceManager.GetString("Reflection_MemberMust_BeMethodOrProperty", resourceCulture); } } - + internal static string ResolverCompiler_UnknownParameterType { get { return ResourceManager.GetString("ResolverCompiler_UnknownParameterType", resourceCulture); } } - + internal static string ResolverTypeBindingBuilder_FieldBuilderNotSupported { get { return ResourceManager.GetString("ResolverTypeBindingBuilder_FieldBuilderNotSupported", resourceCulture); } } - + internal static string ResolverTypeBindingBuilder_FieldNotComplete { get { return ResourceManager.GetString("ResolverTypeBindingBuilder_FieldNotComplete", resourceCulture); } } - + internal static string Scalar_Cannot_Deserialize { get { return ResourceManager.GetString("Scalar_Cannot_Deserialize", resourceCulture); } } - + internal static string Scalar_Cannot_ParseLiteral { get { return ResourceManager.GetString("Scalar_Cannot_ParseLiteral", resourceCulture); } } - + internal static string Scalar_Cannot_ParseValue { get { return ResourceManager.GetString("Scalar_Cannot_ParseValue", resourceCulture); } } - + internal static string Scalar_Cannot_Serialize { get { return ResourceManager.GetString("Scalar_Cannot_Serialize", resourceCulture); } } - + internal static string SchemaBuilderExtensions_DirectiveTypeIsBaseType { get { return ResourceManager.GetString("SchemaBuilderExtensions_DirectiveTypeIsBaseType", resourceCulture); } } - + internal static string SchemaBuilderExtensions_MustBeDirectiveType { get { return ResourceManager.GetString("SchemaBuilderExtensions_MustBeDirectiveType", resourceCulture); } } - + internal static string SchemaBuilderExtensions_SchemaIsEmpty { get { return ResourceManager.GetString("SchemaBuilderExtensions_SchemaIsEmpty", resourceCulture); } } - + internal static string SchemaBuilder_Binding_CannotBeHandled { get { return ResourceManager.GetString("SchemaBuilder_Binding_CannotBeHandled", resourceCulture); } } - + internal static string SchemaBuilder_Binding_Invalid { get { return ResourceManager.GetString("SchemaBuilder_Binding_Invalid", resourceCulture); } } - + internal static string SchemaBuilder_ISchemaNotTso { get { return ResourceManager.GetString("SchemaBuilder_ISchemaNotTso", resourceCulture); } } - + internal static string SchemaBuilder_NoQueryType { get { return ResourceManager.GetString("SchemaBuilder_NoQueryType", resourceCulture); } } - + internal static string SchemaBuilder_RootType_MustBeClass { get { return ResourceManager.GetString("SchemaBuilder_RootType_MustBeClass", resourceCulture); } } - + internal static string SchemaBuilder_RootType_MustBeObjectType { get { return ResourceManager.GetString("SchemaBuilder_RootType_MustBeObjectType", resourceCulture); } } - + internal static string SchemaBuilder_RootType_NonGenericType { get { return ResourceManager.GetString("SchemaBuilder_RootType_NonGenericType", resourceCulture); } } - + internal static string SchemaBuilder_SchemaTypeInvalid { get { return ResourceManager.GetString("SchemaBuilder_SchemaTypeInvalid", resourceCulture); } } - + internal static string SchemaErrorBuilder_MessageIsNull { get { return ResourceManager.GetString("SchemaErrorBuilder_MessageIsNull", resourceCulture); } } - + internal static string SchemaField_Description { get { return ResourceManager.GetString("SchemaField_Description", resourceCulture); } } - + internal static string SchemaSyntaxVisitor_UnknownOperationType { get { return ResourceManager.GetString("SchemaSyntaxVisitor_UnknownOperationType", resourceCulture); } } - + internal static string Schema_Description { get { return ResourceManager.GetString("Schema_Description", resourceCulture); } } - + internal static string Schema_Directives { get { return ResourceManager.GetString("Schema_Directives", resourceCulture); } } - + internal static string Schema_MutationType { get { return ResourceManager.GetString("Schema_MutationType", resourceCulture); } } - + internal static string Schema_QueryType { get { return ResourceManager.GetString("Schema_QueryType", resourceCulture); } } - + internal static string Schema_SubscriptionType { get { return ResourceManager.GetString("Schema_SubscriptionType", resourceCulture); } } - + internal static string Schema_Types { get { return ResourceManager.GetString("Schema_Types", resourceCulture); } } - + internal static string ShortType_Description { get { return ResourceManager.GetString("ShortType_Description", resourceCulture); } } - + internal static string StringType_Description { get { return ResourceManager.GetString("StringType_Description", resourceCulture); } } - + internal static string String_Argument_NullOrEmpty { get { return ResourceManager.GetString("String_Argument_NullOrEmpty", resourceCulture); } } - + internal static string TypeConfiguration_ConfigureIsNull { get { return ResourceManager.GetString("TypeConfiguration_ConfigureIsNull", resourceCulture); } } - + internal static string TypeConfiguration_DefinitionIsNull { get { return ResourceManager.GetString("TypeConfiguration_DefinitionIsNull", resourceCulture); } } - + internal static string TypeDependency_MustBeSchemaType { get { return ResourceManager.GetString("TypeDependency_MustBeSchemaType", resourceCulture); } } - + internal static string TypeExtensions_InvalidStructure { get { return ResourceManager.GetString("TypeExtensions_InvalidStructure", resourceCulture); } } - + internal static string TypeExtensions_KindIsNotSupported { get { return ResourceManager.GetString("TypeExtensions_KindIsNotSupported", resourceCulture); } } - + internal static string TypeExtensions_NoListType { get { return ResourceManager.GetString("TypeExtensions_NoListType", resourceCulture); } } - + internal static string TypeExtensions_TypeIsNotOfT { get { return ResourceManager.GetString("TypeExtensions_TypeIsNotOfT", resourceCulture); } } - + internal static string TypeField_Description { get { return ResourceManager.GetString("TypeField_Description", resourceCulture); } } - + internal static string TypeInitializer_CannotResolveDependency { get { return ResourceManager.GetString("TypeInitializer_CannotResolveDependency", resourceCulture); } } - + internal static string TypeInitializer_CompleteName_Duplicate { get { return ResourceManager.GetString("TypeInitializer_CompleteName_Duplicate", resourceCulture); } } - + internal static string TypeInitializer_Merge_KindDoesNotMatch { get { return ResourceManager.GetString("TypeInitializer_Merge_KindDoesNotMatch", resourceCulture); } } - + internal static string TypeKind_Description { get { return ResourceManager.GetString("TypeKind_Description", resourceCulture); } } - + internal static string TypeKind_Enum { get { return ResourceManager.GetString("TypeKind_Enum", resourceCulture); } } - + internal static string TypeKind_InputObject { get { return ResourceManager.GetString("TypeKind_InputObject", resourceCulture); } } - + internal static string TypeKind_Interface { get { return ResourceManager.GetString("TypeKind_Interface", resourceCulture); } } - + internal static string TypeKind_List { get { return ResourceManager.GetString("TypeKind_List", resourceCulture); } } - + internal static string TypeKind_NonNull { get { return ResourceManager.GetString("TypeKind_NonNull", resourceCulture); } } - + internal static string TypeKind_Object { get { return ResourceManager.GetString("TypeKind_Object", resourceCulture); } } - + internal static string TypeKind_Scalar { get { return ResourceManager.GetString("TypeKind_Scalar", resourceCulture); } } - + internal static string TypeKind_Union { get { return ResourceManager.GetString("TypeKind_Union", resourceCulture); } } - + internal static string TypeNameField_Description { get { return ResourceManager.GetString("TypeNameField_Description", resourceCulture); } } - + internal static string TypeNameHelper_InvalidTypeStructure { get { return ResourceManager.GetString("TypeNameHelper_InvalidTypeStructure", resourceCulture); } } - + internal static string TypeNameHelper_OnlyTsosAreAllowed { get { return ResourceManager.GetString("TypeNameHelper_OnlyTsosAreAllowed", resourceCulture); } } - + internal static string TypeResourceHelper_TypeNameEmptyOrNull { get { return ResourceManager.GetString("TypeResourceHelper_TypeNameEmptyOrNull", resourceCulture); } } - + internal static string Type_Description { get { return ResourceManager.GetString("Type_Description", resourceCulture); } } - + internal static string UnionTypeExtension_CannotMerge { get { return ResourceManager.GetString("UnionTypeExtension_CannotMerge", resourceCulture); } } - + internal static string VariableValueBuilder_InputType { get { return ResourceManager.GetString("VariableValueBuilder_InputType", resourceCulture); } } - + internal static string VariableValueBuilder_InvalidValue { get { return ResourceManager.GetString("VariableValueBuilder_InvalidValue", resourceCulture); } } - + internal static string VariableValueBuilder_NodeKind { get { return ResourceManager.GetString("VariableValueBuilder_NodeKind", resourceCulture); } } - + internal static string VariableValueBuilder_NonNull { get { return ResourceManager.GetString("VariableValueBuilder_NonNull", resourceCulture); } } - + internal static string VariableValueBuilder_NonNull_In_Graph { get { return ResourceManager.GetString("VariableValueBuilder_NonNull_In_Graph", resourceCulture); } } - + internal static string VariableValueBuilder_VarNameEmpty { get { return ResourceManager.GetString("VariableValueBuilder_VarNameEmpty", resourceCulture); } } - + internal static string Argument_TypeIsNull { get { return ResourceManager.GetString("Argument_TypeIsNull", resourceCulture); } } - + internal static string NonNullType_NotAnInputType { get { return ResourceManager.GetString("NonNullType_NotAnInputType", resourceCulture); } } - + internal static string NonNullType_TypeIsNunNullType { get { return ResourceManager.GetString("NonNullType_TypeIsNunNullType", resourceCulture); } } - + internal static string NonNullType_ValueIsNull { get { return ResourceManager.GetString("NonNullType_ValueIsNull", resourceCulture); } } - + internal static string ObjectTypeExtension_CannotMerge { get { return ResourceManager.GetString("ObjectTypeExtension_CannotMerge", resourceCulture); } } - + internal static string TypeSystemObjectBase_DefinitionIsNull { get { return ResourceManager.GetString("TypeSystemObjectBase_DefinitionIsNull", resourceCulture); } } - + internal static string TypeSystemObjectBase_NameIsNull { get { return ResourceManager.GetString("TypeSystemObjectBase_NameIsNull", resourceCulture); } } - + internal static string TypeSystemObject_DescriptionImmutable { get { return ResourceManager.GetString("TypeSystemObject_DescriptionImmutable", resourceCulture); } } - + internal static string TypeSystemObject_NameImmutable { get { return ResourceManager.GetString("TypeSystemObject_NameImmutable", resourceCulture); } } - + internal static string UnionType_MustHaveTypes { get { return ResourceManager.GetString("UnionType_MustHaveTypes", resourceCulture); } } - + internal static string UnionType_UnableToResolveType { get { return ResourceManager.GetString("UnionType_UnableToResolveType", resourceCulture); } } - + internal static string SchemaBuilder_MustBeSchemaType { get { return ResourceManager.GetString("SchemaBuilder_MustBeSchemaType", resourceCulture); } } - + internal static string TypeRegistrar_TypesInconsistent { get { return ResourceManager.GetString("TypeRegistrar_TypesInconsistent", resourceCulture); } } - + internal static string TypeConvertion_ConvertNotSupported { get { return ResourceManager.GetString("TypeConvertion_ConvertNotSupported", resourceCulture); } } - + internal static string SchemaBuilder_Interceptor_NotSuppported { get { return ResourceManager.GetString("SchemaBuilder_Interceptor_NotSuppported", resourceCulture); } } - + internal static string IdSerializer_UnableToEncode { get { return ResourceManager.GetString("IdSerializer_UnableToEncode", resourceCulture); } } - + internal static string IdSerializer_UnableToDecode { get { return ResourceManager.GetString("IdSerializer_UnableToDecode", resourceCulture); } } - + internal static string SchemaBuilder_Convention_NotSuppported { get { return ResourceManager.GetString("SchemaBuilder_Convention_NotSuppported", resourceCulture); } } - + internal static string TimeSpanType_Description { get { return ResourceManager.GetString("TimeSpanType_Description", resourceCulture); } } - + internal static string DefaultDataLoaderRegistry_GetOrRegister { get { return ResourceManager.GetString("DefaultDataLoaderRegistry_GetOrRegister", resourceCulture); } } - + internal static string DataLoaderResolverContextExtensions_CreateDataLoader_AbstractType { get { return ResourceManager.GetString("DataLoaderResolverContextExtensions_CreateDataLoader_AbstractType", resourceCulture); } } - + internal static string DataLoaderResolverContextExtensions_CreateDataLoader_UnableToCreate { get { return ResourceManager.GetString("DataLoaderResolverContextExtensions_CreateDataLoader_UnableToCreate", resourceCulture); } } - + internal static string NonNamedType_IsInstanceOfType_NotAnInputType { get { return ResourceManager.GetString("NonNamedType_IsInstanceOfType_NotAnInputType", resourceCulture); } } - + internal static string RegisteredType_CompletionContext_Not_Initialized { get { return ResourceManager.GetString("RegisteredType_CompletionContext_Not_Initialized", resourceCulture); } } - + internal static string RegisteredType_CompletionContext_Already_Set { get { return ResourceManager.GetString("RegisteredType_CompletionContext_Already_Set", resourceCulture); } } - + internal static string DeferDirectiveType_Description { get { return ResourceManager.GetString("DeferDirectiveType_Description", resourceCulture); } } - + internal static string DeferDirectiveType_Label_Description { get { return ResourceManager.GetString("DeferDirectiveType_Label_Description", resourceCulture); } } - + internal static string DeferDirectiveType_If_Description { get { return ResourceManager.GetString("DeferDirectiveType_If_Description", resourceCulture); } } - + internal static string StreamDirectiveType_Description { get { return ResourceManager.GetString("StreamDirectiveType_Description", resourceCulture); } } - + internal static string StreamDirectiveType_Label_Description { get { return ResourceManager.GetString("StreamDirectiveType_Label_Description", resourceCulture); } } - + internal static string StreamDirectiveType_InitialCount_Description { get { return ResourceManager.GetString("StreamDirectiveType_InitialCount_Description", resourceCulture); } } - + internal static string StreamDirectiveType_If_Description { get { return ResourceManager.GetString("StreamDirectiveType_If_Description", resourceCulture); } } - + internal static string SchemaBuilder_AddRootType_TypeAlreadyRegistered { get { return ResourceManager.GetString("SchemaBuilder_AddRootType_TypeAlreadyRegistered", resourceCulture); } } - + internal static string NodeDescriptor_IdField_MustBePropertyOrMethod { get { return ResourceManager.GetString("NodeDescriptor_IdField_MustBePropertyOrMethod", resourceCulture); } } - + internal static string DeprecatedDirectiveType_TypeDescription { get { return ResourceManager.GetString("DeprecatedDirectiveType_TypeDescription", resourceCulture); } } - + internal static string DeprecatedDirectiveType_ReasonDescription { get { return ResourceManager.GetString("DeprecatedDirectiveType_ReasonDescription", resourceCulture); } } - + internal static string IncludeDirectiveType_TypeDescription { get { return ResourceManager.GetString("IncludeDirectiveType_TypeDescription", resourceCulture); } } - + internal static string IncludeDirectiveType_IfDescription { get { return ResourceManager.GetString("IncludeDirectiveType_IfDescription", resourceCulture); } } - + internal static string SkipDirectiveType_TypeDescription { get { return ResourceManager.GetString("SkipDirectiveType_TypeDescription", resourceCulture); } } - + internal static string SkipDirectiveType_IfDescription { get { return ResourceManager.GetString("SkipDirectiveType_IfDescription", resourceCulture); } } - + internal static string SpecifiedByDirectiveType_TypeDescription { get { return ResourceManager.GetString("SpecifiedByDirectiveType_TypeDescription", resourceCulture); } } - + internal static string SpecifiedByDirectiveType_UrlDescription { get { return ResourceManager.GetString("SpecifiedByDirectiveType_UrlDescription", resourceCulture); } } - + internal static string NodeType_TypeDescription { get { return ResourceManager.GetString("NodeType_TypeDescription", resourceCulture); } } - + internal static string AnyType_CycleInObjectGraph { get { return ResourceManager.GetString("AnyType_CycleInObjectGraph", resourceCulture); } } - + internal static string UuidType_FormatUnknown { get { return ResourceManager.GetString("UuidType_FormatUnknown", resourceCulture); } } - + internal static string Directive_GetArgument_ArgumentNameIsInvalid { get { return ResourceManager.GetString("Directive_GetArgument_ArgumentNameIsInvalid", resourceCulture); } } - + internal static string ___AppliedDirective_Description { get { return ResourceManager.GetString("__AppliedDirective_Description", resourceCulture); } } - + internal static string ___DirectiveArgument_Description { get { return ResourceManager.GetString("__DirectiveArgument_Description", resourceCulture); } } - + internal static string ThrowHelper_UsePagingAttribute_NodeTypeUnknown { get { return ResourceManager.GetString("ThrowHelper_UsePagingAttribute_NodeTypeUnknown", resourceCulture); } } - + internal static string Schema_GetDirectiveType_DoesNotExist { get { return ResourceManager.GetString("Schema_GetDirectiveType_DoesNotExist", resourceCulture); } } - + internal static string ErrorHelper_ObjectField_HasNoResolver { get { return ResourceManager.GetString("ErrorHelper_ObjectField_HasNoResolver", resourceCulture); } } - + internal static string ExtendedTypeReferenceHandler_NonGenericExecutableNotAllowed { get { return ResourceManager.GetString("ExtendedTypeReferenceHandler_NonGenericExecutableNotAllowed", resourceCulture); } } - + internal static string BindingCompiler_AddBinding_BindingCannotBeHandled { get { return ResourceManager.GetString("BindingCompiler_AddBinding_BindingCannotBeHandled", resourceCulture); } } - + internal static string Type_SpecifiedByUrl_Description { get { return ResourceManager.GetString("Type_SpecifiedByUrl_Description", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddObjectType_TIsSchemaType { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddObjectType_TIsSchemaType", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddUnionType_TIsSchemaType { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddUnionType_TIsSchemaType", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddEnumType_TIsSchemaType { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddEnumType_TIsSchemaType", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddInterfaceType_TIsSchemaType { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddInterfaceType_TIsSchemaType", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddInputObjectType_TIsSchemaType { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddInputObjectType_TIsSchemaType", resourceCulture); } } - + internal static string CostDirective_ComplexityCannotBeBelowOne { get { return ResourceManager.GetString("CostDirective_ComplexityCannotBeBelowOne", resourceCulture); } } - + internal static string CostDirective_DefaultMultiplierCannotBeBelowTwo { get { return ResourceManager.GetString("CostDirective_DefaultMultiplierCannotBeBelowTwo", resourceCulture); } } - + internal static string EventMessageParameterExpressionBuilder_MessageNotFound { get { return ResourceManager.GetString("EventMessageParameterExpressionBuilder_MessageNotFound", resourceCulture); } } - + internal static string DefaultResolverCompilerService_CreateResolver_ArgumentValudationError { get { return ResourceManager.GetString("DefaultResolverCompilerService_CreateResolver_ArgumentValudationError", resourceCulture); } } - + internal static string DefaultResolverCompilerService_CompileSubscribe_OnlyMethodsAllowed { get { return ResourceManager.GetString("DefaultResolverCompilerService_CompileSubscribe_OnlyMethodsAllowed", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddResolverConfig_ContextInvalid { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddResolverConfig_ContextInvalid", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddResolver_EmptyCooridnates { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddResolver_EmptyCooridnates", resourceCulture); } } - + internal static string ExpressionHelper_GetGlobalStateWithDefault_NoDefaults { get { return ResourceManager.GetString("ExpressionHelper_GetGlobalStateWithDefault_NoDefaults", resourceCulture); } } - + internal static string ExpressionHelper_ResolveScopedContextData_KeyDoesNotExist { get { return ResourceManager.GetString("ExpressionHelper_ResolveScopedContextData_KeyDoesNotExist", resourceCulture); } } - + internal static string ExpressionHelper_GetScopedStateWithDefault_NoDefaultValue { get { return ResourceManager.GetString("ExpressionHelper_GetScopedStateWithDefault_NoDefaultValue", resourceCulture); } } - + internal static string ClaimsPrincipalParameterExpressionBuilder_NoClaimsFound { get { return ResourceManager.GetString("ClaimsPrincipalParameterExpressionBuilder_NoClaimsFound", resourceCulture); } } - + internal static string DirectiveLocation_VariableDefinition { get { return ResourceManager.GetString("DirectiveLocation_VariableDefinition", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddResolver_TypeConditionNotMet { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddResolver_TypeConditionNotMet", resourceCulture); } } - + internal static string SchemaBuilderExtensions_AddRootResolver_NeedsToBeClassOrInterface { get { return ResourceManager.GetString("SchemaBuilderExtensions_AddRootResolver_NeedsToBeClassOrInterface", resourceCulture); } } - + internal static string Relay_NodeField_Description { get { return ResourceManager.GetString("Relay_NodeField_Description", resourceCulture); } } - + internal static string Relay_NodeField_Id_Description { get { return ResourceManager.GetString("Relay_NodeField_Id_Description", resourceCulture); } } - + internal static string Relay_NodesField_Description { get { return ResourceManager.GetString("Relay_NodesField_Description", resourceCulture); } } - + internal static string Relay_NodesField_Ids_Description { get { return ResourceManager.GetString("Relay_NodesField_Ids_Description", resourceCulture); } } - + internal static string ErrorHelper_MiddlewareOrderInvalid { get { return ResourceManager.GetString("ErrorHelper_MiddlewareOrderInvalid", resourceCulture); } } - + internal static string ErrorHelper_NoSchemaTypesAllowedAsRuntimeType { get { return ResourceManager.GetString("ErrorHelper_NoSchemaTypesAllowedAsRuntimeType", resourceCulture); } } - + internal static string FieldInitHelper_CompleteFields_MaxFieldCountToSmall { get { return ResourceManager.GetString("FieldInitHelper_CompleteFields_MaxFieldCountToSmall", resourceCulture); } } - + internal static string RegisteredType_Completion_NotYetReady { get { return ResourceManager.GetString("RegisteredType_Completion_NotYetReady", resourceCulture); } } - + internal static string EdgeType_IsInstanceOfType_NonObject { get { return ResourceManager.GetString("EdgeType_IsInstanceOfType_NonObject", resourceCulture); } } - + internal static string EdgeType_Description { get { return ResourceManager.GetString("EdgeType_Description", resourceCulture); } } - + internal static string EdgeType_Cursor_Description { get { return ResourceManager.GetString("EdgeType_Cursor_Description", resourceCulture); } } - + internal static string EdgeType_Node_Description { get { return ResourceManager.GetString("EdgeType_Node_Description", resourceCulture); } } - + internal static string ConnectionType_Description { get { return ResourceManager.GetString("ConnectionType_Description", resourceCulture); } } - + internal static string ConnectionType_PageInfo_Description { get { return ResourceManager.GetString("ConnectionType_PageInfo_Description", resourceCulture); } } - + internal static string ConnectionType_Edges_Description { get { return ResourceManager.GetString("ConnectionType_Edges_Description", resourceCulture); } } - + internal static string ConnectionType_TotalCount_Description { get { return ResourceManager.GetString("ConnectionType_TotalCount_Description", resourceCulture); } } - + internal static string CollectionSegmentType_PageInfo_Description { get { return ResourceManager.GetString("CollectionSegmentType_PageInfo_Description", resourceCulture); } } - + internal static string CollectionSegmentType_Description { get { return ResourceManager.GetString("CollectionSegmentType_Description", resourceCulture); } } - + internal static string CollectionSegmentType_Items_Description { get { return ResourceManager.GetString("CollectionSegmentType_Items_Description", resourceCulture); } } - + internal static string ConnectionType_Nodes_Description { get { return ResourceManager.GetString("ConnectionType_Nodes_Description", resourceCulture); } } - + internal static string ServiceHelper_UseResolverServiceInternal_Order { get { return ResourceManager.GetString("ServiceHelper_UseResolverServiceInternal_Order", resourceCulture); } } - + internal static string DefaultNamingConventions_FormatFieldName_EmptyOrNull { get { return ResourceManager.GetString("DefaultNamingConventions_FormatFieldName_EmptyOrNull", resourceCulture); } } - + internal static string OneOfDirectiveType_Description { get { return ResourceManager.GetString("OneOfDirectiveType_Description", resourceCulture); } } - + internal static string ThrowHelper_OneOfNoFieldSet { get { return ResourceManager.GetString("ThrowHelper_OneOfNoFieldSet", resourceCulture); } } - + internal static string ThrowHelper_OneOfMoreThanOneFieldSet { get { return ResourceManager.GetString("ThrowHelper_OneOfMoreThanOneFieldSet", resourceCulture); } } - + internal static string ThrowHelper_OneOfFieldIsNull { get { return ResourceManager.GetString("ThrowHelper_OneOfFieldIsNull", resourceCulture); } } - + internal static string ReflectionUtils_ExtractMethod_MethodExpected { get { return ResourceManager.GetString("ReflectionUtils_ExtractMethod_MethodExpected", resourceCulture); } } - + internal static string ResolverContextExtensions_ScopedContextData_KeyNotFound { get { return ResourceManager.GetString("ResolverContextExtensions_ScopedContextData_KeyNotFound", resourceCulture); } } - + internal static string ResolverContextExtensions_LocalContextData_KeyNotFound { get { return ResourceManager.GetString("ResolverContextExtensions_LocalContextData_KeyNotFound", resourceCulture); } } - + internal static string ResolverContextExtensions_ContextData_KeyNotFound { get { return ResourceManager.GetString("ResolverContextExtensions_ContextData_KeyNotFound", resourceCulture); } } - + internal static string SchemaTypes_GetType_DoesNotExist { get { return ResourceManager.GetString("SchemaTypes_GetType_DoesNotExist", resourceCulture); } } - + internal static string SchemaTypes_DefinitionInvalid { get { return ResourceManager.GetString("SchemaTypes_DefinitionInvalid", resourceCulture); } } - + internal static string InputObjectTypeDescriptor_OnlyProperties { get { return ResourceManager.GetString("InputObjectTypeDescriptor_OnlyProperties", resourceCulture); } } - + internal static string InterfaceTypeDescriptor_MustBePropertyOrMethod { get { return ResourceManager.GetString("InterfaceTypeDescriptor_MustBePropertyOrMethod", resourceCulture); } } - + internal static string ThrowHelper_FieldBase_Sealed { get { return ResourceManager.GetString("ThrowHelper_FieldBase_Sealed", resourceCulture); } } - - - internal static string TypeInitializer_CannotFindType - { - get - { + + internal static string TypeInitializer_CannotFindType { + get { return ResourceManager.GetString("TypeInitializer_CannotFindType", resourceCulture); } } - + internal static string ThrowHelper_RelayIdFieldHelpers_NoFieldType { get { return ResourceManager.GetString("ThrowHelper_RelayIdFieldHelpers_NoFieldType", resourceCulture); } } - + internal static string ThrowHelper_NodeResolver_ObjNoDefinition { get { return ResourceManager.GetString("ThrowHelper_NodeResolver_ObjNoDefinition", resourceCulture); } } - + internal static string ThrowHelper_NodeResolver_ArgumentTypeMissing { get { return ResourceManager.GetString("ThrowHelper_NodeResolver_ArgumentTypeMissing", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_TypeNotFound { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_TypeNotFound", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_FieldNotFound { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_FieldNotFound", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_FieldArgNotFound { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_FieldArgNotFound", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_InvalidCoordinate { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_InvalidCoordinate", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_InputFieldNotFound { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_InputFieldNotFound", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_EnumValueNotFound { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_EnumValueNotFound", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_DirectiveNotFound { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_DirectiveNotFound", resourceCulture); } } - + internal static string ThrowHelper_Schema_GetMember_DirectiveArgumentNotFound { get { return ResourceManager.GetString("ThrowHelper_Schema_GetMember_DirectiveArgumentNotFound", resourceCulture); } } - + internal static string ThrowHelper_FormatResultLeaf_InvalidSyntaxKind { get { return ResourceManager.GetString("ThrowHelper_FormatResultLeaf_InvalidSyntaxKind", resourceCulture); } } - + internal static string ThrowHelper_FormatResultList_InvalidObjectKind { get { return ResourceManager.GetString("ThrowHelper_FormatResultList_InvalidObjectKind", resourceCulture); } } - + internal static string ThrowHelper_FormatResultObject_InvalidObjectKind { get { return ResourceManager.GetString("ThrowHelper_FormatResultObject_InvalidObjectKind", resourceCulture); } } - + internal static string ThrowHelper_FormatValueList_InvalidObjectKind { get { return ResourceManager.GetString("ThrowHelper_FormatValueList_InvalidObjectKind", resourceCulture); } } - + internal static string ThrowHelper_ParseList_InvalidObjectKind { get { return ResourceManager.GetString("ThrowHelper_ParseList_InvalidObjectKind", resourceCulture); } } - + internal static string ThrowHelper_ParseNestedList_InvalidSyntaxKind { get { return ResourceManager.GetString("ThrowHelper_ParseNestedList_InvalidSyntaxKind", resourceCulture); } } - + internal static string ThrowHelper_ParseInputObject_InvalidObjectKind { get { return ResourceManager.GetString("ThrowHelper_ParseInputObject_InvalidObjectKind", resourceCulture); } } - + internal static string ThrowHelper_ParseInputObject_InvalidSyntaxKind { get { return ResourceManager.GetString("ThrowHelper_ParseInputObject_InvalidSyntaxKind", resourceCulture); } } - + internal static string ThrowHelper_NonNullInputViolation { get { return ResourceManager.GetString("ThrowHelper_NonNullInputViolation", resourceCulture); } } - + internal static string ThrowHelper_InvalidInputFieldNames { get { return ResourceManager.GetString("ThrowHelper_InvalidInputFieldNames", resourceCulture); } } - + internal static string ThrowHelper_RequiredInputFieldIsMissing { get { return ResourceManager.GetString("ThrowHelper_RequiredInputFieldIsMissing", resourceCulture); } } - + internal static string ThrowHelper_DataLoader_InvalidType { get { return ResourceManager.GetString("ThrowHelper_DataLoader_InvalidType", resourceCulture); } } - + internal static string ThrowHelper_Convention_ConventionCouldNotBeCreated { get { return ResourceManager.GetString("ThrowHelper_Convention_ConventionCouldNotBeCreated", resourceCulture); } } - + internal static string ThrowHelper_Convention_TwoConventionsRegisteredForScope { get { return ResourceManager.GetString("ThrowHelper_Convention_TwoConventionsRegisteredForScope", resourceCulture); } } - + internal static string ThrowHelper_NodeAttribute_IdFieldNotFound { get { return ResourceManager.GetString("ThrowHelper_NodeAttribute_IdFieldNotFound", resourceCulture); } } - + internal static string ThrowHelper_NodeAttribute_NodeResolverNotFound { get { return ResourceManager.GetString("ThrowHelper_NodeAttribute_NodeResolverNotFound", resourceCulture); } } - + internal static string ThrowHelper_TypeCompletionContext_UnableToResolveType { get { return ResourceManager.GetString("ThrowHelper_TypeCompletionContext_UnableToResolveType", resourceCulture); } } - + internal static string ThrowHelper_TypeRegistrar_CreateInstanceFailed { get { return ResourceManager.GetString("ThrowHelper_TypeRegistrar_CreateInstanceFailed", resourceCulture); } } - + internal static string ThrowHelper_Convention_UnableToCreateConvention { get { return ResourceManager.GetString("ThrowHelper_Convention_UnableToCreateConvention", resourceCulture); } } - + internal static string ThrowHelper_SubscribeAttribute_SubscribeResolverNotFound { get { return ResourceManager.GetString("ThrowHelper_SubscribeAttribute_SubscribeResolverNotFound", resourceCulture); } } - + internal static string ThrowHelper_SubscribeAttribute_TopicOnParameterAndMethod { get { return ResourceManager.GetString("ThrowHelper_SubscribeAttribute_TopicOnParameterAndMethod", resourceCulture); } } - + internal static string ThrowHelper_SubscribeAttribute_TopicTypeUnspecified { get { return ResourceManager.GetString("ThrowHelper_SubscribeAttribute_TopicTypeUnspecified", resourceCulture); } } - + internal static string ThrowHelper_SubscribeAttribute_MessageTypeUnspecified { get { return ResourceManager.GetString("ThrowHelper_SubscribeAttribute_MessageTypeUnspecified", resourceCulture); } } - + internal static string ThrowHelper_EventMessage_NotFound { get { return ResourceManager.GetString("ThrowHelper_EventMessage_NotFound", resourceCulture); } } - + internal static string ThrowHelper_EventMessage_InvalidCast { get { return ResourceManager.GetString("ThrowHelper_EventMessage_InvalidCast", resourceCulture); } } - + internal static string ErrorHelper_NeedsOneAtLeastField { get { return ResourceManager.GetString("ErrorHelper_NeedsOneAtLeastField", resourceCulture); } } - + internal static string ErrorHelper_TwoUnderscoresNotAllowedField { get { return ResourceManager.GetString("ErrorHelper_TwoUnderscoresNotAllowedField", resourceCulture); } } - + internal static string ErrorHelper_TwoUnderscoresNotAllowedOnArgument { get { return ResourceManager.GetString("ErrorHelper_TwoUnderscoresNotAllowedOnArgument", resourceCulture); } } - + internal static string ErrorHelper_TwoUnderscoresNotAllowedOnDirectiveName { get { return ResourceManager.GetString("ErrorHelper_TwoUnderscoresNotAllowedOnDirectiveName", resourceCulture); } } - + internal static string ErrorHelper_NotTransitivelyImplemented { get { return ResourceManager.GetString("ErrorHelper_NotTransitivelyImplemented", resourceCulture); } } - + internal static string ErrorHelper_InvalidFieldType { get { return ResourceManager.GetString("ErrorHelper_InvalidFieldType", resourceCulture); } } - + internal static string ErrorHelper_FieldNotImplemented { get { return ResourceManager.GetString("ErrorHelper_FieldNotImplemented", resourceCulture); } } - + internal static string ErrorHelper_InvalidArgumentType { get { return ResourceManager.GetString("ErrorHelper_InvalidArgumentType", resourceCulture); } } - + internal static string ErrorHelper_AdditionalArgumentNotNullable { get { return ResourceManager.GetString("ErrorHelper_AdditionalArgumentNotNullable", resourceCulture); } } - + internal static string ErrorHelper_ArgumentNotImplemented { get { return ResourceManager.GetString("ErrorHelper_ArgumentNotImplemented", resourceCulture); } } - + internal static string ErrorHelper_OneofInputObjectMustHaveNullableFieldsWithoutDefaults { get { return ResourceManager.GetString("ErrorHelper_OneofInputObjectMustHaveNullableFieldsWithoutDefaults", resourceCulture); } } - + internal static string ErrorHelper_RequiredArgumentCannotBeDeprecated { get { return ResourceManager.GetString("ErrorHelper_RequiredArgumentCannotBeDeprecated", resourceCulture); } } - + internal static string ErrorHelper_RequiredFieldCannotBeDeprecated { get { return ResourceManager.GetString("ErrorHelper_RequiredFieldCannotBeDeprecated", resourceCulture); } } - + internal static string ErrorHelper_InterfaceHasNoImplementation { get { return ResourceManager.GetString("ErrorHelper_InterfaceHasNoImplementation", resourceCulture); } } - + internal static string ErrorHelper_CompleteInterfacesHelper_UnableToResolveInterface { get { return ResourceManager.GetString("ErrorHelper_CompleteInterfacesHelper_UnableToResolveInterface", resourceCulture); } } - + internal static string ErrorHelper_DirectiveCollection_ArgumentValueTypeIsWrong { get { return ResourceManager.GetString("ErrorHelper_DirectiveCollection_ArgumentValueTypeIsWrong", resourceCulture); } } - + internal static string ErrorHelper_DirectiveCollection_ArgumentDoesNotExist { get { return ResourceManager.GetString("ErrorHelper_DirectiveCollection_ArgumentDoesNotExist", resourceCulture); } } - + internal static string ErrorHelper_DirectiveCollection_ArgumentNonNullViolation { get { return ResourceManager.GetString("ErrorHelper_DirectiveCollection_ArgumentNonNullViolation", resourceCulture); } } - + internal static string ErrorHelper_ObjectType_UnableToInferOrResolveType { get { return ResourceManager.GetString("ErrorHelper_ObjectType_UnableToInferOrResolveType", resourceCulture); } } - + internal static string ErrorHelper_Relay_NoNodeResolver { get { return ResourceManager.GetString("ErrorHelper_Relay_NoNodeResolver", resourceCulture); } } - + internal static string ErrorHelper_NodeResolver_MustHaveExactlyOneIdArg { get { return ResourceManager.GetString("ErrorHelper_NodeResolver_MustHaveExactlyOneIdArg", resourceCulture); } } - + internal static string ErrorHelper_NodeResolver_MustReturnObject { get { return ResourceManager.GetString("ErrorHelper_NodeResolver_MustReturnObject", resourceCulture); } } - + internal static string ErrorHelper_NodeResolver_NodeTypeHasNoId { get { return ResourceManager.GetString("ErrorHelper_NodeResolver_NodeTypeHasNoId", resourceCulture); } } - + internal static string ThrowHelper_InvalidInputFieldNames_Single { get { return ResourceManager.GetString("ThrowHelper_InvalidInputFieldNames_Single", resourceCulture); diff --git a/src/HotChocolate/Core/src/Types/Properties/TypeResources.resx b/src/HotChocolate/Core/src/Types/Properties/TypeResources.resx index d91d8331b8d..4842acfdefb 100644 --- a/src/HotChocolate/Core/src/Types/Properties/TypeResources.resx +++ b/src/HotChocolate/Core/src/Types/Properties/TypeResources.resx @@ -122,6 +122,9 @@ PublicKeyToken=b77a5c561934e089 + + The {0}-directive is missing the if-argument. + The argument type has to be an input-type. diff --git a/src/HotChocolate/Core/src/Types/Types/Extensions/DirectiveCollectionExtensions.cs b/src/HotChocolate/Core/src/Types/Types/Extensions/DirectiveCollectionExtensions.cs index e0bd8ebf177..c410201677c 100644 --- a/src/HotChocolate/Core/src/Types/Types/Extensions/DirectiveCollectionExtensions.cs +++ b/src/HotChocolate/Core/src/Types/Types/Extensions/DirectiveCollectionExtensions.cs @@ -1,11 +1,335 @@ -using System.Linq; +#nullable enable +using System; +using System.Collections.Generic; +using System.IO; +using HotChocolate.Execution; +using HotChocolate.Execution.Processing; +using HotChocolate.Language; +using HotChocolate.Utilities; +using ThrowHelper = HotChocolate.Utilities.ThrowHelper; + +// ReSharper disable once CheckNamespace namespace HotChocolate.Types; public static class DirectiveCollectionExtensions { - public static T SingleOrDefault(this IDirectiveCollection directives) => - directives - .Where(t => typeof(T).IsAssignableFrom(t.Type.RuntimeType)) - .Select(t => t.ToObject()).SingleOrDefault(); + public static T SingleOrDefault(this IDirectiveCollection directives) + { + foreach (var directive in directives) + { + if (typeof(T).IsAssignableFrom(directive.Type.RuntimeType)) + { + return directive.ToObject(); + } + } + + return default; + } + + internal static IValueNode? SkipValue(this IReadOnlyList directives) + { + var directive = directives.GetSkipDirectiveNode(); + return directive is null + ? null + : GetIfArgumentValue(directive); + } + + internal static IValueNode? IncludeValue(this IReadOnlyList directives) + { + var directive = directives.GetIncludeDirectiveNode(); + return directive is null + ? null + : GetIfArgumentValue(directive); + } + + internal static bool IsDeferrable(this InlineFragmentNode fragmentNode) + => fragmentNode.Directives.IsDeferrable(); + + internal static bool IsDeferrable(this FragmentSpreadNode fragmentSpreadNode) + => fragmentSpreadNode.Directives.IsDeferrable(); + + internal static bool IsDeferrable(this IReadOnlyList directives) + { + var directive = directives.GetDeferDirectiveNode(); + var ifValue = directive?.GetIfArgumentValueOrDefault(); + + // a fragment is not deferrable if we do not find a defer directive or + // if the `if` of the defer directive is a bool literal with a false value. + return directive is not null && ifValue is not BooleanValueNode { Value: false }; + } + + internal static bool IsStreamable(this FieldNode field) + { + var directive = field.Directives.GetStreamDirectiveNode(); + var ifValue = directive?.GetIfArgumentValueOrDefault(); + + // a field is not streamable if we do not find a streamable directive or + // if the `if` of the streamable directive is a bool literal with a false value. + return directive is not null && ifValue is not BooleanValueNode { Value: false }; + } + + internal static bool HasStreamOrDeferDirective(this IReadOnlyList directives) + { + if (directives.Count == 0) + { + return false; + } + + for (var i = 0; i < directives.Count; i++) + { + var directive = directives[i]; + + if (directive.Name.Value.EqualsOrdinal(WellKnownDirectives.Defer) || + directive.Name.Value.EqualsOrdinal(WellKnownDirectives.Stream)) + { + return true; + } + } + + return false; + } + + private static IValueNode GetIfArgumentValue(DirectiveNode directive) + { + if (directive.Arguments.Count == 1) + { + var argument = directive.Arguments[0]; + + if (string.Equals( + argument.Name.Value, + WellKnownDirectives.IfArgument, + StringComparison.Ordinal)) + { + return argument.Value; + } + } + + throw ThrowHelper.MissingIfArgument(directive); + } + + private static DirectiveNode? GetSkipDirectiveNode( + this IReadOnlyList directives) + => GetDirectiveNode(directives, WellKnownDirectives.Skip); + + private static DirectiveNode? GetIncludeDirectiveNode( + this IReadOnlyList directives) + => GetDirectiveNode(directives, WellKnownDirectives.Include); + + internal static DeferDirective? GetDeferDirective( + this IReadOnlyList directives, + IVariableValueCollection variables) + { + var directiveNode = GetDirectiveNode(directives, WellKnownDirectives.Defer); + + if (directiveNode is not null) + { + var @if = true; + string? label = null; + + foreach (var argument in directiveNode.Arguments) + { + switch (argument.Name.Value) + { + case WellKnownDirectives.IfArgument: + @if = argument.Value switch + { + VariableNode variable + => variables.GetVariable(variable.Name.Value), + BooleanValueNode b => b.Value, + _ => @if + }; + break; + + case WellKnownDirectives.LabelArgument: + label = argument.Value switch + { + VariableNode variable + => variables.GetVariable(variable.Name.Value), + StringValueNode b => b.Value, + _ => label + }; + break; + } + } + + return new DeferDirective(@if, label); + } + + return null; + } + + internal static StreamDirective? GetStreamDirective( + this ISelection selection, + IVariableValueCollection variables) => + selection.SyntaxNode.GetStreamDirective(variables); + + internal static StreamDirective? GetStreamDirective( + this FieldNode fieldNode, + IVariableValueCollection variables) + { + var directiveNode = GetDirectiveNode(fieldNode.Directives, WellKnownDirectives.Stream); + + if (directiveNode is not null) + { + var @if = true; + string? label = null; + var initialCount = 0; + + foreach (var argument in directiveNode.Arguments) + { + switch (argument.Name.Value) + { + case WellKnownDirectives.IfArgument: + @if = argument.Value switch + { + VariableNode variable + => variables.GetVariable(variable.Name.Value), + BooleanValueNode b => b.Value, + _ => @if + }; + break; + + case WellKnownDirectives.LabelArgument: + label = argument.Value switch + { + VariableNode variable + => variables.GetVariable(variable.Name.Value), + StringValueNode b => b.Value, + _ => label + }; + break; + + case WellKnownDirectives.InitialCount: + initialCount = argument.Value switch + { + VariableNode variable + => variables.GetVariable(variable.Name.Value), + IntValueNode b => b.ToInt32(), + _ => initialCount + }; + break; + } + } + + return new StreamDirective(@if, initialCount, label); + } + + return null; + } + + internal static IValueNode? GetIfArgumentValueOrDefault(this DirectiveNode directive) + { + for (var i = 0; i < directive.Arguments.Count; i++) + { + var argument = directive.Arguments[i]; + + if (argument.Name.Value.EqualsOrdinal(WellKnownDirectives.IfArgument)) + { + return argument.Value; + } + } + + return null; + } + + internal static IValueNode? GetLabelArgumentValueOrDefault(this DirectiveNode directive) + { + for (var i = 0; i < directive.Arguments.Count; i++) + { + var argument = directive.Arguments[i]; + + if (argument.Name.Value.EqualsOrdinal(WellKnownDirectives.LabelArgument)) + { + return argument.Value; + } + } + + return null; + } + + internal static bool StreamDirectiveEquals( + this DirectiveNode streamA, + DirectiveNode streamB) + { + var argsA = CreateStreamArgs(streamA); + var argsB = CreateStreamArgs(streamB); + + return SyntaxComparer.BySyntax.Equals(argsA.If, argsB.If) && + SyntaxComparer.BySyntax.Equals(argsA.InitialCount, argsB.InitialCount) && + SyntaxComparer.BySyntax.Equals(argsA.Label, argsB.Label); + } + + private static StreamArgs CreateStreamArgs(DirectiveNode directiveNode) + { + var args = new StreamArgs(); + + for (var i = 0; i < directiveNode.Arguments.Count; i++) + { + var argument = directiveNode.Arguments[i]; + + switch (argument.Name.Value) + { + case WellKnownDirectives.IfArgument: + args.If = argument.Value; + break; + + case WellKnownDirectives.LabelArgument: + args.Label = argument.Value; + break; + + case WellKnownDirectives.InitialCount: + args.InitialCount = argument.Value; + break; + } + } + + return args; + } + + internal static DirectiveNode? GetDeferDirectiveNode( + this Language.IHasDirectives container) => + GetDirectiveNode(container.Directives, WellKnownDirectives.Defer); + + internal static DirectiveNode? GetDeferDirectiveNode( + this IReadOnlyList directives) => + GetDirectiveNode(directives, WellKnownDirectives.Defer); + + internal static DirectiveNode? GetStreamDirectiveNode( + this FieldNode selection) => + GetDirectiveNode(selection.Directives, WellKnownDirectives.Stream); + + internal static DirectiveNode? GetStreamDirectiveNode( + this IReadOnlyList directives) => + GetDirectiveNode(directives, WellKnownDirectives.Stream); + + private static DirectiveNode? GetDirectiveNode( + this IReadOnlyList directives, + string name) + { + if (directives.Count == 0) + { + return null; + } + + for (var i = 0; i < directives.Count; i++) + { + var directive = directives[i]; + + if (directive.Name.Value.EqualsOrdinal(name)) + { + return directive; + } + } + return null; + } + + private ref struct StreamArgs + { + public IValueNode? If { get; set; } + + public IValueNode? Label { get; set; } + + public IValueNode? InitialCount { get; set; } + } } diff --git a/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs b/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs index bd31fdc874e..48afeaf9ee8 100644 --- a/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs +++ b/src/HotChocolate/Core/src/Types/Utilities/ThrowHelper.cs @@ -539,4 +539,14 @@ public static InvalidOperationException NodeResolver_ObjNoDefinition() return new SchemaException(builder.Build()); } + + public static GraphQLException MissingIfArgument( + DirectiveNode directive) + => new( + ErrorBuilder.New() + .SetMessage( + ThrowHelper_MissingDirectiveIfArgument, + directive.Name.Value) + .AddLocation(directive) + .Build()); } diff --git a/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs b/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs index 0742ea81a6c..d4d1a9fa0d4 100644 --- a/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs +++ b/src/HotChocolate/Core/src/Validation/DocumentValidatorContext.cs @@ -34,6 +34,8 @@ public ISchema Schema } } + public OperationType? OperationType { get; set; } + public IOutputType NonNullString { get diff --git a/src/HotChocolate/Core/src/Validation/ErrorHelper.cs b/src/HotChocolate/Core/src/Validation/ErrorHelper.cs index 228f7d57b1c..f1534b08680 100644 --- a/src/HotChocolate/Core/src/Validation/ErrorHelper.cs +++ b/src/HotChocolate/Core/src/Validation/ErrorHelper.cs @@ -683,4 +683,46 @@ internal static class ErrorHelper .SetExtension(nameof(field), field.ToString()) .SpecifiedBy("sec-Oneof–Input-Objects-Have-Exactly-One-Field", rfc: 825) .Build(); + + public static IError DeferAndStreamNotAllowedOnMutationOrSubscriptionRoot( + ISelectionNode selection) + => ErrorBuilder.New() + .SetMessage(Resources.ErrorHelper_DeferAndStreamNotAllowedOnMutationOrSubscriptionRoot) + .AddLocation(selection) + .SpecifiedBy("sec-Defer-And-Stream-Directives-Are-Used-On-Valid-Root-Field") + .Build(); + + public static IError DeferAndStreamDuplicateLabel( + this IDocumentValidatorContext context, + ISyntaxNode selection, + string label) + => ErrorBuilder.New() + .SetMessage(Resources.ErrorHelper_DeferAndStreamDuplicateLabel) + .AddLocation(selection) + .SpecifiedBy("sec-Defer-And-Stream-Directive-Labels-Are-Unique") + .SetExtension(nameof(label), label) + .SetPath(context.CreateErrorPath()) + .Build(); + + public static IError DeferAndStreamLabelIsVariable( + this IDocumentValidatorContext context, + ISyntaxNode selection, + string variable) + => ErrorBuilder.New() + .SetMessage(Resources.ErrorHelper_DeferAndStreamLabelIsVariable) + .AddLocation(selection) + .SpecifiedBy("sec-Defer-And-Stream-Directive-Labels-Are-Unique") + .SetExtension(nameof(variable),$"${variable}") + .SetPath(context.CreateErrorPath()) + .Build(); + + public static IError StreamOnNonListField( + this IDocumentValidatorContext context, + ISyntaxNode selection) + => ErrorBuilder.New() + .SetMessage("@stream directive is only valid on list fields.") + .AddLocation(selection) + .SpecifiedBy("sec-Stream-Directives-Are-Used-On-List-Fields") + .SetPath(context.CreateErrorPath()) + .Build(); } diff --git a/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs b/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs index a82672ac931..426b10ed500 100644 --- a/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs +++ b/src/HotChocolate/Core/src/Validation/IDocumentValidatorContext.cs @@ -17,6 +17,11 @@ public interface IDocumentValidatorContext : ISyntaxVisitorContext /// ISchema Schema { get; } + /// + /// Gets the current operation type. + /// + OperationType? OperationType { get; set; } + /// /// Gets a non-null string type. /// @@ -25,7 +30,7 @@ public interface IDocumentValidatorContext : ISyntaxVisitorContext /// /// Specifies the max allowed validation errors. /// - int MaxAllowedErrors { get;} + int MaxAllowedErrors { get; } /// /// The current visitation path of syntax nodes. diff --git a/src/HotChocolate/Core/src/Validation/Properties/Resources.Designer.cs b/src/HotChocolate/Core/src/Validation/Properties/Resources.Designer.cs index 38d154f39cc..a4d2d94e2cf 100644 --- a/src/HotChocolate/Core/src/Validation/Properties/Resources.Designer.cs +++ b/src/HotChocolate/Core/src/Validation/Properties/Resources.Designer.cs @@ -296,5 +296,23 @@ internal class Resources { return ResourceManager.GetString("ErrorHelper_OneOfVariablesMustBeNonNull", resourceCulture); } } + + internal static string ErrorHelper_DeferAndStreamNotAllowedOnMutationOrSubscriptionRoot { + get { + return ResourceManager.GetString("ErrorHelper_DeferAndStreamNotAllowedOnMutationOrSubscriptionRoot", resourceCulture); + } + } + + internal static string ErrorHelper_DeferAndStreamDuplicateLabel { + get { + return ResourceManager.GetString("ErrorHelper_DeferAndStreamDuplicateLabel", resourceCulture); + } + } + + internal static string ErrorHelper_DeferAndStreamLabelIsVariable { + get { + return ResourceManager.GetString("ErrorHelper_DeferAndStreamLabelIsVariable", resourceCulture); + } + } } } diff --git a/src/HotChocolate/Core/src/Validation/Properties/Resources.resx b/src/HotChocolate/Core/src/Validation/Properties/Resources.resx index 0ab512baafe..790915e2eb7 100644 --- a/src/HotChocolate/Core/src/Validation/Properties/Resources.resx +++ b/src/HotChocolate/Core/src/Validation/Properties/Resources.resx @@ -224,4 +224,13 @@ The variable `${0}` assigned to the field `{1}` of the Oneof Input Object `{2}` must be non-null. + + The defer and stream directives are not allowed to be used on root fields of the mutation or subscription type. + + + If a label is passed, it must be unique within all other @defer and @stream directives in the document. + + + If a label for @defer or @stream is passed, it must not be a variable. + diff --git a/src/HotChocolate/Core/src/Validation/Rules/DirectiveVisitor.cs b/src/HotChocolate/Core/src/Validation/Rules/DirectiveVisitor.cs index b6acee271e6..563857552f0 100644 --- a/src/HotChocolate/Core/src/Validation/Rules/DirectiveVisitor.cs +++ b/src/HotChocolate/Core/src/Validation/Rules/DirectiveVisitor.cs @@ -1,6 +1,11 @@ using HotChocolate.Language; using HotChocolate.Language.Visitors; +using HotChocolate.Types; +using HotChocolate.Types.Descriptors; +using HotChocolate.Utilities; +using static HotChocolate.Language.SyntaxKind; using DirectiveLoc = HotChocolate.Types.DirectiveLocation; +using IHasDirectives = HotChocolate.Language.IHasDirectives; namespace HotChocolate.Validation.Rules; @@ -31,6 +36,15 @@ namespace HotChocolate.Validation.Rules; /// therefore only one of each directive is allowed per location. /// /// http://spec.graphql.org/draft/#sec-Directives-Are-Unique-Per-Location +/// +/// AND +/// +/// The @defer and @stream directives each accept an argument “label”. +/// This label may be used by GraphQL clients to uniquely identify response payloads. +/// If a label is passed, it must not be a variable and it must be unique within +/// all other @defer and @stream directives in the document. +/// +/// http://spec.graphql.org/draft/#sec-Defer-And-Stream-Directive-Labels-Are-Unique /// internal sealed class DirectiveVisitor : DocumentValidatorVisitor { @@ -48,15 +62,15 @@ public DirectiveVisitor() { switch (node.Kind) { - case SyntaxKind.Field: - case SyntaxKind.SelectionSet: - case SyntaxKind.InlineFragment: - case SyntaxKind.FragmentSpread: - case SyntaxKind.FragmentDefinition: + case Field: + case SelectionSet: + case InlineFragment: + case FragmentSpread: + case FragmentDefinition: case SyntaxKind.Directive: - case SyntaxKind.VariableDefinition: - case SyntaxKind.OperationDefinition: - case SyntaxKind.Document: + case VariableDefinition: + case OperationDefinition: + case Document: return base.Enter(node, context); default: @@ -68,7 +82,7 @@ public DirectiveVisitor() OperationDefinitionNode node, IDocumentValidatorContext context) { - ValidateDirectiveAreUniquePerLocation(node, context); + ValidateDirectives(node, context); return Continue; } @@ -76,7 +90,7 @@ public DirectiveVisitor() VariableDefinitionNode node, IDocumentValidatorContext context) { - ValidateDirectiveAreUniquePerLocation(node, context); + ValidateDirectives(node, context); return Continue; } @@ -84,7 +98,7 @@ public DirectiveVisitor() FieldNode node, IDocumentValidatorContext context) { - ValidateDirectiveAreUniquePerLocation(node, context); + ValidateDirectives(node, context); return Continue; } @@ -92,7 +106,7 @@ public DirectiveVisitor() InlineFragmentNode node, IDocumentValidatorContext context) { - ValidateDirectiveAreUniquePerLocation(node, context); + ValidateDirectives(node, context); return Continue; } @@ -100,7 +114,7 @@ public DirectiveVisitor() FragmentDefinitionNode node, IDocumentValidatorContext context) { - ValidateDirectiveAreUniquePerLocation(node, context); + ValidateDirectives(node, context); return Continue; } @@ -108,7 +122,7 @@ public DirectiveVisitor() FragmentSpreadNode node, IDocumentValidatorContext context) { - ValidateDirectiveAreUniquePerLocation(node, context); + ValidateDirectives(node, context); return Continue; } @@ -132,20 +146,39 @@ public DirectiveVisitor() return Skip; } - private void ValidateDirectiveAreUniquePerLocation( + private static void ValidateDirectives( T node, IDocumentValidatorContext context) - where T : ISyntaxNode, Language.IHasDirectives + where T : ISyntaxNode, IHasDirectives { context.Names.Clear(); foreach (var directive in node.Directives) { + // ValidateDirectiveAreUniquePerLocation if (context.Schema.TryGetDirectiveType(directive.Name.Value, out var dt) && !dt.IsRepeatable && !context.Names.Add(directive.Name.Value)) { context.ReportError(context.DirectiveMustBeUniqueInLocation(directive)); } + + // Defer And Stream Directive Labels Are Unique + if (node.Kind is Field or InlineFragment or FragmentSpread && + (directive.Name.Value.EqualsOrdinal(WellKnownDirectives.Defer) || + directive.Name.Value.EqualsOrdinal(WellKnownDirectives.Stream))) + { + if (directive.GetLabelArgumentValueOrDefault() is StringValueNode sn) + { + if (!context.Declared.Add(sn.Value)) + { + context.ReportError(context.DeferAndStreamDuplicateLabel(node, sn.Value)); + } + } + else if (directive.GetLabelArgumentValueOrDefault() is VariableNode vn) + { + context.ReportError(context.DeferAndStreamLabelIsVariable(node, vn.Name.Value)); + } + } } } @@ -153,27 +186,27 @@ private static bool TryLookupLocation(ISyntaxNode node, out DirectiveLoc locatio { switch (node.Kind) { - case SyntaxKind.Field: + case Field: location = DirectiveLoc.Field; return true; - case SyntaxKind.FragmentDefinition: + case FragmentDefinition: location = DirectiveLoc.FragmentDefinition; return true; - case SyntaxKind.FragmentSpread: + case FragmentSpread: location = DirectiveLoc.FragmentSpread; return true; - case SyntaxKind.InlineFragment: + case InlineFragment: location = DirectiveLoc.InlineFragment; return true; - case SyntaxKind.VariableDefinition: + case VariableDefinition: location = DirectiveLoc.VariableDefinition; return true; - case SyntaxKind.OperationDefinition: + case OperationDefinition: switch (((OperationDefinitionNode)node).Operation) { case OperationType.Query: diff --git a/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs b/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs index 0a53e88bed0..de582a560cb 100644 --- a/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs +++ b/src/HotChocolate/Core/src/Validation/Rules/FieldVisitor.cs @@ -53,9 +53,10 @@ internal sealed class FieldVisitor : TypeDocumentValidatorVisitor if (node.SelectionSet.Selections.Count == 0) { - context.ReportError(context.NoSelectionOnRootType( - node, - context.Schema.GetOperationType(node.Operation)!)); + context.ReportError( + context.NoSelectionOnRootType( + node, + context.Schema.GetOperationType(node.Operation)!)); } return base.Leave(node, context); @@ -66,6 +67,7 @@ internal sealed class FieldVisitor : TypeDocumentValidatorVisitor IDocumentValidatorContext context) { var selectionSet = context.SelectionSets.Peek(); + if (!context.FieldSets.TryGetValue(selectionSet, out var fields)) { fields = context.RentFieldInfoList(); @@ -74,6 +76,11 @@ internal sealed class FieldVisitor : TypeDocumentValidatorVisitor if (IntrospectionFields.TypeName.EqualsOrdinal(node.Name.Value)) { + if (node.IsStreamable()) + { + context.ReportError(context.StreamOnNonListField(node)); + } + fields.Add(new FieldInfo(context.Types.Peek(), context.NonNullString, node)); return Skip; } @@ -103,6 +110,13 @@ internal sealed class FieldVisitor : TypeDocumentValidatorVisitor } } + // if the directive is annotated with the @stream directive then the fields + // return type must bi a list. + if (node.IsStreamable() && !of.Type.IsListType()) + { + context.ReportError(context.StreamOnNonListField(node)); + } + context.OutputFields.Push(of); context.Types.Push(of.Type); return Continue; @@ -168,8 +182,8 @@ internal sealed class FieldVisitor : TypeDocumentValidatorVisitor IDocumentValidatorContext context) { if (context.Fragments.TryGetValue( - node.Name.Value, - out var fragment) && + node.Name.Value, + out var fragment) && context.VisitedFragments.Add(fragment.Name.Value)) { var result = Visit(fragment, node, context); @@ -189,6 +203,7 @@ private static bool HasFields(SelectionSetNode selectionSet) for (var i = 0; i < selectionSet.Selections.Count; i++) { var selection = selectionSet.Selections[i]; + if (selection.Kind is SyntaxKind.Field) { if (!IsTypeNameField(((FieldNode)selection).Name.Value)) @@ -221,15 +236,18 @@ private static bool IsTypeNameField(string fieldName) for (var i = 0; i < fields.Count - 1; i++) { var fieldA = fields[i]; + for (var j = i + 1; j < fields.Count; j++) { var fieldB = fields[j]; + if (!ReferenceEquals(fieldA.Field, fieldB.Field) && string.Equals(fieldA.ResponseName, fieldB.ResponseName, Ordinal)) { if (SameResponseShape( fieldA.Type.RewriteNullability(fieldA.Field.Required), - fieldB.Type.RewriteNullability(fieldB.Field.Required))) + fieldB.Type.RewriteNullability(fieldB.Field.Required)) && + SameStreamDirective(fieldA, fieldB)) { if (IsParentTypeAligned(fieldA, fieldB)) { @@ -303,9 +321,11 @@ private static bool AreArgumentsIdentical(FieldNode fieldA, FieldNode fieldB) for (var i = 0; i < fieldA.Arguments.Count; i++) { var argumentA = fieldA.Arguments[i]; + for (var j = 0; j < fieldB.Arguments.Count; j++) { var argumentB = fieldB.Arguments[j]; + if (BySyntax.Equals(argumentA.Name, argumentB.Name)) { if (BySyntax.Equals(argumentA.Value, argumentB.Value)) @@ -359,4 +379,25 @@ private static bool SameResponseShape(IType typeA, IType typeB) return false; } + + private static bool SameStreamDirective(FieldInfo fieldA, FieldInfo fieldB) + { + var streamA = fieldA.Field.GetStreamDirectiveNode(); + var streamB = fieldB.Field.GetStreamDirectiveNode(); + + // if both fields do not have any stream directive they are mergeable. + if (streamA is null) + { + return streamB is null; + } + + // if stream a is not nullable and stream b is null then we cannot merge. + if (streamB is null) + { + return false; + } + + // if both fields have a stream directive we need to check if they are equal. + return streamA.StreamDirectiveEquals(streamB); + } } diff --git a/src/HotChocolate/Core/src/Validation/Rules/OperationVisitor.cs b/src/HotChocolate/Core/src/Validation/Rules/OperationVisitor.cs index 05fe9b81faf..9f6d7a60c7a 100644 --- a/src/HotChocolate/Core/src/Validation/Rules/OperationVisitor.cs +++ b/src/HotChocolate/Core/src/Validation/Rules/OperationVisitor.cs @@ -1,7 +1,9 @@ using System.Linq; using HotChocolate.Language; using HotChocolate.Language.Visitors; +using HotChocolate.Types; using HotChocolate.Types.Introspection; +using static HotChocolate.Validation.ErrorHelper; namespace HotChocolate.Validation.Rules; @@ -23,6 +25,12 @@ namespace HotChocolate.Validation.Rules; /// Subscription operations must have exactly one root field. /// /// http://spec.graphql.org/June2018/#sec-Single-root-field +/// +/// AND +/// +/// Defer And Stream Directives Are Used On Valid Root Field +/// +/// http://spec.graphql.org/draft/#sec-Defer-And-Stream-Directives-Are-Used-On-Valid-Root-Field /// /// /// http://spec.graphql.org/draft/#sec-Validation.Operations @@ -75,6 +83,12 @@ public class OperationVisitor : DocumentValidatorVisitor IDocumentValidatorContext context) { context.Names.Clear(); + context.OperationType = node.Operation; + + if (node.Operation == OperationType.Mutation) + { + return Continue; + } if (node.Operation == OperationType.Subscription) { @@ -88,13 +102,16 @@ public class OperationVisitor : DocumentValidatorVisitor OperationDefinitionNode node, IDocumentValidatorContext context) { - if (context.Names.Count > 1) - { - context.ReportError(context.SubscriptionSingleRootField(node)); - } - else if (IntrospectionFields.TypeName.Equals(context.Names.Single())) + if (node.Operation == OperationType.Subscription) { - context.ReportError(context.SubscriptionNoTopLevelIntrospectionField(node)); + if (context.Names.Count > 1) + { + context.ReportError(context.SubscriptionSingleRootField(node)); + } + else if (IntrospectionFields.TypeName.Equals(context.Names.Single())) + { + context.ReportError(context.SubscriptionNoTopLevelIntrospectionField(node)); + } } return Continue; @@ -105,6 +122,39 @@ public class OperationVisitor : DocumentValidatorVisitor IDocumentValidatorContext context) { context.Names.Add((node.Alias ?? node.Name).Value); + + if (context.OperationType is OperationType.Mutation or OperationType.Subscription && + node.Directives.HasStreamOrDeferDirective()) + { + context.ReportError(DeferAndStreamNotAllowedOnMutationOrSubscriptionRoot(node)); + } + return Skip; } + + protected override ISyntaxVisitorAction Enter( + InlineFragmentNode node, + IDocumentValidatorContext context) + { + if (context.OperationType is OperationType.Mutation or OperationType.Subscription && + node.Directives.HasStreamOrDeferDirective()) + { + context.ReportError(DeferAndStreamNotAllowedOnMutationOrSubscriptionRoot(node)); + } + + return base.Enter(node, context); + } + + protected override ISyntaxVisitorAction Enter( + FragmentSpreadNode node, + IDocumentValidatorContext context) + { + if (context.OperationType is OperationType.Mutation or OperationType.Subscription && + node.Directives.HasStreamOrDeferDirective()) + { + context.ReportError(DeferAndStreamNotAllowedOnMutationOrSubscriptionRoot(node)); + } + + return base.Enter(node, context); + } } diff --git a/src/HotChocolate/Core/test/Abstractions.Tests/Execution/QueryResultBuilderTests.cs b/src/HotChocolate/Core/test/Abstractions.Tests/Execution/QueryResultBuilderTests.cs index e2af6c4b015..1a2037be5b6 100644 --- a/src/HotChocolate/Core/test/Abstractions.Tests/Execution/QueryResultBuilderTests.cs +++ b/src/HotChocolate/Core/test/Abstractions.Tests/Execution/QueryResultBuilderTests.cs @@ -31,6 +31,19 @@ public void Create_Result_Set_Data() builder.Create().MatchSnapshot(); } + [Fact] + public void Create_Result_Set_Items() + { + // arrange + var builder = new QueryResultBuilder(); + + // act + builder.SetItems(new List { 1 }); + + // assert + builder.Create().MatchSnapshot(); + } + [Fact] public void ExpectQueryResult() { @@ -60,4 +73,4 @@ public void ExpectResponseStream() // assert Assert.Throws(Fail); } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Core/test/Abstractions.Tests/Execution/__snapshots__/QueryResultBuilderTests.Create_Result_Set_Data.snap b/src/HotChocolate/Core/test/Abstractions.Tests/Execution/__snapshots__/QueryResultBuilderTests.Create_Result_Set_Data.snap index a9e0fa3bc93..68d62543d17 100644 --- a/src/HotChocolate/Core/test/Abstractions.Tests/Execution/__snapshots__/QueryResultBuilderTests.Create_Result_Set_Data.snap +++ b/src/HotChocolate/Core/test/Abstractions.Tests/Execution/__snapshots__/QueryResultBuilderTests.Create_Result_Set_Data.snap @@ -5,6 +5,7 @@ "Data": { "a": "b" }, + "Items": null, "Errors": null, "Extensions": null, "Incremental": null, diff --git a/src/HotChocolate/Core/test/Abstractions.Tests/Execution/__snapshots__/QueryResultBuilderTests.Create_Result_Set_Items.snap b/src/HotChocolate/Core/test/Abstractions.Tests/Execution/__snapshots__/QueryResultBuilderTests.Create_Result_Set_Items.snap new file mode 100644 index 00000000000..a5235ee0b0f --- /dev/null +++ b/src/HotChocolate/Core/test/Abstractions.Tests/Execution/__snapshots__/QueryResultBuilderTests.Create_Result_Set_Items.snap @@ -0,0 +1,14 @@ +{ + "Kind": "SingleResult", + "Label": null, + "Path": null, + "Data": null, + "Items": [ + 1 + ], + "Errors": null, + "Extensions": null, + "Incremental": null, + "ContextData": null, + "HasNext": null +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/DeferAndStreamTestSchema.cs b/src/HotChocolate/Core/test/Execution.Tests/DeferAndStreamTestSchema.cs new file mode 100644 index 00000000000..9dc01cc10b0 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/DeferAndStreamTestSchema.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using HotChocolate.Types; +using HotChocolate.Types.Relay; +using Microsoft.Extensions.DependencyInjection; + +namespace HotChocolate.Execution; + +internal static class DeferAndStreamTestSchema +{ + public static async Task CreateAsync() + { + return await new ServiceCollection() + .AddGraphQL() + .AddQueryType() + .AddGlobalObjectIdentification() + .BuildRequestExecutorAsync(); + } + + public class Query + { + private readonly List _persons = new() + { + new Person(1, "Pascal"), + new Person(2, "Rafi"), + new Person(3, "Martin"), + new Person(4, "Michael"), + }; + + [NodeResolver] + public async Task GetPersonAsync(int id) + { + await Task.Delay(50); + return _persons[id - 1]; + } + + public async IAsyncEnumerable GetPersons() + { + foreach (var person in _persons) + { + await Task.Delay(50); + yield return person; + } + } + + [UsePaging] + public IEnumerable GetPersonNodes() + { + foreach (var person in _persons) + { + yield return person; + } + } + + public async Task Wait(int m, CancellationToken ct) + { + await Task.Delay(m, ct); + return true; + } + } + + public class Person + { + private readonly string _name; + + public Person(int id, string name) + { + Id = id; + _name = name; + } + + public int Id { get; } + + public async Task GetNameAsync(CancellationToken cancellationToken) + { + await Task.Delay(Id * 200, cancellationToken); + return _name; + } + } +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/DeferTests.cs b/src/HotChocolate/Core/test/Execution.Tests/DeferTests.cs index 8e02f62bb07..f4a4e1251bb 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/DeferTests.cs +++ b/src/HotChocolate/Core/test/Execution.Tests/DeferTests.cs @@ -1,243 +1,223 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using CookieCrumble; -using Microsoft.Extensions.DependencyInjection; -using HotChocolate.StarWars; -using Xunit; -using static HotChocolate.Execution.QueryResultBuilder; namespace HotChocolate.Execution; public class DeferTests { [Fact] - public async Task NoOptimization_Defer_Single_Scalar_Field() + public async Task InlineFragment_Defer() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ - hero(episode: NEW_HOPE) { - id - ... @defer { - name - } - } - }"); - - var stream = Assert.IsType(result); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer { + person(id: ""UGVyc29uCmkx"") { + id + } + } + }"); - stream.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task NoOptimization_Defer_Only_Root() + public async Task InlineFragment_Defer_Nested() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer { + person(id: ""UGVyc29uCmkx"") { + id ... @defer { - hero(episode: NEW_HOPE) { - id - name - } + name } - }"); - - var stream = Assert.IsType(result); + } + } + }"); - stream.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task NoOptimization_Defer_One_Root() + public async Task InlineFragment_Defer_Label_Set_To_abc() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ - ... @defer { - a: hero(episode: NEW_HOPE) { - id - name - } - } - b: hero(episode: NEW_HOPE) { - id - name - } - }"); - - var stream = Assert.IsType(result); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer(label: ""abc"") { + person(id: ""UGVyc29uCmkx"") { + id + } + } + }"); - stream.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task NoOptimization_Nested_Defer() + public async Task InlineFragment_Defer_If_Set_To_false() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ - hero(episode: NEW_HOPE) { - id - ... @defer(label: ""friends"") { - friends { - nodes { - id - ... @defer { - name - } - } - } - } - } - }"); - - var stream = Assert.IsType(result); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer(if: false) { + person(id: ""UGVyc29uCmkx"") { + id + } + } + }"); - stream.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task NoOptimization_Spread_Defer() + public async Task InlineFragment_Defer_If_Variable_Set_To_false() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ - hero(episode: NEW_HOPE) { - id - ... deferred @defer(label: ""friends"") - } - } - - fragment deferred on Character { - friends { - nodes { + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + QueryRequestBuilder + .New() + .SetQuery( + @"query($defer: Boolean!) { + ... @defer(if: $defer) { + person(id: ""UGVyc29uCmkx"") { id } } - }"); - - var stream = Assert.IsType(result); + }") + .SetVariableValue("defer", false) + .Create()); - stream.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task Do_Not_Defer() + public async Task FragmentSpread_Defer() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ - hero(episode: NEW_HOPE) { - id - ... deferred @defer(label: ""friends"", if: false) - } - } - - fragment deferred on Character { - friends { - nodes { - id - } - } - }"); - - var queryResult = Assert.IsType(result); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... Foo @defer + } + + fragment Foo on Query { + person(id: ""UGVyc29uCmkx"") { + id + } + }"); - queryResult.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task Do_Not_Defer_If_Variable_Set_To_False() + public async Task FragmentSpread_Defer_Nested() { - var request = QueryRequestBuilder.New() - .SetQuery( - @"query($if: Boolean!) { - hero(episode: NEW_HOPE) { - id - ... deferred @defer(label: ""friends"", if: $if) + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... Foo @defer + } + + fragment Foo on Query { + person(id: ""UGVyc29uCmkx"") { + id + ... @defer { + name } } + }"); - fragment deferred on Character { - friends { - nodes { - id - } - } - }") - .SetVariableValue("if", false) - .Create(); - - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync(request); + Assert.IsType(result).MatchSnapshot(); + } - var queryResult = Assert.IsType(result); + [Fact] + public async Task FragmentSpread_Defer_Label_Set_To_abc() + { + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... Foo @defer(label: ""abc"") + } + + fragment Foo on Query { + person(id: ""UGVyc29uCmkx"") { + id + } + }"); - queryResult.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task Do_Defer_If_Variable_Set_To_True() + public async Task FragmentSpread_Defer_If_Set_To_false() { - var request = QueryRequestBuilder.New() - .SetQuery( - @"query($if: Boolean!) { - hero(episode: NEW_HOPE) { - id - ... deferred @defer(label: ""friends"", if: $if) - } + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... Foo @defer(if: false) + } + + fragment Foo on Query { + person(id: ""UGVyc29uCmkx"") { + id } + }"); - fragment deferred on Character { - friends { - nodes { + Assert.IsType(result).MatchSnapshot(); + } + + [Fact] + public async Task FragmentSpread_Defer_If_Variable_Set_To_false() + { + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + QueryRequestBuilder + .New() + .SetQuery( + @"query ($defer: Boolean!) { + ... Foo @defer(if: $defer) + } + + fragment Foo on Query { + person(id: ""UGVyc29uCmkx"") { id } - } - }") - .SetVariableValue("if", true) - .Create(); - - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync(request); - - var stream = Assert.IsType(result); + }") + .SetVariableValue("defer", false) + .Create()); - stream.MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } } diff --git a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader.snap b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader.snap index 73c4c36d908..d8924263305 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader.snap @@ -10,6 +10,7 @@ "c": "c" } }, + "Items": null, "Errors": null, "Extensions": { "loads": [ @@ -31,6 +32,7 @@ "Data": { "a": "a" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ @@ -50,6 +52,7 @@ "Data": { "c": "c" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ diff --git a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoaderWithKey.snap b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoaderWithKey.snap index 40b84b70b34..4e51e804f16 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoaderWithKey.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoaderWithKey.snap @@ -7,6 +7,7 @@ "a": "a", "b": "b" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ @@ -27,6 +28,7 @@ "Data": { "a": "a" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ @@ -46,6 +48,7 @@ "Data": { "c": "c" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ diff --git a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader_Resolve_From_DependencyInjection.snap b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader_Resolve_From_DependencyInjection.snap index 40b84b70b34..4e51e804f16 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader_Resolve_From_DependencyInjection.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.ClassDataLoader_Resolve_From_DependencyInjection.snap @@ -7,6 +7,7 @@ "a": "a", "b": "b" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ @@ -27,6 +28,7 @@ "Data": { "a": "a" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ @@ -46,6 +48,7 @@ "Data": { "c": "c" }, + "Items": null, "Errors": null, "Extensions": { "loads": [ diff --git a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.StackedDataLoader.snap b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.StackedDataLoader.snap index 7540b3aaa24..0c7effbf745 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.StackedDataLoader.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/Integration/DataLoader/__snapshots__/DataLoaderTests.StackedDataLoader.snap @@ -7,6 +7,7 @@ "a": "aaabacadaeafagah", "b": "babbbcbdbebfbgbh" }, + "Items": null, "Errors": null, "Extensions": null, "Incremental": null, @@ -20,6 +21,7 @@ "Data": { "a": "aaabacadaeafagah" }, + "Items": null, "Errors": null, "Extensions": null, "Incremental": null, @@ -33,6 +35,7 @@ "Data": { "c": "cacbcccdcecfcgch" }, + "Items": null, "Errors": null, "Extensions": null, "Incremental": null, diff --git a/src/HotChocolate/Core/test/Execution.Tests/StreamTests.cs b/src/HotChocolate/Core/test/Execution.Tests/StreamTests.cs index 114edb88df0..24bc78af3b2 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/StreamTests.cs +++ b/src/HotChocolate/Core/test/Execution.Tests/StreamTests.cs @@ -1,362 +1,162 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; using System.Threading.Tasks; -using GreenDonut; -using HotChocolate.StarWars; -using HotChocolate.Tests; -using HotChocolate.Types; -using Microsoft.Extensions.DependencyInjection; -using Snapshooter.Xunit; -using Xunit; +using CookieCrumble; namespace HotChocolate.Execution; public class StreamTests { + /// + /// This test shows how IAsyncEnumerable is translated to SDL + /// [Fact] - public async Task Stream_Nodes() + public async Task Schema() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ - hero(episode: NEW_HOPE) { - id - ... @defer(label: ""friends"") { - friends { - nodes @stream(initialCount: 1) { - id - name - } - } - } - } - }"); - - IResponseStream stream = Assert.IsType(result); - - var results = new StringBuilder(); - - await foreach (var payload in stream.ReadResultsAsync()) - { - results.AppendLine(payload.ToJson()); - results.AppendLine(); - } - - results.ToString().MatchSnapshot(); + var executor = await DeferAndStreamTestSchema.CreateAsync(); + executor.Schema.MatchSnapshot(); } [Fact] - public async Task Do_Not_Stream_Nodes() + public async Task Stream() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - QueryRequestBuilder.New() - .SetQuery( - @"query($stream: Boolean) { - hero(episode: NEW_HOPE) { - id - ... @defer(label: ""friends"") { - friends { - nodes @stream(initialCount: 1, if: $stream) { - id - name - } - } - } - } - }") - .SetVariableValue("stream", false) - .Create()); - - IResponseStream stream = Assert.IsType(result); - - var results = new StringBuilder(); - - await foreach (var payload in stream.ReadResultsAsync()) - { - results.AppendLine(payload.ToJson()); - results.AppendLine(); - } - - results.ToString().MatchSnapshot(); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer { + wait(m: 300) + } + persons @stream { + id + } + }"); + + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task Stream_Nested_Nodes() + public async Task Stream_Nested_Defer() { - var result = - await new ServiceCollection() - .AddStarWarsRepositories() - .AddGraphQL() - .AddStarWarsTypes() - .ExecuteRequestAsync( - @"{ - hero(episode: NEW_HOPE) { - id - ... @defer(label: ""friends"") { - friends { - nodes @stream(initialCount: 1) { - id - name - friends { - nodes @stream(initialCount: 1) { - id - name - } - } - } - } - } - } - }"); - - IResponseStream stream = Assert.IsType(result); - - var temp = new List(); - var results = new StringBuilder(); - - await foreach (var payload in stream.ReadResultsAsync()) - { - temp.Add(payload); - } - - foreach (var payload in temp.OrderBy(t => t.Path?.ToString() ?? string.Empty)) - { - results.AppendLine(payload.ToJson()); - results.AppendLine(); - } - - results.ToString().MatchSnapshot(); - } - - [Fact] - public async Task Stream_With_AsyncEnumerable_Schema() - { - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .BuildSchemaAsync() - .MatchSnapshotAsync(); - } - - [Fact] - public async Task List_With_AsyncEnumerable() - { - var result = - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .ExecuteRequestAsync( - @"{ - persons { + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer { + wait(m: 800) + } + personNodes(first: 1) { + nodes @stream { + ... @defer { name } - }"); + } + } + }"); - await Assert.IsType(result).MatchSnapshotAsync(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task List_With_AsyncEnumerable_Wrapped_Into_An_Object() + public async Task Stream_InitialCount_Set_To_1() { - var result = - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .ExecuteRequestAsync( - @"{ - persons2 { - name - } - }"); - - await Assert.IsType(result).MatchSnapshotAsync(); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer { + wait(m: 300) + } + persons @stream(initialCount: 1) { + id + } + }"); + + Assert.IsType(result).MatchSnapshot(); } + [Fact] - public async Task Stream_With_AsyncEnumerable() + public async Task Stream_Label_Set_To_abc() { - var result = - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .ExecuteRequestAsync( - @"{ - persons @stream(initialCount: 0) { - name - } - }"); - - IResponseStream stream = Assert.IsType(result); - - var results = new StringBuilder(); - - await foreach (var payload in stream.ReadResultsAsync()) - { - results.AppendLine(payload.ToJson()); - results.AppendLine(); - } - - results.ToString().MatchSnapshot(); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + ... @defer { + wait(m: 300) + } + persons @stream(label: ""abc"") { + id + } + }"); + + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task Stream_With_AsyncEnumerable_InitialCount_1() + public async Task Stream_If_Set_To_false() { - var result = - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .ExecuteRequestAsync( - @"{ - persons @stream(initialCount: 1) { - name - } - }"); - - IResponseStream stream = Assert.IsType(result); - - var results = new StringBuilder(); - - await foreach (var payload in stream.ReadResultsAsync()) - { - results.AppendLine(payload.ToJson()); - results.AppendLine(); - } - - results.ToString().MatchSnapshot(); + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + @"{ + persons @stream(if: false) { + id + } + }"); + + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task Stream_With_DataLoader() + public async Task Stream_If_Variable_Set_To_false() { - var result = - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .AddDataLoader() - .ExecuteRequestAsync( - @"{ - persons @stream(initialCount: 0) { - name - } - }"); - - IResponseStream stream = Assert.IsType(result); - - var results = new StringBuilder(); - - await foreach (var payload in stream.ReadResultsAsync()) - { - results.AppendLine(payload.ToJson()); - results.AppendLine(); - } + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + QueryRequestBuilder + .New() + .SetQuery( + @"query ($stream: Boolean!) { + persons @stream(if: $stream) { + id + } + }") + .SetVariableValue("stream", false) + .Create()); - results.ToString().MatchSnapshot(); + Assert.IsType(result).MatchSnapshot(); } [Fact] - public async Task Stream_With_DataLoader_InitialCount_1() + public async Task AsyncEnumerable_Result() { - var result = - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .AddDataLoader() - .ExecuteRequestAsync( + // arrange + var executor = await DeferAndStreamTestSchema.CreateAsync(); + + // act + var result = await executor.ExecuteAsync( + QueryRequestBuilder + .New() + .SetQuery( @"{ - persons @stream(initialCount: 1) { - name - } - }"); - - IResponseStream stream = Assert.IsType(result); - - var results = new StringBuilder(); - - await foreach (var payload in stream.ReadResultsAsync()) - { - results.AppendLine(payload.ToJson()); - results.AppendLine(); - } - - results.ToString().MatchSnapshot(); - } - - public class Query - { - public async IAsyncEnumerable GetPersonsAsync() - { - await Task.Delay(1); - yield return new Person { Name = "Foo" }; - await Task.Delay(1); - yield return new Person { Name = "Bar" }; - } - - [StreamResult] - public PersonStream GetPersons2() => new(); - } - - public class PersonStream : IAsyncEnumerable - { - public async IAsyncEnumerator GetAsyncEnumerator( - CancellationToken cancellationToken = default) - { - await Task.Delay(1); - yield return new Person { Name = "Foo" }; - await Task.Delay(1); - yield return new Person { Name = "Bar" }; - } - } - - public class QueryWithDataLoader - { - public async IAsyncEnumerable GetPersonsAsync(PersonsGroupDataLoader dl) - { - var persons = await dl.LoadAsync("abc"); - - foreach (var person in persons) - { - yield return person; - } - } - } - - public class PersonsGroupDataLoader : GroupedDataLoader - { - public PersonsGroupDataLoader( - IBatchScheduler batchScheduler, - DataLoaderOptions options = null) - : base(batchScheduler, options) - { - } - - protected override Task> LoadGroupedBatchAsync( - IReadOnlyList keys, - CancellationToken cancellationToken) - { - return Task.FromResult(new List - { - new() { GroupId = keys[0], Name = "Foo" }, - new() { GroupId = keys[0], Name = "Bar" } - }.ToLookup(t => t.GroupId)); - } - } - - public class Person - { - public string GroupId { get; set; } + persons { + id + } + }") + .Create()); - public string Name { get; set; } + Assert.IsType(result).MatchSnapshot(); } } diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Nested_Defer.snap b/src/HotChocolate/Core/test/Execution.Tests/__resources__/DeferTests.NoOptimization_Nested_Defer.snap similarity index 100% rename from src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Nested_Defer.snap rename to src/HotChocolate/Core/test/Execution.Tests/__resources__/DeferTests.NoOptimization_Nested_Defer.snap index 0d9a6095b3f..dfb523867c0 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Nested_Defer.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__resources__/DeferTests.NoOptimization_Nested_Defer.snap @@ -31,35 +31,35 @@ }, { "data": { - "name": "Luke Skywalker" + "name": "Leia Organa" }, "path": [ "hero", "friends", "nodes", - 0 + 2 ] }, { "data": { - "name": "Leia Organa" + "name": "Han Solo" }, "path": [ "hero", "friends", "nodes", - 2 + 1 ] }, { "data": { - "name": "Han Solo" + "name": "Luke Skywalker" }, "path": [ "hero", "friends", "nodes", - 1 + 0 ] } ], diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Defer_If_Variable_Set_To_True.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Defer_If_Variable_Set_To_True.snap deleted file mode 100644 index 1b4dac3fdb0..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Defer_If_Variable_Set_To_True.snap +++ /dev/null @@ -1,34 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001" - } - }, - "hasNext": true -} -{ - "incremental": [ - { - "data": { - "friends": { - "nodes": [ - { - "id": "1000" - }, - { - "id": "1002" - }, - { - "id": "1003" - } - ] - } - }, - "label": "friends", - "path": [ - "hero" - ] - } - ], - "hasNext": false -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Not_Defer.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Not_Defer.snap deleted file mode 100644 index a8a4861f9ec..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Not_Defer.snap +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001", - "friends": { - "nodes": [ - { - "id": "1000" - }, - { - "id": "1002" - }, - { - "id": "1003" - } - ] - } - } - } -} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Not_Defer_If_Variable_Set_To_False.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Not_Defer_If_Variable_Set_To_False.snap deleted file mode 100644 index a8a4861f9ec..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.Do_Not_Defer_If_Variable_Set_To_False.snap +++ /dev/null @@ -1,20 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001", - "friends": { - "nodes": [ - { - "id": "1000" - }, - { - "id": "1002" - }, - { - "id": "1003" - } - ] - } - } - } -} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_Only_Root.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer.snap similarity index 68% rename from src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_Only_Root.snap rename to src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer.snap index 50a4bcf39fb..2899f2044a9 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_Only_Root.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer.snap @@ -6,9 +6,8 @@ "incremental": [ { "data": { - "hero": { - "id": "2001", - "name": "R2-D2" + "person": { + "id": "UGVyc29uCmkx" } }, "path": [] diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_If_Set_To_false.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_If_Set_To_false.snap new file mode 100644 index 00000000000..7d9adb3b1e6 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_If_Set_To_false.snap @@ -0,0 +1,7 @@ +{ + "data": { + "person": { + "id": "UGVyc29uCmkx" + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_If_Variable_Set_To_false.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_If_Variable_Set_To_false.snap new file mode 100644 index 00000000000..7d9adb3b1e6 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_If_Variable_Set_To_false.snap @@ -0,0 +1,7 @@ +{ + "data": { + "person": { + "id": "UGVyc29uCmkx" + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_Label_Set_To_abc.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_Label_Set_To_abc.snap new file mode 100644 index 00000000000..31b60e4ca64 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_Label_Set_To_abc.snap @@ -0,0 +1,18 @@ +{ + "data": {}, + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "person": { + "id": "UGVyc29uCmkx" + } + }, + "label": "abc", + "path": [] + } + ], + "hasNext": false +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_Nested.snap similarity index 52% rename from src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable.snap rename to src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_Nested.snap index 3ad37e3b0ae..ad10b03e02f 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.FragmentSpread_Defer_Nested.snap @@ -1,41 +1,30 @@ -{ - "data": { - "persons": [] - }, +{ + "data": {}, "hasNext": true } - { "incremental": [ { "data": { - "name": "Foo" + "person": { + "id": "UGVyc29uCmkx" + } }, - "path": [ - "persons", - 0 - ] + "path": [] } ], "hasNext": true } - { "incremental": [ { "data": { - "name": "Bar" + "name": "Pascal" }, "path": [ - "persons", - 1 + "person" ] } ], - "hasNext": true -} - -{ "hasNext": false } - diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer.snap new file mode 100644 index 00000000000..2899f2044a9 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer.snap @@ -0,0 +1,17 @@ +{ + "data": {}, + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "person": { + "id": "UGVyc29uCmkx" + } + }, + "path": [] + } + ], + "hasNext": false +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_If_Set_To_false.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_If_Set_To_false.snap new file mode 100644 index 00000000000..7d9adb3b1e6 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_If_Set_To_false.snap @@ -0,0 +1,7 @@ +{ + "data": { + "person": { + "id": "UGVyc29uCmkx" + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_If_Variable_Set_To_false.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_If_Variable_Set_To_false.snap new file mode 100644 index 00000000000..7d9adb3b1e6 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_If_Variable_Set_To_false.snap @@ -0,0 +1,7 @@ +{ + "data": { + "person": { + "id": "UGVyc29uCmkx" + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_Label_Set_To_abc.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_Label_Set_To_abc.snap new file mode 100644 index 00000000000..31b60e4ca64 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_Label_Set_To_abc.snap @@ -0,0 +1,18 @@ +{ + "data": {}, + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "person": { + "id": "UGVyc29uCmkx" + } + }, + "label": "abc", + "path": [] + } + ], + "hasNext": false +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_DataLoader.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_Nested.snap similarity index 50% rename from src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_DataLoader.snap rename to src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_Nested.snap index edccfd00c72..ad10b03e02f 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_DataLoader.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.InlineFragment_Defer_Nested.snap @@ -1,35 +1,30 @@ -{ - "data": { - "persons": [] - }, +{ + "data": {}, "hasNext": true } - { "incremental": [ { "data": { - "name": "Foo" + "person": { + "id": "UGVyc29uCmkx" + } }, - "path": [ - "persons", - 0 - ] - }, + "path": [] + } + ], + "hasNext": true +} +{ + "incremental": [ { "data": { - "name": "Bar" + "name": "Pascal" }, "path": [ - "persons", - 1 + "person" ] } ], - "hasNext": true -} - -{ "hasNext": false } - diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_One_Root.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_One_Root.snap deleted file mode 100644 index ce366a0d9f5..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_One_Root.snap +++ /dev/null @@ -1,23 +0,0 @@ -{ - "data": { - "b": { - "id": "2001", - "name": "R2-D2" - } - }, - "hasNext": true -} -{ - "incremental": [ - { - "data": { - "a": { - "id": "2001", - "name": "R2-D2" - } - }, - "path": [] - } - ], - "hasNext": false -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_Single_Scalar_Field.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_Single_Scalar_Field.snap deleted file mode 100644 index a35f50546f7..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Defer_Single_Scalar_Field.snap +++ /dev/null @@ -1,21 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001" - } - }, - "hasNext": true -} -{ - "incremental": [ - { - "data": { - "name": "R2-D2" - }, - "path": [ - "hero" - ] - } - ], - "hasNext": false -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Spread_Defer.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Spread_Defer.snap deleted file mode 100644 index 1b4dac3fdb0..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/DeferTests.NoOptimization_Spread_Defer.snap +++ /dev/null @@ -1,34 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001" - } - }, - "hasNext": true -} -{ - "incremental": [ - { - "data": { - "friends": { - "nodes": [ - { - "id": "1000" - }, - { - "id": "1002" - }, - { - "id": "1003" - } - ] - } - }, - "label": "friends", - "path": [ - "hero" - ] - } - ], - "hasNext": false -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/ScopedContextDataTests.ScopedContextDataIsPassedAlongCorrectly.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/ScopedContextDataTests.ScopedContextDataIsPassedAlongCorrectly.snap index 060a90d39ca..d02949c28db 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/ScopedContextDataTests.ScopedContextDataIsPassedAlongCorrectly.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/ScopedContextDataTests.ScopedContextDataIsPassedAlongCorrectly.snap @@ -12,6 +12,7 @@ } } }, + "Items": null, "Errors": null, "Extensions": null, "Incremental": null, diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/SourceObjectConversionTests.ConvertSourceObject.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/SourceObjectConversionTests.ConvertSourceObject.snap index 464730e0f41..02435429b80 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/SourceObjectConversionTests.ConvertSourceObject.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/SourceObjectConversionTests.ConvertSourceObject.snap @@ -7,6 +7,7 @@ "qux": "bar" } }, + "Items": null, "Errors": null, "Extensions": null, "Incremental": null, diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.AsyncEnumerable_Result.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.AsyncEnumerable_Result.snap new file mode 100644 index 00000000000..3351c0aad8e --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.AsyncEnumerable_Result.snap @@ -0,0 +1,18 @@ +{ + "data": { + "persons": [ + { + "id": "UGVyc29uCmkx" + }, + { + "id": "UGVyc29uCmky" + }, + { + "id": "UGVyc29uCmkz" + }, + { + "id": "UGVyc29uCmk0" + } + ] + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Do_Not_Stream_Nodes.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Do_Not_Stream_Nodes.snap deleted file mode 100644 index cd05c48dd84..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Do_Not_Stream_Nodes.snap +++ /dev/null @@ -1,39 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001" - } - }, - "hasNext": true -} - -{ - "incremental": [ - { - "data": { - "friends": { - "nodes": [ - { - "id": "1000", - "name": "Luke Skywalker" - }, - { - "id": "1002", - "name": "Han Solo" - }, - { - "id": "1003", - "name": "Leia Organa" - } - ] - } - }, - "label": "friends", - "path": [ - "hero" - ] - } - ], - "hasNext": false -} - diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.List_With_AsyncEnumerable.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.List_With_AsyncEnumerable.snap deleted file mode 100644 index 3e73d11736a..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.List_With_AsyncEnumerable.snap +++ /dev/null @@ -1,12 +0,0 @@ -{ - "data": { - "persons": [ - { - "name": "Foo" - }, - { - "name": "Bar" - } - ] - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.List_With_AsyncEnumerable_Wrapped_Into_An_Object.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.List_With_AsyncEnumerable_Wrapped_Into_An_Object.snap deleted file mode 100644 index 35f325e5720..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.List_With_AsyncEnumerable_Wrapped_Into_An_Object.snap +++ /dev/null @@ -1,12 +0,0 @@ -{ - "data": { - "persons2": [ - { - "name": "Foo" - }, - { - "name": "Bar" - } - ] - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable_Schema.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Schema.graphql similarity index 50% rename from src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable_Schema.snap rename to src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Schema.graphql index 3991b78c516..104b12a506d 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable_Schema.snap +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Schema.graphql @@ -1,19 +1,60 @@ -schema { +schema { query: Query } -type Person { - groupId: String +"The node interface is implemented by entities that have a global unique identifier." +interface Node { + id: ID! +} + +"Information about pagination in a connection." +type PageInfo { + "Indicates whether more edges exist following the set defined by the clients arguments." + hasNextPage: Boolean! + "Indicates whether more edges exist prior the set defined by the clients arguments." + hasPreviousPage: Boolean! + "When paginating backwards, the cursor to continue." + startCursor: String + "When paginating forwards, the cursor to continue." + endCursor: String +} + +type Person implements Node { name: String + id: ID! +} + +"A connection to a list of items." +type PersonNodesConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [PersonNodesEdge!] + "A flattened list of the nodes." + nodes: [Person] +} + +"An edge in a connection." +type PersonNodesEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: Person } type Query { + "Fetches an object given its ID." + node("ID of the object." id: ID!): Node + "Lookup nodes by a list of IDs." + nodes("The list of node IDs." ids: [ID!]!): [Node]! + person(id: ID!): Person persons: [Person] - persons2: [Person] + personNodes("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): PersonNodesConnection + wait(m: Int!): Boolean! } "The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`." directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT "The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`." -directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! = 0 "Streamed when true." if: Boolean) on FIELD +directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! = 0 "Streamed when true." if: Boolean) on FIELD \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream.snap new file mode 100644 index 00000000000..9cfb47e106d --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream.snap @@ -0,0 +1,81 @@ +{ + "data": { + "persons": [] + }, + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmkx" + } + ], + "path": [ + "persons", + 0 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmky" + } + ], + "path": [ + "persons", + 1 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmkz" + } + ], + "path": [ + "persons", + 2 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmk0" + } + ], + "path": [ + "persons", + 3 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "wait": true + }, + "path": [] + } + ], + "hasNext": false +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_If_Set_To_false.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_If_Set_To_false.snap new file mode 100644 index 00000000000..3351c0aad8e --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_If_Set_To_false.snap @@ -0,0 +1,18 @@ +{ + "data": { + "persons": [ + { + "id": "UGVyc29uCmkx" + }, + { + "id": "UGVyc29uCmky" + }, + { + "id": "UGVyc29uCmkz" + }, + { + "id": "UGVyc29uCmk0" + } + ] + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_If_Variable_Set_To_false.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_If_Variable_Set_To_false.snap new file mode 100644 index 00000000000..3351c0aad8e --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_If_Variable_Set_To_false.snap @@ -0,0 +1,18 @@ +{ + "data": { + "persons": [ + { + "id": "UGVyc29uCmkx" + }, + { + "id": "UGVyc29uCmky" + }, + { + "id": "UGVyc29uCmkz" + }, + { + "id": "UGVyc29uCmk0" + } + ] + } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_InitialCount_Set_To_1.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_InitialCount_Set_To_1.snap new file mode 100644 index 00000000000..2634294df64 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_InitialCount_Set_To_1.snap @@ -0,0 +1,69 @@ +{ + "data": { + "persons": [ + { + "id": "UGVyc29uCmkx" + } + ] + }, + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmky" + } + ], + "path": [ + "persons", + 1 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmkz" + } + ], + "path": [ + "persons", + 2 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmk0" + } + ], + "path": [ + "persons", + 3 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "wait": true + }, + "path": [] + } + ], + "hasNext": false +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Label_Set_To_abc.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Label_Set_To_abc.snap new file mode 100644 index 00000000000..9b17d9ad20a --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Label_Set_To_abc.snap @@ -0,0 +1,85 @@ +{ + "data": { + "persons": [] + }, + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmkx" + } + ], + "label": "abc", + "path": [ + "persons", + 0 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmky" + } + ], + "label": "abc", + "path": [ + "persons", + 1 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmkz" + } + ], + "label": "abc", + "path": [ + "persons", + 2 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + { + "id": "UGVyc29uCmk0" + } + ], + "label": "abc", + "path": [ + "persons", + 3 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "wait": true + }, + "path": [] + } + ], + "hasNext": false +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nested_Defer.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nested_Defer.snap new file mode 100644 index 00000000000..5abd676cc28 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nested_Defer.snap @@ -0,0 +1,49 @@ +{ + "data": { + "personNodes": { + "nodes": [] + } + }, + "hasNext": true +} +{ + "incremental": [ + { + "items": [ + {} + ], + "path": [ + "personNodes", + "nodes", + 0 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "name": "Pascal" + }, + "path": [ + "personNodes", + "nodes", + 0 + ] + } + ], + "hasNext": true +} +{ + "incremental": [ + { + "data": { + "wait": true + }, + "path": [] + } + ], + "hasNext": false +} diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nested_Nodes.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nested_Nodes.snap deleted file mode 100644 index e43b5cd7057..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nested_Nodes.snap +++ /dev/null @@ -1,112 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001" - } - }, - "hasNext": true -} - -{ - "incremental": [ - { - "data": { - "friends": { - "nodes": [ - { - "id": "1000", - "name": "Luke Skywalker", - "friends": { - "nodes": [ - { - "id": "1002", - "name": "Han Solo" - } - ] - } - } - ] - } - }, - "label": "friends", - "path": [ - "hero" - ] - }, - { - "data": { - "id": "1003", - "name": "Leia Organa" - }, - "path": [ - "hero", - "friends", - "nodes", - 0, - "friends", - "nodes", - 1 - ] - }, - { - "data": { - "id": "2000", - "name": "C-3PO" - }, - "path": [ - "hero", - "friends", - "nodes", - 0, - "friends", - "nodes", - 2 - ] - }, - { - "data": { - "id": "1002", - "name": "Han Solo" - }, - "path": [ - "hero", - "friends", - "nodes", - 1 - ] - }, - { - "data": { - "id": "2001", - "name": "R2-D2" - }, - "path": [ - "hero", - "friends", - "nodes", - 0, - "friends", - "nodes", - 3 - ] - }, - { - "data": { - "id": "1003", - "name": "Leia Organa" - }, - "path": [ - "hero", - "friends", - "nodes", - 2 - ] - } - ], - "hasNext": true -} - -{ - "hasNext": false -} - diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nodes.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nodes.snap deleted file mode 100644 index e9e0ed3dc3f..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_Nodes.snap +++ /dev/null @@ -1,65 +0,0 @@ -{ - "data": { - "hero": { - "id": "2001" - } - }, - "hasNext": true -} - -{ - "incremental": [ - { - "data": { - "friends": { - "nodes": [ - { - "id": "1000", - "name": "Luke Skywalker" - } - ] - } - }, - "label": "friends", - "path": [ - "hero" - ] - } - ], - "hasNext": true -} - -{ - "incremental": [ - { - "data": { - "id": "1002", - "name": "Han Solo" - }, - "path": [ - "hero", - "friends", - "nodes", - 1 - ] - }, - { - "data": { - "id": "1003", - "name": "Leia Organa" - }, - "path": [ - "hero", - "friends", - "nodes", - 2 - ] - } - ], - "hasNext": true -} - -{ - "hasNext": false -} - diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable_InitialCount_1.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable_InitialCount_1.snap deleted file mode 100644 index 159a4e2cddc..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_AsyncEnumerable_InitialCount_1.snap +++ /dev/null @@ -1,30 +0,0 @@ -{ - "data": { - "persons": [ - { - "name": "Foo" - } - ] - }, - "hasNext": true -} - -{ - "incremental": [ - { - "data": { - "name": "Bar" - }, - "path": [ - "persons", - 1 - ] - } - ], - "hasNext": true -} - -{ - "hasNext": false -} - diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_DataLoader_InitialCount_1.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_DataLoader_InitialCount_1.snap deleted file mode 100644 index 159a4e2cddc..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/StreamTests.Stream_With_DataLoader_InitialCount_1.snap +++ /dev/null @@ -1,30 +0,0 @@ -{ - "data": { - "persons": [ - { - "name": "Foo" - } - ] - }, - "hasNext": true -} - -{ - "incremental": [ - { - "data": { - "name": "Bar" - }, - "path": [ - "persons", - 1 - ] - } - ], - "hasNext": true -} - -{ - "hasNext": false -} - diff --git a/src/HotChocolate/Core/test/Validation.Tests/AllVariableUsagesAreAllowedRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/AllVariableUsagesAreAllowedRuleTests.cs index 7f4c8a15d4c..29e05162a51 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/AllVariableUsagesAreAllowedRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/AllVariableUsagesAreAllowedRuleTests.cs @@ -1,21 +1,21 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class AllVariableUsagesAreAllowedRuleTests + : DocumentValidatorVisitorTestBase { - public class AllVariableUsagesAreAllowedRuleTests - : DocumentValidatorVisitorTestBase - { - public AllVariableUsagesAreAllowedRuleTests() - : base(builder => builder.AddVariableRules()) - { - } - - [Fact] - public void IntCannotGoIntoBoolean() - { - // arrange - ExpectErrors(@" + public AllVariableUsagesAreAllowedRuleTests() + : base(builder => builder.AddVariableRules()) + { + } + + [Fact] + public void IntCannotGoIntoBoolean() + { + // arrange + ExpectErrors(@" query intCannotGoIntoBoolean($intArg: Int) { arguments { booleanArgField(booleanArg: $intArg) @@ -26,13 +26,13 @@ public void IntCannotGoIntoBoolean() "The variable `intArg` is not compatible with the " + "type of the current location.", t.Message)); - } + } - [Fact] - public void BooleanListCannotGoIntoBoolean() - { - // arrange - ExpectErrors(@" + [Fact] + public void BooleanListCannotGoIntoBoolean() + { + // arrange + ExpectErrors(@" query booleanListCannotGoIntoBoolean($booleanListArg: [Boolean]) { arguments { booleanArgField(booleanArg: $booleanListArg) @@ -43,13 +43,13 @@ public void BooleanListCannotGoIntoBoolean() "The variable `booleanListArg` is not compatible with the " + "type of the current location.", t.Message)); - } + } - [Fact] - public void BooleanArgQuery() - { - // arrange - ExpectErrors(@" + [Fact] + public void BooleanArgQuery() + { + // arrange + ExpectErrors(@" query booleanArgQuery($booleanArg: Boolean) { arguments { nonNullBooleanArgField(nonNullBooleanArg: $booleanArg) @@ -60,39 +60,39 @@ public void BooleanArgQuery() "The variable `booleanArg` is not compatible with the " + "type of the current location.", t.Message)); - } + } - [Fact] - public void NonNullListToList() - { - // arrange - ExpectValid(@" + [Fact] + public void NonNullListToList() + { + // arrange + ExpectValid(@" query nonNullListToList($nonNullBooleanList: [Boolean]!) { arguments { booleanListArgField(booleanListArg: $nonNullBooleanList) } } "); - } + } - [Fact] - public void BooleanVariableAsListElement() - { - // arrange - ExpectValid(@" + [Fact] + public void BooleanVariableAsListElement() + { + // arrange + ExpectValid(@" query nonNullListToList($b: Boolean) { arguments { booleanListArgField(booleanListArg: [$b]) } } "); - } + } - [Fact] - public void NullableBooleanVariableAsListElement() - { - // arrange - ExpectErrors(@" + [Fact] + public void NullableBooleanVariableAsListElement() + { + // arrange + ExpectErrors(@" query nonNullBooleanListArgField($nullableBoolean: Boolean) { arguments { nonNullBooleanListArgField(booleanListArg: [$nullableBoolean]) @@ -103,13 +103,13 @@ public void NullableBooleanVariableAsListElement() "The variable `nullableBoolean` is not compatible with the " + "type of the current location.", t.Message)); - } + } - [Fact] - public void ListToNonNullList() - { - // arrange - ExpectErrors(@" + [Fact] + public void ListToNonNullList() + { + // arrange + ExpectErrors(@" query listToNonNullList($booleanList: [Boolean]) { arguments { nonNullBooleanListField(nonNullBooleanListArg: $booleanList) @@ -120,36 +120,36 @@ public void ListToNonNullList() "The variable `booleanList` is not compatible with the " + "type of the current location.", t.Message)); - } + } - [Fact] - public void BooleanArgQueryWithDefault1() - { - ExpectValid(@" + [Fact] + public void BooleanArgQueryWithDefault1() + { + ExpectValid(@" query booleanArgQueryWithDefault($booleanArg: Boolean) { arguments { optionalNonNullBooleanArgField(optionalBooleanArg: $booleanArg) } } "); - } + } - [Fact] - public void BooleanArgQueryWithDefault2() - { - ExpectValid(@" + [Fact] + public void BooleanArgQueryWithDefault2() + { + ExpectValid(@" query booleanArgQueryWithDefault($booleanArg: Boolean = true) { arguments { nonNullBooleanArgField(nonNullBooleanArg: $booleanArg) } } "); - } + } - [Fact] - public void BooleanToBoolean() - { - ExpectValid(@" + [Fact] + public void BooleanToBoolean() + { + ExpectValid(@" query Query($booleanArg: Boolean) { arguments { @@ -157,12 +157,12 @@ query Query($booleanArg: Boolean) } } "); - } + } - [Fact] - public void BooleanToBooleanWithinFragment() - { - ExpectValid(@" + [Fact] + public void BooleanToBooleanWithinFragment() + { + ExpectValid(@" fragment booleanArgFrag on Arguments { booleanArgField(booleanArg: $booleanArg) } @@ -174,12 +174,12 @@ query Query($booleanArg: Boolean) } } "); - } + } - [Fact] - public void NonNullableBooleanToBoolean() - { - ExpectValid(@" + [Fact] + public void NonNullableBooleanToBoolean() + { + ExpectValid(@" query Query($nonNullBooleanArg: Boolean!) { arguments { @@ -187,12 +187,12 @@ query Query($nonNullBooleanArg: Boolean!) } } "); - } + } - [Fact] - public void NonNullableBooleanToBooleanWithinFragment() - { - ExpectValid(@" + [Fact] + public void NonNullableBooleanToBooleanWithinFragment() + { + ExpectValid(@" fragment booleanArgFrag on Arguments { booleanArgField(booleanArg: $nonNullBooleanArg) } @@ -204,12 +204,12 @@ query Query($nonNullBooleanArg: Boolean!) } } "); - } + } - [Fact] - public void StringArrayToStringArray() - { - ExpectValid(@" + [Fact] + public void StringArrayToStringArray() + { + ExpectValid(@" query Query($stringListVar: [String]) { arguments { @@ -217,12 +217,12 @@ query Query($stringListVar: [String]) } } "); - } + } - [Fact] - public void ElemenIsNonNullableStringArrayToStringArray() - { - ExpectValid(@" + [Fact] + public void ElemenIsNonNullableStringArrayToStringArray() + { + ExpectValid(@" query Query($stringListVar: [String!]) { arguments { @@ -230,12 +230,12 @@ query Query($stringListVar: [String!]) } } "); - } + } - [Fact] - public void StringToStringInItemPosition() - { - ExpectValid(@" + [Fact] + public void StringToStringInItemPosition() + { + ExpectValid(@" query Query($stringVar: String) { arguments { @@ -243,12 +243,12 @@ query Query($stringVar: String) } } "); - } + } - [Fact] - public void NonNullableStringToStringInItemPosition() - { - ExpectValid(@" + [Fact] + public void NonNullableStringToStringInItemPosition() + { + ExpectValid(@" query Query($stringVar: String!) { arguments { @@ -256,12 +256,12 @@ query Query($stringVar: String!) } } "); - } + } - [Fact] - public void ComplexInputToComplexInput() - { - ExpectValid(@" + [Fact] + public void ComplexInputToComplexInput() + { + ExpectValid(@" query Query($complexVar: Complex3Input) { arguments { @@ -269,12 +269,12 @@ query Query($complexVar: Complex3Input) } } "); - } + } - [Fact] - public void ComplexInputToComplexInputInFieldPosition() - { - ExpectValid(@" + [Fact] + public void ComplexInputToComplexInputInFieldPosition() + { + ExpectValid(@" query Query($boolVar: Boolean = false) { arguments { @@ -282,35 +282,35 @@ query Query($boolVar: Boolean = false) } } "); - } + } - [Fact] - public void NullableBooleanToBooleanInDirective() - { - ExpectValid(@" + [Fact] + public void NullableBooleanToBooleanInDirective() + { + ExpectValid(@" query Query($boolVar: Boolean!) { dog @include(if: $boolVar) } "); - } + } - [Fact] - public void IntToNullableInt() - { - ExpectErrors(@" + [Fact] + public void IntToNullableInt() + { + ExpectErrors(@" query Query($intArg: Int) { arguments { nonNullIntArgField(intArg: $intArg) } } "); - } + } - [Fact] - public void IntNullableToIntWithinFragment() - { - ExpectErrors(@" + [Fact] + public void IntNullableToIntWithinFragment() + { + ExpectErrors(@" fragment nonNullIntArgFieldFrag on Arguments { nonNullIntArgField(intArg: $intArg) } @@ -321,12 +321,12 @@ public void IntNullableToIntWithinFragment() } } "); - } + } - [Fact] - public void IntNullableToIntWithinNestedFragment() - { - ExpectErrors(@" + [Fact] + public void IntNullableToIntWithinNestedFragment() + { + ExpectErrors(@" fragment outerFrag on Arguments { ...nonNullIntArgFieldFrag } @@ -341,56 +341,56 @@ public void IntNullableToIntWithinNestedFragment() } } "); - } + } - [Fact] - public void StringOverBoolean() - { - ExpectErrors(@" + [Fact] + public void StringOverBoolean() + { + ExpectErrors(@" query Query($stringVar: String) { arguments { booleanArgField(booleanArg: $stringVar) } } "); - } + } - [Fact] - public void StringToStringArray() - { - ExpectErrors(@" + [Fact] + public void StringToStringArray() + { + ExpectErrors(@" query Query($stringVar: String) { arguments { stringListArgField(stringListArg: $stringVar) } } "); - } + } - [Fact] - public void BooleanToBooleanInDirective() - { - ExpectErrors(@" + [Fact] + public void BooleanToBooleanInDirective() + { + ExpectErrors(@" query Query($boolVar: Boolean) { dog @include(if: $boolVar) } "); - } + } - [Fact] - public void StringToNullableBooleanInDirective() - { - ExpectErrors(@" + [Fact] + public void StringToNullableBooleanInDirective() + { + ExpectErrors(@" query Query($stringVar: String) { dog @include(if: $stringVar) } "); - } + } - [Fact] - public void StringToElementIsNullableString() - { - ExpectErrors(@" + [Fact] + public void StringToElementIsNullableString() + { + ExpectErrors(@" query Query($stringListVar: [String]) { arguments { @@ -398,52 +398,51 @@ query Query($stringListVar: [String]) } } "); - } + } - [Fact] - public void IntToNullableIntFailsWhenVariableProvidesNullDefaultValue() - { - ExpectErrors(@" + [Fact] + public void IntToNullableIntFailsWhenVariableProvidesNullDefaultValue() + { + ExpectErrors(@" query Query($intVar: Int = null) { arguments { nonNullIntArgField(intArg: $intVar) } } "); - } + } - [Fact] - public void IntToNullableIntWhenVariableProvidesNonNullDefaultValue() - { - ExpectValid(@" + [Fact] + public void IntToNullableIntWhenVariableProvidesNonNullDefaultValue() + { + ExpectValid(@" query Query($intVar: Int = 1) { arguments { nonNullIntArgField(intArg: $intVar) } } "); - } + } - [Fact] - public void IntToNullableIntWhenOptionalArgumentProvidesDefaultValue() - { - ExpectValid(@" + [Fact] + public void IntToNullableIntWhenOptionalArgumentProvidesDefaultValue() + { + ExpectValid(@" query Query($intVar: Int) { arguments { nonNullFieldWithDefault(nonNullIntArg: $intVar) } } "); - } + } - [Fact] - public void BooleanToNullableBooleanInDirectiveWithDefaultValueWithOption() - { - ExpectValid(@" + [Fact] + public void BooleanToNullableBooleanInDirectiveWithDefaultValueWithOption() + { + ExpectValid(@" query Query($boolVar: Boolean = false) { dog @include(if: $boolVar) } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/AllVariablesUsedRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/AllVariablesUsedRuleTests.cs index c34183d13ab..a557d5ea253 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/AllVariablesUsedRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/AllVariablesUsedRuleTests.cs @@ -1,21 +1,21 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class AllVariablesUsedRuleTests + : DocumentValidatorVisitorTestBase { - public class AllVariablesUsedRuleTests - : DocumentValidatorVisitorTestBase + public AllVariablesUsedRuleTests() + : base(builder => builder.AddVariableRules()) { - public AllVariablesUsedRuleTests() - : base(builder => builder.AddVariableRules()) - { - } + } - [Fact] - public void VariableUnused() - { - // arrange - ExpectErrors(@" + [Fact] + public void VariableUnused() + { + // arrange + ExpectErrors(@" query variableUnused($atOtherHomes: Boolean) { dog { isHouseTrained @@ -25,12 +25,12 @@ public void VariableUnused() t => Assert.Equal( "The following variables were not used: " + "atOtherHomes.", t.Message)); - } + } - [Fact] - public void VariableUsedInFragment() - { - ExpectValid(@" + [Fact] + public void VariableUsedInFragment() + { + ExpectValid(@" query variableUsedInFragment($atOtherHomes: Boolean) { dog { ...isHousetrainedFragment @@ -41,12 +41,12 @@ public void VariableUsedInFragment() isHouseTrained(atOtherHomes: $atOtherHomes) } "); - } + } - [Fact] - public void VariableUsedInSecondLevelFragment() - { - ExpectValid(@" + [Fact] + public void VariableUsedInSecondLevelFragment() + { + ExpectValid(@" query variableUsedInFragment($atOtherHomes: Boolean) { dog { ...isHousetrainedFragment @@ -61,12 +61,12 @@ public void VariableUsedInSecondLevelFragment() isHouseTrained(atOtherHomes: $atOtherHomes) } "); - } + } - [Fact] - public void VariableUsedInDirective() - { - ExpectValid(@" + [Fact] + public void VariableUsedInDirective() + { + ExpectValid(@" query variableUsedInFragment($atOtherHomes: Boolean!) { dog { ...isHousetrainedFragment @@ -78,7 +78,7 @@ isHouseTrained @skip(if: $atOtherHomes) } "); - ExpectValid(@" + ExpectValid(@" query variableUsedInFragment($atOtherHomes: Boolean!) { dog { ...isHousetrainedFragment @skip(if: $atOtherHomes) @@ -89,13 +89,13 @@ ...isHousetrainedFragment @skip(if: $atOtherHomes) isHouseTrained } "); - } + } - [Fact] - public void VariableNotUsedWithinFragment() - { - // arrange - ExpectErrors(@" + [Fact] + public void VariableNotUsedWithinFragment() + { + // arrange + ExpectErrors(@" query variableNotUsedWithinFragment($atOtherHomes: Boolean) { dog { ...isHousetrainedWithoutVariableFragment @@ -109,12 +109,12 @@ public void VariableNotUsedWithinFragment() t => Assert.Equal( "The following variables were not used: " + "atOtherHomes.", t.Message)); - } + } - [Fact] - public void QueryWithExtraVar() - { - ExpectErrors(@" + [Fact] + public void QueryWithExtraVar() + { + ExpectErrors(@" query queryWithUsedVar($atOtherHomes: Boolean) { dog { ...isHousetrainedFragment @@ -134,62 +134,62 @@ public void QueryWithExtraVar() t => Assert.Equal( "The following variables were not used: " + "extra.", t.Message)); - } + } - [Fact] - public void VariableUsedAndDeclared() - { - ExpectValid(@" + [Fact] + public void VariableUsedAndDeclared() + { + ExpectValid(@" query variableIsDefined($atOtherHomes: Boolean) { dog { isHouseTrained(atOtherHomes: $atOtherHomes) } }"); - } + } - [Fact] - public void VariableUsedInComplexInput() - { - ExpectValid(@" + [Fact] + public void VariableUsedInComplexInput() + { + ExpectValid(@" query queryWithComplexInput($name: String) { findDog(complex: { name: $name }) { name } }"); - } + } - [Fact] - public void VariableUsedInListInput() - { - ExpectValid(@" + [Fact] + public void VariableUsedInListInput() + { + ExpectValid(@" query queryWithListInput($value: Boolean!) { booleanList(booleanListArg: [ $value ]) }"); - } + } - [Fact] - public void VariableUsedAndNotDeclared() - { - // arrange - ExpectErrors(@" + [Fact] + public void VariableUsedAndNotDeclared() + { + // arrange + ExpectErrors(@" query variableIsDefined { dog { isHouseTrained(atOtherHomes: $atOtherHomes) } }", - t => Assert.Equal( - "The following variables were not declared: " + - "atOtherHomes.", t.Message)); - } + t => Assert.Equal( + "The following variables were not declared: " + + "atOtherHomes.", t.Message)); + } - [Fact] - public void VariableUsedAndNotDeclared2() - { - ExpectErrors(@" + [Fact] + public void VariableUsedAndNotDeclared2() + { + ExpectErrors(@" query variableIsNotDefinedUsedInNestedFragment { dog { ...outerHousetrainedFragment @@ -203,15 +203,15 @@ public void VariableUsedAndNotDeclared2() fragment isHousetrainedFragment on Dog { isHouseTrained(atOtherHomes: $atOtherHomes) }", - t => Assert.Equal( - "The following variables were not declared: " + - "atOtherHomes.", t.Message)); - } + t => Assert.Equal( + "The following variables were not declared: " + + "atOtherHomes.", t.Message)); + } - [Fact] - public void VarsMustBeDefinedInAllOperationsInWhichAFragmentIsUsed() - { - ExpectValid(@" + [Fact] + public void VarsMustBeDefinedInAllOperationsInWhichAFragmentIsUsed() + { + ExpectValid(@" query housetrainedQueryOne($atOtherHomes: Boolean) { dog { ...isHousetrainedFragment @@ -233,12 +233,12 @@ public void VarsMustBeDefinedInAllOperationsInWhichAFragmentIsUsed() fragment isHousetrainedFragment on Dog { isHouseTrained(atOtherHomes: $atOtherHomes) }"); - } + } - [Fact] - public void VarsMustBeDefinedInAllOperationsInWhichAFragmentIsUsedErr() - { - ExpectErrors(@" + [Fact] + public void VarsMustBeDefinedInAllOperationsInWhichAFragmentIsUsedErr() + { + ExpectErrors(@" query variableIsNotDefinedUsedInNestedFragment { dog { ...outerHousetrainedFragment @@ -252,9 +252,8 @@ public void VarsMustBeDefinedInAllOperationsInWhichAFragmentIsUsedErr() fragment isHousetrainedFragment on Dog { isHouseTrained(atOtherHomes: $atOtherHomes) }", - t => Assert.Equal( - "The following variables were not declared: " + - "atOtherHomes.", t.Message)); - } + t => Assert.Equal( + "The following variables were not declared: " + + "atOtherHomes.", t.Message)); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/ArgumentNamesRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/ArgumentNamesRuleTests.cs index 0ed1591348e..7e7c9d623f3 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/ArgumentNamesRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/ArgumentNamesRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class ArgumentNamesRuleTests + : DocumentValidatorVisitorTestBase { - public class ArgumentNamesRuleTests - : DocumentValidatorVisitorTestBase + public ArgumentNamesRuleTests() + : base(builder => builder.AddArgumentRules()) + { + } + + [Fact] + public void ArgOnRequiredArg() { - public ArgumentNamesRuleTests() - : base(builder => builder.AddArgumentRules()) - { - } - - [Fact] - public void ArgOnRequiredArg() - { - ExpectValid(@" + ExpectValid(@" query { dog { ... argOnRequiredArg @@ -25,12 +25,12 @@ ... argOnRequiredArg doesKnowCommand(dogCommand: SIT) } "); - } + } - [Fact] - public void ArgOnOptional() - { - ExpectValid(@" + [Fact] + public void ArgOnOptional() + { + ExpectValid(@" query { dog { ... argOnOptional @@ -41,12 +41,12 @@ ... argOnOptional isHouseTrained(atOtherHomes: true) @include(if: true) } "); - } + } - [Fact] - public void InvalidFieldArgName() - { - ExpectErrors(@" + [Fact] + public void InvalidFieldArgName() + { + ExpectErrors(@" query { dog { ... invalidArgName @@ -61,12 +61,12 @@ ... invalidArgName $"The argument `command` does not exist.", t.Message), t => Assert.Equal( $"The argument `dogCommand` is required.", t.Message)); - } + } - [Fact] - public void InvalidDirectiveArgName() - { - ExpectErrors(@" + [Fact] + public void InvalidDirectiveArgName() + { + ExpectErrors(@" query { dog { ... invalidArgName @@ -81,12 +81,12 @@ ... invalidArgName $"The argument `unless` does not exist.", t.Message), t => Assert.Equal( $"The argument `if` is required.", t.Message)); - } + } - [Fact] - public void ArgumentOrderDoesNotMatter() - { - ExpectValid(@" + [Fact] + public void ArgumentOrderDoesNotMatter() + { + ExpectValid(@" query { arguments { ... multipleArgs @@ -102,12 +102,12 @@ ... multipleArgsReverseOrder multipleReqs(y: 1, x: 2) } "); - } + } - [Fact] - public void ArgsAreKnowDeeply() - { - ExpectValid(@" + [Fact] + public void ArgsAreKnowDeeply() + { + ExpectValid(@" { dog { doesKnowCommand(dogCommand: SIT) @@ -121,52 +121,52 @@ public void ArgsAreKnowDeeply() } } "); - } + } - [Fact] - public void DirectiveArgsAreKnown() - { - ExpectValid(@" + [Fact] + public void DirectiveArgsAreKnown() + { + ExpectValid(@" { dog @skip(if: true) } "); - } + } - [Fact] - public void DirectiveWithoutArgsIsValid() - { - ExpectValid(@" + [Fact] + public void DirectiveWithoutArgsIsValid() + { + ExpectValid(@" { dog @complex } "); - } + } - [Fact] - public void DirectiveWithWrongArgsIsInvalid() - { - ExpectErrors(@" + [Fact] + public void DirectiveWithWrongArgsIsInvalid() + { + ExpectErrors(@" { dog @complex(if:false) } "); - } + } - [Fact] - public void MisspelledDirectiveArgsAreReported() - { - ExpectErrors(@" + [Fact] + public void MisspelledDirectiveArgsAreReported() + { + ExpectErrors(@" { dog @skip(iff: true) } "); - } + } - [Fact] - public void MisspelledFieldArgsAreReported() - { - ExpectErrors(@" + [Fact] + public void MisspelledFieldArgsAreReported() + { + ExpectErrors(@" query { dog { ... invalidArgName @@ -176,12 +176,12 @@ ... invalidArgName doesKnowCommand(DogCommand: true) } "); - } + } - [Fact] - public void UnknownArgsAmongstKnowArgs() - { - ExpectErrors(@" + [Fact] + public void UnknownArgsAmongstKnowArgs() + { + ExpectErrors(@" query { dog { ... oneGoodArgOneInvalidArg @@ -191,12 +191,12 @@ ... oneGoodArgOneInvalidArg doesKnowCommand(whoKnows: 1, dogCommand: SIT, unknown: true) } "); - } + } - [Fact] - public void UnknownArgsDeeply() - { - ExpectErrors(@" + [Fact] + public void UnknownArgsDeeply() + { + ExpectErrors(@" { dog { doesKnowCommand(unknown: true) @@ -210,150 +210,149 @@ public void UnknownArgsDeeply() } } "); - } + } - [Fact] - public void NoArgumentsOnField() - { - // arrange - ExpectValid(@" + [Fact] + public void NoArgumentsOnField() + { + // arrange + ExpectValid(@" { fieldWithArg } "); - } + } - [Fact] - public void NoArgumentsOnDirective() - { - // arrange - ExpectValid(@" + [Fact] + public void NoArgumentsOnDirective() + { + // arrange + ExpectValid(@" { fieldWithArg @directive } "); - } + } - [Fact] - public void ArgumentOnField() - { - // arrange - ExpectValid(@" + [Fact] + public void ArgumentOnField() + { + // arrange + ExpectValid(@" { fieldWithArg(arg: ""value"") } "); - } + } - [Fact] - public void ArgumentOnDirective() - { - // arrange - ExpectValid(@" + [Fact] + public void ArgumentOnDirective() + { + // arrange + ExpectValid(@" { fieldWithArg @directive(arg: ""value"") } "); - } + } - [Fact] - public void SameArgumentOnTwoFields() - { - // arrange - ExpectValid(@" + [Fact] + public void SameArgumentOnTwoFields() + { + // arrange + ExpectValid(@" { one: fieldWithArg(arg: ""value"") two: fieldWithArg(arg: ""value"") } "); - } + } - [Fact] - public void SameArgumentOnFieldAndDirective() - { - // arrange - ExpectValid(@" + [Fact] + public void SameArgumentOnFieldAndDirective() + { + // arrange + ExpectValid(@" { fieldWithArg(arg: ""value"") @directive(arg: ""value"") } "); - } + } - [Fact] - public void SameArgumentOnTwoDirectives() - { - // arrange - ExpectValid(@" + [Fact] + public void SameArgumentOnTwoDirectives() + { + // arrange + ExpectValid(@" { fieldWithArg @directive1(arg: ""value"") @directive2(arg: ""value"") } "); - } + } - [Fact] - public void MultipleFieldArguments() - { - // arrange - ExpectValid(@" + [Fact] + public void MultipleFieldArguments() + { + // arrange + ExpectValid(@" { fieldWithArg(arg1: ""value"", arg2: ""value"", arg3: ""value"") } "); - } + } - [Fact] - public void MultipleDirectiveArguments() - { - // arrange - ExpectValid(@" + [Fact] + public void MultipleDirectiveArguments() + { + // arrange + ExpectValid(@" { fieldWithArg @directive(arg1: ""value"", arg2: ""value"", arg3: ""value"") } "); - } + } - [Fact] - public void DuplicateFieldArguments() - { - // arrange - ExpectErrors(@" + [Fact] + public void DuplicateFieldArguments() + { + // arrange + ExpectErrors(@" { fieldWithArg(arg1: ""value"", arg1: ""value"") } "); - } + } - [Fact] - public void ManyDuplicateFieldArguments() - { - // arrange - ExpectErrors(@" + [Fact] + public void ManyDuplicateFieldArguments() + { + // arrange + ExpectErrors(@" { fieldWithArg(arg1: ""value"", arg1: ""value"", arg1: ""value"") } "); - } + } - [Fact] - public void DuplicateDirectiveArguments() - { - // arrange - ExpectErrors(@" + [Fact] + public void DuplicateDirectiveArguments() + { + // arrange + ExpectErrors(@" { fieldWithArg @directive(arg1: ""value"", arg1: ""value"") } "); - } + } - [Fact] - public void ManyDuplicateDirectiveArguments() - { - // arrange - ExpectErrors(@" + [Fact] + public void ManyDuplicateDirectiveArguments() + { + // arrange + ExpectErrors(@" { fieldWithArg @directive(arg1: ""value"", arg1: ""value"", arg1: ""value"") } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/ArgumentUniquenessRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/ArgumentUniquenessRuleTests.cs index b2b80c51b44..33316dc18c4 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/ArgumentUniquenessRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/ArgumentUniquenessRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class ArgumentUniquenessRuleTests + : DocumentValidatorVisitorTestBase { - public class ArgumentUniquenessRuleTests - : DocumentValidatorVisitorTestBase + public ArgumentUniquenessRuleTests() + : base(builder => builder.AddArgumentRules()) { - public ArgumentUniquenessRuleTests() - : base(builder => builder.AddArgumentRules()) - { - } + } - [Fact] - public void NoDuplicateArgument() - { - ExpectValid(@" + [Fact] + public void NoDuplicateArgument() + { + ExpectValid(@" query { arguments { ... goodNonNullArg @@ -25,12 +25,12 @@ ... goodNonNullArg nonNullBooleanArgField(nonNullBooleanArg: true) } "); - } + } - [Fact] - public void DuplicateArgument() - { - ExpectErrors(@" + [Fact] + public void DuplicateArgument() + { + ExpectErrors(@" query { arguments { ... goodNonNullArg @@ -45,6 +45,5 @@ ... goodNonNullArg "More than one argument with the same name in an argument " + "set is ambiguous and invalid.", t.Message)); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/DeferAndStreamDirectiveLabelsAreUniqueTests.cs b/src/HotChocolate/Core/test/Validation.Tests/DeferAndStreamDirectiveLabelsAreUniqueTests.cs new file mode 100644 index 00000000000..0e57f55b865 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/DeferAndStreamDirectiveLabelsAreUniqueTests.cs @@ -0,0 +1,118 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace HotChocolate.Validation; + +public class DeferAndStreamDirectiveLabelsAreUniqueTests + : DocumentValidatorVisitorTestBase +{ + public DeferAndStreamDirectiveLabelsAreUniqueTests() + : base(builder => builder.AddDirectiveRules()) + { + } + + [Fact] + public void Label_Duplicate_On_Defer() + { + ExpectErrors( + @"query { + ... @defer(label: ""a"") { + a: __typename + } + ... @defer(label: ""a"") { + b: __typename + } + }", + t => Assert.Equal( + "If a label is passed, it must be unique within all other @defer " + + "and @stream directives in the document.", + t.Message)); + } + + [Fact] + public void Label_Duplicate_On_Stream() + { + ExpectErrors( + @"query { + a: __schema { + _types @stream(label: ""a"") { + name + } + } + b: __schema { + _types @stream(label: ""a"") { + name + } + } + }", + t => Assert.Equal( + "If a label is passed, it must be unique within all other @defer " + + "and @stream directives in the document.", + t.Message)); + } + + [Fact] + public void Label_Duplicate_On_Either_Stream_Or_Defer() + { + ExpectErrors( + @"query { + ... @defer(label: ""a"") { + a: __typename + } + b: __schema { + _types @stream(label: ""a"") { + name + } + } + }", + t => Assert.Equal( + "If a label is passed, it must be unique within all other @defer " + + "and @stream directives in the document.", + t.Message)); + } + + [Fact] + public void Label_Is_Variable_On_Defer() + { + ExpectErrors( + @"query($a: String) { + ... @defer(label: $a) { + a: __typename + } + }", + t => Assert.Equal( + "If a label for @defer or @stream is passed, it must not be a variable.", + t.Message)); + } + + [Fact] + public void Label_Can_Be_Null_And_Is_Optional_And_Can_Be_A_Unique_Name() + { + ExpectValid( + @"query { + ... @defer(label: null) { + a: __typename + } + ... @defer { + a: __typename + } + ... @defer(label: ""c"") { + c: __typename + } + d: __schema { + _types @stream(label: null) { + name + } + } + e: __schema { + _types @stream { + name + } + } + f: __schema { + _types @stream(label: ""b"") { + name + } + } + }"); + } +} diff --git a/src/HotChocolate/Core/test/Validation.Tests/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.cs b/src/HotChocolate/Core/test/Validation.Tests/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.cs new file mode 100644 index 00000000000..521a5a508e9 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.cs @@ -0,0 +1,76 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace HotChocolate.Validation; + +public class DeferAndStreamDirectivesAreUsedOnValidRootFieldTests + : DocumentValidatorVisitorTestBase +{ + public DeferAndStreamDirectivesAreUsedOnValidRootFieldTests() + : base(builder => builder.AddOperationRules()) + { + } + + [Fact] + public void Defer_On_Subscriptions_Root() + { + ExpectErrors( + @"subscription { + ... @defer { + disallowedSecondRootField + } + }", + t => Assert.Equal( + "The defer and stream directives are not allowed to " + + "be used on root fields of the mutation or subscription type.", + t.Message)); + } + + [Fact] + public void Defer_On_Subscriptions_Root_In_Nested_Fragment() + { + ExpectErrors( + @"subscription { + ... a + } + + fragment a on Subscription { + ... b + } + + fragment b on Subscription { + ... @defer { + disallowedSecondRootField + } + }", + t => Assert.Equal( + "The defer and stream directives are not allowed to " + + "be used on root fields of the mutation or subscription type.", + t.Message)); + } + + [Fact] + public void Stream_On_Subscriptions_Root() + { + ExpectErrors( + @"subscription { + listEvent @stream + }", + t => Assert.Equal( + "The defer and stream directives are not allowed to " + + "be used on root fields of the mutation or subscription type.", + t.Message)); + } + + [Fact] + public void Defer_On_Subscriptions_Sub_Selection() + { + ExpectValid( + @"subscription { + newMessage { + ... @defer { + body + } + } + }"); + } +} diff --git a/src/HotChocolate/Core/test/Validation.Tests/DirectivesAreDefinedRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/DirectivesAreDefinedRuleTests.cs index 070492c3052..bcb9028abae 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/DirectivesAreDefinedRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/DirectivesAreDefinedRuleTests.cs @@ -1,32 +1,32 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class DirectivesAreDefinedRuleTests + : DocumentValidatorVisitorTestBase { - public class DirectivesAreDefinedRuleTests - : DocumentValidatorVisitorTestBase + public DirectivesAreDefinedRuleTests() + : base(builder => builder.AddDirectiveRules()) { - public DirectivesAreDefinedRuleTests() - : base(builder => builder.AddDirectiveRules()) - { - } + } - [Fact] - public void SupportedDirective() - { - ExpectValid(@" + [Fact] + public void SupportedDirective() + { + ExpectValid(@" { dog { name @skip(if: true) } } "); - } + } - [Fact] - public void UnsupportedDirective() - { - ExpectErrors(@" + [Fact] + public void UnsupportedDirective() + { + ExpectErrors(@" { dog { name @foo(bar: true) @@ -37,12 +37,12 @@ name @foo(bar: true) "The specified directive `foo` " + "is not supported by the current schema.", t.Message)); - } + } - [Fact] - public void SkipDirectiveIsInTheWrongPlace() - { - ExpectErrors(@" + [Fact] + public void SkipDirectiveIsInTheWrongPlace() + { + ExpectErrors(@" query @skip(if: $foo) { field } @@ -50,22 +50,22 @@ public void SkipDirectiveIsInTheWrongPlace() t => Assert.Equal( "The specified directive is not valid the " + "current location.", t.Message)); - } + } - [Fact] - public void SkipDirectiveIsInTheRightPlace() - { - ExpectValid(@" + [Fact] + public void SkipDirectiveIsInTheRightPlace() + { + ExpectValid(@" query a { field @skip(if: $foo) } "); - } + } - [Fact] - public void DuplicateSkipDirectives() - { - ExpectErrors(@" + [Fact] + public void DuplicateSkipDirectives() + { + ExpectErrors(@" query ($foo: Boolean = true, $bar: Boolean = false) { field @skip(if: $foo) @skip(if: $bar) } @@ -73,12 +73,12 @@ field @skip(if: $foo) @skip(if: $bar) t => Assert.Equal( "Only one of each directive is allowed per location.", t.Message)); - } + } - [Fact] - public void SkipOnTwoDifferentFields() - { - ExpectValid(@" + [Fact] + public void SkipOnTwoDifferentFields() + { + ExpectValid(@" query ($foo: Boolean = true, $bar: Boolean = false) { field @skip(if: $foo) { subfieldA @@ -88,12 +88,12 @@ public void SkipOnTwoDifferentFields() } } "); - } + } - [Fact] - public void WithNoDirectives() - { - ExpectValid(@" + [Fact] + public void WithNoDirectives() + { + ExpectValid(@" query Foo { name ...Frag @@ -102,12 +102,12 @@ public void WithNoDirectives() name } "); - } + } - [Fact] - public void WithKnownDirectives() - { - ExpectValid(@" + [Fact] + public void WithKnownDirectives() + { + ExpectValid(@" { dog @include(if: true) { name @@ -117,24 +117,24 @@ public void WithKnownDirectives() } } "); - } + } - [Fact] - public void WithUnknownDirectives() - { - ExpectErrors(@" + [Fact] + public void WithUnknownDirectives() + { + ExpectErrors(@" { dog @unknown(directive: ""value"") { name } } "); - } + } - [Fact] - public void WithManyUnknownDirectives() - { - ExpectErrors(@" + [Fact] + public void WithManyUnknownDirectives() + { + ExpectErrors(@" { dog @unknown(directive: ""value"") { name @@ -147,12 +147,12 @@ public void WithManyUnknownDirectives() } } "); - } + } - [Fact] - public void WithWellPlacedDirectives() - { - ExpectValid(@" + [Fact] + public void WithWellPlacedDirectives() + { + ExpectValid(@" query ($var: Boolean) @onQuery { name @include(if: $var) ...Frag @include(if: true) @@ -175,82 +175,82 @@ ...SkippedFrag @skip(if: true) someField } "); - } + } - [Fact] - public void WithWellPlacedVariableDefinitionDirective() - { - ExpectValid(@" + [Fact] + public void WithWellPlacedVariableDefinitionDirective() + { + ExpectValid(@" query Foo($var: Boolean @onVariableDefinition) { name } "); - } + } - [Fact] - public void WithMisplacedDirectiveOnQuery() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedDirectiveOnQuery() + { + ExpectErrors(@" query Foo($var: Boolean) @include(if: true) { name } "); - } + } - [Fact] - public void WithMisplacedDirectivesOnField() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedDirectivesOnField() + { + ExpectErrors(@" query Foo($var: Boolean) { name @onQuery } "); - } + } - [Fact] - public void WithMisplacedDirectivesOnFieldRepeatedly() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedDirectivesOnFieldRepeatedly() + { + ExpectErrors(@" query Foo($var: Boolean) { name @onQuery @include(if: $var) } "); - } + } - [Fact] - public void WithMisplacedDirectivesOnMutation() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedDirectivesOnMutation() + { + ExpectErrors(@" mutation Bar @onQuery { someField } "); - } + } - [Fact] - public void WithMisplacedDirectivesOnSubscription() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedDirectivesOnSubscription() + { + ExpectErrors(@" subscription Bar @onQuery { someField } "); - } + } - [Fact] - public void WithMisplacedDirectivesOnVariableDefinition() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedDirectivesOnVariableDefinition() + { + ExpectErrors(@" query Foo($var: Boolean @onQuery(if: true)) { name } "); - } + } - [Fact] - public void WithMisplacedDirectivesOnFragemnt() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedDirectivesOnFragemnt() + { + ExpectErrors(@" query Foo($var: Boolean) { ...Frag @onQuery } @@ -258,22 +258,22 @@ ...Frag @onQuery name } "); - } + } - [Fact] - public void WithMisplacedVariableDefinitionDirective() - { - ExpectErrors(@" + [Fact] + public void WithMisplacedVariableDefinitionDirective() + { + ExpectErrors(@" query Foo($var: Boolean @onField) { name } "); - } + } - [Fact] - public void NoDirectives() - { - ExpectValid(@" + [Fact] + public void NoDirectives() + { + ExpectValid(@" { ...Test } @@ -281,12 +281,12 @@ public void NoDirectives() name } "); - } + } - [Fact] - public void UniqueDirectivesInDifferentLocations() - { - ExpectValid(@" + [Fact] + public void UniqueDirectivesInDifferentLocations() + { + ExpectValid(@" { ...Test } @@ -294,12 +294,12 @@ public void UniqueDirectivesInDifferentLocations() field @directiveB } "); - } + } - [Fact] - public void UniqueDirectivesInSameLocations() - { - ExpectValid(@" + [Fact] + public void UniqueDirectivesInSameLocations() + { + ExpectValid(@" { ...Test } @@ -307,12 +307,12 @@ public void UniqueDirectivesInSameLocations() field @directiveA @directiveB } "); - } + } - [Fact] - public void SameDirectivesInDifferentLocations() - { - ExpectValid(@" + [Fact] + public void SameDirectivesInDifferentLocations() + { + ExpectValid(@" { ...Test } @@ -320,12 +320,12 @@ public void SameDirectivesInDifferentLocations() field @directiveA } "); - } + } - [Fact] - public void SameDirectivesInSimilarLocations() - { - ExpectValid(@" + [Fact] + public void SameDirectivesInSimilarLocations() + { + ExpectValid(@" { ...Test } @@ -334,12 +334,12 @@ field @directiveA field @directiveA } "); - } + } - [Fact] - public void RepeatableDirectivesInSameLocation() - { - ExpectValid(@" + [Fact] + public void RepeatableDirectivesInSameLocation() + { + ExpectValid(@" { ...Test } @@ -347,12 +347,12 @@ public void RepeatableDirectivesInSameLocation() field @repeatable @repeatable } "); - } + } - [Fact] - public void DuplicateDirectivesInOneLocation() - { - ExpectErrors(@" + [Fact] + public void DuplicateDirectivesInOneLocation() + { + ExpectErrors(@" { ...Test } @@ -360,12 +360,12 @@ public void DuplicateDirectivesInOneLocation() field @directiveA @directiveA } "); - } + } - [Fact] - public void ManyDuplicateDirectivesInOneLocation() - { - ExpectErrors(@" + [Fact] + public void ManyDuplicateDirectivesInOneLocation() + { + ExpectErrors(@" { ...Test } @@ -373,12 +373,12 @@ public void ManyDuplicateDirectivesInOneLocation() field @directiveA @directiveA @directiveA } "); - } + } - [Fact] - public void DifferentDuplicateDirectivesInOneLocation() - { - ExpectErrors(@" + [Fact] + public void DifferentDuplicateDirectivesInOneLocation() + { + ExpectErrors(@" { ...Test } @@ -386,12 +386,12 @@ public void DifferentDuplicateDirectivesInOneLocation() field @directiveA @directiveB @directiveA @directiveB } "); - } + } - [Fact] - public void DuplicateDirectivesInManyLocations() - { - ExpectErrors(@" + [Fact] + public void DuplicateDirectivesInManyLocations() + { + ExpectErrors(@" { ...Test } @@ -399,6 +399,5 @@ public void DuplicateDirectivesInManyLocations() field @directiveA @directiveA } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorTests.cs b/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorTests.cs index 01ef3b9f348..41978bbab49 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorTests.cs @@ -8,43 +8,43 @@ using Snapshooter.Xunit; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class DocumentValidatorTests { - public class DocumentValidatorTests + [Fact] + public void DocumentIsNull() { - [Fact] - public void DocumentIsNull() - { - // arrange - ISchema schema = ValidationUtils.CreateSchema(); - IDocumentValidator queryValidator = CreateValidator(); + // arrange + var schema = ValidationUtils.CreateSchema(); + var queryValidator = CreateValidator(); - // act - Action a = () => queryValidator.Validate(schema, null!); + // act + Action a = () => queryValidator.Validate(schema, null!); - // assert - Assert.Throws(a); - } + // assert + Assert.Throws(a); + } - [Fact] - public void SchemaIsNull() - { - // arrange - IDocumentValidator queryValidator = CreateValidator(); + [Fact] + public void SchemaIsNull() + { + // arrange + var queryValidator = CreateValidator(); - // act - // act - Action a = () => queryValidator.Validate(null!, - new DocumentNode(null, new List())); + // act + // act + Action a = () => queryValidator.Validate(null!, + new DocumentNode(null, new List())); - // assert - Assert.Throws(a); - } + // assert + Assert.Throws(a); + } - [Fact] - public void QueryWithTypeSystemDefinitions() - { - ExpectErrors(@" + [Fact] + public void QueryWithTypeSystemDefinitions() + { + ExpectErrors(@" query getDogName { dog { name @@ -62,12 +62,12 @@ public void QueryWithTypeSystemDefinitions() t => Assert.Equal( "The field `color` does not exist " + "on the type `Dog`.", t.Message)); - } + } - [Fact] - public void QueryWithOneAnonymousAndOneNamedOperation() - { - ExpectErrors(@" + [Fact] + public void QueryWithOneAnonymousAndOneNamedOperation() + { + ExpectErrors(@" { dog { name @@ -89,12 +89,12 @@ public void QueryWithOneAnonymousAndOneNamedOperation() "operations when only that one operation exists in " + "the document.", t.Message); }); - } + } - [Fact] - public void TwoQueryOperationsWithTheSameName() - { - ExpectErrors(@" + [Fact] + public void TwoQueryOperationsWithTheSameName() + { + ExpectErrors(@" query getName { dog { name @@ -110,14 +110,14 @@ public void TwoQueryOperationsWithTheSameName() } ", t => Assert.Equal( - $"The operation name `getName` is not unique.", - t.Message)); - } + $"The operation name `getName` is not unique.", + t.Message)); + } - [Fact] - public void OperationWithTwoVariablesThatHaveTheSameName() - { - ExpectErrors(@" + [Fact] + public void OperationWithTwoVariablesThatHaveTheSameName() + { + ExpectErrors(@" query houseTrainedQuery( $atOtherHomes: Boolean, $atOtherHomes: Boolean) { dog { @@ -129,12 +129,12 @@ public void OperationWithTwoVariablesThatHaveTheSameName() "A document containing operations that " + "define more than one variable with the same " + "name is invalid for execution.", t.Message)); - } + } - [Fact] - public void DuplicateArgument() - { - ExpectErrors(@" + [Fact] + public void DuplicateArgument() + { + ExpectErrors(@" { arguments { ... goodNonNullArg @@ -148,12 +148,12 @@ ... goodNonNullArg t => Assert.Equal( $"More than one argument with the same name in an argument set " + "is ambiguous and invalid.", t.Message)); - } + } - [Fact] - public void MissingRequiredArgNonNullBooleanArg() - { - ExpectErrors(@" + [Fact] + public void MissingRequiredArgNonNullBooleanArg() + { + ExpectErrors(@" { arguments { ... missingRequiredArg @@ -164,15 +164,15 @@ ... missingRequiredArg nonNullBooleanArgField(nonNullBooleanArg: null) } ", - t => Assert.Equal( - "The argument `nonNullBooleanArg` is required.", - t.Message)); - } + t => Assert.Equal( + "The argument `nonNullBooleanArg` is required.", + t.Message)); + } - [Fact] - public void DisallowedSecondRootField() - { - ExpectErrors(@" + [Fact] + public void DisallowedSecondRootField() + { + ExpectErrors(@" subscription sub { newMessage { body @@ -187,12 +187,12 @@ public void DisallowedSecondRootField() t => Assert.Equal( "The field `disallowedSecondRootFieldNonExisting` does not exist " + "on the type `Subscription`.", t.Message)); - } + } - [Fact] - public void FieldIsNotDefinedOnTypeInFragment() - { - ExpectErrors(@" + [Fact] + public void FieldIsNotDefinedOnTypeInFragment() + { + ExpectErrors(@" { dog { ... fieldNotDefined @@ -214,12 +214,12 @@ ... aliasedLyingFieldTargetNotDefined t => Assert.Equal( "The field `kawVolume` does not exist " + "on the type `Dog`.", t.Message)); - } + } - [Fact] - public void VariableNotUsedWithinFragment() - { - ExpectErrors(@" + [Fact] + public void VariableNotUsedWithinFragment() + { + ExpectErrors(@" query variableNotUsedWithinFragment($atOtherHomes: Boolean) { dog { ...isHouseTrainedWithoutVariableFragment @@ -233,32 +233,32 @@ public void VariableNotUsedWithinFragment() t => Assert.Equal( "The following variables were not used: " + "atOtherHomes.", t.Message)); - } + } - [Fact] - public void SkipDirectiveIsInTheWrongPlace() - { - ExpectErrors(@" + [Fact] + public void SkipDirectiveIsInTheWrongPlace() + { + ExpectErrors(@" query @skip(if: $foo) { field } "); - } + } - [Fact] - public void QueriesWithInvalidVariableTypes() - { - // arrange - ExpectErrors( - null, - new ServiceCollection() - .AddValidation() - .ModifyValidationOptions(o => o.MaxAllowedErrors = int.MaxValue) - .Services - .BuildServiceProvider() - .GetRequiredService() - .CreateValidator(), - @" + [Fact] + public void QueriesWithInvalidVariableTypes() + { + // arrange + ExpectErrors( + null, + new ServiceCollection() + .AddValidation() + .ModifyValidationOptions(o => o.MaxAllowedErrors = int.MaxValue) + .Services + .BuildServiceProvider() + .GetRequiredService() + .CreateValidator(), + @" query takesCat($cat: Cat) { # ... } @@ -274,67 +274,67 @@ public void QueriesWithInvalidVariableTypes() query takesCatOrDog($catOrDog: CatOrDog) { # ... }", - t => Assert.Equal( - "Operation `takesCat` has a empty selection set. Root types without " + - "subfields are disallowed.", - t.Message), - t => Assert.Equal( - "Operation `takesDogBang` has a empty selection set. Root types without " + - "subfields are disallowed.", - t.Message), - t => Assert.Equal( - "Operation `takesListOfPet` has a empty selection set. Root types without " + - "subfields are disallowed.", - t.Message), - t => Assert.Equal( - "Operation `takesCatOrDog` has a empty selection set. Root types without " + - "subfields are disallowed.", - t.Message), - t => Assert.Equal( - "The type of variable `cat` is not an input type.", - t.Message), - t => Assert.Equal( - "The following variables were not used: cat.", - t.Message), - t => Assert.Equal( - "The type of variable `dog` is not an input type.", - t.Message), - t => Assert.Equal( - "The following variables were not used: dog.", - t.Message), - t => Assert.Equal( - "The type of variable `pets` is not an input type.", - t.Message), - t => Assert.Equal( - "The following variables were not used: pets.", - t.Message), - t => Assert.Equal( - "The type of variable `catOrDog` is not an input type.", - t.Message), - t => Assert.Equal( - "The following variables were not used: catOrDog.", - t.Message)); - } + t => Assert.Equal( + "Operation `takesCat` has a empty selection set. Root types without " + + "subfields are disallowed.", + t.Message), + t => Assert.Equal( + "Operation `takesDogBang` has a empty selection set. Root types without " + + "subfields are disallowed.", + t.Message), + t => Assert.Equal( + "Operation `takesListOfPet` has a empty selection set. Root types without " + + "subfields are disallowed.", + t.Message), + t => Assert.Equal( + "Operation `takesCatOrDog` has a empty selection set. Root types without " + + "subfields are disallowed.", + t.Message), + t => Assert.Equal( + "The type of variable `cat` is not an input type.", + t.Message), + t => Assert.Equal( + "The following variables were not used: cat.", + t.Message), + t => Assert.Equal( + "The type of variable `dog` is not an input type.", + t.Message), + t => Assert.Equal( + "The following variables were not used: dog.", + t.Message), + t => Assert.Equal( + "The type of variable `pets` is not an input type.", + t.Message), + t => Assert.Equal( + "The following variables were not used: pets.", + t.Message), + t => Assert.Equal( + "The type of variable `catOrDog` is not an input type.", + t.Message), + t => Assert.Equal( + "The following variables were not used: catOrDog.", + t.Message)); + } - [Fact] - public void ConflictingBecauseAlias() - { - ExpectErrors(@" + [Fact] + public void ConflictingBecauseAlias() + { + ExpectErrors(@" fragment conflictingBecauseAlias on Dog { name: nickname name } ", - t => Assert.Equal( + t => Assert.Equal( "The specified fragment `conflictingBecauseAlias` " + "is not used within the current document.", t.Message)); - } + } - [Fact] - public void InvalidFieldArgName() - { - ExpectErrors(@" + [Fact] + public void InvalidFieldArgName() + { + ExpectErrors(@" { dog { ... invalidArgName @@ -350,12 +350,12 @@ ... invalidArgName t => Assert.Equal( "The argument `dogCommand` is required.", t.Message)); - } + } - [Fact] - public void UnusedFragment() - { - ExpectErrors(@" + [Fact] + public void UnusedFragment() + { + ExpectErrors(@" fragment nameFragment on Dog { # unused name } @@ -369,12 +369,12 @@ public void UnusedFragment() t => Assert.Equal( "The specified fragment `nameFragment` " + "is not used within the current document.", t.Message)); - } + } - [Fact] - public void DuplicateFragments() - { - ExpectErrors(@" + [Fact] + public void DuplicateFragments() + { + ExpectErrors(@" { dog { ...fragmentOne @@ -394,12 +394,12 @@ public void DuplicateFragments() t => Assert.Equal( "There are multiple fragments with the name `fragmentOne`.", t.Message)); - } + } - [Fact] - public void ScalarSelectionsNotAllowedOnInt() - { - ExpectErrors(@" + [Fact] + public void ScalarSelectionsNotAllowedOnInt() + { + ExpectErrors(@" { dog { barkVolume { @@ -412,12 +412,12 @@ public void ScalarSelectionsNotAllowedOnInt() "`barkVolume` returns a scalar value. Selections on scalars or enums" + " are never allowed, because they are the leaf nodes of any GraphQL query.", t.Message)); - } + } - [Fact] - public void InlineFragOnScalar() - { - ExpectErrors(@" + [Fact] + public void InlineFragOnScalar() + { + ExpectErrors(@" { dog { ... inlineFragOnScalar @@ -433,12 +433,12 @@ ... inlineFragOnScalar t => Assert.Equal(t.Message, "Fragments can only be declared on unions, interfaces, " + "and objects.")); - } + } - [Fact] - public void FragmentCycle1() - { - ExpectErrors(@" + [Fact] + public void FragmentCycle1() + { + ExpectErrors(@" { dog { ...nameFragment @@ -460,12 +460,12 @@ public void FragmentCycle1() "cycles including spreading itself. Otherwise an " + "operation could infinitely spread or infinitely " + "execute on cycles in the underlying data.")); - } + } - [Fact] - public void UndefinedFragment() - { - ExpectErrors(@" + [Fact] + public void UndefinedFragment() + { + ExpectErrors(@" { dog { ...undefinedFragment @@ -476,12 +476,12 @@ public void UndefinedFragment() "The specified fragment `undefinedFragment` " + "does not exist.", t.Message)); - } + } - [Fact] - public void FragmentDoesNotMatchType() - { - ExpectErrors(@" + [Fact] + public void FragmentDoesNotMatchType() + { + ExpectErrors(@" { dog { ...fragmentDoesNotMatchType @@ -496,12 +496,12 @@ public void FragmentDoesNotMatchType() "The parent type does not match the type condition on " + "the fragment.", t.Message)); - } + } - [Fact] - public void NotExistingTypeOnInlineFragment() - { - ExpectErrors(@" + [Fact] + public void NotExistingTypeOnInlineFragment() + { + ExpectErrors(@" { dog { ...inlineNotExistingType @@ -520,12 +520,12 @@ public void NotExistingTypeOnInlineFragment() "Unknown type `NotInSchema`.", t.Message); }); - } + } - [Fact] - public void InvalidInputObjectFieldsExist() - { - ExpectErrors(@" + [Fact] + public void InvalidInputObjectFieldsExist() + { + ExpectErrors(@" { findDog(complex: { favoriteCookieFlavor: ""Bacon"" }) { @@ -537,12 +537,12 @@ public void InvalidInputObjectFieldsExist() "The specified input object field " + "`favoriteCookieFlavor` does not exist.", t.Message)); - } + } - [Fact] - public void RequiredFieldIsNull() - { - ExpectErrors(@" + [Fact] + public void RequiredFieldIsNull() + { + ExpectErrors(@" { findDog2(complex: { name: null }) { @@ -553,12 +553,12 @@ public void RequiredFieldIsNull() t => Assert.Equal( "`name` is a required field and cannot be null.", t.Message)); - } + } - [Fact] - public void NameFieldIsAmbiguous() - { - ExpectErrors(@" + [Fact] + public void NameFieldIsAmbiguous() + { + ExpectErrors(@" { findDog(complex: { name: ""A"", name: ""B"" }) { @@ -568,12 +568,12 @@ public void NameFieldIsAmbiguous() ", t => Assert.Equal("There can be only one input field named `name`.", t.Message)); - } + } - [Fact] - public void UnsupportedDirective() - { - ExpectErrors(@" + [Fact] + public void UnsupportedDirective() + { + ExpectErrors(@" { dog { name @foo(bar: true) @@ -584,12 +584,12 @@ name @foo(bar: true) "The specified directive `foo` " + "is not supported by the current schema.", t.Message)); - } + } - [Fact] - public void StringIntoInt() - { - ExpectErrors(@" + [Fact] + public void StringIntoInt() + { + ExpectErrors(@" { arguments { ...stringIntoInt @@ -604,21 +604,21 @@ public void StringIntoInt() "The specified argument value does not match the " + "argument type.", t.Message)); - } + } - [Fact] - public void MaxDepthRuleIsIncluded() - { - ExpectErrors( - null, - new ServiceCollection() - .AddValidation() - .AddMaxExecutionDepthRule(1) - .Services - .BuildServiceProvider() - .GetRequiredService() - .CreateValidator(), - @" + [Fact] + public void MaxDepthRuleIsIncluded() + { + ExpectErrors( + null, + new ServiceCollection() + .AddValidation() + .AddMaxExecutionDepthRule(1) + .Services + .BuildServiceProvider() + .GetRequiredService() + .CreateValidator(), + @" query { catOrDog { @@ -628,19 +628,19 @@ public void MaxDepthRuleIsIncluded() } } ", - t => - { - Assert.Equal( - "The GraphQL document has an execution depth of 2 " + - "which exceeds the max allowed execution depth of 1.", - t.Message); - }); - } + t => + { + Assert.Equal( + "The GraphQL document has an execution depth of 2 " + + "which exceeds the max allowed execution depth of 1.", + t.Message); + }); + } - [Fact] - public void GoodBooleanArgDefault2() - { - ExpectValid(@" + [Fact] + public void GoodBooleanArgDefault2() + { + ExpectValid(@" query { arguments { ... goodBooleanArgDefault @@ -651,62 +651,62 @@ ... goodBooleanArgDefault optionalNonNullBooleanArgField2 } "); - } - - [Fact] - public void StarWars_Query_Is_Valid() - { - ExpectValid( - SchemaBuilder.New().AddStarWarsTypes().Create(), - null, - FileResource.Open("StarWars_Request.graphql")); - } + } - [Fact] - public void DuplicatesWillBeIgnoredOnFieldMerging() - { - // arrange - ISchema schema = SchemaBuilder.New() - .AddStarWarsTypes() - .Create(); - - DocumentNode document = Utf8GraphQLParser.Parse( - FileResource.Open("InvalidIntrospectionQuery.graphql")); - - var originalOperation = ((OperationDefinitionNode)document.Definitions[0]); - OperationDefinitionNode operationWithDuplicates = originalOperation.WithSelectionSet( - originalOperation.SelectionSet.WithSelections( - new List - { - originalOperation.SelectionSet.Selections[0], - originalOperation.SelectionSet.Selections[0] - })); + [Fact] + public void StarWars_Query_Is_Valid() + { + ExpectValid( + SchemaBuilder.New().AddStarWarsTypes().Create(), + null, + FileResource.Open("StarWars_Request.graphql")); + } - document = document.WithDefinitions( - new List(document.Definitions.Skip(1)) + [Fact] + public void DuplicatesWillBeIgnoredOnFieldMerging() + { + // arrange + var schema = SchemaBuilder.New() + .AddStarWarsTypes() + .Create(); + + var document = Utf8GraphQLParser.Parse( + FileResource.Open("InvalidIntrospectionQuery.graphql")); + + var originalOperation = ((OperationDefinitionNode)document.Definitions[0]); + var operationWithDuplicates = originalOperation.WithSelectionSet( + originalOperation.SelectionSet.WithSelections( + new List { - operationWithDuplicates - }); + originalOperation.SelectionSet.Selections[0], + originalOperation.SelectionSet.Selections[0] + })); - ServiceProvider services = new ServiceCollection() - .AddValidation() - .Services - .BuildServiceProvider(); + document = document.WithDefinitions( + new List(document.Definitions.Skip(1)) + { + operationWithDuplicates + }); - IDocumentValidatorFactory factory = services.GetRequiredService(); - IDocumentValidator validator = factory.CreateValidator(); + var services = new ServiceCollection() + .AddValidation() + .Services + .BuildServiceProvider(); - // act - DocumentValidatorResult result = validator.Validate(schema, document); + var factory = services.GetRequiredService(); + var validator = factory.CreateValidator(); - // assert - Assert.False(result.HasErrors); - } + // act + var result = validator.Validate(schema, document); - [Fact] - public void Ensure_That_Merged_Fields_Are_Not_In_Violation_Of_Duplicate_Directives_Rule() - { - ExpectValid(@" + // assert + Assert.False(result.HasErrors); + } + + [Fact] + public void Ensure_That_Merged_Fields_Are_Not_In_Violation_Of_Duplicate_Directives_Rule() + { + ExpectValid(@" query ($a: Boolean!) { dog { ... inlineFragOnScalar @@ -722,18 +722,18 @@ ... inlineFragOnScalar } } "); - } + } - [Fact] - public void Ensure_Recursive_Fragments_Fail() - { - ExpectErrors("fragment f on Query{...f} {...f}"); - } + [Fact] + public void Ensure_Recursive_Fragments_Fail() + { + ExpectErrors("fragment f on Query{...f} {...f}"); + } - [Fact] - public void Ensure_Recursive_Fragments_Fail_2() - { - ExpectErrors(@" + [Fact] + public void Ensure_Recursive_Fragments_Fail_2() + { + ExpectErrors(@" fragment f on Query { ...f f { @@ -745,126 +745,125 @@ public void Ensure_Recursive_Fragments_Fail_2() } {...f}"); - } - - [Fact] - public void Short_Long_Names() - { - ExpectErrors(FileResource.Open("short_long_names_query.graphql")); - } - - [Fact] - public void Anonymous_empty_query_repeated_25000() - { - ExpectErrors(FileResource.Open("anonymous_empty_query_repeated_25000.graphql")); - } + } - [Fact] - public void Type_query_repeated_6250() - { - ExpectErrors(FileResource.Open("__type_query_repeated_6250.graphql")); - } + [Fact] + public void Short_Long_Names() + { + ExpectErrors(FileResource.Open("short_long_names_query.graphql")); + } - [Fact] - public void Typename_query_repeated_4167() - { - ExpectErrors(FileResource.Open("__typename_query_repeated_4167.graphql")); - } + [Fact] + public void Anonymous_empty_query_repeated_25000() + { + ExpectErrors(FileResource.Open("anonymous_empty_query_repeated_25000.graphql")); + } - [Fact] - public void Typename_query() - { - ExpectValid(FileResource.Open("__typename_query.graphql")); - } + [Fact] + public void Type_query_repeated_6250() + { + ExpectErrors(FileResource.Open("__type_query_repeated_6250.graphql")); + } - [Fact] - public void Produce_Many_Errors_100_query() - { - ExpectErrors(FileResource.Open("100_query.graphql")); - } + [Fact] + public void Typename_query_repeated_4167() + { + ExpectErrors(FileResource.Open("__typename_query_repeated_4167.graphql")); + } - [Fact] - public void Produce_Many_Errors_1000_query() - { - ExpectErrors(FileResource.Open("1000_query.graphql")); - } + [Fact] + public void Typename_query() + { + ExpectValid(FileResource.Open("__typename_query.graphql")); + } - [Fact] - public void Produce_Many_Errors_10000_query() - { - ExpectErrors(FileResource.Open("10000_query.graphql")); - } + [Fact] + public void Produce_Many_Errors_100_query() + { + ExpectErrors(FileResource.Open("100_query.graphql")); + } - [Fact] - public void Produce_Many_Errors_25000_query() - { - ExpectErrors(FileResource.Open("25000_query.graphql")); - } + [Fact] + public void Produce_Many_Errors_1000_query() + { + ExpectErrors(FileResource.Open("1000_query.graphql")); + } - [Fact] - public void Produce_Many_Errors_30000_query() - { - ExpectErrors(FileResource.Open("30000_query.graphql")); - } + [Fact] + public void Produce_Many_Errors_10000_query() + { + ExpectErrors(FileResource.Open("10000_query.graphql")); + } - [Fact] - public void Produce_Many_Errors_50000_query() - { - ExpectErrors(FileResource.Open("50000_query.graphql")); - } + [Fact] + public void Produce_Many_Errors_25000_query() + { + ExpectErrors(FileResource.Open("25000_query.graphql")); + } - private void ExpectValid(string sourceText) => ExpectValid(null, null, sourceText); + [Fact] + public void Produce_Many_Errors_30000_query() + { + ExpectErrors(FileResource.Open("30000_query.graphql")); + } - private void ExpectValid(ISchema schema, IDocumentValidator validator, string sourceText) - { - // arrange - schema ??= ValidationUtils.CreateSchema(); - validator ??= CreateValidator(); - DocumentNode query = Utf8GraphQLParser.Parse(sourceText); + [Fact] + public void Produce_Many_Errors_50000_query() + { + ExpectErrors(FileResource.Open("50000_query.graphql")); + } - // act - DocumentValidatorResult result = validator.Validate(schema, query); + private void ExpectValid(string sourceText) => ExpectValid(null, null, sourceText); - // assert - Assert.Empty(result.Errors); - } + private void ExpectValid(ISchema schema, IDocumentValidator validator, string sourceText) + { + // arrange + schema ??= ValidationUtils.CreateSchema(); + validator ??= CreateValidator(); + var query = Utf8GraphQLParser.Parse(sourceText); - private void ExpectErrors(string sourceText, params Action[] elementInspectors) => - ExpectErrors(null, null, sourceText, elementInspectors); + // act + var result = validator.Validate(schema, query); - private void ExpectErrors( - ISchema schema, - IDocumentValidator validator, - string sourceText, - params Action[] elementInspectors) - { - // arrange - schema ??= ValidationUtils.CreateSchema(); - validator ??= CreateValidator(); - DocumentNode query = Utf8GraphQLParser.Parse(sourceText); + // assert + Assert.Empty(result.Errors); + } - // act - DocumentValidatorResult result = validator.Validate(schema, query); + private void ExpectErrors(string sourceText, params Action[] elementInspectors) => + ExpectErrors(null, null, sourceText, elementInspectors); - // assert - Assert.NotEmpty(result.Errors); + private void ExpectErrors( + ISchema schema, + IDocumentValidator validator, + string sourceText, + params Action[] elementInspectors) + { + // arrange + schema ??= ValidationUtils.CreateSchema(); + validator ??= CreateValidator(); + var query = Utf8GraphQLParser.Parse(sourceText); - if (elementInspectors.Length > 0) - { - Assert.Collection(result.Errors, elementInspectors); - } + // act + var result = validator.Validate(schema, query); - result.Errors.MatchSnapshot(); - } + // assert + Assert.NotEmpty(result.Errors); - private static IDocumentValidator CreateValidator() + if (elementInspectors.Length > 0) { - return new ServiceCollection() - .AddValidation() - .Services - .BuildServiceProvider() - .GetRequiredService() - .CreateValidator(); + Assert.Collection(result.Errors, elementInspectors); } + + result.Errors.MatchSnapshot(); + } + + private static IDocumentValidator CreateValidator() + { + return new ServiceCollection() + .AddValidation() + .Services + .BuildServiceProvider() + .GetRequiredService() + .CreateValidator(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorVisitorTestBase.cs b/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorVisitorTestBase.cs index 5d231790ab6..e62e0001ae4 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorVisitorTestBase.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/DocumentValidatorVisitorTestBase.cs @@ -7,105 +7,104 @@ using Snapshooter.Xunit; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public abstract class DocumentValidatorVisitorTestBase { - public abstract class DocumentValidatorVisitorTestBase + public DocumentValidatorVisitorTestBase(Action configure) { - public DocumentValidatorVisitorTestBase(Action configure) - { - var serviceCollection = new ServiceCollection(); + var serviceCollection = new ServiceCollection(); - IValidationBuilder builder = serviceCollection - .AddValidation() - .ConfigureValidation(c => c.Modifiers.Add(o => o.Rules.Clear())) - .ModifyValidationOptions(o => o.MaxAllowedErrors = int.MaxValue); - configure(builder); + var builder = serviceCollection + .AddValidation() + .ConfigureValidation(c => c.Modifiers.Add(o => o.Rules.Clear())) + .ModifyValidationOptions(o => o.MaxAllowedErrors = int.MaxValue); + configure(builder); - IServiceProvider services = serviceCollection.BuildServiceProvider(); + IServiceProvider services = serviceCollection.BuildServiceProvider(); - Rule = services - .GetRequiredService() - .GetRules(Schema.DefaultName).First(); + Rule = services + .GetRequiredService() + .GetRules(Schema.DefaultName).First(); - StarWars = SchemaBuilder.New() - .AddStarWarsTypes() - .ModifyOptions(o => o.EnableOneOf = true) - .Create(); - } + StarWars = SchemaBuilder.New() + .AddStarWarsTypes() + .ModifyOptions(o => o.EnableOneOf = true) + .Create(); + } - protected IDocumentValidatorRule Rule { get; } + protected IDocumentValidatorRule Rule { get; } - protected ISchema StarWars { get; } + protected ISchema StarWars { get; } - [Fact] - public void ContextIsNull() - { - // arrange - DocumentNode query = Utf8GraphQLParser.Parse(@"{ foo }"); + [Fact] + public void ContextIsNull() + { + // arrange + var query = Utf8GraphQLParser.Parse(@"{ foo }"); - // act - Action a = () => Rule.Validate(null!, query); + // act + var a = () => Rule.Validate(null!, query); - // assert - Assert.Throws(a); - } + // assert + Assert.Throws(a); + } - [Fact] - public void QueryIsNull() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); + [Fact] + public void QueryIsNull() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); - // act - Action a = () => Rule.Validate(context, null); + // act + var a = () => Rule.Validate(context, null); - // assert - Assert.Throws(a); - } - - protected void ExpectValid(string sourceText) => ExpectValid(null, sourceText); + // assert + Assert.Throws(a); + } - protected void ExpectValid(ISchema schema, string sourceText) - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(schema); - DocumentNode query = Utf8GraphQLParser.Parse(sourceText); - context.Prepare(query); + protected void ExpectValid(string sourceText) => ExpectValid(null, sourceText); - // act - Rule.Validate(context, query); + protected void ExpectValid(ISchema schema, string sourceText) + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(schema); + var query = Utf8GraphQLParser.Parse(sourceText); + context.Prepare(query); - // assert - Assert.False(context.UnexpectedErrorsDetected); - Assert.Empty(context.Errors); - } + // act + Rule.Validate(context, query); - protected void ExpectErrors(string sourceText, params Action[] elementInspectors) - => ExpectErrors(null, sourceText, elementInspectors); + // assert + Assert.False(context.UnexpectedErrorsDetected); + Assert.Empty(context.Errors); + } - protected void ExpectErrors( - ISchema schema, - string sourceText, - params Action[] elementInspectors) - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(schema); - context.MaxAllowedErrors = int.MaxValue; - DocumentNode query = Utf8GraphQLParser.Parse(sourceText); - context.Prepare(query); + protected void ExpectErrors(string sourceText, params Action[] elementInspectors) + => ExpectErrors(null, sourceText, elementInspectors); - // act - Rule.Validate(context, query); + protected void ExpectErrors( + ISchema schema, + string sourceText, + params Action[] elementInspectors) + { + // arrange + var context = ValidationUtils.CreateContext(schema); + context.MaxAllowedErrors = int.MaxValue; + var query = Utf8GraphQLParser.Parse(sourceText); + context.Prepare(query); - // assert - Assert.NotEmpty(context.Errors); + // act + Rule.Validate(context, query); - if (elementInspectors.Length > 0) - { - Assert.Collection(context.Errors, elementInspectors); - } + // assert + Assert.NotEmpty(context.Errors); - context.Errors.MatchSnapshot(); + if (elementInspectors.Length > 0) + { + Assert.Collection(context.Errors, elementInspectors); } + + context.Errors.MatchSnapshot(); } } diff --git a/src/HotChocolate/Core/test/Validation.Tests/ExecutableDefinitionsRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/ExecutableDefinitionsRuleTests.cs index a48c41601bd..78c4e1802b9 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/ExecutableDefinitionsRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/ExecutableDefinitionsRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class ExecutableDefinitionsRuleTests + : DocumentValidatorVisitorTestBase { - public class ExecutableDefinitionsRuleTests - : DocumentValidatorVisitorTestBase + public ExecutableDefinitionsRuleTests() + : base(builder => builder.AddDocumentRules()) { - public ExecutableDefinitionsRuleTests() - : base(builder => builder.AddDocumentRules()) - { - } + } - [Fact] - public void QueryWithTypeSystemDefinitions() - { - ExpectErrors(@" + [Fact] + public void QueryWithTypeSystemDefinitions() + { + ExpectErrors(@" query getDogName { dog { name @@ -27,14 +27,14 @@ public void QueryWithTypeSystemDefinitions() } ", t => Assert.Equal( - "A document containing TypeSystemDefinition " + - "is invalid for execution.", t.Message)); - } + "A document containing TypeSystemDefinition " + + "is invalid for execution.", t.Message)); + } - [Fact] - public void QueryWithoutTypeSystemDefinitions() - { - ExpectValid(@" + [Fact] + public void QueryWithoutTypeSystemDefinitions() + { + ExpectValid(@" query getDogName { dog { name @@ -42,24 +42,24 @@ public void QueryWithoutTypeSystemDefinitions() } } "); - } + } - [Fact] - public void GoodExecuableDefinitionsWithOnlyOperation() - { - ExpectValid(@" + [Fact] + public void GoodExecuableDefinitionsWithOnlyOperation() + { + ExpectValid(@" query Foo { dog { name } } "); - } + } - [Fact] - public void GoodExecuableDefinitionsWithOperationAndFragment() - { - ExpectValid(@" + [Fact] + public void GoodExecuableDefinitionsWithOperationAndFragment() + { + ExpectValid(@" query Foo { dog { name @@ -70,12 +70,12 @@ public void GoodExecuableDefinitionsWithOperationAndFragment() name } "); - } + } - [Fact] - public void GoodExecuableDefinitionsWithTypeDefinitions() - { - ExpectErrors(@" + [Fact] + public void GoodExecuableDefinitionsWithTypeDefinitions() + { + ExpectErrors(@" query Foo { dog { name @@ -88,12 +88,12 @@ public void GoodExecuableDefinitionsWithTypeDefinitions() color: String } "); - } + } - [Fact] - public void GoodExecuableDefinitionsWithSchemaDefinitions() - { - ExpectErrors(@" + [Fact] + public void GoodExecuableDefinitionsWithSchemaDefinitions() + { + ExpectErrors(@" schema { query: Query } @@ -104,6 +104,5 @@ public void GoodExecuableDefinitionsWithSchemaDefinitions() extend schema @directive "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FieldMustBeDefinedRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FieldMustBeDefinedRuleTests.cs index ccdee22ec43..8501871c72e 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FieldMustBeDefinedRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FieldMustBeDefinedRuleTests.cs @@ -4,24 +4,24 @@ using Snapshooter.Xunit; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FieldMustBeDefinedRuleTests + : DocumentValidatorVisitorTestBase { - public class FieldMustBeDefinedRuleTests - : DocumentValidatorVisitorTestBase + public FieldMustBeDefinedRuleTests() + : base(builder => builder.AddFieldRules()) + { + } + + [Fact] + public void FieldIsNotDefinedOnTypeInFragment() { - public FieldMustBeDefinedRuleTests() - : base(builder => builder.AddFieldRules()) - { - } - - [Fact] - public void FieldIsNotDefinedOnTypeInFragment() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; - - DocumentNode query = Utf8GraphQLParser.Parse(@" + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; + + var query = Utf8GraphQLParser.Parse(@" query { dog { ... fieldNotDefined @@ -37,28 +37,28 @@ ... aliasedLyingFieldTargetNotDefined barkVolume: kawVolume } "); - context.Prepare(query); - - // act - Rule.Validate(context, query); - - // assert - Assert.Collection(context.Errors, - t => Assert.Equal( - "The field `meowVolume` does not exist " + - "on the type `Dog`.", t.Message), - t => Assert.Equal( - "The field `kawVolume` does not exist " + - "on the type `Dog`.", t.Message)); - context.Errors.MatchSnapshot(); - } - - [Fact] - public void InterfaceFieldSelectionOnPet() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + context.Prepare(query); + + // act + Rule.Validate(context, query); + + // assert + Assert.Collection(context.Errors, + t => Assert.Equal( + "The field `meowVolume` does not exist " + + "on the type `Dog`.", t.Message), + t => Assert.Equal( + "The field `kawVolume` does not exist " + + "on the type `Dog`.", t.Message)); + context.Errors.MatchSnapshot(); + } + + [Fact] + public void InterfaceFieldSelectionOnPet() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query { dog { ... interfaceFieldSelection @@ -69,23 +69,23 @@ ... interfaceFieldSelection name } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void DefinedOnImplementorsButNotInterfaceOnPet() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; + [Fact] + public void DefinedOnImplementorsButNotInterfaceOnPet() + { + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; - DocumentNode query = Utf8GraphQLParser.Parse(@" + var query = Utf8GraphQLParser.Parse(@" query { dog { ... definedOnImplementorsButNotInterface @@ -96,25 +96,25 @@ ... definedOnImplementorsButNotInterface nickname } "); - context.Prepare(query); - - // act - Rule.Validate(context, query); - - // assert - Assert.Collection(context.Errors, - t => Assert.Equal( - "The field `nickname` does not exist " + - "on the type `Pet`.", t.Message)); - context.Errors.First().MatchSnapshot(); - } - - [Fact] - public void InDirectFieldSelectionOnUnion() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + context.Prepare(query); + + // act + Rule.Validate(context, query); + + // assert + Assert.Collection(context.Errors, + t => Assert.Equal( + "The field `nickname` does not exist " + + "on the type `Pet`.", t.Message)); + context.Errors.First().MatchSnapshot(); + } + + [Fact] + public void InDirectFieldSelectionOnUnion() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query { dog { ... inDirectFieldSelectionOnUnion @@ -131,24 +131,24 @@ ... inDirectFieldSelectionOnUnion } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void DirectFieldSelectionOnUnion() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; + [Fact] + public void DirectFieldSelectionOnUnion() + { + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; - DocumentNode query = Utf8GraphQLParser.Parse(@" + var query = Utf8GraphQLParser.Parse(@" query { catOrDog { ... directFieldSelectionOnUnion @@ -160,25 +160,25 @@ ... directFieldSelectionOnUnion barkVolume } "); - context.Prepare(query); - - // act - Rule.Validate(context, query); - - // assert - Assert.Collection(context.Errors, - t => Assert.Equal( - "A union type cannot declare a field directly. " + - "Use inline fragments or fragments instead.", t.Message)); - context.Errors.First().MatchSnapshot(); - } - - [Fact] - public void IntrospectionFieldsOnInterface() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + context.Prepare(query); + + // act + Rule.Validate(context, query); + + // assert + Assert.Collection(context.Errors, + t => Assert.Equal( + "A union type cannot declare a field directly. " + + "Use inline fragments or fragments instead.", t.Message)); + context.Errors.First().MatchSnapshot(); + } + + [Fact] + public void IntrospectionFieldsOnInterface() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query { dog { ... interfaceFieldSelection @@ -189,21 +189,21 @@ ... interfaceFieldSelection __typename } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void IntrospectionFieldsOnUnion() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void IntrospectionFieldsOnUnion() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query { dog { ... unionFieldSelection @@ -214,21 +214,21 @@ ... unionFieldSelection __typename } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void IntrospectionFieldsOnObject() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void IntrospectionFieldsOnObject() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query { catOrDog { ... unionFieldSelection @@ -239,13 +239,12 @@ ... unionFieldSelection __typename } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs index c3884f73e27..ef54cfdbdb4 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FieldSelectionMergingRuleTests.cs @@ -1,22 +1,21 @@ using ChilliCream.Testing; using HotChocolate.Types; using Microsoft.Extensions.DependencyInjection; -using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FieldSelectionMergingRuleTests + : DocumentValidatorVisitorTestBase { - public class FieldSelectionMergingRuleTests - : DocumentValidatorVisitorTestBase + public FieldSelectionMergingRuleTests() + : base(builder => builder.AddFieldRules()) + { + } + + [Fact] + public void MergeIdenticalFields() { - public FieldSelectionMergingRuleTests() - : base(builder => builder.AddFieldRules()) - { - } - - [Fact] - public void MergeIdenticalFields() - { - ExpectValid(@" + ExpectValid(@" { dog { ... mergeIdenticalFields @@ -28,12 +27,12 @@ ... mergeIdenticalFields name } "); - } + } - [Fact] - public void MergeIdenticalAliasesAndFields() - { - ExpectValid(@" + [Fact] + public void MergeIdenticalAliasesAndFields() + { + ExpectValid(@" { dog { ... mergeIdenticalAliasesAndFields @@ -45,12 +44,12 @@ ... mergeIdenticalAliasesAndFields otherName: name } "); - } + } - [Fact] - public void ConflictingBecauseAlias() - { - ExpectErrors(@" + [Fact] + public void ConflictingBecauseAlias() + { + ExpectErrors(@" { dog { ... conflictingBecauseAlias @@ -65,12 +64,12 @@ ... conflictingBecauseAlias t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void MergeIdenticalFieldsWithIdenticalArgs() - { - ExpectValid(@" + [Fact] + public void MergeIdenticalFieldsWithIdenticalArgs() + { + ExpectValid(@" { dog { ... mergeIdenticalFieldsWithIdenticalArgs @@ -82,12 +81,12 @@ ... mergeIdenticalFieldsWithIdenticalArgs doesKnowCommand(dogCommand: SIT) } "); - } + } - [Fact] - public void MergeIdenticalFieldsWithIdenticalValues() - { - ExpectValid(@" + [Fact] + public void MergeIdenticalFieldsWithIdenticalValues() + { + ExpectValid(@" { dog { ... mergeIdenticalFieldsWithIdenticalValues @@ -99,12 +98,12 @@ ... mergeIdenticalFieldsWithIdenticalValues doesKnowCommand(dogCommand: $dogCommand) } "); - } + } - [Fact] - public void ConflictingArgsOnValues() - { - ExpectErrors(@" + [Fact] + public void ConflictingArgsOnValues() + { + ExpectErrors(@" { dog { ... conflictingArgsOnValues @@ -119,12 +118,12 @@ ... conflictingArgsOnValues t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void ConflictingArgsValueAndVar() - { - ExpectErrors(@" + [Fact] + public void ConflictingArgsValueAndVar() + { + ExpectErrors(@" query($dogCommand: DogCommand!) { dog { ... conflictingArgsValueAndVar @@ -139,12 +138,12 @@ ... conflictingArgsValueAndVar t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void ConflictingArgsWithVars() - { - ExpectErrors(@" + [Fact] + public void ConflictingArgsWithVars() + { + ExpectErrors(@" query($varOne: DogCommand! $varTwo: DogCommand!) { dog { ... conflictingArgsWithVars @@ -159,12 +158,12 @@ ... conflictingArgsWithVars t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void DifferingArgs() - { - ExpectErrors(@" + [Fact] + public void DifferingArgs() + { + ExpectErrors(@" { dog { ... differingArgs @@ -179,12 +178,12 @@ ... differingArgs t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void SameResponseNameDifferentFieldName() - { - ExpectErrors(@" + [Fact] + public void SameResponseNameDifferentFieldName() + { + ExpectErrors(@" { catOrDog { ... dog @@ -201,12 +200,12 @@ ... dog t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void SafeDifferingFields() - { - ExpectValid(@" + [Fact] + public void SafeDifferingFields() + { + ExpectValid(@" { catOrDog { ... safeDifferingFields @@ -222,12 +221,12 @@ ... safeDifferingFields } } "); - } + } - [Fact] - public void SafeDifferingArgs() - { - ExpectValid(@" + [Fact] + public void SafeDifferingArgs() + { + ExpectValid(@" { dog { ... safeDifferingArgs @@ -243,12 +242,12 @@ ... safeDifferingArgs } } "); - } + } - [Fact] - public void ConflictingDifferingResponses() - { - ExpectErrors(@" + [Fact] + public void ConflictingDifferingResponses() + { + ExpectErrors(@" { dog { ... conflictingDifferingResponses @@ -267,13 +266,13 @@ ... conflictingDifferingResponses t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void ShortHandQueryWithNoDuplicateFields() - { - ExpectValid( - @"{ + [Fact] + public void ShortHandQueryWithNoDuplicateFields() + { + ExpectValid( + @"{ __type (type: ""Foo"") { name fields { @@ -284,12 +283,75 @@ public void ShortHandQueryWithNoDuplicateFields() } } }"); - } + } + + [Fact] + public void Stream_Mergeable() + { + ExpectValid( + @"{ + __type (type: ""Foo"") { + name + fields @stream(initialCount: 1) { + type { + name + } + } + fields @stream(initialCount: 1) { + name + } + } + }"); + } - [Fact] - public void ShortHandQueryWithDuplicateFieldInSecondLevelFragment() - { - ExpectErrors(@" + [Fact] + public void Stream_Argument_Mismatch() + { + ExpectErrors( + @"{ + __type (type: ""Foo"") { + name + fields @stream(initialCount: 1) { + type { + name + } + } + fields @stream(initialCount: 2) { + name + } + } + }", + t => Assert.Equal( + "Encountered fields for the same object that cannot be merged.", + t.Message)); + } + + [Fact] + public void Stream_On_Some_Fields() + { + ExpectErrors( + @"{ + __type (type: ""Foo"") { + name + fields @stream(initialCount: 1) { + type { + name + } + } + fields { + name + } + } + }", + t => Assert.Equal( + "Encountered fields for the same object that cannot be merged.", + t.Message)); + } + + [Fact] + public void ShortHandQueryWithDuplicateFieldInSecondLevelFragment() + { + ExpectErrors(@" { dog { doesKnowCommand(dogCommand: DOWN) @@ -308,13 +370,13 @@ ... FooLevel2 t => Assert.Equal( "Encountered fields for the same object that cannot be merged.", t.Message)); - } + } - [Fact] - public void ShortHandQueryWithDupMergableFieldInSecondLevelFragment() - { - // arrange - ExpectValid(@" + [Fact] + public void ShortHandQueryWithDupMergableFieldInSecondLevelFragment() + { + // arrange + ExpectValid(@" { dog { doesKnowCommand(dogCommand: DOWN) @@ -330,13 +392,13 @@ ... FooLevel2 doesKnowCommand(dogCommand: DOWN) } "); - } + } - [Fact] - public void TypeNameFieldOnInterfaceIsMergable() - { - // arrange - ExpectValid(@" + [Fact] + public void TypeNameFieldOnInterfaceIsMergable() + { + // arrange + ExpectValid(@" { dog { ... interfaceFieldSelection @@ -348,12 +410,12 @@ ... interfaceFieldSelection __typename } "); - } + } - [Fact] - public void TypeNameFieldOnUnionIsMergable() - { - ExpectValid(@" + [Fact] + public void TypeNameFieldOnUnionIsMergable() + { + ExpectValid(@" { catOrDog { ... interfaceFieldSelection @@ -365,12 +427,12 @@ ... interfaceFieldSelection __typename } "); - } + } - [Fact] - public void TypeNameFieldOnObjectIsMergeable() - { - ExpectValid(@" + [Fact] + public void TypeNameFieldOnObjectIsMergeable() + { + ExpectValid(@" { catOrDog { ... interfaceFieldSelection @@ -382,18 +444,18 @@ ... interfaceFieldSelection __typename } "); - } - - [Fact] - public void InvalidFieldsShouldNotRaiseValidationError() - { - ExpectValid(FileResource.Open("InvalidIntrospectionQuery.graphql")); - } - - [Fact] - public void UniqueFields() - { - ExpectValid(@" + } + + [Fact] + public void InvalidFieldsShouldNotRaiseValidationError() + { + ExpectValid(FileResource.Open("InvalidIntrospectionQuery.graphql")); + } + + [Fact] + public void UniqueFields() + { + ExpectValid(@" { catOrDog { ... uniqueFields @@ -405,12 +467,12 @@ ... uniqueFields nickname } "); - } + } - [Fact] - public void IdenticalFields() - { - ExpectValid(@" + [Fact] + public void IdenticalFields() + { + ExpectValid(@" { catOrDog { ... mergeIdenticalFields @@ -422,12 +484,12 @@ ... mergeIdenticalFields name } "); - } + } - [Fact] - public void IdenticalFieldsWithIdenticalArgs() - { - ExpectValid(@" + [Fact] + public void IdenticalFieldsWithIdenticalArgs() + { + ExpectValid(@" { catOrDog { ... mergeIdenticalFieldsWithIdenticalArgs @@ -439,12 +501,12 @@ ... mergeIdenticalFieldsWithIdenticalArgs doesKnowCommand(dogCommand: SIT) } "); - } + } - [Fact] - public void DifferentArgsWithDifferentAliases() - { - ExpectValid(@" + [Fact] + public void DifferentArgsWithDifferentAliases() + { + ExpectValid(@" { catOrDog { ... differentArgsWithDifferentAliases @@ -456,12 +518,12 @@ ... differentArgsWithDifferentAliases knowsDown: doesKnowCommand(dogCommand: DOWN) } "); - } + } - [Fact] - public void DifferentDirectivesWithDifferentAliases() - { - ExpectValid(@" + [Fact] + public void DifferentDirectivesWithDifferentAliases() + { + ExpectValid(@" { catOrDog { ... differentDirectivesWithDifferentAliases @@ -473,12 +535,12 @@ ... differentDirectivesWithDifferentAliases nameIfFalse: name @include(if: false) } "); - } + } - [Fact] - public void DifferentSkipIncludeDirectivesAccepted() - { - ExpectValid(@" + [Fact] + public void DifferentSkipIncludeDirectivesAccepted() + { + ExpectValid(@" { catOrDog { ... differentDirectivesWithDifferentAliases @@ -490,12 +552,12 @@ name @include(if: true) name @include(if: false) } "); - } + } - [Fact] - public void SameAliasesWithDifferentFieldTargets() - { - ExpectErrors(@" + [Fact] + public void SameAliasesWithDifferentFieldTargets() + { + ExpectErrors(@" { catOrDog { ... sameAliasesWithDifferentFieldTargets @@ -507,12 +569,12 @@ ... sameAliasesWithDifferentFieldTargets fido: nickname } "); - } + } - [Fact] - public void SameAliasesAllowedOnNonOverlappingFields() - { - ExpectErrors(@" + [Fact] + public void SameAliasesAllowedOnNonOverlappingFields() + { + ExpectErrors(@" { catOrDog { ... sameAliasesWithDifferentFieldTargets @@ -528,12 +590,12 @@ ... sameAliasesWithDifferentFieldTargets } } "); - } + } - [Fact] - public void AliasMaskingDirectFieldAccess() - { - ExpectErrors(@" + [Fact] + public void AliasMaskingDirectFieldAccess() + { + ExpectErrors(@" { catOrDog { ... aliasMaskingDirectFieldAccess @@ -545,12 +607,12 @@ ... aliasMaskingDirectFieldAccess name } "); - } + } - [Fact] - public void DifferentArgsSecondAddsAnArgument() - { - ExpectErrors(@" + [Fact] + public void DifferentArgsSecondAddsAnArgument() + { + ExpectErrors(@" { catOrDog { ... conflictingArgs @@ -562,12 +624,12 @@ ... conflictingArgs doesKnowCommand(dogCommand: HEEL) } "); - } + } - [Fact] - public void DifferentArgsSecondMissingAnArgument() - { - ExpectErrors(@" + [Fact] + public void DifferentArgsSecondMissingAnArgument() + { + ExpectErrors(@" { catOrDog { ... conflictingArgs @@ -579,12 +641,12 @@ ... conflictingArgs doesKnowCommand } "); - } + } - [Fact] - public void ConflictingArgValues() - { - ExpectErrors(@" + [Fact] + public void ConflictingArgValues() + { + ExpectErrors(@" { catOrDog { ... conflictingArgs @@ -596,12 +658,12 @@ ... conflictingArgs doesKnowCommand(dogCommand: HEEL) } "); - } + } - [Fact] - public void ConflictingArgNames() - { - ExpectErrors(@" + [Fact] + public void ConflictingArgNames() + { + ExpectErrors(@" { catOrDog { ... conflictingArgs @@ -613,12 +675,12 @@ ... conflictingArgs isAtLocation(y: 0) } "); - } + } - [Fact] - public void AllowsDifferentArgsWhereNoConflictIsPossible() - { - ExpectValid(@" + [Fact] + public void AllowsDifferentArgsWhereNoConflictIsPossible() + { + ExpectValid(@" { catOrDog { ... conflictingArgs @@ -634,12 +696,12 @@ ... conflictingArgs } } "); - } + } - [Fact] - public void EncountersConflictInFragments() - { - ExpectErrors(@" + [Fact] + public void EncountersConflictInFragments() + { + ExpectErrors(@" { ...A ...B @@ -653,12 +715,12 @@ public void EncountersConflictInFragments() x: b } "); - } + } - [Fact] - public void ReportsEachConflictOnce() - { - ExpectErrors(@" + [Fact] + public void ReportsEachConflictOnce() + { + ExpectErrors(@" { f1 { ...A @@ -683,12 +745,12 @@ public void ReportsEachConflictOnce() x: b } "); - } + } - [Fact] - public void DeepConflict() - { - ExpectErrors(@" + [Fact] + public void DeepConflict() + { + ExpectErrors(@" { f1 { x: a @@ -698,12 +760,12 @@ public void DeepConflict() } } "); - } + } - [Fact] - public void DeepConflictWithMultipleIssues() - { - ExpectErrors(@" + [Fact] + public void DeepConflictWithMultipleIssues() + { + ExpectErrors(@" { f1 { x: a @@ -715,12 +777,12 @@ public void DeepConflictWithMultipleIssues() } } "); - } + } - [Fact] - public void VeryDeepConflict() - { - ExpectErrors(@" + [Fact] + public void VeryDeepConflict() + { + ExpectErrors(@" { f1 { f2 { @@ -734,12 +796,12 @@ public void VeryDeepConflict() } } "); - } + } - [Fact] - public void ReportsDeepConflictToNearestCommonAncestor() - { - ExpectErrors(@" + [Fact] + public void ReportsDeepConflictToNearestCommonAncestor() + { + ExpectErrors(@" { f1 { f2 { @@ -756,12 +818,12 @@ public void ReportsDeepConflictToNearestCommonAncestor() } } "); - } + } - [Fact] - public void ReportsDeepConflictToNearestCommonAncestorInFragments() - { - ExpectErrors(@" + [Fact] + public void ReportsDeepConflictToNearestCommonAncestorInFragments() + { + ExpectErrors(@" { f1 { ...F @@ -786,12 +848,12 @@ public void ReportsDeepConflictToNearestCommonAncestorInFragments() } } "); - } + } - [Fact] - public void ReportsDeepConflictInNestedFragments() - { - ExpectErrors(@" + [Fact] + public void ReportsDeepConflictInNestedFragments() + { + ExpectErrors(@" { f1 { ...F @@ -819,13 +881,13 @@ public void ReportsDeepConflictInNestedFragments() x: b } "); - } + } - [Fact] - public void ConflictingReturnTypesWhichPotentiallyOverlap() - { - ExpectErrors(TestSchema, @" + [Fact] + public void ConflictingReturnTypesWhichPotentiallyOverlap() + { + ExpectErrors(TestSchema, @" { someBox { ...on IntBox { @@ -837,12 +899,12 @@ public void ConflictingReturnTypesWhichPotentiallyOverlap() } } "); - } + } - [Fact] - public void CompatibleReturnShapesOnDifferentReturnTypes() - { - ExpectValid(TestSchema, @" + [Fact] + public void CompatibleReturnShapesOnDifferentReturnTypes() + { + ExpectValid(TestSchema, @" { someBox { ... on SomeBox { @@ -858,12 +920,12 @@ public void CompatibleReturnShapesOnDifferentReturnTypes() } } "); - } + } - [Fact] - public void DisallowsDifferingReturnTypesDespiteNoOverlap() - { - ExpectErrors(TestSchema, @" + [Fact] + public void DisallowsDifferingReturnTypesDespiteNoOverlap() + { + ExpectErrors(TestSchema, @" { someBox { ... on IntBox { @@ -875,12 +937,12 @@ public void DisallowsDifferingReturnTypesDespiteNoOverlap() } } "); - } + } - [Fact] - public void DisallowsDifferingReturnTypeNullabilityDespiteNoOverlap() - { - ExpectErrors(TestSchema, @" + [Fact] + public void DisallowsDifferingReturnTypeNullabilityDespiteNoOverlap() + { + ExpectErrors(TestSchema, @" { someBox { ... on NonNullStringBox1 { @@ -892,12 +954,12 @@ public void DisallowsDifferingReturnTypeNullabilityDespiteNoOverlap() } } "); - } + } - [Fact] - public void DisallowsDifferingReturnTypeListDespiteNoOverlap() - { - ExpectErrors(TestSchema, @" + [Fact] + public void DisallowsDifferingReturnTypeListDespiteNoOverlap() + { + ExpectErrors(TestSchema, @" { someBox { ... on IntBox { @@ -912,12 +974,12 @@ public void DisallowsDifferingReturnTypeListDespiteNoOverlap() } } }"); - } + } - [Fact] - public void DisallowsDifferingReturnTypeListDespiteNoOverlapReverse() - { - ExpectErrors(TestSchema, @" + [Fact] + public void DisallowsDifferingReturnTypeListDespiteNoOverlapReverse() + { + ExpectErrors(TestSchema, @" { someBox { ... on IntBox { @@ -932,13 +994,13 @@ public void DisallowsDifferingReturnTypeListDespiteNoOverlapReverse() } } }"); - } + } - [Fact] - public void DisallowsDifferingSubfields() - { - ExpectErrors(TestSchema, - @"{ + [Fact] + public void DisallowsDifferingSubfields() + { + ExpectErrors(TestSchema, + @"{ someBox { ... on IntBox { box: stringBox { @@ -953,13 +1015,13 @@ public void DisallowsDifferingSubfields() } } }"); - } + } - // TODO : Fix this issue - [Fact(Skip = "This one needs fixing!")] - public void DisallowsDifferingDeepReturnTypesDespiteNoOverlap() - { - ExpectErrors(TestSchema, @" + // TODO : Fix this issue + [Fact(Skip = "This one needs fixing!")] + public void DisallowsDifferingDeepReturnTypesDespiteNoOverlap() + { + ExpectErrors(TestSchema, @" { someBox { ... on IntBox { @@ -974,12 +1036,12 @@ public void DisallowsDifferingDeepReturnTypesDespiteNoOverlap() } } }"); - } + } - [Fact] - public void AllowsNonConflictingOverlappingTypes() - { - ExpectValid(TestSchema, @" + [Fact] + public void AllowsNonConflictingOverlappingTypes() + { + ExpectValid(TestSchema, @" { someBox { ... on IntBox { @@ -990,13 +1052,13 @@ public void AllowsNonConflictingOverlappingTypes() } } }"); - } + } - // TODO : we need to analyze this validation issue further. - [Fact(Skip = "This one needs to be analyzed further.")] - public void SameWrappedScalarReturnTypes() - { - ExpectErrors(TestSchema, @" + // TODO : we need to analyze this validation issue further. + [Fact(Skip = "This one needs to be analyzed further.")] + public void SameWrappedScalarReturnTypes() + { + ExpectErrors(TestSchema, @" { someBox { ...on NonNullStringBox1 { @@ -1007,24 +1069,24 @@ public void SameWrappedScalarReturnTypes() } } }"); - } + } - [Fact] - public void AllowsInlineFragmentsWithoutTypeCondition() - { - ExpectValid(TestSchema, @" + [Fact] + public void AllowsInlineFragmentsWithoutTypeCondition() + { + ExpectValid(TestSchema, @" { a ... { a } }"); - } + } - [Fact] - public void ComparesDeepTypesIncludingList() - { - ExpectErrors(TestSchema, @" + [Fact] + public void ComparesDeepTypesIncludingList() + { + ExpectErrors(TestSchema, @" { connection { ...edgeID @@ -1043,12 +1105,12 @@ public void ComparesDeepTypesIncludingList() } } }"); - } + } - [Fact] - public void FindsInvalidCaseEvenWithImmediatelyRecursiveFragment() - { - ExpectErrors(@" + [Fact] + public void FindsInvalidCaseEvenWithImmediatelyRecursiveFragment() + { + ExpectErrors(@" { dogOrHuman { ... sameAliasesWithDifferentFieldTargets @@ -1060,12 +1122,12 @@ ... sameAliasesWithDifferentFieldTargets fido: name fido: nickname }"); - } + } - [Fact] - public void ConflictingDifferingResponse() - { - ExpectErrors(@" + [Fact] + public void ConflictingDifferingResponse() + { + ExpectErrors(@" { catOrDog { ... conflictingDifferingResponses @@ -1080,12 +1142,12 @@ ... conflictingDifferingResponses someValue: nickname! } }"); - } + } - [Fact] - public void MergeableNullabilityChange() - { - ExpectValid(@" + [Fact] + public void MergeableNullabilityChange() + { + ExpectValid(@" { catOrDog { ... conflictingDifferingResponses @@ -1100,11 +1162,11 @@ ... conflictingDifferingResponses someValue: nickname! } }"); - } + } - private static readonly ISchema TestSchema = - SchemaBuilder.New() - .AddDocumentFromString(@" + private static readonly ISchema TestSchema = + SchemaBuilder.New() + .AddDocumentFromString(@" interface SomeBox { deepBox: SomeBox unrelatedField: String @@ -1187,5 +1249,4 @@ interface NonNullStringBox2 { .AddResolver("Query", "y", () => "") .AddType(new AnyType()) .Create(); - } } diff --git a/src/HotChocolate/Core/test/Validation.Tests/FieldsOnCorrectTypeRule.cs b/src/HotChocolate/Core/test/Validation.Tests/FieldsOnCorrectTypeRule.cs index 07c4b33d855..cecac4d94bb 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FieldsOnCorrectTypeRule.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FieldsOnCorrectTypeRule.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FieldsOnCorrectTypeRuleTests + : DocumentValidatorVisitorTestBase { - public class FieldsOnCorrectTypeRuleTests - : DocumentValidatorVisitorTestBase + public FieldsOnCorrectTypeRuleTests() + : base(services => services.AddFieldRules()) { - public FieldsOnCorrectTypeRuleTests() - : base(services => services.AddFieldRules()) - { - } - - [Fact] - public void GoodObjectFieldSelection() - { - ExpectValid(@" + } + + [Fact] + public void GoodObjectFieldSelection() + { + ExpectValid(@" fragment objectFieldSelection on Dog { __typename name @@ -26,12 +26,12 @@ public void GoodObjectFieldSelection() } } "); - } + } - [Fact] - public void GoodAliasedObjectFieldSelection() - { - ExpectValid(@" + [Fact] + public void GoodAliasedObjectFieldSelection() + { + ExpectValid(@" fragment aliasedObjectFieldSelection on Dog { tn : __typename otherName : name @@ -43,12 +43,12 @@ public void GoodAliasedObjectFieldSelection() } } "); - } + } - [Fact] - public void GoodInterfacesObjectFieldSelection() - { - ExpectValid(@" + [Fact] + public void GoodInterfacesObjectFieldSelection() + { + ExpectValid(@" fragment interfaceFieldSelection on Pet { otherName : name } @@ -59,12 +59,12 @@ public void GoodInterfacesObjectFieldSelection() } } "); - } + } - [Fact] - public void BadReportsErrorWhenTypeIsKnown() - { - ExpectErrors(@" + [Fact] + public void BadReportsErrorWhenTypeIsKnown() + { + ExpectErrors(@" fragment typeKnownAgain on Pet { unknown_pet_field { ... on Cat { @@ -78,12 +78,12 @@ public void BadReportsErrorWhenTypeIsKnown() } } "); - } + } - [Fact] - public void BadFieldNotDefinedOnFragement() - { - ExpectErrors(@" + [Fact] + public void BadFieldNotDefinedOnFragement() + { + ExpectErrors(@" fragment fieldNotDefined on Dog { meowVolume } @@ -94,12 +94,12 @@ public void BadFieldNotDefinedOnFragement() } } "); - } + } - [Fact] - public void BadIgnoresDeeplyUnknownField() - { - ExpectErrors(@" + [Fact] + public void BadIgnoresDeeplyUnknownField() + { + ExpectErrors(@" fragment deepFieldNotDefined on Dog { unknown_field { deeper_unknown_field @@ -112,12 +112,12 @@ public void BadIgnoresDeeplyUnknownField() } } "); - } + } - [Fact] - public void BadSubFieldNotDefined() - { - ExpectErrors(@" + [Fact] + public void BadSubFieldNotDefined() + { + ExpectErrors(@" fragment subFieldNotDefined on Human { pets { unknown_field @@ -130,12 +130,12 @@ public void BadSubFieldNotDefined() } } "); - } + } - [Fact] - public void BadFieldNotDefinedOnInlineFragment() - { - ExpectErrors(@" + [Fact] + public void BadFieldNotDefinedOnInlineFragment() + { + ExpectErrors(@" fragment fieldNotDefined on Pet { ... on Dog { meowVolume @@ -148,12 +148,12 @@ public void BadFieldNotDefinedOnInlineFragment() } } "); - } + } - [Fact] - public void BadAliasedFieldTargetNotDefined() - { - ExpectErrors(@" + [Fact] + public void BadAliasedFieldTargetNotDefined() + { + ExpectErrors(@" fragment aliasedFieldTargetNotDefined on Dog { volume : mooVolume } @@ -164,12 +164,12 @@ public void BadAliasedFieldTargetNotDefined() } } "); - } + } - [Fact] - public void BadAliasedLyingFieldTargetNotDefined() - { - ExpectErrors(@" + [Fact] + public void BadAliasedLyingFieldTargetNotDefined() + { + ExpectErrors(@" fragment aliasedLyingFieldTargetNotDefined on Dog { barkVolume : kawVolume } @@ -180,12 +180,12 @@ public void BadAliasedLyingFieldTargetNotDefined() } } "); - } + } - [Fact] - public void BadNotDefinedOnInterface() - { - ExpectErrors(@" + [Fact] + public void BadNotDefinedOnInterface() + { + ExpectErrors(@" fragment notDefinedOnInterface on Pet { tailLength } @@ -196,12 +196,12 @@ public void BadNotDefinedOnInterface() } } "); - } + } - [Fact] - public void DefinedOnImplementorsButNotOnInterface() - { - ExpectErrors(@" + [Fact] + public void DefinedOnImplementorsButNotOnInterface() + { + ExpectErrors(@" fragment definedOnImplementorsButNotInterface on Pet { nickname } @@ -212,12 +212,12 @@ public void DefinedOnImplementorsButNotOnInterface() } } "); - } + } - [Fact] - public void MetaFieldSelectionOnUnion() - { - ExpectValid(@" + [Fact] + public void MetaFieldSelectionOnUnion() + { + ExpectValid(@" fragment directFieldSelectionOnUnion on CatOrDog { __typename } @@ -228,12 +228,12 @@ public void MetaFieldSelectionOnUnion() } } "); - } + } - [Fact] - public void DireftFieldSelectionOnUnion() - { - ExpectErrors(@" + [Fact] + public void DireftFieldSelectionOnUnion() + { + ExpectErrors(@" fragment directFieldSelectionOnUnion on CatOrDog { directField } @@ -244,12 +244,12 @@ public void DireftFieldSelectionOnUnion() } } "); - } + } - [Fact] - public void DefinedOnImplementorQueriedOnUnion() - { - ExpectErrors(@" + [Fact] + public void DefinedOnImplementorQueriedOnUnion() + { + ExpectErrors(@" fragment definedOnImplementorsQueriedOnUnion on CatOrDog { name } @@ -260,12 +260,12 @@ public void DefinedOnImplementorQueriedOnUnion() } } "); - } + } - [Fact] - public void FieldInInlineFragment() - { - ExpectValid(@" + [Fact] + public void FieldInInlineFragment() + { + ExpectValid(@" fragment objectFieldSelection on Pet { ... on Dog { name @@ -281,36 +281,35 @@ public void FieldInInlineFragment() } } "); - } - - [Fact] - public void WrongFieldsOnUnionTypeList() - { - // arrange - ISchema schema = SchemaBuilder - .New() - .AddDocumentFromString(@" + } + + [Fact] + public void WrongFieldsOnUnionTypeList() + { + // arrange + var schema = SchemaBuilder + .New() + .AddDocumentFromString(@" type Bar { baz: String } type Baz { baz: String } union Foo = Bar | Baz type Query { list: [Foo!] }") - .AddResolver("Query", "list", ctx => null!) - .AddResolver("Bar", "baz", ctx => null!) - .AddResolver("Baz", "baz", ctx => null!) - .Create(); + .AddResolver("Query", "list", ctx => null!) + .AddResolver("Bar", "baz", ctx => null!) + .AddResolver("Baz", "baz", ctx => null!) + .Create(); - ExpectErrors( - schema, - @" + ExpectErrors( + schema, + @" query { list { qux } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FragmentNameUniquenessRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FragmentNameUniquenessRuleTests.cs index a26e0cdb5e0..1280b865f6d 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FragmentNameUniquenessRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FragmentNameUniquenessRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FragmentNameUniquenessRuleTests + : DocumentValidatorVisitorTestBase { - public class FragmentNameUniquenessRuleTests - : DocumentValidatorVisitorTestBase + public FragmentNameUniquenessRuleTests() + : base(builder => builder.AddFragmentRules()) { - public FragmentNameUniquenessRuleTests() - : base(builder => builder.AddFragmentRules()) - { - } + } - [Fact] - public void UniqueFragments() - { - ExpectValid(@" + [Fact] + public void UniqueFragments() + { + ExpectValid(@" { dog { ...fragmentOne @@ -32,12 +32,12 @@ public void UniqueFragments() } } "); - } + } - [Fact] - public void DuplicateFragments() - { - ExpectErrors(@" + [Fact] + public void DuplicateFragments() + { + ExpectErrors(@" { dog { ...fragmentOne @@ -54,16 +54,16 @@ public void DuplicateFragments() } } ", - t => Assert.Equal( + t => Assert.Equal( "There are multiple fragments with the name `fragmentOne`.", t.Message)); - } + } - [Fact] - public void OneFragment() - { - // arrange - ExpectValid(@" + [Fact] + public void OneFragment() + { + // arrange + ExpectValid(@" { ...fragA } @@ -74,13 +74,13 @@ public void OneFragment() } } "); - } + } - [Fact] - public void ManyFragments() - { - // arrange - ExpectValid(@" + [Fact] + public void ManyFragments() + { + // arrange + ExpectValid(@" { ...fragA ...fragB @@ -103,13 +103,13 @@ public void ManyFragments() anyArg } "); - } + } - [Fact] - public void InlineFragmentsAreAlwaysUnique() - { - // arrange - ExpectValid(@" + [Fact] + public void InlineFragmentsAreAlwaysUnique() + { + // arrange + ExpectValid(@" { ...on Query { arguments { @@ -123,13 +123,13 @@ public void InlineFragmentsAreAlwaysUnique() } } "); - } + } - [Fact] - public void FragmentAndOperationNamedTheSame() - { - // arrange - ExpectValid(@" + [Fact] + public void FragmentAndOperationNamedTheSame() + { + // arrange + ExpectValid(@" query Foo { ...Foo } @@ -140,13 +140,13 @@ public void FragmentAndOperationNamedTheSame() } } "); - } + } - [Fact] - public void FragmentsNamedTheSame() - { - // arrange - ExpectErrors(@" + [Fact] + public void FragmentsNamedTheSame() + { + // arrange + ExpectErrors(@" { ...fragA } @@ -163,13 +163,13 @@ public void FragmentsNamedTheSame() } } "); - } + } - [Fact] - public void FragmentsNamedTheSameWithoutBeingReferenced() - { - // arrange - ExpectErrors(@" + [Fact] + public void FragmentsNamedTheSameWithoutBeingReferenced() + { + // arrange + ExpectErrors(@" fragment fragA on Query { arguments { idArgField @@ -182,6 +182,5 @@ public void FragmentsNamedTheSameWithoutBeingReferenced() } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadIsPossibleRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadIsPossibleRuleTests.cs index da0bfdc0f02..a5644f5284f 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadIsPossibleRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadIsPossibleRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FragmentSpreadIsPossibleRuleTests + : DocumentValidatorVisitorTestBase { - public class FragmentSpreadIsPossibleRuleTests - : DocumentValidatorVisitorTestBase + public FragmentSpreadIsPossibleRuleTests() + : base(builder => builder.AddFragmentRules()) + { + } + + [Fact] + public void FragmentDoesNotMatchType() { - public FragmentSpreadIsPossibleRuleTests() - : base(builder => builder.AddFragmentRules()) - { - } - - [Fact] - public void FragmentDoesNotMatchType() - { - ExpectErrors(@" + ExpectErrors(@" { dog { ...fragmentDoesNotMatchType @@ -26,14 +26,14 @@ public void FragmentDoesNotMatchType() } ", t => Assert.Equal(t.Message, - "The parent type does not match the type condition on " + - "the fragment.")); - } - - [Fact] - public void InterfaceTypeDoesMatch() - { - ExpectValid(@" + "The parent type does not match the type condition on " + + "the fragment.")); + } + + [Fact] + public void InterfaceTypeDoesMatch() + { + ExpectValid(@" { dog { ...interfaceTypeDoesMatch @@ -44,12 +44,12 @@ public void InterfaceTypeDoesMatch() name } "); - } + } - [Fact] - public void UnionTypeDoesMatch() - { - ExpectValid(@" + [Fact] + public void UnionTypeDoesMatch() + { + ExpectValid(@" { dog { ...unionTypeDoesMatch @@ -60,12 +60,12 @@ public void UnionTypeDoesMatch() __typename } "); - } + } - [Fact] - public void ObjectTypeDoesMatch() - { - ExpectValid(@" + [Fact] + public void ObjectTypeDoesMatch() + { + ExpectValid(@" { dog { ...objectTypeDoesMatch @@ -76,14 +76,14 @@ public void ObjectTypeDoesMatch() name } "); - } - - [Fact] - public void Star_Wars_With_Inline_Fragments() - { - ExpectValid( - StarWars, - @" + } + + [Fact] + public void Star_Wars_With_Inline_Fragments() + { + ExpectValid( + StarWars, + @" query ExecutionDepthShouldNotLeadToEmptyObects { hero(episode: NEW_HOPE) { __typename @@ -118,12 +118,12 @@ public void Star_Wars_With_Inline_Fragments() } } }"); - } + } - [Fact] - public void OfTheSameObject() - { - ExpectValid(@" + [Fact] + public void OfTheSameObject() + { + ExpectValid(@" { dog { ...objectWithinObject @@ -133,12 +133,12 @@ public void OfTheSameObject() fragment objectWithinObject on Dog { ...dogFragment } fragment dogFragment on Dog { barkVolume } "); - } + } - [Fact] - public void OfTheSameObjectWithInlineFragment() - { - ExpectValid(@" + [Fact] + public void OfTheSameObjectWithInlineFragment() + { + ExpectValid(@" { dog { ...objectWithinObjectAnon @@ -147,12 +147,12 @@ public void OfTheSameObjectWithInlineFragment() fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } } "); - } + } - [Fact] - public void ObjectIntoAnImplementedInterface() - { - ExpectValid(@" + [Fact] + public void ObjectIntoAnImplementedInterface() + { + ExpectValid(@" { human{ pets { @@ -164,12 +164,12 @@ public void ObjectIntoAnImplementedInterface() fragment objectWithinInterface on Pet { ...dogFragment } fragment dogFragment on Dog { barkVolume } "); - } + } - [Fact] - public void ObjectIntoContainingUnion() - { - ExpectValid(@" + [Fact] + public void ObjectIntoContainingUnion() + { + ExpectValid(@" { catOrDog { ...objectWithinUnion @@ -179,12 +179,12 @@ public void ObjectIntoContainingUnion() fragment objectWithinUnion on CatOrDog { ...dogFragment } fragment dogFragment on Dog { barkVolume } "); - } + } - [Fact] - public void UnionIntoContainedObject() - { - ExpectValid(@" + [Fact] + public void UnionIntoContainedObject() + { + ExpectValid(@" { dog { ...unionWithinObject @@ -194,12 +194,12 @@ public void UnionIntoContainedObject() fragment unionWithinObject on Dog { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } "); - } + } - [Fact] - public void UnionIntoOverlappingInterface() - { - ExpectValid(@" + [Fact] + public void UnionIntoOverlappingInterface() + { + ExpectValid(@" { human{ pets { @@ -211,12 +211,12 @@ public void UnionIntoOverlappingInterface() fragment unionWithinInterface on Pet { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } "); - } + } - [Fact] - public void UnionIntoOverlappingUnion() - { - ExpectValid(@" + [Fact] + public void UnionIntoOverlappingUnion() + { + ExpectValid(@" { dogOrHuman { ...unionWithinUnion @@ -226,12 +226,12 @@ public void UnionIntoOverlappingUnion() fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } "); - } + } - [Fact] - public void InterfaceIntoImplementedObject() - { - ExpectValid(@" + [Fact] + public void InterfaceIntoImplementedObject() + { + ExpectValid(@" { dog { ...interfaceWithinObject @@ -241,12 +241,12 @@ public void InterfaceIntoImplementedObject() fragment interfaceWithinObject on Dog { ...petFragment } fragment petFragment on Pet { name } "); - } + } - [Fact] - public void InterfaceIntoOverlappingInterface() - { - ExpectValid(@" + [Fact] + public void InterfaceIntoOverlappingInterface() + { + ExpectValid(@" { human{ pets { @@ -258,12 +258,12 @@ public void InterfaceIntoOverlappingInterface() fragment interfaceWithinInterface on Pet { ...beingFragment } fragment beingFragment on Being { name } "); - } + } - [Fact] - public void InterfaceIntoOverlappingInterfaceInInlineFragment() - { - ExpectValid(@" + [Fact] + public void InterfaceIntoOverlappingInterfaceInInlineFragment() + { + ExpectValid(@" { human{ pets { @@ -274,12 +274,12 @@ public void InterfaceIntoOverlappingInterfaceInInlineFragment() fragment interfaceWithinInterface on Pet { ... on Being { name } } "); - } + } - [Fact] - public void InterfaceIntoOverlappingUnion() - { - ExpectValid(@" + [Fact] + public void InterfaceIntoOverlappingUnion() + { + ExpectValid(@" { catOrDog { ...objectWithinUnion @@ -289,12 +289,12 @@ public void InterfaceIntoOverlappingUnion() fragment objectWithinUnion on CatOrDog { ...dogFragment } fragment dogFragment on Dog { barkVolume } "); - } + } - [Fact] - public void DifferentObjectIntoObject() - { - ExpectErrors(@" + [Fact] + public void DifferentObjectIntoObject() + { + ExpectErrors(@" { human{ pets { @@ -306,12 +306,12 @@ public void DifferentObjectIntoObject() fragment invalidObjectWithinObject on Cat { ...dogFragment } fragment dogFragment on Dog { barkVolume } "); - } + } - [Fact] - public void DifferentObjectIntoObjectInInlineFragment() - { - ExpectErrors(@" + [Fact] + public void DifferentObjectIntoObjectInInlineFragment() + { + ExpectErrors(@" { human{ pets { @@ -324,12 +324,12 @@ public void DifferentObjectIntoObjectInInlineFragment() ... on Dog { barkVolume } } "); - } + } - [Fact] - public void ObjectIntoNotImplementingInterface() - { - ExpectErrors(@" + [Fact] + public void ObjectIntoNotImplementingInterface() + { + ExpectErrors(@" { human{ pets { @@ -341,12 +341,12 @@ public void ObjectIntoNotImplementingInterface() fragment invalidObjectWithinInterface on Pet { ...humanFragment } fragment humanFragment on Human { pets { name } } "); - } + } - [Fact] - public void ObjectIntoNotContainingUnion() - { - ExpectErrors(@" + [Fact] + public void ObjectIntoNotContainingUnion() + { + ExpectErrors(@" { catOrDog { ...invalidObjectWithinUnion @@ -356,12 +356,12 @@ public void ObjectIntoNotContainingUnion() fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment } fragment humanFragment on Human { pets { name } } "); - } + } - [Fact] - public void UnionIntoNotContainedObject() - { - ExpectErrors(@" + [Fact] + public void UnionIntoNotContainedObject() + { + ExpectErrors(@" { human { ...invalidUnionWithinObject @@ -371,12 +371,12 @@ public void UnionIntoNotContainedObject() fragment invalidUnionWithinObject on Human { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } "); - } + } - [Fact] - public void UnionIntoNonOverlappingInterface() - { - ExpectErrors(@" + [Fact] + public void UnionIntoNonOverlappingInterface() + { + ExpectErrors(@" { human{ pets { @@ -388,12 +388,12 @@ public void UnionIntoNonOverlappingInterface() fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } "); - } + } - [Fact] - public void UnionIntoNonOverlappingUnion() - { - ExpectErrors(@" + [Fact] + public void UnionIntoNonOverlappingUnion() + { + ExpectErrors(@" { catOrDog { ...invalidUnionWithinUnion @@ -403,12 +403,12 @@ public void UnionIntoNonOverlappingUnion() fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } "); - } + } - [Fact] - public void InterfaceIntoNonImplementingObject() - { - ExpectErrors(@" + [Fact] + public void InterfaceIntoNonImplementingObject() + { + ExpectErrors(@" { catOrDog { ...invalidInterfaceWithinObject @@ -418,12 +418,12 @@ public void InterfaceIntoNonImplementingObject() fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment } fragment intelligentFragment on Intelligent { iq } "); - } + } - [Fact] - public void InterfaceIntoNonOverlappingInterface() - { - ExpectErrors(@" + [Fact] + public void InterfaceIntoNonOverlappingInterface() + { + ExpectErrors(@" { human{ pets { @@ -437,12 +437,12 @@ public void InterfaceIntoNonOverlappingInterface() } fragment intelligentFragment on Intelligent { iq } "); - } + } - [Fact] - public void InterfaceIntoNonOverlappingInterfaceInInlineFragment() - { - ExpectErrors(@" + [Fact] + public void InterfaceIntoNonOverlappingInterfaceInInlineFragment() + { + ExpectErrors(@" { human{ pets { @@ -455,12 +455,12 @@ public void InterfaceIntoNonOverlappingInterfaceInInlineFragment() ...on Intelligent { iq } } "); - } + } - [Fact] - public void InterfaceIntoNonOverlappingUnion() - { - ExpectErrors(@" + [Fact] + public void InterfaceIntoNonOverlappingUnion() + { + ExpectErrors(@" { catOrDog { ...invalidInterfaceWithinUnion @@ -470,6 +470,5 @@ public void InterfaceIntoNonOverlappingUnion() fragment invalidInterfaceWithinUnion on CatOrDog { ...petFragment } fragment petFragment on HumanOrAlien { name } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTargetDefinedRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTargetDefinedRuleTests.cs index 50a969ba29d..303b9d3dc19 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTargetDefinedRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTargetDefinedRuleTests.cs @@ -3,50 +3,50 @@ using Snapshooter.Xunit; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FragmentSpreadTargetDefinedRuleTests + : DocumentValidatorVisitorTestBase { - public class FragmentSpreadTargetDefinedRuleTests - : DocumentValidatorVisitorTestBase + public FragmentSpreadTargetDefinedRuleTests() + : base(builder => builder.AddFragmentRules()) { - public FragmentSpreadTargetDefinedRuleTests() - : base(builder => builder.AddFragmentRules()) - { - } + } - [Fact] - public void UndefinedFragment() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; + [Fact] + public void UndefinedFragment() + { + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; - DocumentNode query = Utf8GraphQLParser.Parse(@" + var query = Utf8GraphQLParser.Parse(@" { dog { ...undefinedFragment } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Collection(context.Errors, - t => Assert.Equal( - "The specified fragment `undefinedFragment` " + - "does not exist.", - t.Message)); - context.Errors.MatchSnapshot(); - } + // assert + Assert.Collection(context.Errors, + t => Assert.Equal( + "The specified fragment `undefinedFragment` " + + "does not exist.", + t.Message)); + context.Errors.MatchSnapshot(); + } - [Fact] - public void DefinedFragment() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void DefinedFragment() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" { dog { ...definedFragment @@ -58,13 +58,12 @@ public void DefinedFragment() barkVolume } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTypeExistenceRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTypeExistenceRuleTests.cs index 2272ed1cd98..57c50416298 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTypeExistenceRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadTypeExistenceRuleTests.cs @@ -3,22 +3,22 @@ using Snapshooter.Xunit; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FragmentSpreadTypeExistenceRuleTests + : DocumentValidatorVisitorTestBase { - public class FragmentSpreadTypeExistenceRuleTests - : DocumentValidatorVisitorTestBase + public FragmentSpreadTypeExistenceRuleTests() + : base(builder => builder.AddFragmentRules()) + { + } + + [Fact] + public void CorrectTypeOnFragment() { - public FragmentSpreadTypeExistenceRuleTests() - : base(builder => builder.AddFragmentRules()) - { - } - - [Fact] - public void CorrectTypeOnFragment() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" { dog { ...correctType @@ -29,21 +29,21 @@ public void CorrectTypeOnFragment() name } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void CorrectTypeOnInlineFragment() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void CorrectTypeOnInlineFragment() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" { dog { ...inlineFragment @@ -56,21 +56,21 @@ public void CorrectTypeOnInlineFragment() } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void CorrectTypeOnInlineFragment2() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void CorrectTypeOnInlineFragment2() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" { dog { ...inlineFragment2 @@ -83,23 +83,23 @@ public void CorrectTypeOnInlineFragment2() } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void NotOnExistingTypeOnFragment() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; + [Fact] + public void NotOnExistingTypeOnFragment() + { + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; - DocumentNode query = Utf8GraphQLParser.Parse(@" + var query = Utf8GraphQLParser.Parse(@" { dog { ...notOnExistingType @@ -110,30 +110,30 @@ public void NotOnExistingTypeOnFragment() name } "); - context.Prepare(query); + context.Prepare(query); + + // act + Rule.Validate(context, query); + + // assert + Assert.Collection(context.Errors, + t => + { + Assert.Equal( + "Unknown type `NotInSchema`.", + t.Message); + }); + context.Errors.MatchSnapshot(); + } - // act - Rule.Validate(context, query); + [Fact] + public void NotExistingTypeOnInlineFragment() + { + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; - // assert - Assert.Collection(context.Errors, - t => - { - Assert.Equal( - "Unknown type `NotInSchema`.", - t.Message); - }); - context.Errors.MatchSnapshot(); - } - - [Fact] - public void NotExistingTypeOnInlineFragment() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; - - DocumentNode query = Utf8GraphQLParser.Parse(@" + var query = Utf8GraphQLParser.Parse(@" { dog { ...inlineNotExistingType @@ -146,20 +146,19 @@ public void NotExistingTypeOnInlineFragment() } } "); - context.Prepare(query); - - // act - Rule.Validate(context, query); - - // assert - Assert.Collection(context.Errors, - t => - { - Assert.Equal( - "Unknown type `NotInSchema`.", - t.Message); - }); - context.Errors.MatchSnapshot(); - } + context.Prepare(query); + + // act + Rule.Validate(context, query); + + // assert + Assert.Collection(context.Errors, + t => + { + Assert.Equal( + "Unknown type `NotInSchema`.", + t.Message); + }); + context.Errors.MatchSnapshot(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadsMustNotFormCyclesRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadsMustNotFormCyclesRuleTests.cs index b09f30a005d..136fa079c5b 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadsMustNotFormCyclesRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FragmentSpreadsMustNotFormCyclesRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FragmentSpreadsMustNotFormCyclesRuleTests + : DocumentValidatorVisitorTestBase { - public class FragmentSpreadsMustNotFormCyclesRuleTests - : DocumentValidatorVisitorTestBase + public FragmentSpreadsMustNotFormCyclesRuleTests() + : base(builder => builder.AddFragmentRules()) + { + } + + [Fact] + public void FragmentCycle1() { - public FragmentSpreadsMustNotFormCyclesRuleTests() - : base(builder => builder.AddFragmentRules()) - { - } - - [Fact] - public void FragmentCycle1() - { - ExpectErrors(@" + ExpectErrors(@" { dog { ...nameFragment @@ -36,12 +36,12 @@ public void FragmentCycle1() "cycles including spreading itself. Otherwise an " + "operation could infinitely spread or infinitely " + "execute on cycles in the underlying data.")); - } + } - [Fact] - public void FragmentCycle2() - { - ExpectErrors(@" + [Fact] + public void FragmentCycle2() + { + ExpectErrors(@" { dog { ...nameFragment @@ -73,12 +73,12 @@ public void FragmentCycle2() "cycles including spreading itself. Otherwise an " + "operation could infinitely spread or infinitely " + "execute on cycles in the underlying data.")); - } + } - [Fact] - public void InfiniteRecursion() - { - ExpectErrors(@" + [Fact] + public void InfiniteRecursion() + { + ExpectErrors(@" { dog { ...dogFragment @@ -104,12 +104,12 @@ public void InfiniteRecursion() "cycles including spreading itself. Otherwise an " + "operation could infinitely spread or infinitely " + "execute on cycles in the underlying data.")); - } + } - [Fact] - public void QueryWithSideBySideFragSpreads() - { - ExpectValid(@" + [Fact] + public void QueryWithSideBySideFragSpreads() + { + ExpectValid(@" { dog { ...dogFragment @@ -126,12 +126,12 @@ public void QueryWithSideBySideFragSpreads() name } "); - } + } - [Fact] - public void SingleReferenceIsValid() - { - ExpectValid(@" + [Fact] + public void SingleReferenceIsValid() + { + ExpectValid(@" { dog { ...fragA @@ -141,12 +141,12 @@ public void SingleReferenceIsValid() fragment fragA on Dog { ...fragB } fragment fragB on Dog { name } "); - } + } - [Fact] - public void SpreadTwiceIsNotCircular() - { - ExpectValid(@" + [Fact] + public void SpreadTwiceIsNotCircular() + { + ExpectValid(@" { dog { ...fragA @@ -156,12 +156,12 @@ public void SpreadTwiceIsNotCircular() fragment fragA on Dog { ...fragB, ...fragB } fragment fragB on Dog { name } "); - } + } - [Fact] - public void SpreadTwiceIndirectlyIsNotCircular() - { - ExpectValid(@" + [Fact] + public void SpreadTwiceIndirectlyIsNotCircular() + { + ExpectValid(@" { dog { ...fragA @@ -172,12 +172,12 @@ public void SpreadTwiceIndirectlyIsNotCircular() fragment fragB on Dog { ...fragC } fragment fragC on Dog { name } "); - } + } - [Fact] - public void DoubleSpreadWithinAbstractTypes() - { - ExpectValid(@" + [Fact] + public void DoubleSpreadWithinAbstractTypes() + { + ExpectValid(@" { human { pets { @@ -196,12 +196,12 @@ public void DoubleSpreadWithinAbstractTypes() ... on Cat { ...nameFragment } } "); - } + } - [Fact] - public void SpeardingRecursivelyWithinFieldFails() - { - ExpectErrors(@" + [Fact] + public void SpeardingRecursivelyWithinFieldFails() + { + ExpectErrors(@" { human { ...fragA @@ -210,12 +210,12 @@ public void SpeardingRecursivelyWithinFieldFails() fragment fragA on Human { relatives { ...fragA } }, "); - } + } - [Fact] - public void NoSpreadingItselfDirectly() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfDirectly() + { + ExpectErrors(@" { dog { ...fragA @@ -224,12 +224,12 @@ public void NoSpreadingItselfDirectly() fragment fragA on Dog { ...fragA } "); - } + } - [Fact] - public void NoSpreadingItselfDirectlyWithinInlineFragment() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfDirectlyWithinInlineFragment() + { + ExpectErrors(@" { human { pets { @@ -244,12 +244,12 @@ public void NoSpreadingItselfDirectlyWithinInlineFragment() } } "); - } + } - [Fact] - public void NoSpreadingItselfIndirectly() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfIndirectly() + { + ExpectErrors(@" { dog { ...fragA @@ -259,12 +259,12 @@ public void NoSpreadingItselfIndirectly() fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragA } "); - } + } - [Fact] - public void NoSpreadingItselfIndirectlyWithinInlineFragment() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfIndirectlyWithinInlineFragment() + { + ExpectErrors(@" { human { pets { @@ -285,12 +285,12 @@ public void NoSpreadingItselfIndirectlyWithinInlineFragment() } } "); - } + } - [Fact] - public void NoSpreadingItselfDeeply() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfDeeply() + { + ExpectErrors(@" { dog { ...fragA @@ -306,12 +306,12 @@ public void NoSpreadingItselfDeeply() fragment fragO on Dog { ...fragP } fragment fragP on Dog { ...fragA, ...fragX } "); - } + } - [Fact] - public void NoSpreadingItselfDeeplyTwoPaths() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfDeeplyTwoPaths() + { + ExpectErrors(@" { dog { ...fragA @@ -322,12 +322,12 @@ public void NoSpreadingItselfDeeplyTwoPaths() fragment fragB on Dog { ...fragA } fragment fragC on Dog { ...fragA } "); - } + } - [Fact] - public void NoSpreadingItselfDeeplyTwoPathsAltTraverseOrder() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfDeeplyTwoPathsAltTraverseOrder() + { + ExpectErrors(@" { dog { ...fragA @@ -338,12 +338,12 @@ public void NoSpreadingItselfDeeplyTwoPathsAltTraverseOrder() fragment fragB on Dog { ...fragC } fragment fragC on Dog { ...fragA, ...fragB } "); - } + } - [Fact] - public void NoSpreadingItselfDeeplyAndImmediately() - { - ExpectErrors(@" + [Fact] + public void NoSpreadingItselfDeeplyAndImmediately() + { + ExpectErrors(@" { dog { ...fragA @@ -354,12 +354,12 @@ public void NoSpreadingItselfDeeplyAndImmediately() fragment fragB on Dog { ...fragB, ...fragC } fragment fragC on Dog { ...fragA, ...fragB } "); - } + } - [Fact] - public void DoesNotInfiniteLoopOnRecursiveFragment() - { - ExpectErrors(@" + [Fact] + public void DoesNotInfiniteLoopOnRecursiveFragment() + { + ExpectErrors(@" { dogOrHuman { ... fragA @@ -370,12 +370,12 @@ ... fragA name ... fragA }"); - } + } - [Fact] - public void DoesNotInfiniteLoopOnImmediatelyRecursiveFragment() - { - ExpectErrors(@" + [Fact] + public void DoesNotInfiniteLoopOnImmediatelyRecursiveFragment() + { + ExpectErrors(@" { dogOrHuman { ... fragA @@ -389,12 +389,12 @@ ... fragA ... fragA } }"); - } + } - [Fact] - public void DoesNotInfiniteLoopOnTransitivelyRecursiveFragment() - { - ExpectErrors(@" + [Fact] + public void DoesNotInfiniteLoopOnTransitivelyRecursiveFragment() + { + ExpectErrors(@" { dogOrHuman { ... fragA @@ -406,6 +406,5 @@ ... fragC fragment fragA on Human { name, ...fragB } fragment fragB on Human { name, ...fragC } fragment fragC on Human { name, ...fragA }"); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FragmentsMustBeUsedRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/FragmentsMustBeUsedRuleTests.cs index 0a69dd71ddf..fe953ce532d 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FragmentsMustBeUsedRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FragmentsMustBeUsedRuleTests.cs @@ -3,24 +3,24 @@ using Snapshooter.Xunit; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FragmentsMustBeUsedRuleTests + : DocumentValidatorVisitorTestBase { - public class FragmentsMustBeUsedRuleTests - : DocumentValidatorVisitorTestBase + public FragmentsMustBeUsedRuleTests() + : base(builder => builder.AddFragmentRules()) + { + } + + [Fact] + public void UnusedFragment() { - public FragmentsMustBeUsedRuleTests() - : base(builder => builder.AddFragmentRules()) - { - } - - [Fact] - public void UnusedFragment() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; - - DocumentNode query = Utf8GraphQLParser.Parse(@" + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; + + var query = Utf8GraphQLParser.Parse(@" fragment nameFragment on Dog { # unused name } @@ -31,25 +31,25 @@ public void UnusedFragment() } } "); - context.Prepare(query); - - // act - Rule.Validate(context, query); - - // assert - Assert.Collection(context.Errors, - t => Assert.Equal( - "The specified fragment `nameFragment` " + - "is not used within the current document.", t.Message)); - context.Errors.MatchSnapshot(); - } - - [Fact] - public void UsedFragment() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + context.Prepare(query); + + // act + Rule.Validate(context, query); + + // assert + Assert.Collection(context.Errors, + t => Assert.Equal( + "The specified fragment `nameFragment` " + + "is not used within the current document.", t.Message)); + context.Errors.MatchSnapshot(); + } + + [Fact] + public void UsedFragment() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" fragment nameFragment on Dog { name } @@ -61,21 +61,21 @@ ... nameFragment } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void UsedNestedFragment() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void UsedNestedFragment() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" fragment nameFragment on Dog { name ... nestedNameFragment @@ -92,13 +92,12 @@ ... nameFragment } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/FragmentsOnCompositeTypesRule.cs b/src/HotChocolate/Core/test/Validation.Tests/FragmentsOnCompositeTypesRule.cs index 67fbf8e055f..ca2319be79f 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/FragmentsOnCompositeTypesRule.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/FragmentsOnCompositeTypesRule.cs @@ -1,23 +1,23 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class FragmentsOnCompositeTypesRuleTests + : DocumentValidatorVisitorTestBase { - public class FragmentsOnCompositeTypesRuleTests - : DocumentValidatorVisitorTestBase + public FragmentsOnCompositeTypesRuleTests() + : base(builder => builder.AddFragmentRules()) + { + } + + /// + /// Validate: Fragments on composite types + /// + [Fact] + public void Fragment_On_Object_Is_Valid() { - public FragmentsOnCompositeTypesRuleTests() - : base(builder => builder.AddFragmentRules()) - { - } - - /// - /// Validate: Fragments on composite types - /// - [Fact] - public void Fragment_On_Object_Is_Valid() - { - ExpectValid(@" + ExpectValid(@" { dog { ... fragOnObject @@ -28,15 +28,15 @@ ... fragOnObject name } "); - } - - /// - /// Interface is valid fragment type - /// - [Fact] - public void Fragment_On_Interface_Is_Valid() - { - ExpectValid(@" + } + + /// + /// Interface is valid fragment type + /// + [Fact] + public void Fragment_On_Interface_Is_Valid() + { + ExpectValid(@" { dog { ... fragOnInterface @@ -47,15 +47,15 @@ ... fragOnInterface name } "); - } - - /// - /// Object is valid inline fragment type - /// - [Fact] - public void Object_Is_Valid_Inline_FragmentType() - { - ExpectValid(@" + } + + /// + /// Object is valid inline fragment type + /// + [Fact] + public void Object_Is_Valid_Inline_FragmentType() + { + ExpectValid(@" { dog { ... validFragment @@ -68,15 +68,15 @@ ... validFragment } } "); - } - - /// - /// interface is valid inline fragment type - /// - [Fact] - public void Interface_Is_Valid_Inline_FragmentType() - { - ExpectValid(@" + } + + /// + /// interface is valid inline fragment type + /// + [Fact] + public void Interface_Is_Valid_Inline_FragmentType() + { + ExpectValid(@" { dog { ... validFragment @@ -89,15 +89,15 @@ ... validFragment } } "); - } - - /// - /// inline fragment without type is valid - /// - [Fact] - public void InlineFragment_Without_Type_Is_Valid() - { - ExpectValid(@" + } + + /// + /// inline fragment without type is valid + /// + [Fact] + public void InlineFragment_Without_Type_Is_Valid() + { + ExpectValid(@" { dog { ... validFragment @@ -110,16 +110,16 @@ ... validFragment } } "); - } - - /// - /// union is valid fragment type - /// - [Fact] - public void Fragment_On_Union_Is_Valid() - { - // arrange - ExpectValid(@" + } + + /// + /// union is valid fragment type + /// + [Fact] + public void Fragment_On_Union_Is_Valid() + { + // arrange + ExpectValid(@" { dog { ... fragOnUnion @@ -132,12 +132,12 @@ ... fragOnUnion } } "); - } + } - [Fact] - public void Fragment_On_Scalar_Is_Invalid() - { - ExpectErrors(@" + [Fact] + public void Fragment_On_Scalar_Is_Invalid() + { + ExpectErrors(@" { dog { ... fragOnScalar @@ -151,12 +151,12 @@ ... fragOnScalar t => Assert.Equal(t.Message, "Fragments can only be declared on unions, interfaces, " + "and objects.")); - } + } - [Fact] - public void InlineFragment_On_Scalar_Is_Invalid() - { - ExpectErrors(@" + [Fact] + public void InlineFragment_On_Scalar_Is_Invalid() + { + ExpectErrors(@" { dog { ... inlineFragOnScalar @@ -172,6 +172,5 @@ ... inlineFragOnScalar t => Assert.Equal(t.Message, "Fragments can only be declared on unions, interfaces, " + "and objects.")); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldNamesRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldNamesRuleTests.cs index abfcc0f0126..bef7a0edbf5 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldNamesRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldNamesRuleTests.cs @@ -1,30 +1,30 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class InputObjectFieldNamesRuleTests + : DocumentValidatorVisitorTestBase { - public class InputObjectFieldNamesRuleTests - : DocumentValidatorVisitorTestBase + public InputObjectFieldNamesRuleTests() + : base(builder => builder.AddValueRules()) { - public InputObjectFieldNamesRuleTests() - : base(builder => builder.AddValueRules()) - { - } + } - [Fact] - public void AllInputObjectFieldsExist() - { - ExpectValid(@" + [Fact] + public void AllInputObjectFieldsExist() + { + ExpectValid(@" { findDog(complex: { name: ""Fido"" }) } "); - } + } - [Fact] - public void InvalidInputObjectFieldsExist() - { - ExpectErrors(@" + [Fact] + public void InvalidInputObjectFieldsExist() + { + ExpectErrors(@" { findDog(complex: { favoriteCookieFlavor: ""Bacon"" }) } @@ -33,13 +33,13 @@ public void InvalidInputObjectFieldsExist() "The specified input object field " + "`favoriteCookieFlavor` does not exist.", t.Message)); - } + } - [Fact] - public void InvalidNestedInputObjectFieldsExist() - { - // arrange - ExpectErrors(@" + [Fact] + public void InvalidNestedInputObjectFieldsExist() + { + // arrange + ExpectErrors(@" { findDog(complex: { child: { favoriteCookieFlavor: ""Bacon"" } }) } @@ -48,6 +48,5 @@ public void InvalidNestedInputObjectFieldsExist() "The specified input object field " + "`favoriteCookieFlavor` does not exist.", t.Message)); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldUniquenessRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldUniquenessRuleTests.cs index 0315d65121e..87305493b05 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldUniquenessRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/InputObjectFieldUniquenessRuleTests.cs @@ -1,55 +1,55 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class InputObjectFieldUniquenessRuleTests + : DocumentValidatorVisitorTestBase { - public class InputObjectFieldUniquenessRuleTests - : DocumentValidatorVisitorTestBase + public InputObjectFieldUniquenessRuleTests() + : base(builder => builder.AddValueRules()) { - public InputObjectFieldUniquenessRuleTests() - : base(builder => builder.AddValueRules()) - { - } + } - [Fact] - public void NoFieldAmbiguity() - { - ExpectValid(@" + [Fact] + public void NoFieldAmbiguity() + { + ExpectValid(@" { findDog(complex: { name: ""A"", owner: ""B"" }) } "); - } + } - [Fact] - public void NameFieldIsAmbiguous() - { - // arrange - ExpectErrors(@" + [Fact] + public void NameFieldIsAmbiguous() + { + // arrange + ExpectErrors(@" { findDog(complex: { name: ""A"", name: ""B"" }) } ", error => Assert.Equal("There can be only one input field named `name`.", error.Message)); - } + } - [Fact] - public void InputObjectWithField() - { - ExpectValid(@" + [Fact] + public void InputObjectWithField() + { + ExpectValid(@" { arguments { complexArgField(complexArg: {requiredField: true, f: true }) } } "); - } + } - [Fact] - public void SameInputObjectWithinTwoArgs() - { - ExpectValid(@" + [Fact] + public void SameInputObjectWithinTwoArgs() + { + ExpectValid(@" { arguments { complexArgField( @@ -58,12 +58,12 @@ public void SameInputObjectWithinTwoArgs() } } "); - } + } - [Fact] - public void MultipleInputObjectFields() - { - ExpectValid(@" + [Fact] + public void MultipleInputObjectFields() + { + ExpectValid(@" { arguments { complexArgField(complexArg: { @@ -74,12 +74,12 @@ public void MultipleInputObjectFields() } } "); - } + } - [Fact] - public void AllowsForNestedInputObjectsWithSimilarFields() - { - ExpectValid(@" + [Fact] + public void AllowsForNestedInputObjectsWithSimilarFields() + { + ExpectValid(@" { arguments { complexArgField(complexArg: { @@ -97,12 +97,12 @@ public void AllowsForNestedInputObjectsWithSimilarFields() } } "); - } + } - [Fact] - public void DuplicateInputObjectFields() - { - ExpectErrors(@" + [Fact] + public void DuplicateInputObjectFields() + { + ExpectErrors(@" { arguments { complexArgField(complexArg: { @@ -112,12 +112,12 @@ public void DuplicateInputObjectFields() } } "); - } + } - [Fact] - public void ManyDuplicateInputObjectFields() - { - ExpectErrors(@" + [Fact] + public void ManyDuplicateInputObjectFields() + { + ExpectErrors(@" { arguments { complexArgField(complexArg: { @@ -128,12 +128,12 @@ public void ManyDuplicateInputObjectFields() } } "); - } + } - [Fact] - public void NestedDuplicateInputObjectFields() - { - ExpectErrors(@" + [Fact] + public void NestedDuplicateInputObjectFields() + { + ExpectErrors(@" { arguments { complexArgField(complexArg: { @@ -145,6 +145,5 @@ public void NestedDuplicateInputObjectFields() } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/InputObjectRequiredFieldsRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/InputObjectRequiredFieldsRuleTests.cs index c301dc462b0..eab55e4c398 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/InputObjectRequiredFieldsRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/InputObjectRequiredFieldsRuleTests.cs @@ -1,40 +1,40 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class InputObjectRequiredFieldsRuleTests + : DocumentValidatorVisitorTestBase { - public class InputObjectRequiredFieldsRuleTests - : DocumentValidatorVisitorTestBase + public InputObjectRequiredFieldsRuleTests() + : base(builder => builder.AddValueRules()) { - public InputObjectRequiredFieldsRuleTests() - : base(builder => builder.AddValueRules()) - { - } + } - [Fact] - public void RequiredFieldsHaveValidValue() - { - ExpectValid(@" + [Fact] + public void RequiredFieldsHaveValidValue() + { + ExpectValid(@" { findDog2(complex: { name: ""Foo"" }) } "); - } + } - [Fact] - public void NestedRequiredFieldsHaveValidValue() - { - ExpectValid(@" + [Fact] + public void NestedRequiredFieldsHaveValidValue() + { + ExpectValid(@" { findDog2(complex: { name: ""Foo"" child: { name: ""123"" } }) } "); - } + } - [Fact] - public void RequiredFieldIsNull() - { - ExpectErrors(@" + [Fact] + public void RequiredFieldIsNull() + { + ExpectErrors(@" { findDog2(complex: { name: null }) } @@ -42,13 +42,13 @@ public void RequiredFieldIsNull() t => Assert.Equal( "`name` is a required field and cannot be null.", t.Message)); - } + } - [Fact] - public void RequiredFieldIsNotSet() - { - // arrange - ExpectErrors(@" + [Fact] + public void RequiredFieldIsNotSet() + { + // arrange + ExpectErrors(@" { findDog2(complex: { }) } @@ -56,13 +56,13 @@ public void RequiredFieldIsNotSet() t => Assert.Equal( "`name` is a required field and cannot be null.", t.Message)); - } + } - [Fact] - public void NestedRequiredFieldIsNotSet() - { - // arrange - ExpectErrors(@" + [Fact] + public void NestedRequiredFieldIsNotSet() + { + // arrange + ExpectErrors(@" { findDog2(complex: { name: ""foo"" child: { owner: ""bar"" } }) } @@ -70,12 +70,12 @@ public void NestedRequiredFieldIsNotSet() t => Assert.Equal( "`name` is a required field and cannot be null.", t.Message)); - } + } - [Fact] - public void BadNullToNonNullField() - { - ExpectErrors(@" + [Fact] + public void BadNullToNonNullField() + { + ExpectErrors(@" { arguments { complexArgField(complexArg: { @@ -85,6 +85,5 @@ public void BadNullToNonNullField() } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/IntrospectionRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/IntrospectionRuleTests.cs index a298f7b4daa..44c71d2686a 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/IntrospectionRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/IntrospectionRuleTests.cs @@ -5,120 +5,119 @@ using Xunit; using static HotChocolate.Validation.TestHelper; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class IntrospectionRuleTests { - public class IntrospectionRuleTests + [Fact] + public void IntrospectionNotAllowed_Schema_Field() { - [Fact] - public void IntrospectionNotAllowed_Schema_Field() - { - ExpectErrors( - CreateSchema(), - b => b.AddIntrospectionAllowedRule(), - @" + ExpectErrors( + CreateSchema(), + b => b.AddIntrospectionAllowedRule(), + @" { __schema }"); - } + } - [Fact] - public void IntrospectionNotAllowed_Schema_Field_Custom_MessageFactory() - { - ExpectErrors( - CreateSchema(), - b => b.AddIntrospectionAllowedRule(), - @" + [Fact] + public void IntrospectionNotAllowed_Schema_Field_Custom_MessageFactory() + { + ExpectErrors( + CreateSchema(), + b => b.AddIntrospectionAllowedRule(), + @" { __schema }", - new KeyValuePair[] - { - new(WellKnownContextData.IntrospectionMessage, new Func(() => "Bar")) - }); - } + new KeyValuePair[] + { + new(WellKnownContextData.IntrospectionMessage, new Func(() => "Bar")) + }); + } - [Fact] - public void IntrospectionNotAllowed_Schema_Field_Custom_Message() - { - ExpectErrors( - CreateSchema(), - b => b.AddIntrospectionAllowedRule(), - @" + [Fact] + public void IntrospectionNotAllowed_Schema_Field_Custom_Message() + { + ExpectErrors( + CreateSchema(), + b => b.AddIntrospectionAllowedRule(), + @" { __schema }", - new KeyValuePair[] - { - new(WellKnownContextData.IntrospectionMessage, "Baz") - }); - } + new KeyValuePair[] + { + new(WellKnownContextData.IntrospectionMessage, "Baz") + }); + } - [Fact] - public void IntrospectionNotAllowed_Type_Field() - { - ExpectErrors( - CreateSchema(), - b => b.AddIntrospectionAllowedRule(), - @" + [Fact] + public void IntrospectionNotAllowed_Type_Field() + { + ExpectErrors( + CreateSchema(), + b => b.AddIntrospectionAllowedRule(), + @" { __type(name: ""foo"") }"); - } + } - [Fact] - public void IntrospectionAllowed_Typename_Field() - { - ExpectValid( - CreateSchema(), - b => b.AddIntrospectionAllowedRule(), - @" + [Fact] + public void IntrospectionAllowed_Typename_Field() + { + ExpectValid( + CreateSchema(), + b => b.AddIntrospectionAllowedRule(), + @" { __typename }"); - } + } - [Fact] - public void IntrospectionAllowed_Schema_Field() - { - ExpectValid( - CreateSchema(), - b => b.AddIntrospectionAllowedRule(), - @" + [Fact] + public void IntrospectionAllowed_Schema_Field() + { + ExpectValid( + CreateSchema(), + b => b.AddIntrospectionAllowedRule(), + @" { __schema { name } }", - new KeyValuePair[] - { - new(WellKnownContextData.IntrospectionAllowed, null) - }); - } + new KeyValuePair[] + { + new(WellKnownContextData.IntrospectionAllowed, null) + }); + } - [Fact] - public void IntrospectionAllowed_Type_Field() - { - ExpectValid( - CreateSchema(), - b => b.AddIntrospectionAllowedRule(), - @" + [Fact] + public void IntrospectionAllowed_Type_Field() + { + ExpectValid( + CreateSchema(), + b => b.AddIntrospectionAllowedRule(), + @" { __type(name: ""foo"") }", - new KeyValuePair[] - { - new(WellKnownContextData.IntrospectionAllowed, null) - }); - } + new KeyValuePair[] + { + new(WellKnownContextData.IntrospectionAllowed, null) + }); + } - private ISchema CreateSchema() - { - return SchemaBuilder.New() - .AddDocumentFromString(FileResource.Open("CostSchema.graphql")) - .AddCostDirectiveType() - .Use(_ => _ => default) - .Create(); - } + private ISchema CreateSchema() + { + return SchemaBuilder.New() + .AddDocumentFromString(FileResource.Open("CostSchema.graphql")) + .AddCostDirectiveType() + .Use(_ => _ => default) + .Create(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/KnownFragmentNamesRule.cs b/src/HotChocolate/Core/test/Validation.Tests/KnownFragmentNamesRule.cs index af549675e2e..540a8298a37 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/KnownFragmentNamesRule.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/KnownFragmentNamesRule.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class KnownFragmentNamesTests + : DocumentValidatorVisitorTestBase { - public class KnownFragmentNamesTests - : DocumentValidatorVisitorTestBase + public KnownFragmentNamesTests() + : base(services => services.AddFragmentRules()) { - public KnownFragmentNamesTests() - : base(services => services.AddFragmentRules()) - { - } + } - [Fact] - public void UniqueFragments() - { - ExpectValid(@" + [Fact] + public void UniqueFragments() + { + ExpectValid(@" { human(id: 4) { ...HumanFields1 @@ -37,13 +37,13 @@ public void UniqueFragments() name } "); - } + } - [Fact] - public void DuplicateFragments() - { - // arrange - ExpectErrors(@" + [Fact] + public void DuplicateFragments() + { + // arrange + ExpectErrors(@" { human(id: 4) { ...UnknownFragment1 @@ -57,6 +57,5 @@ public void DuplicateFragments() ...UnknownFragment3 } " ); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/LeafFieldSelectionsRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/LeafFieldSelectionsRuleTests.cs index 3900c9d8138..fe09e1c9c53 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/LeafFieldSelectionsRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/LeafFieldSelectionsRuleTests.cs @@ -1,42 +1,42 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class LeafFieldSelectionsRuleTests + : DocumentValidatorVisitorTestBase { - public class LeafFieldSelectionsRuleTests - : DocumentValidatorVisitorTestBase + public LeafFieldSelectionsRuleTests() + : base(builder => builder.AddFieldRules()) { - public LeafFieldSelectionsRuleTests() - : base(builder => builder.AddFieldRules()) - { - } + } - [Fact] - public void ScalarSelection() - { - ExpectValid(@" + [Fact] + public void ScalarSelection() + { + ExpectValid(@" { dog { barkVolume } } "); - } + } - [Fact] - public void StringList() - { - ExpectValid(@" + [Fact] + public void StringList() + { + ExpectValid(@" { stringList } "); - } + } - [Fact] - public void ScalarSelectionsNotAllowedOnInt() - { - ExpectErrors(@" + [Fact] + public void ScalarSelectionsNotAllowedOnInt() + { + ExpectErrors(@" { dog { barkVolume { @@ -50,12 +50,12 @@ public void ScalarSelectionsNotAllowedOnInt() "or enums are never allowed, because they are the leaf " + "nodes of any GraphQL query.", t.Message)); - } + } - [Fact] - public void DirectQueryOnObjectWithoutSubFields() - { - ExpectErrors(@" + [Fact] + public void DirectQueryOnObjectWithoutSubFields() + { + ExpectErrors(@" query directQueryOnObjectWithoutSubFields { human } @@ -65,12 +65,12 @@ public void DirectQueryOnObjectWithoutSubFields() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void DirectQueryOnObjectWithoutSubFieldsEmptySelection() - { - ExpectErrors(@" + [Fact] + public void DirectQueryOnObjectWithoutSubFieldsEmptySelection() + { + ExpectErrors(@" query directQueryOnObjectWithoutSubFields { human {} } @@ -80,12 +80,12 @@ public void DirectQueryOnObjectWithoutSubFieldsEmptySelection() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void DirectQueryOnInterfaceWithoutSubFields() - { - ExpectErrors(@" + [Fact] + public void DirectQueryOnInterfaceWithoutSubFields() + { + ExpectErrors(@" query directQueryOnInterfaceWithoutSubFields { pet } @@ -95,12 +95,12 @@ public void DirectQueryOnInterfaceWithoutSubFields() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void DirectQueryOnInterfaceWithoutSubFieldsEmptySelection() - { - ExpectErrors(@" + [Fact] + public void DirectQueryOnInterfaceWithoutSubFieldsEmptySelection() + { + ExpectErrors(@" query directQueryOnInterfaceWithoutSubFields { pet {} } @@ -110,12 +110,12 @@ public void DirectQueryOnInterfaceWithoutSubFieldsEmptySelection() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void DirectQueryOnUnionWithoutSubFields() - { - ExpectErrors(@" + [Fact] + public void DirectQueryOnUnionWithoutSubFields() + { + ExpectErrors(@" query directQueryOnUnionWithoutSubFields { catOrDog } @@ -125,12 +125,12 @@ public void DirectQueryOnUnionWithoutSubFields() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void DirectQueryOnUnionWithoutSubFieldsEmptySelection() - { - ExpectErrors(@" + [Fact] + public void DirectQueryOnUnionWithoutSubFieldsEmptySelection() + { + ExpectErrors(@" query directQueryOnUnionWithoutSubFields { catOrDog {} } @@ -140,12 +140,12 @@ public void DirectQueryOnUnionWithoutSubFieldsEmptySelection() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void InterfaceTypeMissingSelection() - { - ExpectErrors(@" + [Fact] + public void InterfaceTypeMissingSelection() + { + ExpectErrors(@" { human { pets } } @@ -155,12 +155,12 @@ public void InterfaceTypeMissingSelection() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void InterfaceTypeMissingSelectionEmptySelection() - { - ExpectErrors(@" + [Fact] + public void InterfaceTypeMissingSelectionEmptySelection() + { + ExpectErrors(@" { human { pets {} } } @@ -170,84 +170,84 @@ public void InterfaceTypeMissingSelectionEmptySelection() "field. Leaf selections on objects, interfaces, and " + "unions without subfields are disallowed.", t.Message)); - } + } - [Fact] - public void EmptyQueryType() - { - ExpectErrors(@" + [Fact] + public void EmptyQueryType() + { + ExpectErrors(@" { } ", t => Assert.Equal( "Operation `Unnamed` has a empty selection set. Root types without " + "subfields are disallowed.", t.Message)); - } + } - [Fact] - public void EmptyNamedQueryType() - { - ExpectErrors(@" + [Fact] + public void EmptyNamedQueryType() + { + ExpectErrors(@" query Foo { } ", t => Assert.Equal( "Operation `Foo` has a empty selection set. Root types without " + "subfields are disallowed.", t.Message)); - } + } - [Fact] - public void EmptyMutationType() - { - ExpectErrors(@" + [Fact] + public void EmptyMutationType() + { + ExpectErrors(@" mutation { } ", t => Assert.Equal( "Operation `Unnamed` has a empty selection set. Root types without " + "subfields are disallowed.", t.Message)); - } + } - [Fact] - public void EmptyNamedMutationType() - { - ExpectErrors(@" + [Fact] + public void EmptyNamedMutationType() + { + ExpectErrors(@" mutation Foo { } ", t => Assert.Equal( "Operation `Foo` has a empty selection set. Root types without " + "subfields are disallowed.", t.Message)); - } + } - [Fact] - public void EmptySubscriptionType() - { - ExpectErrors(@" + [Fact] + public void EmptySubscriptionType() + { + ExpectErrors(@" subscription { } ", t => Assert.Equal( "Operation `Unnamed` has a empty selection set. Root types without " + "subfields are disallowed.", t.Message)); - } + } - [Fact] - public void EmptyNamedSubscriptionType() - { - ExpectErrors(@" + [Fact] + public void EmptyNamedSubscriptionType() + { + ExpectErrors(@" subscription Foo { } ", t => Assert.Equal( "Operation `Foo` has a empty selection set. Root types without " + "subfields are disallowed.", t.Message)); - } + } - [Fact] - public void ScalarSelectionNotAllowedOnBoolean() - { - ExpectErrors(@" + [Fact] + public void ScalarSelectionNotAllowedOnBoolean() + { + ExpectErrors(@" { dog { barks { @@ -261,12 +261,12 @@ public void ScalarSelectionNotAllowedOnBoolean() "or enums are never allowed, because they are the leaf " + "nodes of any GraphQL query.", t.Message)); - } + } - [Fact] - public void ScalarSelectionNotAllowedOnEnum() - { - ExpectErrors(@" + [Fact] + public void ScalarSelectionNotAllowedOnEnum() + { + ExpectErrors(@" { catOrDog { ... on Cat { @@ -282,12 +282,12 @@ public void ScalarSelectionNotAllowedOnEnum() "or enums are never allowed, because they are the leaf " + "nodes of any GraphQL query.", t.Message)); - } + } - [Fact] - public void ScalarSelectionNotAllowedWithArgs() - { - ExpectErrors(@" + [Fact] + public void ScalarSelectionNotAllowedWithArgs() + { + ExpectErrors(@" { dog { doesKnowCommand(dogCommand: SIT) { sinceWhen } @@ -299,12 +299,12 @@ public void ScalarSelectionNotAllowedWithArgs() "or enums are never allowed, because they are the leaf " + "nodes of any GraphQL query.", t.Message)); - } + } - [Fact] - public void ScalarSelectionNotAllowedWithDirectives() - { - ExpectErrors(@" + [Fact] + public void ScalarSelectionNotAllowedWithDirectives() + { + ExpectErrors(@" { dog { name @include(if: true) { isAlsoHumanName } @@ -316,12 +316,12 @@ public void ScalarSelectionNotAllowedWithDirectives() "or enums are never allowed, because they are the leaf " + "nodes of any GraphQL query.", t.Message)); - } + } - [Fact] - public void ScalarSelectionNotAllowedWithDirectivesAndArgs() - { - ExpectErrors(@" + [Fact] + public void ScalarSelectionNotAllowedWithDirectivesAndArgs() + { + ExpectErrors(@" { dog { doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen } @@ -333,6 +333,5 @@ public void ScalarSelectionNotAllowedWithDirectivesAndArgs() "or enums are never allowed, because they are the leaf " + "nodes of any GraphQL query.", t.Message)); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/LoneAnonymousOperationRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/LoneAnonymousOperationRuleTests.cs index 9eb1b9cbd64..7e40784ea20 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/LoneAnonymousOperationRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/LoneAnonymousOperationRuleTests.cs @@ -1,32 +1,32 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class LoneAnonymousOperationRuleTests + : DocumentValidatorVisitorTestBase { - public class LoneAnonymousOperationRuleTests - : DocumentValidatorVisitorTestBase + public LoneAnonymousOperationRuleTests() + : base(builder => builder.AddOperationRules()) { - public LoneAnonymousOperationRuleTests() - : base(builder => builder.AddOperationRules()) - { - } + } - [Fact] - public void QueryContainsOneAnonymousOperation() - { - ExpectValid(@" + [Fact] + public void QueryContainsOneAnonymousOperation() + { + ExpectValid(@" { dog { name } } "); - } + } - [Fact] - public void QueryWithOneAnonymousAndOneNamedOperation() - { - ExpectErrors(@" + [Fact] + public void QueryWithOneAnonymousAndOneNamedOperation() + { + ExpectErrors(@" { dog { name @@ -45,12 +45,12 @@ public void QueryWithOneAnonymousAndOneNamedOperation() "GraphQL allows a short‐hand form for defining query " + "operations when only that one operation exists in the " + "document.", t.Message)); - } + } - [Fact] - public void QueryWithTwoAnonymousOperations() - { - ExpectErrors(@" + [Fact] + public void QueryWithTwoAnonymousOperations() + { + ExpectErrors(@" { dog { name @@ -67,12 +67,12 @@ public void QueryWithTwoAnonymousOperations() "GraphQL allows a short‐hand form for defining query " + "operations when only that one operation exists in the " + "document.", t.Message)); - } + } - [Fact] - public void MultipleNamedOperations() - { - ExpectValid(@" + [Fact] + public void MultipleNamedOperations() + { + ExpectValid(@" query Foo { dog { name @@ -84,12 +84,12 @@ public void MultipleNamedOperations() } } "); - } + } - [Fact] - public void AnonymousOperationWithFragment() - { - ExpectValid(@" + [Fact] + public void AnonymousOperationWithFragment() + { + ExpectValid(@" { ...Foo } @@ -99,12 +99,12 @@ public void AnonymousOperationWithFragment() } } "); - } + } - [Fact] - public void AnonymousOperationWithAMutation() - { - ExpectErrors(@" + [Fact] + public void AnonymousOperationWithAMutation() + { + ExpectErrors(@" { dog { name @@ -114,12 +114,12 @@ public void AnonymousOperationWithAMutation() fieldB } "); - } + } - [Fact] - public void AnonymousOperationWithASubscription() - { - ExpectErrors(@" + [Fact] + public void AnonymousOperationWithASubscription() + { + ExpectErrors(@" { dog { name @@ -129,6 +129,5 @@ public void AnonymousOperationWithASubscription() newMessage } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTests.cs index 1e18b877022..f154e00b664 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTests.cs @@ -1,19 +1,19 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class MaxDepthRuleTests : DocumentValidatorVisitorTestBase { - public class MaxDepthRuleTests : DocumentValidatorVisitorTestBase + public MaxDepthRuleTests() + : base(b => b.AddMaxExecutionDepthRule(3, skipIntrospectionFields: false)) { - public MaxDepthRuleTests() - : base(b => b.AddMaxExecutionDepthRule(3, skipIntrospectionFields: false)) - { - } + } - [Fact] - public void MaxDepth3_QueryWith4Levels_MaxDepthReached() - { - ExpectErrors(@" + [Fact] + public void MaxDepth3_QueryWith4Levels_MaxDepthReached() + { + ExpectErrors(@" query { level1_1 { level2_1 { @@ -33,12 +33,12 @@ public void MaxDepth3_QueryWith4Levels_MaxDepthReached() } } "); - } + } - [Fact] - public void MaxDepth3_QueryWith4LevelsViaFragments_MaxDepthReached() - { - ExpectErrors(@" + [Fact] + public void MaxDepth3_QueryWith4LevelsViaFragments_MaxDepthReached() + { + ExpectErrors(@" query { level1_1 { ... level2 @@ -64,12 +64,12 @@ ... level4 level4 } "); - } + } - [Fact] - public void MaxDepth3_QueryWith4LevelsWithInlineFragment_MaxDepthReached() - { - ExpectErrors(@" + [Fact] + public void MaxDepth3_QueryWith4LevelsWithInlineFragment_MaxDepthReached() + { + ExpectErrors(@" query { level1_1 { ... on Level2 { @@ -85,12 +85,12 @@ public void MaxDepth3_QueryWith4LevelsWithInlineFragment_MaxDepthReached() } } "); - } + } - [Fact] - public void MaxDepth3_IntrospectionQuery_Exceeds_Allowed_Depth_Error() - { - ExpectErrors(@" + [Fact] + public void MaxDepth3_IntrospectionQuery_Exceeds_Allowed_Depth_Error() + { + ExpectErrors(@" query { __schema { types { @@ -115,12 +115,12 @@ public void MaxDepth3_IntrospectionQuery_Exceeds_Allowed_Depth_Error() } } }"); - } + } - [Fact] - public void MaxDepth3_QueryWith3Levels_Valid() - { - ExpectValid(@" + [Fact] + public void MaxDepth3_QueryWith3Levels_Valid() + { + ExpectValid(@" query { level1_1 { level2_1 { @@ -138,12 +138,12 @@ public void MaxDepth3_QueryWith3Levels_Valid() } } "); - } + } - [Fact] - public void MaxDepth3_QueryWith3LevelsViaFragments_Valid() - { - ExpectValid(@" + [Fact] + public void MaxDepth3_QueryWith3LevelsViaFragments_Valid() + { + ExpectValid(@" query { level1_1 { ... level2 @@ -162,13 +162,13 @@ ... level3 level3_1 } "); - } + } - [Fact] - public void MaxDepth3_QueryWith3LevelsWithInlineFragment_Valid() - { - // arrange - ExpectValid(@" + [Fact] + public void MaxDepth3_QueryWith3LevelsWithInlineFragment_Valid() + { + // arrange + ExpectValid(@" query { level1_1 { ... on Level2 { @@ -181,6 +181,5 @@ public void MaxDepth3_QueryWith3LevelsWithInlineFragment_Valid() } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTestsSkipIntrospection.cs b/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTestsSkipIntrospection.cs index 584db46415b..64c1609a6fb 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTestsSkipIntrospection.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/MaxDepthRuleTestsSkipIntrospection.cs @@ -1,19 +1,19 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class MaxDepthRuleTestsSkipIntrospection : DocumentValidatorVisitorTestBase { - public class MaxDepthRuleTestsSkipIntrospection : DocumentValidatorVisitorTestBase + public MaxDepthRuleTestsSkipIntrospection() + : base(b => b.AddMaxExecutionDepthRule(3, skipIntrospectionFields: true)) { - public MaxDepthRuleTestsSkipIntrospection() - : base(b => b.AddMaxExecutionDepthRule(3, skipIntrospectionFields: true)) - { - } + } - [Fact] - public void MaxDepth3_QueryWith4Levels_MaxDepthReached() - { - ExpectErrors(@" + [Fact] + public void MaxDepth3_QueryWith4Levels_MaxDepthReached() + { + ExpectErrors(@" query { level1_1 { level2_1 { @@ -33,12 +33,12 @@ public void MaxDepth3_QueryWith4Levels_MaxDepthReached() } } "); - } + } - [Fact] - public void MaxDepth3_QueryWith4LevelsViaFragments_MaxDepthReached() - { - ExpectErrors(@" + [Fact] + public void MaxDepth3_QueryWith4LevelsViaFragments_MaxDepthReached() + { + ExpectErrors(@" query { level1_1 { ... level2 @@ -64,12 +64,12 @@ ... level4 level4 } "); - } + } - [Fact] - public void MaxDepth3_QueryWith4LevelsWithInlineFragment_MaxDepthReached() - { - ExpectErrors(@" + [Fact] + public void MaxDepth3_QueryWith4LevelsWithInlineFragment_MaxDepthReached() + { + ExpectErrors(@" query { level1_1 { ... on Level2 { @@ -85,12 +85,12 @@ public void MaxDepth3_QueryWith4LevelsWithInlineFragment_MaxDepthReached() } } "); - } + } - [Fact] - public void MaxDepth3_IntrospectionQuery_Exceeds_Allowed_Depth_Valid() - { - ExpectValid(@" + [Fact] + public void MaxDepth3_IntrospectionQuery_Exceeds_Allowed_Depth_Valid() + { + ExpectValid(@" query { __schema { types { @@ -115,12 +115,12 @@ public void MaxDepth3_IntrospectionQuery_Exceeds_Allowed_Depth_Valid() } } }"); - } + } - [Fact] - public void MaxDepth3_QueryWith3Levels_Valid() - { - ExpectValid(@" + [Fact] + public void MaxDepth3_QueryWith3Levels_Valid() + { + ExpectValid(@" query { level1_1 { level2_1 { @@ -138,12 +138,12 @@ public void MaxDepth3_QueryWith3Levels_Valid() } } "); - } + } - [Fact] - public void MaxDepth3_QueryWith3LevelsViaFragments_Valid() - { - ExpectValid(@" + [Fact] + public void MaxDepth3_QueryWith3LevelsViaFragments_Valid() + { + ExpectValid(@" query { level1_1 { ... level2 @@ -162,13 +162,13 @@ ... level3 level3_1 } "); - } + } - [Fact] - public void MaxDepth3_QueryWith3LevelsWithInlineFragment_Valid() - { - // arrange - ExpectValid(@" + [Fact] + public void MaxDepth3_QueryWith3LevelsWithInlineFragment_Valid() + { + // arrange + ExpectValid(@" query { level1_1 { ... on Level2 { @@ -181,6 +181,5 @@ public void MaxDepth3_QueryWith3LevelsWithInlineFragment_Valid() } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/Alien.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/Alien.cs index 056024be847..fcd9bcbda51 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/Alien.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/Alien.cs @@ -1,9 +1,8 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class Alien + : ISentient { - public class Alien - : ISentient - { - public string Name { get; set; } - public string HomePlanet { get; set; } - } -} + public string Name { get; set; } + public string HomePlanet { get; set; } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/Cat.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/Cat.cs index 4b06526b887..e6795a774c6 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/Cat.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/Cat.cs @@ -1,17 +1,16 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class Cat + : IPet { - public class Cat - : IPet - { - public string Name { get; set; } + public string Name { get; set; } - public string Nickname { get; set; } + public string Nickname { get; set; } - public int? MeowVolume { get; set; } + public int? MeowVolume { get; set; } - public bool DoesKnowCommand(CatCommand catCommand) - { - return true; - } + public bool DoesKnowCommand(CatCommand catCommand) + { + return true; } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/CatCommand.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/CatCommand.cs index 61c86b603dd..dc786b160bb 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/CatCommand.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/CatCommand.cs @@ -1,9 +1,6 @@ -namespace HotChocolate.Validation -{ - public enum CatCommand - { - JUMP - } - +namespace HotChocolate.Validation; -} +public enum CatCommand +{ + JUMP +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput.cs index 965b93af96c..e71624e85a3 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput.cs @@ -1,11 +1,10 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class ComplexInput { - public class ComplexInput - { - public string Name { get; set; } + public string Name { get; set; } - public string Owner { get; set; } + public string Owner { get; set; } - public ComplexInput Child { get; set; } - } -} + public ComplexInput Child { get; set; } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput2.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput2.cs index 5f63e52e334..4a318baedc5 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput2.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/ComplexInput2.cs @@ -1,11 +1,10 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class ComplexInput2 { - public class ComplexInput2 - { - public string Name { get; set; } + public string Name { get; set; } - public string Owner { get; set; } + public string Owner { get; set; } - public ComplexInput2 Child { get; set; } - } -} + public ComplexInput2 Child { get; set; } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/Dog.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/Dog.cs index 8109e845e94..de11eebdce6 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/Dog.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/Dog.cs @@ -1,29 +1,28 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class Dog + : IPet { - public class Dog - : IPet - { - public string Name { get; set; } + public string Name { get; set; } - public string Nickname { get; set; } + public string Nickname { get; set; } - public int? BarkVolume { get; set; } + public int? BarkVolume { get; set; } - public bool Barks { get; set; } + public bool Barks { get; set; } - public bool DoesKnowCommand(DogCommand dogCommand) - { - return true; - } + public bool DoesKnowCommand(DogCommand dogCommand) + { + return true; + } - public bool IsHouseTrained(bool? atOtherHomes) - { - return true; - } + public bool IsHouseTrained(bool? atOtherHomes) + { + return true; + } - public Human GetOwner() - { - return null; - } + public Human GetOwner() + { + return null; } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/DogCommand.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/DogCommand.cs index 91927ef947f..234fcac3c52 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/DogCommand.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/DogCommand.cs @@ -1,11 +1,8 @@ -namespace HotChocolate.Validation -{ - public enum DogCommand - { - Sit, - Down, - Heel - } - +namespace HotChocolate.Validation; -} +public enum DogCommand +{ + Sit, + Down, + Heel +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/Human.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/Human.cs index 8d55a94270e..d42395a7c67 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/Human.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/Human.cs @@ -1,9 +1,8 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class Human : ISentient { - public class Human : ISentient - { - public string Name { get; set; } + public string Name { get; set; } - public string Address { get; set; } - } -} + public string Address { get; set; } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/IPet.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/IPet.cs index de05a57f2c4..5d8e6e8d296 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/IPet.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/IPet.cs @@ -1,7 +1,6 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public interface IPet { - public interface IPet - { - string Name { get; } - } -} + string Name { get; } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/ISentient.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/ISentient.cs index 9851ad7b4db..bea5df750d4 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/ISentient.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/ISentient.cs @@ -1,9 +1,6 @@ -namespace HotChocolate.Validation -{ - public interface ISentient - { - string Name { get; } - } - +namespace HotChocolate.Validation; -} +public interface ISentient +{ + string Name { get; } +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Models/Query.cs b/src/HotChocolate/Core/test/Validation.Tests/Models/Query.cs index 1033ea04562..7a7166d2f79 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Models/Query.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Models/Query.cs @@ -1,78 +1,77 @@ -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class Query { - public class Query - { - public string A { get; set; } + public string A { get; set; } - public string B { get; set; } + public string B { get; set; } - public string C { get; set; } + public string C { get; set; } - public string D { get; set; } - - public string Y { get; set; } - - public Query F1 { get; set; } - - public Query F2 { get; set; } - - public Query F3 { get; set; } - - public Query GetField() => null; - - public Dog GetDog() - { - return null; - } - - public Dog FindDog(ComplexInput complex) - { - return null; - } - - public Dog FindDog2(ComplexInput2 complex) - { - return null; - } - - public bool BooleanList(bool[] booleanListArg) - { - return true; - } - - public Human GetHuman() - { - return null; - } - - public Human GetPet() - { - return null; - } - - public object GetCatOrDog() - { - return null; - } - - public object GetDogOrHuman() - { - return null; - } - - public string[] GetStringList() - { - return null; - } - - public string GetFieldWithArg( - string arg, - string arg1, - string arg2, - string arg3, - string arg4) - { - return null; - } + public string D { get; set; } + + public string Y { get; set; } + + public Query F1 { get; set; } + + public Query F2 { get; set; } + + public Query F3 { get; set; } + + public Query GetField() => null; + + public Dog GetDog() + { + return null; + } + + public Dog FindDog(ComplexInput complex) + { + return null; + } + + public Dog FindDog2(ComplexInput2 complex) + { + return null; + } + + public bool BooleanList(bool[] booleanListArg) + { + return true; + } + + public Human GetHuman() + { + return null; + } + + public Human GetPet() + { + return null; + } + + public object GetCatOrDog() + { + return null; + } + + public object GetDogOrHuman() + { + return null; + } + + public string[] GetStringList() + { + return null; + } + + public string GetFieldWithArg( + string arg, + string arg1, + string arg2, + string arg3, + string arg4) + { + return null; } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/NoUndefinedVariablesRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/NoUndefinedVariablesRuleTests.cs index 22cef398166..56de04ee041 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/NoUndefinedVariablesRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/NoUndefinedVariablesRuleTests.cs @@ -1,30 +1,30 @@ using Xunit; using Microsoft.Extensions.DependencyInjection; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class NoUndefinedVariablesRuleTests + : DocumentValidatorVisitorTestBase { - public class NoUndefinedVariablesRuleTests - : DocumentValidatorVisitorTestBase + public NoUndefinedVariablesRuleTests() + : base(services => services.AddVariableRules()) { - public NoUndefinedVariablesRuleTests() - : base(services => services.AddVariableRules()) - { - } + } - [Fact] - public void AllVariablesDefined() - { - ExpectValid(@" + [Fact] + public void AllVariablesDefined() + { + ExpectValid(@" query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } "); - } + } - [Fact] - public void AllVariablesDeeplyDefined() - { - ExpectValid(@" + [Fact] + public void AllVariablesDeeplyDefined() + { + ExpectValid(@" query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { @@ -33,12 +33,12 @@ public void AllVariablesDeeplyDefined() } } "); - } + } - [Fact] - public void AllVariablesDeeplyInInlineFragmentsDefined() - { - ExpectValid(@" + [Fact] + public void AllVariablesDeeplyInInlineFragmentsDefined() + { + ExpectValid(@" query Foo($a: String, $b: String, $c: String) { ... on Query { field(a: $a) { @@ -51,12 +51,12 @@ public void AllVariablesDeeplyInInlineFragmentsDefined() } } "); - } + } - [Fact] - public void AllVariablesInFragmentsDeeplyDefined() - { - ExpectValid(@" + [Fact] + public void AllVariablesInFragmentsDeeplyDefined() + { + ExpectValid(@" query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -74,12 +74,12 @@ public void AllVariablesInFragmentsDeeplyDefined() field(c: $c) } "); - } + } - [Fact] - public void VariableWithinSingleFragmentDefinedInMultipleOperations() - { - ExpectValid(@" + [Fact] + public void VariableWithinSingleFragmentDefinedInMultipleOperations() + { + ExpectValid(@" query Foo($a: String) { ...FragA } @@ -92,12 +92,12 @@ public void VariableWithinSingleFragmentDefinedInMultipleOperations() field(a: $a) } "); - } + } - [Fact] - public void VariableWithinFragmentsDefinedInOperations() - { - ExpectValid(@" + [Fact] + public void VariableWithinFragmentsDefinedInOperations() + { + ExpectValid(@" query Foo($a: String) { ...FragA } @@ -114,12 +114,12 @@ public void VariableWithinFragmentsDefinedInOperations() field(b: $b) } "); - } + } - [Fact] - public void VariableWithinRecursiveFragmentDefined() - { - ExpectValid(@" + [Fact] + public void VariableWithinRecursiveFragmentDefined() + { + ExpectValid(@" query Foo($a: String) { ...FragA } @@ -130,42 +130,42 @@ public void VariableWithinRecursiveFragmentDefined() } } "); - } + } - [Fact] - public void VariableNotDefined() - { - ExpectErrors(@" + [Fact] + public void VariableNotDefined() + { + ExpectErrors(@" query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c, d: $d) } "); - } + } - [Fact] - public void VariableNotDefinedByUnNamedQuery() - { - ExpectErrors(@" + [Fact] + public void VariableNotDefinedByUnNamedQuery() + { + ExpectErrors(@" query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c, d: $d) } "); - } + } - [Fact] - public void MultipleVariablesNotDefined() - { - ExpectErrors(@" + [Fact] + public void MultipleVariablesNotDefined() + { + ExpectErrors(@" query Foo($b: String) { field(a: $a, b: $b, c: $c) } "); - } + } - [Fact] - public void VariableInFragmentNotDefinedByUnNamedQuery() - { - ExpectErrors(@" + [Fact] + public void VariableInFragmentNotDefinedByUnNamedQuery() + { + ExpectErrors(@" { ...FragA } @@ -174,12 +174,12 @@ public void VariableInFragmentNotDefinedByUnNamedQuery() field(a: $a) } "); - } + } - [Fact] - public void VariableInFragmentNotDefinedByOperation() - { - ExpectErrors(@" + [Fact] + public void VariableInFragmentNotDefinedByOperation() + { + ExpectErrors(@" query Foo($a: String, $b: String) { ...FragA } @@ -200,12 +200,12 @@ public void VariableInFragmentNotDefinedByOperation() field(c: $c) } "); - } + } - [Fact] - public void MultipleVariablesInFragmentsNotDefined() - { - ExpectErrors(@" + [Fact] + public void MultipleVariablesInFragmentsNotDefined() + { + ExpectErrors(@" query Foo($b: String) { ...FragA } @@ -226,12 +226,12 @@ public void MultipleVariablesInFragmentsNotDefined() field(c: $c) } "); - } + } - [Fact] - public void SingleVariableInFragmentNotDefinedByMultipleOperations() - { - ExpectErrors(@" + [Fact] + public void SingleVariableInFragmentNotDefinedByMultipleOperations() + { + ExpectErrors(@" query Foo($a: String) { ...FragAB } @@ -244,12 +244,12 @@ public void SingleVariableInFragmentNotDefinedByMultipleOperations() field(a: $a, b: $b) } "); - } + } - [Fact] - public void VariablesInFragmentNotDefinedByMultipleOperations() - { - ExpectErrors(@" + [Fact] + public void VariablesInFragmentNotDefinedByMultipleOperations() + { + ExpectErrors(@" query Foo($b: String) { ...FragAB } @@ -262,12 +262,12 @@ public void VariablesInFragmentNotDefinedByMultipleOperations() field(a: $a, b: $b) } "); - } + } - [Fact] - public void VariableInFragmentUsedByOtherOperation() - { - ExpectErrors(@" + [Fact] + public void VariableInFragmentUsedByOtherOperation() + { + ExpectErrors(@" query Foo($b: String) { ...FragA } @@ -284,12 +284,12 @@ public void VariableInFragmentUsedByOtherOperation() field(b: $b) } "); - } + } - [Fact] - public void MultipleUndefinedVariablesProduceMultipleErrors() - { - ExpectErrors(@" + [Fact] + public void MultipleUndefinedVariablesProduceMultipleErrors() + { + ExpectErrors(@" query Foo($b: String) { ...FragA } @@ -306,6 +306,5 @@ public void MultipleUndefinedVariablesProduceMultipleErrors() field(b: $b) } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/NoUnusedFragmentsRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/NoUnusedFragmentsRuleTests.cs index 02e570470b9..1f69a7b7e21 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/NoUnusedFragmentsRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/NoUnusedFragmentsRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class NoUnusedFragmentsRuleTests + : DocumentValidatorVisitorTestBase { - public class NoUnusedFragmentsRuleTests - : DocumentValidatorVisitorTestBase + public NoUnusedFragmentsRuleTests() + : base(services => services.AddFragmentRules()) { - public NoUnusedFragmentsRuleTests() - : base(services => services.AddFragmentRules()) - { - } + } - [Fact] - public void AllFragmentNamesAreUsed() - { - ExpectValid(@" + [Fact] + public void AllFragmentNamesAreUsed() + { + ExpectValid(@" { human { ...HumanFields1 @@ -34,12 +34,12 @@ public void AllFragmentNamesAreUsed() name } "); - } + } - [Fact] - public void AllFragmentNamesAreUsedByMultipleOperations() - { - ExpectValid(@" + [Fact] + public void AllFragmentNamesAreUsedByMultipleOperations() + { + ExpectValid(@" query Foo { human(id: 4) { ...HumanFields1 @@ -61,12 +61,12 @@ public void AllFragmentNamesAreUsedByMultipleOperations() name } "); - } + } - [Fact] - public void ContainsUnknownFragments() - { - ExpectErrors(@" + [Fact] + public void ContainsUnknownFragments() + { + ExpectErrors(@" query Foo { human(id: 4) { ...HumanFields1 @@ -94,12 +94,12 @@ public void ContainsUnknownFragments() name } "); - } + } - [Fact] - public void ContainsUnknownFragmentsWithRefCycle() - { - ExpectErrors(@" + [Fact] + public void ContainsUnknownFragmentsWithRefCycle() + { + ExpectErrors(@" query Foo { human(id: 4) { ...HumanFields1 @@ -129,11 +129,11 @@ public void ContainsUnknownFragmentsWithRefCycle() ...Unused1 } "); - } - [Fact] - public void ContainsUnknownAndUndefFragments() - { - ExpectErrors(@" + } + [Fact] + public void ContainsUnknownAndUndefFragments() + { + ExpectErrors(@" query Foo { human(id: 4) { ...bar @@ -143,6 +143,5 @@ public void ContainsUnknownAndUndefFragments() name } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/NoUnusedVariablesRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/NoUnusedVariablesRuleTests.cs index 5af54cc67a6..7ff67d64245 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/NoUnusedVariablesRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/NoUnusedVariablesRuleTests.cs @@ -1,30 +1,30 @@ using Xunit; using Microsoft.Extensions.DependencyInjection; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class NoUnusedVariablesRuleTests + : DocumentValidatorVisitorTestBase { - public class NoUnusedVariablesRuleTests - : DocumentValidatorVisitorTestBase + public NoUnusedVariablesRuleTests() + : base(services => services.AddVariableRules()) { - public NoUnusedVariablesRuleTests() - : base(services => services.AddVariableRules()) - { - } + } - [Fact] - public void UsesAllVariables() - { - ExpectValid(@" + [Fact] + public void UsesAllVariables() + { + ExpectValid(@" query ($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } "); - } + } - [Fact] - public void UsesAllVariablesDeeply() - { - ExpectValid(@" + [Fact] + public void UsesAllVariablesDeeply() + { + ExpectValid(@" query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { @@ -33,12 +33,12 @@ public void UsesAllVariablesDeeply() } } "); - } + } - [Fact] - public void UsesAllVariablesDeeplyInInlineFragments() - { - ExpectValid(@" + [Fact] + public void UsesAllVariablesDeeplyInInlineFragments() + { + ExpectValid(@" query Foo($a: String, $b: String, $c: String) { ... on Query { field(a: $a) { @@ -51,12 +51,12 @@ public void UsesAllVariablesDeeplyInInlineFragments() } } "); - } + } - [Fact] - public void UsesAllVariablesInFragments() - { - ExpectValid(@" + [Fact] + public void UsesAllVariablesInFragments() + { + ExpectValid(@" query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -74,12 +74,12 @@ public void UsesAllVariablesInFragments() field(c: $c) } "); - } + } - [Fact] - public void VariableUsedByFragmentInMultipleOperations() - { - ExpectValid(@" + [Fact] + public void VariableUsedByFragmentInMultipleOperations() + { + ExpectValid(@" query Foo($a: String) { ...FragA } @@ -93,12 +93,12 @@ public void VariableUsedByFragmentInMultipleOperations() field(b: $b) } "); - } + } - [Fact] - public void VariableUsedByRecursiveFragment() - { - ExpectValid(@" + [Fact] + public void VariableUsedByRecursiveFragment() + { + ExpectValid(@" query Foo($a: String) { ...FragA } @@ -108,22 +108,22 @@ public void VariableUsedByRecursiveFragment() } } "); - } + } - [Fact] - public void MultipleVariablesNotUsed() - { - ExpectErrors(@" + [Fact] + public void MultipleVariablesNotUsed() + { + ExpectErrors(@" query Foo($a: String, $b: String, $c: String) { field(b: $b) } "); - } + } - [Fact] - public void VariableNotUsedInFragments() - { - ExpectErrors(@" + [Fact] + public void VariableNotUsedInFragments() + { + ExpectErrors(@" query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -141,12 +141,12 @@ public void VariableNotUsedInFragments() field } "); - } + } - [Fact] - public void MultipleVariablesNotUsedInFragments() - { - ExpectErrors(@" + [Fact] + public void MultipleVariablesNotUsedInFragments() + { + ExpectErrors(@" query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -164,12 +164,12 @@ public void MultipleVariablesNotUsedInFragments() field } "); - } + } - [Fact] - public void VariableNotUsedByUnreferencedFragment() - { - ExpectErrors(@" + [Fact] + public void VariableNotUsedByUnreferencedFragment() + { + ExpectErrors(@" query Foo($b: String) { ...FragA } @@ -180,12 +180,12 @@ public void VariableNotUsedByUnreferencedFragment() field(b: $b) } "); - } + } - [Fact] - public void VariableNotUsedByFragmentUsedByOtherOperation() - { - ExpectErrors(@" + [Fact] + public void VariableNotUsedByFragmentUsedByOtherOperation() + { + ExpectErrors(@" query Foo($b: String) { ...FragA } @@ -199,8 +199,7 @@ public void VariableNotUsedByFragmentUsedByOtherOperation() field(b: $b) } "); - } + } - } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/OneOfRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/OneOfRuleTests.cs index 529374e1c5b..ce0c4bb1b67 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/OneOfRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/OneOfRuleTests.cs @@ -1,102 +1,101 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class OneOfRuleTests : DocumentValidatorVisitorTestBase { - public class OneOfRuleTests : DocumentValidatorVisitorTestBase + public OneOfRuleTests() + : base(builder => builder.AddValueRules()) { - public OneOfRuleTests() - : base(builder => builder.AddValueRules()) - { - } + } - [Fact] - public void EmptyOneOf() - { - ExpectErrors(@" + [Fact] + public void EmptyOneOf() + { + ExpectErrors(@" mutation addPet { addPet(pet: { }) { name } } "); - } + } - [Fact] - public void MultipleFieldsAreNotAllowed_1() - { - ExpectErrors(@" + [Fact] + public void MultipleFieldsAreNotAllowed_1() + { + ExpectErrors(@" mutation addPet($cat: CatInput, $dog: DogInput) { addPet(pet: {cat: $cat, dog: $dog}) { name } }"); - } + } - [Fact] - public void MultipleFieldsAreNotAllowed_2() - { - ExpectErrors(@" + [Fact] + public void MultipleFieldsAreNotAllowed_2() + { + ExpectErrors(@" mutation addPet($dog: DogInput) { addPet(pet: { cat: { name: ""Brontie"" }, dog: $dog }) { name } }"); - } + } - [Fact] - public void MultipleFieldsAreNotAllowed_3() - { - ExpectErrors(@" + [Fact] + public void MultipleFieldsAreNotAllowed_3() + { + ExpectErrors(@" mutation addPet($cat: CatInput, $dog: DogInput) { addPet(pet: {cat: $cat, dog: $dog}) { name } }"); - } + } - [Fact] - public void VariablesUsedForOneofInputObjectFieldsMustBeNonNullable_Valid() - { - ExpectValid(@" + [Fact] + public void VariablesUsedForOneofInputObjectFieldsMustBeNonNullable_Valid() + { + ExpectValid(@" mutation addPet($cat: CatInput!) { addPet(pet: { cat: $cat }) { name } }"); - } + } - [Fact] - public void VariablesUsedForOneofInputObjectFieldsMustBeNonNullable_Error() - { - ExpectErrors(@" + [Fact] + public void VariablesUsedForOneofInputObjectFieldsMustBeNonNullable_Error() + { + ExpectErrors(@" mutation addPet($cat: CatInput) { addPet(pet: { cat: $cat }) { name } }"); - } + } - [Fact] - public void IfFieldWithLiteralValueIsPresentThenTheValueMustNotBeNull_Valid() - { - ExpectValid(@" + [Fact] + public void IfFieldWithLiteralValueIsPresentThenTheValueMustNotBeNull_Valid() + { + ExpectValid(@" mutation addPet { addPet(pet: { cat: { name: ""Brontie"" } }) { name } }"); - } + } - [Fact] - public void IfFieldWithLiteralValueIsPresentThenTheValueMustNotBeNull_Error() - { - ExpectErrors(@" + [Fact] + public void IfFieldWithLiteralValueIsPresentThenTheValueMustNotBeNull_Error() + { + ExpectErrors(@" mutation addPet { addPet(pet: { cat: null }) { name } }"); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/OperationNameUniquenessRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/OperationNameUniquenessRuleTests.cs index ba1973aad66..b6b6534ed47 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/OperationNameUniquenessRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/OperationNameUniquenessRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class OperationNameUniquenessRuleTests + : DocumentValidatorVisitorTestBase { - public class OperationNameUniquenessRuleTests - : DocumentValidatorVisitorTestBase + public OperationNameUniquenessRuleTests() + : base(builder => builder.AddOperationRules()) { - public OperationNameUniquenessRuleTests() - : base(builder => builder.AddOperationRules()) - { - } + } - [Fact] - public void TwoUniqueQueryOperations() - { - ExpectValid(@" + [Fact] + public void TwoUniqueQueryOperations() + { + ExpectValid(@" query getDogName { dog { name @@ -29,12 +29,12 @@ public void TwoUniqueQueryOperations() } } "); - } + } - [Fact] - public void TwoQueryOperationsWithTheSameName() - { - ExpectErrors(@" + [Fact] + public void TwoQueryOperationsWithTheSameName() + { + ExpectErrors(@" query getName { dog { name @@ -52,12 +52,12 @@ public void TwoQueryOperationsWithTheSameName() t => Assert.Equal( $"The operation name `getName` is not unique.", t.Message)); - } + } - [Fact] - public void TwoOperationsWithTheSameName() - { - ExpectErrors(@" + [Fact] + public void TwoOperationsWithTheSameName() + { + ExpectErrors(@" query dogOperation { dog { name @@ -73,32 +73,32 @@ public void TwoOperationsWithTheSameName() t => Assert.Equal( $"The operation name `dogOperation` is not unique.", t.Message)); - } + } - [Fact] - public void OneAnonOperation() - { - ExpectValid(@" + [Fact] + public void OneAnonOperation() + { + ExpectValid(@" { anyArg } "); - } + } - [Fact] - public void OneNamedOperation() - { - ExpectValid(@" + [Fact] + public void OneNamedOperation() + { + ExpectValid(@" query Foo { anyArg } "); - } + } - [Fact] - public void MultipleOperationsOfDifferentTypes() - { - ExpectValid(@" + [Fact] + public void MultipleOperationsOfDifferentTypes() + { + ExpectValid(@" query Foo { anyArg } @@ -113,12 +113,12 @@ public void MultipleOperationsOfDifferentTypes() } } "); - } + } - [Fact] - public void FragmentAndOperationNamedTheSame() - { - ExpectValid(@" + [Fact] + public void FragmentAndOperationNamedTheSame() + { + ExpectValid(@" query Foo { ...Foo } @@ -127,12 +127,12 @@ public void FragmentAndOperationNamedTheSame() anyArg } "); - } + } - [Fact] - public void MultipleOperationsOfSameName() - { - ExpectErrors(@" + [Fact] + public void MultipleOperationsOfSameName() + { + ExpectErrors(@" query Foo { anyArg } @@ -141,12 +141,12 @@ public void MultipleOperationsOfSameName() anyArg } "); - } + } - [Fact] - public void MultipleOpsOfSameNameOfDifferentTypesMutation() - { - ExpectErrors(@" + [Fact] + public void MultipleOpsOfSameNameOfDifferentTypesMutation() + { + ExpectErrors(@" query Foo { anyArg } @@ -155,12 +155,12 @@ public void MultipleOpsOfSameNameOfDifferentTypesMutation() fieldB } "); - } + } - [Fact] - public void MultipleOpsOfSameNameOfDifferentTypesSubscription() - { - ExpectErrors(@" + [Fact] + public void MultipleOpsOfSameNameOfDifferentTypesSubscription() + { + ExpectErrors(@" query Foo { anyArg } @@ -171,6 +171,5 @@ public void MultipleOpsOfSameNameOfDifferentTypesSubscription() } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/RequiredArgumentRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/RequiredArgumentRuleTests.cs index 80c1bd831f1..3abd2c58430 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/RequiredArgumentRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/RequiredArgumentRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class RequiredArgumentRuleTests + : DocumentValidatorVisitorTestBase { - public class RequiredArgumentRuleTests - : DocumentValidatorVisitorTestBase + public RequiredArgumentRuleTests() + : base(builder => builder.AddArgumentRules()) + { + } + + [Fact] + public void BooleanArgFieldAndNonNullBooleanArgField() { - public RequiredArgumentRuleTests() - : base(builder => builder.AddArgumentRules()) - { - } - - [Fact] - public void BooleanArgFieldAndNonNullBooleanArgField() - { - ExpectValid(@" + ExpectValid(@" query { arguments { ... goodBooleanArg @@ -30,12 +30,12 @@ ... goodNonNullArg nonNullBooleanArgField(nonNullBooleanArg: true) } "); - } + } - [Fact] - public void GoodBooleanArgDefault() - { - ExpectValid(@" + [Fact] + public void GoodBooleanArgDefault() + { + ExpectValid(@" query { arguments { ... goodBooleanArgDefault @@ -46,12 +46,12 @@ ... goodBooleanArgDefault booleanArgField } "); - } + } - [Fact] - public void GoodBooleanArgDefault2() - { - ExpectValid(@" + [Fact] + public void GoodBooleanArgDefault2() + { + ExpectValid(@" query { arguments { ... goodBooleanArgDefault @@ -62,13 +62,13 @@ ... goodBooleanArgDefault optionalNonNullBooleanArgField2 } "); - } + } - [Fact] - public void MissingRequiredArg() - { - // arrange - ExpectErrors(@" + [Fact] + public void MissingRequiredArg() + { + // arrange + ExpectErrors(@" query { arguments { ... missingRequiredArg @@ -81,12 +81,12 @@ ... missingRequiredArg ", t => Assert.Equal( $"The argument `nonNullBooleanArg` is required.", t.Message)); - } + } - [Fact] - public void MissingRequiredArgNonNullBooleanArg() - { - ExpectErrors(@" + [Fact] + public void MissingRequiredArgNonNullBooleanArg() + { + ExpectErrors(@" query { arguments { ... missingRequiredArg @@ -99,12 +99,12 @@ ... missingRequiredArg ", t => Assert.Equal( $"The argument `nonNullBooleanArg` is required.", t.Message)); - } + } - [Fact] - public void MissingRequiredDirectiveArg() - { - ExpectErrors(@" + [Fact] + public void MissingRequiredDirectiveArg() + { + ExpectErrors(@" query { arguments { ... missingRequiredArg @@ -117,251 +117,251 @@ ... missingRequiredArg ", t => Assert.Equal( $"The argument `if` is required.", t.Message)); - } - [Fact] - public void BadMultipleNullValueType() - { - ExpectErrors(@" + } + [Fact] + public void BadMultipleNullValueType() + { + ExpectErrors(@" { arguments { multipleReqs(x: 1, y: null) } } "); - } + } - [Fact] - public void BadNullIntoNonNullBool() - { - ExpectErrors(@" + [Fact] + public void BadNullIntoNonNullBool() + { + ExpectErrors(@" { arguments { nonNullBooleanArgField(nonNullBooleanArg: null) } } "); - } + } - [Fact] - public void BadNullIntoNonNullFloat() - { - ExpectErrors(@" + [Fact] + public void BadNullIntoNonNullFloat() + { + ExpectErrors(@" { arguments { nonNullFloatArgField(floatArg: null) } } "); - } + } - [Fact] - public void BadNullIntoNonNullId() - { - ExpectErrors(@" + [Fact] + public void BadNullIntoNonNullId() + { + ExpectErrors(@" { arguments { nonNullIdArgField(idArg: null) } } "); - } + } - [Fact] - public void BadNullIntoNonNullInt() - { - ExpectErrors(@" + [Fact] + public void BadNullIntoNonNullInt() + { + ExpectErrors(@" { arguments { nonNullIntArgField(intArg: null) } } "); - } + } - [Fact] - public void BadNullIntoNonNullString() - { - ExpectErrors(@" + [Fact] + public void BadNullIntoNonNullString() + { + ExpectErrors(@" { arguments { nonNullStringArgField(stringArg: null) } } "); - } + } - [Fact] - public void ArgOnOptionalArg() - { - ExpectValid(@" + [Fact] + public void ArgOnOptionalArg() + { + ExpectValid(@" { dog { isHouseTrained(atOtherHomes: true) } } "); - } + } - [Fact] - public void ArgOnNoArgOnOptionalArg() - { - ExpectValid(@" + [Fact] + public void ArgOnNoArgOnOptionalArg() + { + ExpectValid(@" { dog { isHouseTrained } } "); - } + } - [Fact] - public void NoArgOnNonNullFieldWithDefault() - { - ExpectValid(@" + [Fact] + public void NoArgOnNonNullFieldWithDefault() + { + ExpectValid(@" { arguments { optionalNonNullBooleanArgField(y:1) } } "); - } + } - [Fact] - public void MultipleArgs() - { - ExpectValid(@" + [Fact] + public void MultipleArgs() + { + ExpectValid(@" { arguments { multipleReqs(x: 1, y: 2) } } "); - } + } - [Fact] - public void MultipleArgsReverseOrder() - { - ExpectValid(@" + [Fact] + public void MultipleArgsReverseOrder() + { + ExpectValid(@" { arguments { multipleReqs(x: 2, y: 1) } } "); - } + } - [Fact] - public void NoArgsOnMultipleOptional() - { - ExpectValid(@" + [Fact] + public void NoArgsOnMultipleOptional() + { + ExpectValid(@" { arguments { multipleOpts } } "); - } + } - [Fact] - public void OneArgOnMultipleOptional() - { - ExpectValid(@" + [Fact] + public void OneArgOnMultipleOptional() + { + ExpectValid(@" { arguments { multipleOpts(opt1: 1) } } "); - } + } - [Fact] - public void SecondArgOnMultipleOptional() - { - ExpectValid(@" + [Fact] + public void SecondArgOnMultipleOptional() + { + ExpectValid(@" { arguments { multipleOpts(opt2: 2) } } "); - } + } - [Fact] - public void MultipleRequiredArgsOnMixedList() - { - ExpectValid(@" + [Fact] + public void MultipleRequiredArgsOnMixedList() + { + ExpectValid(@" { arguments { multipleOptsAndReqs(req1: 3, req2: 4) } } "); - } + } - [Fact] - public void MultipleRequiredAndOneOptionalArgOnMixedList() - { - ExpectValid(@" + [Fact] + public void MultipleRequiredAndOneOptionalArgOnMixedList() + { + ExpectValid(@" { arguments { multipleOptsAndReqs(req1: 3, req2: 4, opt1: 5) } } "); - } + } - [Fact] - public void AllRequiredAndOptionalArgsOnMixedList() - { - ExpectValid(@" + [Fact] + public void AllRequiredAndOptionalArgsOnMixedList() + { + ExpectValid(@" { arguments { multipleOptsAndReqs(req1: 3, req2: 4, opt1: 5, opt2: 6) } } "); - } + } - [Fact] - public void MissingOneNonNullableArgument() - { - ExpectErrors(@" + [Fact] + public void MissingOneNonNullableArgument() + { + ExpectErrors(@" { arguments { multipleReqs(req2: 2) } } "); - } + } - [Fact] - public void MissingMultipleNonNullableArguments() - { - ExpectErrors(@" + [Fact] + public void MissingMultipleNonNullableArguments() + { + ExpectErrors(@" { arguments { multipleReqs } } "); - } + } - [Fact] - public void IncorrectValueAndMissingArgument() - { - ExpectErrors(@" + [Fact] + public void IncorrectValueAndMissingArgument() + { + ExpectErrors(@" { arguments { multipleReqs(req1: ""one"") } } "); - } + } - [Fact] - public void WithDirectivesOfValidTypes() - { - ExpectValid(@" + [Fact] + public void WithDirectivesOfValidTypes() + { + ExpectValid(@" { dog @include(if: true) { name @@ -371,18 +371,17 @@ public void WithDirectivesOfValidTypes() } } "); - } + } - [Fact] - public void WithDirectiveWithMissingTypes() - { - ExpectErrors(@" + [Fact] + public void WithDirectiveWithMissingTypes() + { + ExpectErrors(@" { dog @include { name @skip } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/StreamDirectivesAreUsedOnListFieldsTests.cs b/src/HotChocolate/Core/test/Validation.Tests/StreamDirectivesAreUsedOnListFieldsTests.cs new file mode 100644 index 00000000000..5291109ebb3 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/StreamDirectivesAreUsedOnListFieldsTests.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace HotChocolate.Validation; + +public class StreamDirectivesAreUsedOnListFieldsTests + : DocumentValidatorVisitorTestBase +{ + public StreamDirectivesAreUsedOnListFieldsTests() + : base(builder => builder.AddFieldRules()) + { + } + + [Fact] + public void Stream_On_String_Field_1() + { + ExpectErrors( + @"query { + __typename @stream + }", + t => Assert.Equal( + "@stream directive is only valid on list fields.", + t.Message)); + } + + [Fact] + public void Stream_On_String_Field_2() + { + ExpectErrors( + @"query { + __schema { + description @stream + } + }", + t => Assert.Equal( + "@stream directive is only valid on list fields.", + t.Message)); + } + + [Fact] + public void Stream_On_Types() + { + ExpectValid( + @"query { + __schema { + types @stream { + name + } + } + }"); + } +} + diff --git a/src/HotChocolate/Core/test/Validation.Tests/SubscriptionSingleRootFieldRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/SubscriptionSingleRootFieldRuleTests.cs index 764e6c02799..16d2d00687d 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/SubscriptionSingleRootFieldRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/SubscriptionSingleRootFieldRuleTests.cs @@ -1,20 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class SubscriptionSingleRootFieldRuleTests + : DocumentValidatorVisitorTestBase { - public class SubscriptionSingleRootFieldRuleTests - : DocumentValidatorVisitorTestBase + public SubscriptionSingleRootFieldRuleTests() + : base(builder => builder.AddOperationRules()) { - public SubscriptionSingleRootFieldRuleTests() - : base(builder => builder.AddOperationRules()) - { - } + } - [Fact] - public void SubscriptionWithOneRootField() - { - ExpectValid(@" + [Fact] + public void SubscriptionWithOneRootField() + { + ExpectValid(@" subscription sub { newMessage { body @@ -22,12 +22,12 @@ public void SubscriptionWithOneRootField() } } "); - } + } - [Fact] - public void SubscriptionWithOneRootFieldAnonymous() - { - ExpectValid(@" + [Fact] + public void SubscriptionWithOneRootFieldAnonymous() + { + ExpectValid(@" subscription { newMessage { body @@ -35,13 +35,13 @@ public void SubscriptionWithOneRootFieldAnonymous() } } "); - } + } - [Fact] - public void SubscriptionWithDirectiveThatContainsOneRootField() - { - // arrange - ExpectValid(@" + [Fact] + public void SubscriptionWithDirectiveThatContainsOneRootField() + { + // arrange + ExpectValid(@" subscription sub { ...newMessageFields } @@ -53,12 +53,12 @@ public void SubscriptionWithDirectiveThatContainsOneRootField() } } "); - } + } - [Fact] - public void DisallowedSecondRootField() - { - ExpectErrors(@" + [Fact] + public void DisallowedSecondRootField() + { + ExpectErrors(@" subscription sub { newMessage { body @@ -70,12 +70,12 @@ public void DisallowedSecondRootField() t => Assert.Equal( $"Subscription operations must " + "have exactly one root field.", t.Message)); - } + } - [Fact] - public void DisallowedSecondRootFieldAnonymous() - { - ExpectErrors(@" + [Fact] + public void DisallowedSecondRootFieldAnonymous() + { + ExpectErrors(@" subscription sub { newMessage { body @@ -87,12 +87,12 @@ public void DisallowedSecondRootFieldAnonymous() t => Assert.Equal( $"Subscription operations must " + "have exactly one root field.", t.Message)); - } + } - [Fact] - public void FailsWithManyMoreThanOneRootField() - { - ExpectErrors(@" + [Fact] + public void FailsWithManyMoreThanOneRootField() + { + ExpectErrors(@" subscription sub { newMessage { body @@ -105,12 +105,12 @@ public void FailsWithManyMoreThanOneRootField() t => Assert.Equal( $"Subscription operations must " + "have exactly one root field.", t.Message)); - } + } - [Fact] - public void DisallowedSecondRootFieldWithinDirective() - { - ExpectErrors(@" + [Fact] + public void DisallowedSecondRootFieldWithinDirective() + { + ExpectErrors(@" subscription sub { ...multipleSubscriptions } @@ -126,12 +126,12 @@ public void DisallowedSecondRootFieldWithinDirective() t => Assert.Equal( $"Subscription operations must " + "have exactly one root field.", t.Message)); - } + } - [Fact] - public void DisallowedIntrospectionField() - { - ExpectErrors(@" + [Fact] + public void DisallowedIntrospectionField() + { + ExpectErrors(@" subscription sub { newMessage { body @@ -143,18 +143,17 @@ public void DisallowedIntrospectionField() t => Assert.Equal( $"Subscription operations must " + "have exactly one root field.", t.Message)); - } + } - [Fact] - public void DisallowedOnlyIntrospectionField() - { - ExpectErrors(@" + [Fact] + public void DisallowedOnlyIntrospectionField() + { + ExpectErrors(@" subscription sub { __typename } ", t => Assert.Equal( "Subscription must not select an introspection top level field.", t.Message)); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/TestHelper.cs b/src/HotChocolate/Core/test/Validation.Tests/TestHelper.cs index c2f89a003b2..1d75d7ba98c 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/TestHelper.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/TestHelper.cs @@ -7,125 +7,124 @@ using Snapshooter.Xunit; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public static class TestHelper { - public static class TestHelper + public static void ExpectValid( + Action configure, + string sourceText, + IEnumerable> contextData = null) { - public static void ExpectValid( - Action configure, - string sourceText, - IEnumerable> contextData = null) - { - ExpectValid( - ValidationUtils.CreateSchema(), - configure, - sourceText, - contextData); - } + ExpectValid( + ValidationUtils.CreateSchema(), + configure, + sourceText, + contextData); + } - public static void ExpectValid( - ISchema schema, - Action configure, - string sourceText, - IEnumerable> contextData = null) - { - // arrange - var serviceCollection = new ServiceCollection(); + public static void ExpectValid( + ISchema schema, + Action configure, + string sourceText, + IEnumerable> contextData = null) + { + // arrange + var serviceCollection = new ServiceCollection(); - IValidationBuilder builder = serviceCollection - .AddValidation() - .ConfigureValidation(c => c.Modifiers.Add(o => o.Rules.Clear())); - configure(builder); + var builder = serviceCollection + .AddValidation() + .ConfigureValidation(c => c.Modifiers.Add(o => o.Rules.Clear())); + configure(builder); - IServiceProvider services = serviceCollection.BuildServiceProvider(); - IDocumentValidatorRule rule = - services.GetRequiredService() - .GetRules(Schema.DefaultName).First(); + IServiceProvider services = serviceCollection.BuildServiceProvider(); + var rule = + services.GetRequiredService() + .GetRules(Schema.DefaultName).First(); - DocumentValidatorContext context = ValidationUtils.CreateContext(schema); - DocumentNode query = Utf8GraphQLParser.Parse(sourceText); - context.Prepare(query); + var context = ValidationUtils.CreateContext(schema); + var query = Utf8GraphQLParser.Parse(sourceText); + context.Prepare(query); - context.ContextData = new Dictionary(); + context.ContextData = new Dictionary(); - if (contextData is not null) + if (contextData is not null) + { + foreach (var (key, value) in contextData) { - foreach (var (key, value) in contextData) - { - context.ContextData[key] = value; - } + context.ContextData[key] = value; } + } - // act - rule.Validate(context, query); + // act + rule.Validate(context, query); - // assert - Assert.False(context.UnexpectedErrorsDetected); - Assert.Empty(context.Errors); - } + // assert + Assert.False(context.UnexpectedErrorsDetected); + Assert.Empty(context.Errors); + } - public static void ExpectErrors( - Action configure, - string sourceText, - IEnumerable> contextData = null, - params Action[] elementInspectors) - { - ExpectErrors( - ValidationUtils.CreateSchema(), - configure, - sourceText, - contextData, - elementInspectors); - } + public static void ExpectErrors( + Action configure, + string sourceText, + IEnumerable> contextData = null, + params Action[] elementInspectors) + { + ExpectErrors( + ValidationUtils.CreateSchema(), + configure, + sourceText, + contextData, + elementInspectors); + } - public static void ExpectErrors( - ISchema schema, - Action configure, - string sourceText, - IEnumerable> contextData = null, - params Action[] elementInspectors) - { - // arrange - var serviceCollection = new ServiceCollection(); + public static void ExpectErrors( + ISchema schema, + Action configure, + string sourceText, + IEnumerable> contextData = null, + params Action[] elementInspectors) + { + // arrange + var serviceCollection = new ServiceCollection(); - IValidationBuilder builder = serviceCollection - .AddValidation() - .ConfigureValidation(c => c.Modifiers.Add(o => o.Rules.Clear())); - configure(builder); + var builder = serviceCollection + .AddValidation() + .ConfigureValidation(c => c.Modifiers.Add(o => o.Rules.Clear())); + configure(builder); - IServiceProvider services = serviceCollection.BuildServiceProvider(); - IDocumentValidatorRule rule = - services.GetRequiredService() - .GetRules(Schema.DefaultName).First(); + IServiceProvider services = serviceCollection.BuildServiceProvider(); + var rule = + services.GetRequiredService() + .GetRules(Schema.DefaultName).First(); - DocumentValidatorContext context = ValidationUtils.CreateContext(schema); - context.MaxAllowedErrors = int.MaxValue; + var context = ValidationUtils.CreateContext(schema); + context.MaxAllowedErrors = int.MaxValue; - DocumentNode query = Utf8GraphQLParser.Parse(sourceText); - context.Prepare(query); + var query = Utf8GraphQLParser.Parse(sourceText); + context.Prepare(query); - context.ContextData = new Dictionary(); + context.ContextData = new Dictionary(); - if (contextData is not null) + if (contextData is not null) + { + foreach (var (key, value) in contextData) { - foreach (var (key, value) in contextData) - { - context.ContextData[key] = value; - } + context.ContextData[key] = value; } + } - // act - rule.Validate(context, query); - - // assert - Assert.NotEmpty(context.Errors); + // act + rule.Validate(context, query); - if (elementInspectors.Length > 0) - { - Assert.Collection(context.Errors, elementInspectors); - } + // assert + Assert.NotEmpty(context.Errors); - context.Errors.MatchSnapshot(); + if (elementInspectors.Length > 0) + { + Assert.Collection(context.Errors, elementInspectors); } + + context.Errors.MatchSnapshot(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/AlienType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/AlienType.cs index 73442e2a705..e3a4d2690cd 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/AlienType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/AlienType.cs @@ -1,14 +1,13 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class AlienType + : ObjectType { - public class AlienType - : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Implements(); - descriptor.Field(t => t.Name).Type>(); - } + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/ArgumentsType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/ArgumentsType.cs index 4ee27bb7855..54a5a3cfa97 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/ArgumentsType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/ArgumentsType.cs @@ -1,182 +1,181 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class ArgumentsType + : ObjectType { - public class ArgumentsType - : ObjectType + public ArgumentsType() + { + } + + protected override void Configure(IObjectTypeDescriptor descriptor) { - public ArgumentsType() - { - } - - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Name("Arguments"); - - // multipleReqs(x: Int!, y: Int!): Int! - descriptor.Field("multipleReqs") - .Argument("x", t => t.Type>()) - .Argument("y", t => t.Type>()) - .Type>() - .Resolve(() => null); - - descriptor.Field("multipleOpts") - .Argument("opt1", t => t.Type()) - .Argument("opt2", t => t.Type()) - .Type>() - .Resolve(() => null); - - descriptor.Field("multipleOptsAndReqs") - .Argument("req1", t => t.Type>()) - .Argument("req2", t => t.Type>()) - .Argument("opt1", t => t.Type()) - .Argument("opt2", t => t.Type()) - .Type>() - .Resolve(() => null); - - // booleanArgField(booleanArg: Boolean) : Boolean - descriptor.Field("booleanArgField") - .Argument("booleanArg", t => t.Type()) - .Type() - .Resolve(() => null); - - // floatArgField(floatArg: Float): Float - descriptor.Field("floatArgField") - .Argument("floatArg", t => t.Type()) - .Type() - .Resolve(() => null); - - // nonNullFloatArgField(floatArg: Float): Float - descriptor.Field("nonNullFloatArgField") - .Argument("floatArg", t => t.Type>()) - .Type() - .Resolve(() => null); - - // intArgField(intArg: Int): Int! - descriptor.Field("intArgField") - .Argument("intArg", t => t.Type()) - .Type>() - .Resolve(() => null); - - // nonNullIntArgField(intArg: Int!): Int! - descriptor.Field("nonNullIntArgField") - .Argument("intArg", t => t.Type>()) - .Type>() - .Resolve(() => null); - - // nonNullBooleanArgField(nonNullBooleanArg: Boolean!): Boolean! - descriptor.Field("nonNullBooleanArgField") - .Argument("nonNullBooleanArg", - t => t.Type>()) - .Type>() - .Resolve(() => null); - - // booleanListArgField(booleanListArg: [Boolean]!) : [Boolean] - descriptor.Field("booleanListArgField") - .Argument("booleanListArg", - t => t.Type>>()) - .Type>() - .Resolve(() => null); - - // nonNullBooleanListArgField(booleanListArg: [Boolean!]!) : [Boolean] - descriptor.Field("nonNullBooleanListArgField") - .Argument("booleanListArg", - t => t.Type>>>()) - .Type>() - .Resolve(() => null); - - // optionalNonNullBooleanArgField(optionalBooleanArg: Boolean! = false) : Boolean! - descriptor.Field("optionalNonNullBooleanArgField") - .Argument("optionalBooleanArg", - t => t.Type>().DefaultValue(false)) - .Argument("y", t => t.Type>()) - .Type>() - .Resolve(() => null); - - // optionalNonNullBooleanArgField2(optionalBooleanArg: Boolean = true) : Boolean! - descriptor.Field("optionalNonNullBooleanArgField2") - .Argument("optionalBooleanArg", - t => t.Type().DefaultValue(true)) - .Type() - .Resolve(() => null); - - // booleanListArgField(booleanListArg: [Boolean]!) : [Boolean] - descriptor.Field("nonNullBooleanListField") - .Argument("nonNullBooleanListArg", - t => t.Type>>()) - .Type>() - .Resolve(() => null); - - // intArgField(intArg: ID): ID! - descriptor.Field("idArgField") - .Argument("idArg", t => t.Type()) - .Type>() - .Resolve(() => null); - - descriptor.Field("nonNullIdArgField") - .Argument("idArg", t => t.Type>()) - .Type>() - .Resolve(() => null); - - // stringArgField(intArg: String): String! - descriptor.Field("stringArgField") - .Argument("stringArg", t => t.Type()) - .Type>() - .Resolve(() => null); - - descriptor.Field("nonNullStringArgField") - .Argument("stringArg", t => t.Type>()) - .Type>() - .Resolve(() => null); - - descriptor.Field("stringListArgField") - .Argument("stringListArg", - t => t.Type>()) - .Type>() - .Resolve(() => null); - - // enumArgField(intArg: DogCommand): String! - descriptor.Field("enumArgField") - .Argument("enumArg", t => t.Type>()) - .Type>() - .Resolve(() => null); - - // "nonNullenumArgField(intArg: DogCommand!): String! - descriptor.Field("nonNullEnumArgField") - .Argument("enumArg", t => t.Type>>()) - .Type>() - .Resolve(() => null); - - descriptor.Field("complexArgField") - .Argument("complexArg", t => t.Type()) - .Type>() - .Argument("complexArg1", t => t.Type()) - .Type>() - .Argument("complexArg2", t => t.Type()) - .Type>() - .Resolve(() => null); - - descriptor.Field("nonNullFieldWithDefault") - .Argument("opt1", t => t.Type>().DefaultValue(0)) - .Type>() - .Resolve(() => null); - - descriptor.Field("nonNullFieldWithDefault") - .Argument("nonNullIntArg", t => t.Type>().DefaultValue(0)) - .Type>() - .Resolve(() => null); - - descriptor.Field("nonNullField") - .Argument("nonNullIntArg", t => t.Type>()) - .Type>() - .Resolve(() => null); - - descriptor.Field("stringListNonNullArgField") - .Argument( - "stringListNonNullArg", - t => t.Type>>()) - .Type>() - .Resolve(() => null); - } + descriptor.Name("Arguments"); + + // multipleReqs(x: Int!, y: Int!): Int! + descriptor.Field("multipleReqs") + .Argument("x", t => t.Type>()) + .Argument("y", t => t.Type>()) + .Type>() + .Resolve(() => null); + + descriptor.Field("multipleOpts") + .Argument("opt1", t => t.Type()) + .Argument("opt2", t => t.Type()) + .Type>() + .Resolve(() => null); + + descriptor.Field("multipleOptsAndReqs") + .Argument("req1", t => t.Type>()) + .Argument("req2", t => t.Type>()) + .Argument("opt1", t => t.Type()) + .Argument("opt2", t => t.Type()) + .Type>() + .Resolve(() => null); + + // booleanArgField(booleanArg: Boolean) : Boolean + descriptor.Field("booleanArgField") + .Argument("booleanArg", t => t.Type()) + .Type() + .Resolve(() => null); + + // floatArgField(floatArg: Float): Float + descriptor.Field("floatArgField") + .Argument("floatArg", t => t.Type()) + .Type() + .Resolve(() => null); + + // nonNullFloatArgField(floatArg: Float): Float + descriptor.Field("nonNullFloatArgField") + .Argument("floatArg", t => t.Type>()) + .Type() + .Resolve(() => null); + + // intArgField(intArg: Int): Int! + descriptor.Field("intArgField") + .Argument("intArg", t => t.Type()) + .Type>() + .Resolve(() => null); + + // nonNullIntArgField(intArg: Int!): Int! + descriptor.Field("nonNullIntArgField") + .Argument("intArg", t => t.Type>()) + .Type>() + .Resolve(() => null); + + // nonNullBooleanArgField(nonNullBooleanArg: Boolean!): Boolean! + descriptor.Field("nonNullBooleanArgField") + .Argument("nonNullBooleanArg", + t => t.Type>()) + .Type>() + .Resolve(() => null); + + // booleanListArgField(booleanListArg: [Boolean]!) : [Boolean] + descriptor.Field("booleanListArgField") + .Argument("booleanListArg", + t => t.Type>>()) + .Type>() + .Resolve(() => null); + + // nonNullBooleanListArgField(booleanListArg: [Boolean!]!) : [Boolean] + descriptor.Field("nonNullBooleanListArgField") + .Argument("booleanListArg", + t => t.Type>>>()) + .Type>() + .Resolve(() => null); + + // optionalNonNullBooleanArgField(optionalBooleanArg: Boolean! = false) : Boolean! + descriptor.Field("optionalNonNullBooleanArgField") + .Argument("optionalBooleanArg", + t => t.Type>().DefaultValue(false)) + .Argument("y", t => t.Type>()) + .Type>() + .Resolve(() => null); + + // optionalNonNullBooleanArgField2(optionalBooleanArg: Boolean = true) : Boolean! + descriptor.Field("optionalNonNullBooleanArgField2") + .Argument("optionalBooleanArg", + t => t.Type().DefaultValue(true)) + .Type() + .Resolve(() => null); + + // booleanListArgField(booleanListArg: [Boolean]!) : [Boolean] + descriptor.Field("nonNullBooleanListField") + .Argument("nonNullBooleanListArg", + t => t.Type>>()) + .Type>() + .Resolve(() => null); + + // intArgField(intArg: ID): ID! + descriptor.Field("idArgField") + .Argument("idArg", t => t.Type()) + .Type>() + .Resolve(() => null); + + descriptor.Field("nonNullIdArgField") + .Argument("idArg", t => t.Type>()) + .Type>() + .Resolve(() => null); + + // stringArgField(intArg: String): String! + descriptor.Field("stringArgField") + .Argument("stringArg", t => t.Type()) + .Type>() + .Resolve(() => null); + + descriptor.Field("nonNullStringArgField") + .Argument("stringArg", t => t.Type>()) + .Type>() + .Resolve(() => null); + + descriptor.Field("stringListArgField") + .Argument("stringListArg", + t => t.Type>()) + .Type>() + .Resolve(() => null); + + // enumArgField(intArg: DogCommand): String! + descriptor.Field("enumArgField") + .Argument("enumArg", t => t.Type>()) + .Type>() + .Resolve(() => null); + + // "nonNullenumArgField(intArg: DogCommand!): String! + descriptor.Field("nonNullEnumArgField") + .Argument("enumArg", t => t.Type>>()) + .Type>() + .Resolve(() => null); + + descriptor.Field("complexArgField") + .Argument("complexArg", t => t.Type()) + .Type>() + .Argument("complexArg1", t => t.Type()) + .Type>() + .Argument("complexArg2", t => t.Type()) + .Type>() + .Resolve(() => null); + + descriptor.Field("nonNullFieldWithDefault") + .Argument("opt1", t => t.Type>().DefaultValue(0)) + .Type>() + .Resolve(() => null); + + descriptor.Field("nonNullFieldWithDefault") + .Argument("nonNullIntArg", t => t.Type>().DefaultValue(0)) + .Type>() + .Resolve(() => null); + + descriptor.Field("nonNullField") + .Argument("nonNullIntArg", t => t.Type>()) + .Type>() + .Resolve(() => null); + + descriptor.Field("stringListNonNullArgField") + .Argument( + "stringListNonNullArg", + t => t.Type>>()) + .Type>() + .Resolve(() => null); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/BeingType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/BeingType.cs index 73a3949ce55..2c709d7e4a8 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/BeingType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/BeingType.cs @@ -1,14 +1,13 @@ using HotChocolate.Types; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class BeingType + : InterfaceType { - public class BeingType - : InterfaceType + protected override void Configure(IInterfaceTypeDescriptor descriptor) { - protected override void Configure(IInterfaceTypeDescriptor descriptor) - { - descriptor.Name("Being"); - descriptor.Field("name").Type>(); - } + descriptor.Name("Being"); + descriptor.Field("name").Type>(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/CatInputType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/CatInputType.cs index 47ab5788746..b66fbd5fc88 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/CatInputType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/CatInputType.cs @@ -1,16 +1,15 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class CatInputType : InputObjectType { - public class CatInputType : InputObjectType + protected override void Configure(IInputObjectTypeDescriptor descriptor) { - protected override void Configure(IInputObjectTypeDescriptor descriptor) - { - descriptor.Name("CatInput"); + descriptor.Name("CatInput"); - descriptor.Field("name").Type("String!"); - descriptor.Field("nickname").Type("String"); - descriptor.Field("meowVolume").Type("Int"); - } + descriptor.Field("name").Type("String!"); + descriptor.Field("nickname").Type("String"); + descriptor.Field("meowVolume").Type("Int"); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/CatOrDogType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/CatOrDogType.cs index fbe638c4486..8d4fe477739 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/CatOrDogType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/CatOrDogType.cs @@ -1,15 +1,14 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class CatOrDogType + : UnionType { - public class CatOrDogType - : UnionType + protected override void Configure(IUnionTypeDescriptor descriptor) { - protected override void Configure(IUnionTypeDescriptor descriptor) - { - descriptor.Name("CatOrDog"); - descriptor.Type(); - descriptor.Type(); - } + descriptor.Name("CatOrDog"); + descriptor.Type(); + descriptor.Type(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/CatType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/CatType.cs index 8829b670455..e5612751a9e 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/CatType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/CatType.cs @@ -1,40 +1,37 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class CatType + : ObjectType { - public class CatType - : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Implements(); - descriptor.Implements(); - descriptor.Implements(); - descriptor.Field(t => t.Name).Type>(); - descriptor.Field(t => t.DoesKnowCommand(default)) - .Argument("catCommand", a => a.Type>>()); - descriptor.Field("furColor").Type().Resolve(() => null); - } + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); + descriptor.Field(t => t.DoesKnowCommand(default)) + .Argument("catCommand", a => a.Type>>()); + descriptor.Field("furColor").Type().Resolve(() => null); } +} - public class MammalType : InterfaceType +public class MammalType : InterfaceType +{ + protected override void Configure(IInterfaceTypeDescriptor descriptor) { - protected override void Configure(IInterfaceTypeDescriptor descriptor) - { - descriptor.Name("Mammal"); - descriptor.Field("name").Type>(); - } + descriptor.Name("Mammal"); + descriptor.Field("name").Type>(); } +} - public class CanineType : InterfaceType +public class CanineType : InterfaceType +{ + protected override void Configure(IInterfaceTypeDescriptor descriptor) { - protected override void Configure(IInterfaceTypeDescriptor descriptor) - { - descriptor.Name("Canine"); - descriptor.Implements(); - descriptor.Field("name").Type>(); - } + descriptor.Name("Canine"); + descriptor.Implements(); + descriptor.Field("name").Type>(); } - - -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/Complex2InputType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/Complex2InputType.cs index 4416816d767..575b9cb2f55 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/Complex2InputType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/Complex2InputType.cs @@ -1,19 +1,18 @@ using HotChocolate.Language; using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class Complex2InputType + : InputObjectType { - public class Complex2InputType - : InputObjectType + protected override void Configure( + IInputObjectTypeDescriptor descriptor) { - protected override void Configure( - IInputObjectTypeDescriptor descriptor) - { - descriptor.Field(t => t.Name) - .Type>(); - descriptor.Field(t => t.Owner) - .Type>() - .DefaultValue(new StringValueNode("1234")); - } + descriptor.Field(t => t.Name) + .Type>(); + descriptor.Field(t => t.Owner) + .Type>() + .DefaultValue(new StringValueNode("1234")); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/Complex3InputType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/Complex3InputType.cs index 26cf10030f3..85e9ce90fba 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/Complex3InputType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/Complex3InputType.cs @@ -1,49 +1,48 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class Complex3InputType + : InputObjectType { - public class Complex3InputType - : InputObjectType + protected override void Configure( + IInputObjectTypeDescriptor descriptor) { - protected override void Configure( - IInputObjectTypeDescriptor descriptor) - { - descriptor.Field("requiredField") - .Type>(); + descriptor.Field("requiredField") + .Type>(); - descriptor.Field("intField") - .Type(); + descriptor.Field("intField") + .Type(); - descriptor.Field("stringField") - .Type(); + descriptor.Field("stringField") + .Type(); - descriptor.Field("booleanField") - .Type(); + descriptor.Field("booleanField") + .Type(); - descriptor.Field("stringListField") - .Type>(); + descriptor.Field("stringListField") + .Type>(); - descriptor.Field("nonNullField") - .Type>() - .DefaultValue(true); + descriptor.Field("nonNullField") + .Type>() + .DefaultValue(true); - descriptor.Field("f") - .Type(); + descriptor.Field("f") + .Type(); - descriptor.Field("f1") - .Type(); + descriptor.Field("f1") + .Type(); - descriptor.Field("f2") - .Type(); + descriptor.Field("f2") + .Type(); - descriptor.Field("f3") - .Type(); + descriptor.Field("f3") + .Type(); - descriptor.Field("id") - .Type(); + descriptor.Field("id") + .Type(); - descriptor.Field("deep") - .Type(); - } + descriptor.Field("deep") + .Type(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexDirective.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexDirective.cs index 864c921223c..4eb9869ab0b 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexDirective.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexDirective.cs @@ -1,24 +1,23 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class ComplexDirective + : DirectiveType { - public class ComplexDirective - : DirectiveType + protected override void Configure( + IDirectiveTypeDescriptor descriptor) { - protected override void Configure( - IDirectiveTypeDescriptor descriptor) - { - descriptor.Repeatable(); + descriptor.Repeatable(); - descriptor.Name("complex"); + descriptor.Name("complex"); - descriptor.Location(HotChocolate.Types.DirectiveLocation.Field); + descriptor.Location(HotChocolate.Types.DirectiveLocation.Field); - descriptor.Argument("anyArg") - .Type(); + descriptor.Argument("anyArg") + .Type(); - descriptor.Argument("stringArg") - .Type(); - } + descriptor.Argument("stringArg") + .Type(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexInputType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexInputType.cs index 6343fcda6f7..c2472780c3c 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexInputType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/ComplexInputType.cs @@ -1,13 +1,12 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class ComplexInputType + : InputObjectType { - public class ComplexInputType - : InputObjectType + protected override void Configure( + IInputObjectTypeDescriptor descriptor) { - protected override void Configure( - IInputObjectTypeDescriptor descriptor) - { - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/CustomDirectiveType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/CustomDirectiveType.cs index 10431106470..9f468f988ed 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/CustomDirectiveType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/CustomDirectiveType.cs @@ -1,37 +1,36 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class CustomDirectiveType + : DirectiveType { - public class CustomDirectiveType - : DirectiveType + private readonly string _name; + + public CustomDirectiveType(string name) + { + _name = name; + } + + protected override void Configure( + IDirectiveTypeDescriptor descriptor) { - private readonly string _name; - - public CustomDirectiveType(string name) - { - _name = name; - } - - protected override void Configure( - IDirectiveTypeDescriptor descriptor) - { - descriptor.Repeatable(); - - descriptor.Name(_name); - - descriptor.Location(DirectiveLocation.Field); - - descriptor.Argument("arg") - .Type(); - descriptor.Argument("arg1") - .Type(); - descriptor.Argument("arg2") - .Type(); - descriptor.Argument("arg3") - .Type(); - descriptor.Argument("arg4") - .Type(); - - } + descriptor.Repeatable(); + + descriptor.Name(_name); + + descriptor.Location(DirectiveLocation.Field); + + descriptor.Argument("arg") + .Type(); + descriptor.Argument("arg1") + .Type(); + descriptor.Argument("arg2") + .Type(); + descriptor.Argument("arg3") + .Type(); + descriptor.Argument("arg4") + .Type(); + } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/DogInputType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/DogInputType.cs index 0ef9756310b..7165ac7d9a8 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/DogInputType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/DogInputType.cs @@ -1,16 +1,15 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class DogInputType : InputObjectType { - public class DogInputType : InputObjectType + protected override void Configure(IInputObjectTypeDescriptor descriptor) { - protected override void Configure(IInputObjectTypeDescriptor descriptor) - { - descriptor.Name("DogInput"); + descriptor.Name("DogInput"); - descriptor.Field("name").Type("String!"); - descriptor.Field("nickname").Type("String"); - descriptor.Field("barkVolume").Type("Int"); - } + descriptor.Field("name").Type("String!"); + descriptor.Field("nickname").Type("String"); + descriptor.Field("barkVolume").Type("Int"); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/DogOrHumanType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/DogOrHumanType.cs index 780edad8e92..395699b4dcd 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/DogOrHumanType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/DogOrHumanType.cs @@ -1,15 +1,14 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class DogOrHumanType + : UnionType { - public class DogOrHumanType - : UnionType + protected override void Configure(IUnionTypeDescriptor descriptor) { - protected override void Configure(IUnionTypeDescriptor descriptor) - { - descriptor.Name("DogOrHuman"); - descriptor.Type(); - descriptor.Type(); - } + descriptor.Name("DogOrHuman"); + descriptor.Type(); + descriptor.Type(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/DogType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/DogType.cs index c9687166e6d..1f01ac3d4d1 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/DogType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/DogType.cs @@ -1,19 +1,18 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class DogType + : ObjectType { - public class DogType - : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Implements(); - descriptor.Implements(); - descriptor.Implements(); - descriptor.Implements(); - descriptor.Field(t => t.Name).Type>(); - descriptor.Field(t => t.DoesKnowCommand(default)) - .Argument("dogCommand", a => a.Type>>()); - } + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); + descriptor.Field(t => t.DoesKnowCommand(default)) + .Argument("dogCommand", a => a.Type>>()); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/FurColor.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/FurColor.cs index c74fdac4078..fe0b2aaf7ce 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/FurColor.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/FurColor.cs @@ -1,14 +1,13 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class FurColor : EnumType { - public class FurColor : EnumType + protected override void Configure(IEnumTypeDescriptor descriptor) { - protected override void Configure(IEnumTypeDescriptor descriptor) - { - descriptor.Value("RED"); - descriptor.Value("BLUE"); - descriptor.Value("GREEN"); - } + descriptor.Value("RED"); + descriptor.Value("BLUE"); + descriptor.Value("GREEN"); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/HumanOrAlienType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/HumanOrAlienType.cs index 2587386209b..f13faad8923 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/HumanOrAlienType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/HumanOrAlienType.cs @@ -1,15 +1,14 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class HumanOrAlienType + : UnionType { - public class HumanOrAlienType - : UnionType + protected override void Configure(IUnionTypeDescriptor descriptor) { - protected override void Configure(IUnionTypeDescriptor descriptor) - { - descriptor.Name("HumanOrAlien"); - descriptor.Type(); - descriptor.Type(); - } + descriptor.Name("HumanOrAlien"); + descriptor.Type(); + descriptor.Type(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/HumanType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/HumanType.cs index 63105908730..557be230071 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/HumanType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/HumanType.cs @@ -1,25 +1,24 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class HumanType + : ObjectType { - public class HumanType - : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Implements(); - descriptor.Implements(); - descriptor.Implements(); - descriptor.Field(t => t.Name).Type>(); - descriptor.Field("iq") - .Type>() - .Resolve(() => ""); - descriptor.Field("pets") - .Type>() - .Resolve(() => ""); - descriptor.Field("relatives") - .Type>() - .Resolve(() => ""); - } + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); + descriptor.Field("iq") + .Type>() + .Resolve(() => ""); + descriptor.Field("pets") + .Type>() + .Resolve(() => ""); + descriptor.Field("relatives") + .Type>() + .Resolve(() => ""); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/IntelligentType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/IntelligentType.cs index ac131ce5ee1..407d0bcd85e 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/IntelligentType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/IntelligentType.cs @@ -1,14 +1,13 @@ using HotChocolate.Types; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class IntelligentType + : InterfaceType { - public class IntelligentType - : InterfaceType + protected override void Configure(IInterfaceTypeDescriptor descriptor) { - protected override void Configure(IInterfaceTypeDescriptor descriptor) - { - descriptor.Name("Intelligent"); - descriptor.Field("iq").Type>(); - } + descriptor.Name("Intelligent"); + descriptor.Field("iq").Type>(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/InvalidScalar.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/InvalidScalar.cs index a503183c595..cb64477933f 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/InvalidScalar.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/InvalidScalar.cs @@ -4,33 +4,32 @@ #nullable enable -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class InvalidScalar : ScalarType { - public class InvalidScalar : ScalarType + public InvalidScalar() + : base("Invalid", BindingBehavior.Explicit) { - public InvalidScalar() - : base("Invalid", BindingBehavior.Explicit) - { - } + } - public override bool IsInstanceOfType(IValueNode literal) - { - return false; - } + public override bool IsInstanceOfType(IValueNode literal) + { + return false; + } - public override object? ParseLiteral(IValueNode valueSyntax) - { - throw new InvalidOperationException(); - } + public override object? ParseLiteral(IValueNode valueSyntax) + { + throw new InvalidOperationException(); + } - public override IValueNode ParseValue(object? value) - { - throw new InvalidOperationException(); - } + public override IValueNode ParseValue(object? value) + { + throw new InvalidOperationException(); + } - public override IValueNode ParseResult(object? resultValue) - { - throw new InvalidOperationException(); - } + public override IValueNode ParseResult(object? resultValue) + { + throw new InvalidOperationException(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/MessageType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/MessageType.cs index a5f49b68e8d..ac42c7e2261 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/MessageType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/MessageType.cs @@ -1,21 +1,20 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class MessageType + : ObjectType { - public class MessageType - : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Name("Message"); + descriptor.Name("Message"); - descriptor.Field("body") - .Type>() - .Resolve(() => "foo"); + descriptor.Field("body") + .Type>() + .Resolve(() => "foo"); - descriptor.Field("sender") - .Type>() - .Resolve(() => "foo"); - } + descriptor.Field("sender") + .Type>() + .Resolve(() => "foo"); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/MutationType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/MutationType.cs index 22dd4a83932..229c70f1eaa 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/MutationType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/MutationType.cs @@ -1,22 +1,21 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class MutationType + : ObjectType { - public class MutationType - : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Name("Mutation"); + descriptor.Name("Mutation"); - descriptor.Field("fieldB") - .Type>() - .Resolve(() => "foo"); + descriptor.Field("fieldB") + .Type>() + .Resolve(() => "foo"); - descriptor.Field("addPet") - .Argument("pet", a => a.Type()) - .Type() - .Resolve(() => "foo"); - } + descriptor.Field("addPet") + .Argument("pet", a => a.Type()) + .Type() + .Resolve(() => "foo"); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/PetInputType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/PetInputType.cs index 23f912dd598..78815d50f39 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/PetInputType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/PetInputType.cs @@ -1,15 +1,14 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class PetInputType : InputObjectType { - public class PetInputType : InputObjectType + protected override void Configure(IInputObjectTypeDescriptor descriptor) { - protected override void Configure(IInputObjectTypeDescriptor descriptor) - { - descriptor.Name("PetInput").OneOf(); + descriptor.Name("PetInput").OneOf(); - descriptor.Field("cat").Type(); - descriptor.Field("dog").Type(); - } + descriptor.Field("cat").Type(); + descriptor.Field("dog").Type(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/PetType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/PetType.cs index 988a3d76fa7..58ee729cd56 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/PetType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/PetType.cs @@ -1,15 +1,14 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class PetType + : InterfaceType { - public class PetType - : InterfaceType + protected override void Configure(IInterfaceTypeDescriptor descriptor) { - protected override void Configure(IInterfaceTypeDescriptor descriptor) - { - descriptor.Name("Pet"); - descriptor.Implements(); - descriptor.Field("name").Type>(); - } + descriptor.Name("Pet"); + descriptor.Implements(); + descriptor.Field("name").Type>(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/QueryType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/QueryType.cs index 938cb24d108..f8c7a659205 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/QueryType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/QueryType.cs @@ -1,43 +1,42 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class QueryType : ObjectType { - public class QueryType : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Field("arguments") - .Type() - .Resolve(() => null); - - descriptor.Field("invalidArg") - .Type() - .Argument("arg", a => a.Type()) - .Resolve(() => null); - - descriptor.Field("anyArg") - .Type() - .Argument("arg", a => a.Type()) - .Resolve(() => null); - - descriptor.Field("field") - .Type() - .Argument("a", a => a.Type()) - .Argument("b", a => a.Type()) - .Argument("c", a => a.Type()) - .Argument("d", a => a.Type()) - .Type() - .Resolve(() => null); - - descriptor.Field(t => t.GetCatOrDog()) - .Type(); - - descriptor.Field(t => t.GetDogOrHuman()) - .Type(); - - descriptor.Field("nonNull") - .Argument("a", a => a.Type>().DefaultValue("abc")) - .Resolve("foo"); - } + descriptor.Field("arguments") + .Type() + .Resolve(() => null); + + descriptor.Field("invalidArg") + .Type() + .Argument("arg", a => a.Type()) + .Resolve(() => null); + + descriptor.Field("anyArg") + .Type() + .Argument("arg", a => a.Type()) + .Resolve(() => null); + + descriptor.Field("field") + .Type() + .Argument("a", a => a.Type()) + .Argument("b", a => a.Type()) + .Argument("c", a => a.Type()) + .Argument("d", a => a.Type()) + .Type() + .Resolve(() => null); + + descriptor.Field(t => t.GetCatOrDog()) + .Type(); + + descriptor.Field(t => t.GetDogOrHuman()) + .Type(); + + descriptor.Field("nonNull") + .Argument("a", a => a.Type>().DefaultValue("abc")) + .Resolve("foo"); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/SentientType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/SentientType.cs index eaef90ab2d8..48124d253ad 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/SentientType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/SentientType.cs @@ -1,14 +1,13 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class SentientType + : InterfaceType { - public class SentientType - : InterfaceType + protected override void Configure(IInterfaceTypeDescriptor descriptor) { - protected override void Configure(IInterfaceTypeDescriptor descriptor) - { - descriptor.Name("Sentient"); - descriptor.Field("name").Type>(); - } + descriptor.Name("Sentient"); + descriptor.Field("name").Type>(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/Types/SubscriptionType.cs b/src/HotChocolate/Core/test/Validation.Tests/Types/SubscriptionType.cs index 08047678f55..126ba1de3a7 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/Types/SubscriptionType.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/Types/SubscriptionType.cs @@ -1,25 +1,27 @@ using HotChocolate.Types; -namespace HotChocolate.Validation.Types +namespace HotChocolate.Validation.Types; + +public class SubscriptionType : ObjectType { - public class SubscriptionType - : ObjectType + protected override void Configure(IObjectTypeDescriptor descriptor) { - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Name("Subscription"); + descriptor.Name("Subscription"); + + descriptor.Field("newMessage") + .Type>() + .Resolve(() => "foo"); - descriptor.Field("newMessage") - .Type>() - .Resolve(() => "foo"); + descriptor.Field("disallowedSecondRootField") + .Type>() + .Resolve(() => "foo"); - descriptor.Field("disallowedSecondRootField") - .Type>() - .Resolve(() => "foo"); + descriptor.Field("disallowedThirdRootField") + .Type>() + .Resolve(() => "foo"); - descriptor.Field("disallowedThirdRootField") - .Type>() - .Resolve(() => "foo"); - } + descriptor.Field("listEvent") + .Type>>() + .Resolve(() => "foo"); } } diff --git a/src/HotChocolate/Core/test/Validation.Tests/ValidationUtils.cs b/src/HotChocolate/Core/test/Validation.Tests/ValidationUtils.cs index e2a41617183..36be91253cb 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/ValidationUtils.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/ValidationUtils.cs @@ -6,86 +6,85 @@ #nullable enable -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public static class ValidationUtils { - public static class ValidationUtils + public static DocumentValidatorContext CreateContext(ISchema? schema = null) { - public static DocumentValidatorContext CreateContext(ISchema? schema = null) - { - return new() { Schema = schema ?? CreateSchema() }; - } + return new() { Schema = schema ?? CreateSchema() }; + } - public static void Prepare(this IDocumentValidatorContext context, DocumentNode document) - { - context.Fragments.Clear(); + public static void Prepare(this IDocumentValidatorContext context, DocumentNode document) + { + context.Fragments.Clear(); - for (var i = 0; i < document.Definitions.Count; i++) + for (var i = 0; i < document.Definitions.Count; i++) + { + var definitionNode = document.Definitions[i]; + if (definitionNode.Kind == SyntaxKind.FragmentDefinition) { - IDefinitionNode definitionNode = document.Definitions[i]; - if (definitionNode.Kind == SyntaxKind.FragmentDefinition) - { - var fragmentDefinition = (FragmentDefinitionNode)definitionNode; - context.Fragments[fragmentDefinition.Name.Value] = fragmentDefinition; - } + var fragmentDefinition = (FragmentDefinitionNode)definitionNode; + context.Fragments[fragmentDefinition.Name.Value] = fragmentDefinition; } } + } - public static ISchemaBuilder AddDirectiveType( - this ISchemaBuilder builder, - string name, - DirectiveLocation location) => - AddDirectiveType(builder, name, location, x => x); + public static ISchemaBuilder AddDirectiveType( + this ISchemaBuilder builder, + string name, + DirectiveLocation location) => + AddDirectiveType(builder, name, location, x => x); - public static ISchemaBuilder AddDirectiveType( - this ISchemaBuilder builder, - string name, - DirectiveLocation location, - Func configure) => - builder.AddDirectiveType(new DirectiveType(x => - configure(x.Name(name).Location(location)))); + public static ISchemaBuilder AddDirectiveType( + this ISchemaBuilder builder, + string name, + DirectiveLocation location, + Func configure) => + builder.AddDirectiveType(new DirectiveType(x => + configure(x.Name(name).Location(location)))); - public static ISchema CreateSchema() - => SchemaBuilder.New() - .AddQueryType() - .AddMutationType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddSubscriptionType() - .AddType() - .AddType() - .AddType() - .AddType() - .AddDirectiveType() - .AddDirectiveType(new CustomDirectiveType("directive")) - .AddDirectiveType(new CustomDirectiveType("directive1")) - .AddDirectiveType(new CustomDirectiveType("directive2")) - .AddDirectiveType("onMutation", DirectiveLocation.Mutation) - .AddDirectiveType("onQuery", DirectiveLocation.Query) - .AddDirectiveType("onSubscription", DirectiveLocation.Subscription) - .AddDirectiveType("onFragmentDefinition", DirectiveLocation.FragmentDefinition) - .AddDirectiveType("onVariableDefinition", DirectiveLocation.VariableDefinition) - .AddDirectiveType("directiveA", - DirectiveLocation.Field | - DirectiveLocation.FragmentDefinition) - .AddDirectiveType("directiveB", - DirectiveLocation.Field | - DirectiveLocation.FragmentDefinition) - .AddDirectiveType("directiveC", - DirectiveLocation.Field | - DirectiveLocation.FragmentDefinition) - .AddDirectiveType("repeatable", - DirectiveLocation.Field | - DirectiveLocation.FragmentDefinition, - x => x.Repeatable()) - .ModifyOptions(o => o.EnableOneOf = true) - .Create(); - } -} + public static ISchema CreateSchema() + => SchemaBuilder.New() + .AddQueryType() + .AddMutationType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddSubscriptionType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddDirectiveType() + .AddDirectiveType(new CustomDirectiveType("directive")) + .AddDirectiveType(new CustomDirectiveType("directive1")) + .AddDirectiveType(new CustomDirectiveType("directive2")) + .AddDirectiveType("onMutation", DirectiveLocation.Mutation) + .AddDirectiveType("onQuery", DirectiveLocation.Query) + .AddDirectiveType("onSubscription", DirectiveLocation.Subscription) + .AddDirectiveType("onFragmentDefinition", DirectiveLocation.FragmentDefinition) + .AddDirectiveType("onVariableDefinition", DirectiveLocation.VariableDefinition) + .AddDirectiveType("directiveA", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition) + .AddDirectiveType("directiveB", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition) + .AddDirectiveType("directiveC", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition) + .AddDirectiveType("repeatable", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition, + x => x.Repeatable()) + .ModifyOptions(o => o.EnableOneOf = true) + .Create(); +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs index 3428f8a9113..a86c062ea22 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs @@ -2,20 +2,20 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class ValuesOfCorrectTypeRuleTests + : DocumentValidatorVisitorTestBase { - public class ValuesOfCorrectTypeRuleTests - : DocumentValidatorVisitorTestBase + public ValuesOfCorrectTypeRuleTests() + : base(builder => builder.AddValueRules()) { - public ValuesOfCorrectTypeRuleTests() - : base(builder => builder.AddValueRules()) - { - } + } - [Fact] - public void GoodBooleanArg() - { - ExpectValid(@" + [Fact] + public void GoodBooleanArg() + { + ExpectValid(@" { arguments { ...goodBooleanArg @@ -26,70 +26,70 @@ public void GoodBooleanArg() booleanArgField(booleanArg: true) } "); - } + } - [Fact] - public void GoodBooleanListArg() - { - ExpectValid(@" + [Fact] + public void GoodBooleanListArg() + { + ExpectValid(@" query queryWithListInput() { booleanList(booleanListArg: [ true, false ]) }"); - } + } - [Fact] - public void GoodBooleanListVariableArg() - { - ExpectValid(@" + [Fact] + public void GoodBooleanListVariableArg() + { + ExpectValid(@" query queryWithListInput($value: Boolean!) { booleanList(booleanListArg: [ true, $value ]) }"); - } + } - [Fact] - public void BadBooleanListArg() - { - ExpectErrors(@" + [Fact] + public void BadBooleanListArg() + { + ExpectErrors(@" query queryWithListInput() { booleanList(booleanListArg: [ true, ""false"" ]) }", - t => - { - Assert.Equal( - "The specified argument value does not" + - " match the argument type.", - t.Message); - Assert.Equal("[Boolean!]", t.Extensions!["locationType"]); - Assert.Equal("booleanListArg", t.Extensions["argument"]); - }); - } - - [Fact] - public void BadBooleanListArgString() - { - ExpectErrors(@" + t => + { + Assert.Equal( + "The specified argument value does not" + + " match the argument type.", + t.Message); + Assert.Equal("[Boolean!]", t.Extensions!["locationType"]); + Assert.Equal("booleanListArg", t.Extensions["argument"]); + }); + } + + [Fact] + public void BadBooleanListArgString() + { + ExpectErrors(@" query queryWithListInput() { booleanList(booleanListArg: ""false"" ) }", - t => - { - Assert.Equal( - "The specified argument value does not" + - " match the argument type.", - t.Message); - Assert.Equal("[Boolean!]", t.Extensions!["locationType"]); - Assert.Equal("booleanListArg", t.Extensions["argument"]); - }); - } - - [Fact] - public void CoercedIntIntoFloatArg() - { - ExpectValid(@" + t => + { + Assert.Equal( + "The specified argument value does not" + + " match the argument type.", + t.Message); + Assert.Equal("[Boolean!]", t.Extensions!["locationType"]); + Assert.Equal("booleanListArg", t.Extensions["argument"]); + }); + } + + [Fact] + public void CoercedIntIntoFloatArg() + { + ExpectValid(@" { arguments { ...coercedIntIntoFloatArg @@ -101,22 +101,22 @@ public void CoercedIntIntoFloatArg() floatArgField(floatArg: 123) } "); - } + } - [Fact] - public void GoodComplexDefaultValue() - { - ExpectValid(@" + [Fact] + public void GoodComplexDefaultValue() + { + ExpectValid(@" query goodComplexDefaultValue($search: ComplexInput = { name: ""Fido"" }) { findDog(complex: $search) } "); - } + } - [Fact] - public void StringIntoInt() - { - ExpectErrors(@" + [Fact] + public void StringIntoInt() + { + ExpectErrors(@" { arguments { ...stringIntoInt @@ -128,15 +128,15 @@ public void StringIntoInt() } ", t => Assert.Equal( - "The specified argument value does not match the " + - "argument type.", - t.Message)); - } - - [Fact] - public void BadComplexValueArgument() - { - ExpectErrors(@" + "The specified argument value does not match the " + + "argument type.", + t.Message)); + } + + [Fact] + public void BadComplexValueArgument() + { + ExpectErrors(@" query badComplexValue { findDog(complex: { name: 123 }) } @@ -145,26 +145,26 @@ public void BadComplexValueArgument() "The specified value type of field `name` " + "does not match the field type.", t.Message)); - } + } - [Fact] - public void BadComplexValueVariable() - { - ExpectErrors(@" + [Fact] + public void BadComplexValueVariable() + { + ExpectErrors(@" query goodComplexDefaultValue($search: ComplexInput = { name: 123 }) { findDog(complex: $search) } ", t => Assert.Equal( "The specified value type of field `name` " + - "does not match the field type.", - t.Message)); - } - - [Fact] - public void BadValueVariable() - { - ExpectErrors(@" + "does not match the field type.", + t.Message)); + } + + [Fact] + public void BadValueVariable() + { + ExpectErrors(@" query goodComplexDefaultValue($search: ComplexInput = 123) { findDog(complex: $search) } @@ -173,767 +173,767 @@ public void BadValueVariable() "The specified value type of variable `search` " + "does not match the variable type.", t.Message)); - } + } - [Fact] - public void GoodNullToIntNullableValue() - { - ExpectValid(@" + [Fact] + public void GoodNullToIntNullableValue() + { + ExpectValid(@" { arguments { intArgField(intArg: null) } } "); - } + } - [Fact] - public void GoodIntValue() - { - ExpectValid(@" + [Fact] + public void GoodIntValue() + { + ExpectValid(@" { arguments { intArgField(intArg: 2) } } "); - } + } - [Fact] - public void GoodIntNegativeValue() - { - ExpectValid(@" + [Fact] + public void GoodIntNegativeValue() + { + ExpectValid(@" { arguments { intArgField(intArg: -2) } } "); - } + } - [Fact] - public void GoodNullToBooleanNullableValue() - { - ExpectValid(@" + [Fact] + public void GoodNullToBooleanNullableValue() + { + ExpectValid(@" { arguments { booleanArgField(booleanArg: true) } } "); - } + } - [Fact] - public void GoodBooleanValue() - { - ExpectValid(@" + [Fact] + public void GoodBooleanValue() + { + ExpectValid(@" { arguments { booleanArgField(booleanArg: true) } } "); - } + } - [Fact] - public void GoodStringValue() - { - ExpectValid(@" + [Fact] + public void GoodStringValue() + { + ExpectValid(@" { arguments { stringArgField(stringArg: ""foo"") } } "); - } + } - [Fact] - public void GoodNullToStringNullableValue() - { - ExpectValid(@" + [Fact] + public void GoodNullToStringNullableValue() + { + ExpectValid(@" { arguments { stringArgField(stringArg: null) } } "); - } + } - [Fact] - public void GoodNullToFloatNullableValue() - { - ExpectValid(@" + [Fact] + public void GoodNullToFloatNullableValue() + { + ExpectValid(@" { arguments { floatArgField(floatArg: null) } } "); - } + } - [Fact] - public void GoodFloatValue() - { - ExpectValid(@" + [Fact] + public void GoodFloatValue() + { + ExpectValid(@" { arguments { floatArgField(floatArg: 1.1) } } "); - } + } - [Fact] - public void GoodNegativeFloatValue() - { - ExpectValid(@" + [Fact] + public void GoodNegativeFloatValue() + { + ExpectValid(@" { arguments { floatArgField(floatArg: -1.1) } } "); - } + } - [Fact] - public void GoodIntToFloat() - { - ExpectValid(@" + [Fact] + public void GoodIntToFloat() + { + ExpectValid(@" { arguments { floatArgField(floatArg: 1) } } "); - } + } - [Fact] - public void GoodIntToId() - { - ExpectValid(@" + [Fact] + public void GoodIntToId() + { + ExpectValid(@" { arguments { idArgField(idArg: 1) } } "); - } + } - [Fact] - public void GoodStringToId() - { - ExpectValid(@" + [Fact] + public void GoodStringToId() + { + ExpectValid(@" { arguments { idArgField(idArg: ""someIdString"") } } "); - } + } - [Fact] - public void GoodNullToIdNullable() - { - ExpectValid(@" + [Fact] + public void GoodNullToIdNullable() + { + ExpectValid(@" { arguments { idArgField(idArg: null) } } "); - } + } - [Fact] - public void GoodEnumValue() - { - ExpectValid(@" + [Fact] + public void GoodEnumValue() + { + ExpectValid(@" { arguments { enumArgField(enumArg: SIT) } } "); - } + } - [Fact] - public void GoodNullToEnumNullableValue() - { - ExpectValid(@" + [Fact] + public void GoodNullToEnumNullableValue() + { + ExpectValid(@" { arguments { enumArgField(enumArg: null) } } "); - } + } - [Fact] - public void BadIntIntoString() - { - ExpectErrors(@" + [Fact] + public void BadIntIntoString() + { + ExpectErrors(@" { arguments { stringArgField(stringArg: 1) } } "); - } + } - [Fact] - public void BadFloatIntoString() - { - ExpectErrors(@" + [Fact] + public void BadFloatIntoString() + { + ExpectErrors(@" { arguments { stringArgField(stringArg: 1.0) } } "); - } + } - [Fact] - public void BadBooleanIntoString() - { - ExpectErrors(@" + [Fact] + public void BadBooleanIntoString() + { + ExpectErrors(@" { arguments { stringArgField(stringArg: true) } } "); - } + } - [Fact] - public void BadEnumIntoString() - { - ExpectErrors(@" + [Fact] + public void BadEnumIntoString() + { + ExpectErrors(@" { arguments { stringArgField(stringArg: BAR) } } "); - } + } - [Fact] - public void BadStringIntoInt() - { - ExpectErrors(@" + [Fact] + public void BadStringIntoInt() + { + ExpectErrors(@" { arguments { intArgField(intArg: ""3"") } } "); - } + } - [Fact] - public void BadBooleanIntoInt() - { - ExpectErrors(@" + [Fact] + public void BadBooleanIntoInt() + { + ExpectErrors(@" { arguments { intArgField(intArg: false) } } "); - } + } - [Fact] - public void BadEnumIntoInt() - { - ExpectErrors(@" + [Fact] + public void BadEnumIntoInt() + { + ExpectErrors(@" { arguments { intArgField(intArg: BAR) } } "); - } + } - [Fact] - public void BadSimpleFloatIntoInt() - { - ExpectErrors(@" + [Fact] + public void BadSimpleFloatIntoInt() + { + ExpectErrors(@" { arguments { intArgField(intArg: 3.0) } } "); - } + } - [Fact] - public void BadFloatIntoInt() - { - ExpectErrors(@" + [Fact] + public void BadFloatIntoInt() + { + ExpectErrors(@" { arguments { intArgField(intArg: 3.333) } } "); - } + } - [Fact] - public void BadStringIntoFloat() - { - ExpectErrors(@" + [Fact] + public void BadStringIntoFloat() + { + ExpectErrors(@" { arguments { floatArgField(floatArg: ""3.333"") } } "); - } + } - [Fact] - public void BadBooleanIntoFloat() - { - ExpectErrors(@" + [Fact] + public void BadBooleanIntoFloat() + { + ExpectErrors(@" { arguments { floatArgField(floatArg: true) } } "); - } + } - [Fact] - public void BadEnumIntoFloat() - { - ExpectErrors(@" + [Fact] + public void BadEnumIntoFloat() + { + ExpectErrors(@" { arguments { floatArgField(floatArg: BAR) } } "); - } + } - [Fact] - public void BadStringIntoBool() - { - ExpectErrors(@" + [Fact] + public void BadStringIntoBool() + { + ExpectErrors(@" { arguments { intArgField(intArg: ""true"") } } "); - } + } - [Fact] - public void BadEnumIntoBool() - { - ExpectErrors(@" + [Fact] + public void BadEnumIntoBool() + { + ExpectErrors(@" { arguments { booleanArgField(booleanArg: BAR) } } "); - } + } - [Fact] - public void BadSimpleFloatIntoBool() - { - ExpectErrors(@" + [Fact] + public void BadSimpleFloatIntoBool() + { + ExpectErrors(@" { arguments { booleanArgField(booleanArg: 3.0) } } "); - } + } - [Fact] - public void BadFloatIntoBool() - { - ExpectErrors(@" + [Fact] + public void BadFloatIntoBool() + { + ExpectErrors(@" { arguments { booleanArgField(booleanArg: 3.333) } } "); - } + } - [Fact] - public void BadFloatIntoId() - { - ExpectErrors(@" + [Fact] + public void BadFloatIntoId() + { + ExpectErrors(@" { arguments { idArgField(idArg: 1.0) } } "); - } + } - [Fact] - public void BadBooleanIntoId() - { - ExpectErrors(@" + [Fact] + public void BadBooleanIntoId() + { + ExpectErrors(@" { arguments { idArgField(idArg: true) } } "); - } + } - [Fact] - public void BadEnumIntoId() - { - ExpectErrors(@" + [Fact] + public void BadEnumIntoId() + { + ExpectErrors(@" { arguments { idArgField(idArg: TRUE) } } "); - } + } - [Fact] - public void BadIntIntoEnum() - { - ExpectErrors(@" + [Fact] + public void BadIntIntoEnum() + { + ExpectErrors(@" { arguments { enumArgField(enumArg: 2) } } "); - } + } - [Fact] - public void BadFloatIntoEnum() - { - ExpectErrors(@" + [Fact] + public void BadFloatIntoEnum() + { + ExpectErrors(@" { arguments { enumArgField(enumArg: 1.0) } } "); - } + } - [Fact] - public void BadStringIntoEnum() - { - ExpectErrors(@" + [Fact] + public void BadStringIntoEnum() + { + ExpectErrors(@" { arguments { enumArgField(enumArg: ""SIT"") } } "); - } + } - [Fact] - public void BadBooleanIntoEnum() - { - ExpectErrors(@" + [Fact] + public void BadBooleanIntoEnum() + { + ExpectErrors(@" { arguments { enumArgField(enumArg: true) } } "); - } + } - [Fact] - public void BadUnknowEnumIntoEnum() - { - ExpectErrors(@" + [Fact] + public void BadUnknowEnumIntoEnum() + { + ExpectErrors(@" { arguments { enumArgField(enumArg: HELLO) } } "); - } + } - [Fact] - public void BadWrongCasingEnumIntoEnum() - { - ExpectErrors(@" + [Fact] + public void BadWrongCasingEnumIntoEnum() + { + ExpectErrors(@" { arguments { enumArgField(enumArg: sit) } } "); - } + } - [Fact(Skip = "This really should be caught! " + - "=> Spec issue http://spec.graphql.org/draft/#sel-JALTHHDHFFCAACEQl_M")] - public void BadNullToString() - { - ExpectErrors(@" + [Fact(Skip = "This really should be caught! " + + "=> Spec issue http://spec.graphql.org/draft/#sel-JALTHHDHFFCAACEQl_M")] + public void BadNullToString() + { + ExpectErrors(@" query InvalidItem { nonNull(a: null) } "); - } + } - [Fact] - public void GoodListValue() - { - ExpectValid(@" + [Fact] + public void GoodListValue() + { + ExpectValid(@" { arguments { stringListArgField(stringListArg: [""one"", null, ""two""]) } } "); - } + } - [Fact] - public void GoodEmptyListValue() - { - ExpectValid(@" + [Fact] + public void GoodEmptyListValue() + { + ExpectValid(@" { arguments { stringListArgField(stringListArg: []) } } "); - } + } - [Fact] - public void GoodNullListValue() - { - ExpectValid(@" + [Fact] + public void GoodNullListValue() + { + ExpectValid(@" { arguments { stringListArgField(stringListArg: null) } } "); - } + } - [Fact] - public void GoodSingleValueListValue() - { - ExpectValid(@" + [Fact] + public void GoodSingleValueListValue() + { + ExpectValid(@" { arguments { stringListArgField(stringListArg: ""singleValueInList"") } } "); - } + } - [Fact] - public void BadIncorrectItemType() - { - ExpectErrors(@" + [Fact] + public void BadIncorrectItemType() + { + ExpectErrors(@" { arguments { stringListArgField(stringListArg: [""one"", 2]) } } "); - } + } - [Fact] - public void BadSingleValueInvalid() - { - ExpectErrors(@" + [Fact] + public void BadSingleValueInvalid() + { + ExpectErrors(@" { arguments { stringListArgField(stringListArg: 2) } } "); - } + } - [Fact] - public void GoodArgOnOptionalArg() - { - ExpectValid(@" + [Fact] + public void GoodArgOnOptionalArg() + { + ExpectValid(@" { dog { isHouseTrained(atOtherHomes: true) } } "); - } + } - [Fact] - public void GoodNoArgOnOptionalArg() - { - ExpectValid(@" + [Fact] + public void GoodNoArgOnOptionalArg() + { + ExpectValid(@" { dog { isHouseTrained } } "); - } + } - [Fact] - public void GoodMultipleArgs() - { - ExpectValid(@" + [Fact] + public void GoodMultipleArgs() + { + ExpectValid(@" { arguments { multipleReqs(x: 1, y: 2) } } "); - } + } - [Fact] - public void GoodMultipleArgsReversed() - { - ExpectValid(@" + [Fact] + public void GoodMultipleArgsReversed() + { + ExpectValid(@" { arguments { multipleReqs(y: 2, x: 1) } } "); - } + } - [Fact] - public void GoodNoMultipleArgsOps() - { - ExpectValid(@" + [Fact] + public void GoodNoMultipleArgsOps() + { + ExpectValid(@" { arguments { multipleOpts } } "); - } + } - [Fact] - public void GoodOneMultipleArgsOps() - { - ExpectValid(@" + [Fact] + public void GoodOneMultipleArgsOps() + { + ExpectValid(@" { arguments { multipleOpts(opt1: 1) } } "); - } + } - [Fact] - public void GoodSecondOneMultipleArgsOps() - { - ExpectValid(@" + [Fact] + public void GoodSecondOneMultipleArgsOps() + { + ExpectValid(@" { arguments { multipleOpts(opt2: 1) } } "); - } + } - [Fact] - public void GoodMultipleRequiredArgsOnMixedList() - { - ExpectValid(@" + [Fact] + public void GoodMultipleRequiredArgsOnMixedList() + { + ExpectValid(@" { arguments { multipleOptsAndReqs(req1: 3, req2: 4) } } "); - } + } - [Fact] - public void GoodMultipleRequiredArgsOnMixedOneOptionalList() - { - ExpectValid(@" + [Fact] + public void GoodMultipleRequiredArgsOnMixedOneOptionalList() + { + ExpectValid(@" { arguments { multipleOptsAndReqs(req1: 3, req2: 4, opt1: 1) } } "); - } + } - [Fact] - public void GoodMultipleRequiredArgsOnMixedAllOptionalList() - { - ExpectValid(@" + [Fact] + public void GoodMultipleRequiredArgsOnMixedAllOptionalList() + { + ExpectValid(@" { arguments { multipleOptsAndReqs(req1: 3, req2: 4, opt1: 1, opt2: 2) } } "); - } + } - [Fact] - public void BadMultipleIncorrectValueType() - { - ExpectErrors(@" + [Fact] + public void BadMultipleIncorrectValueType() + { + ExpectErrors(@" { arguments { multipleReqs(x: ""two"", y: ""one"") } } "); - } + } - [Fact] - public void GoodOptionalArgDespiteRequiredFieldInType() - { - ExpectValid(@" + [Fact] + public void GoodOptionalArgDespiteRequiredFieldInType() + { + ExpectValid(@" { arguments { complexArgField } } "); - } + } - [Fact] - public void GoodPartialObjectOnlyRequired() - { - ExpectValid(@" + [Fact] + public void GoodPartialObjectOnlyRequired() + { + ExpectValid(@" { arguments { complexArgField(complexArg: { requiredField: true }) } } "); - } + } - [Fact] - public void GoodPartialObjectOnlyRequiredCanBeFalse() - { - ExpectValid(@" + [Fact] + public void GoodPartialObjectOnlyRequiredCanBeFalse() + { + ExpectValid(@" { arguments { complexArgField(complexArg: { requiredField: false }) } } "); - } + } - [Fact] - public void GoodPartialObjectIncludingRequired() - { - ExpectValid(@" + [Fact] + public void GoodPartialObjectIncludingRequired() + { + ExpectValid(@" { arguments { complexArgField(complexArg: { requiredField: true, intField: 4 }) } } "); - } + } - [Fact] - public void GoodComplexFullObject() - { - ExpectValid(@" + [Fact] + public void GoodComplexFullObject() + { + ExpectValid(@" { arguments { complexArgField(complexArg: { @@ -946,12 +946,12 @@ public void GoodComplexFullObject() } } "); - } + } - [Fact] - public void GoodComplexFullDfferentOrderObject() - { - ExpectValid(@" + [Fact] + public void GoodComplexFullDfferentOrderObject() + { + ExpectValid(@" { arguments { complexArgField(complexArg: { @@ -964,12 +964,12 @@ public void GoodComplexFullDfferentOrderObject() } } "); - } + } - [Fact] - public void BadComplexInputInvalidElementType() - { - ExpectErrors(@" + [Fact] + public void BadComplexInputInvalidElementType() + { + ExpectErrors(@" { arguments { complexArgField(complexArg: { @@ -979,14 +979,14 @@ public void BadComplexInputInvalidElementType() } } "); - } + } - [Fact] - public void BadUnknownFieldOnComplexType() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void BadUnknownFieldOnComplexType() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" { complicatedArgs { complexArgField(complexArg: { @@ -996,29 +996,29 @@ public void BadUnknownFieldOnComplexType() } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.True(context.UnexpectedErrorsDetected); - } + // assert + Assert.True(context.UnexpectedErrorsDetected); + } - [Fact] - public void BadCustomerScalarIsInvalid() - { - ExpectErrors(@" + [Fact] + public void BadCustomerScalarIsInvalid() + { + ExpectErrors(@" { invalidArg(arg: 123) } "); - } + } - [Fact] - public void GoodCustomerScalarAcceptsComplexLiterals() - { - ExpectValid(@" + [Fact] + public void GoodCustomerScalarAcceptsComplexLiterals() + { + ExpectValid(@" { test1: anyArg(arg: 123) test2: anyArg(arg: ""abc"") @@ -1026,12 +1026,12 @@ public void GoodCustomerScalarAcceptsComplexLiterals() test4: anyArg(arg: {deep: [123, ""abc""]}) } "); - } + } - [Fact] - public void GoodDirectiveValidTypes() - { - ExpectValid(@" + [Fact] + public void GoodDirectiveValidTypes() + { + ExpectValid(@" { dog @include(if: true) { name @@ -1041,12 +1041,12 @@ public void GoodDirectiveValidTypes() } } "); - } + } - [Fact] - public void GoodDirectiveAnyTypes() - { - ExpectValid(@" + [Fact] + public void GoodDirectiveAnyTypes() + { + ExpectValid(@" { dog @complex(anyArg: 123) @complex(anyArg: ""abc"") @@ -1056,24 +1056,24 @@ public void GoodDirectiveAnyTypes() } } "); - } + } - [Fact] - public void BadDirectiveInvalidTypes() - { - ExpectErrors(@" + [Fact] + public void BadDirectiveInvalidTypes() + { + ExpectErrors(@" { dog @include(if: ""yes"") { name @skip(if: ENUM) } } "); - } + } - [Fact] - public void GoodQueryVariablesDefaultValues() - { - ExpectValid(@" + [Fact] + public void GoodQueryVariablesDefaultValues() + { + ExpectValid(@" query WithDefaultValues( $a: Int = 1, $b: String = ""ok"", @@ -1083,12 +1083,12 @@ public void GoodQueryVariablesDefaultValues() dog { name } } "); - } + } - [Fact] - public void GoodQueryVariablesDefaultNullValues() - { - ExpectValid(@" + [Fact] + public void GoodQueryVariablesDefaultNullValues() + { + ExpectValid(@" query WithDefaultValues( $a: Int = null, $b: String = null, @@ -1097,12 +1097,12 @@ public void GoodQueryVariablesDefaultNullValues() dog { name } } "); - } + } - [Fact] - public void GoodQueryVariablesDefaultAnyValues() - { - ExpectValid(@" + [Fact] + public void GoodQueryVariablesDefaultAnyValues() + { + ExpectValid(@" query WithDefaultValues( $test1: Any = 123 $test2: Any = ""abc"" @@ -1112,12 +1112,12 @@ public void GoodQueryVariablesDefaultAnyValues() dog { name } } "); - } + } - [Fact] - public void BadVariablesWithInvalidDefaultValues() - { - ExpectErrors(@" + [Fact] + public void BadVariablesWithInvalidDefaultValues() + { + ExpectErrors(@" query WithDefaultValues( $a: Int! = null, $b: String! = null, @@ -1126,12 +1126,12 @@ public void BadVariablesWithInvalidDefaultValues() dog { name } } "); - } + } - [Fact] - public void BadVariablesWithInvalidDefaultValuesTypes() - { - ExpectErrors(@" + [Fact] + public void BadVariablesWithInvalidDefaultValuesTypes() + { + ExpectErrors(@" query InvalidDefaultValues( $a: Int = ""one"", $b: String = 4, @@ -1140,38 +1140,37 @@ public void BadVariablesWithInvalidDefaultValuesTypes() dog { name } } "); - } + } - [Fact] - public void BadVariablesWithInvalidComplexDefaultValues() - { - ExpectErrors(@" + [Fact] + public void BadVariablesWithInvalidComplexDefaultValues() + { + ExpectErrors(@" query WithDefaultValues( $a: ComplexInput = { requiredField: 123, intField: ""abc"" } ) { dog { name } } "); - } + } - [Fact] - public void BadVariablesComplexVariableMissingRequiredField() - { - ExpectErrors(@" + [Fact] + public void BadVariablesComplexVariableMissingRequiredField() + { + ExpectErrors(@" query MissingRequiredField($a: ComplexInput = {intField: 3}) { dog { name } } "); - } + } - [Fact] - public void BadVariablesListWithInvalidItem() - { - ExpectErrors(@" + [Fact] + public void BadVariablesListWithInvalidItem() + { + ExpectErrors(@" query InvalidItem($a: [String] = [""one"", 2]) { dog { name } } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/VariableUniquenessRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/VariableUniquenessRuleTests.cs index bce239e61b7..a45747b90d3 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/VariableUniquenessRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/VariableUniquenessRuleTests.cs @@ -2,50 +2,50 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class VariableUniquenessRuleTests + : DocumentValidatorVisitorTestBase { - public class VariableUniquenessRuleTests - : DocumentValidatorVisitorTestBase + public VariableUniquenessRuleTests() + : base(builder => builder.AddVariableRules()) { - public VariableUniquenessRuleTests() - : base(builder => builder.AddVariableRules()) - { - } + } - [Fact] - public void OperationWithTwoVariablesThatHaveTheSameName() - { - // arrange - DocumentValidatorContext context = ValidationUtils.CreateContext(); - context.MaxAllowedErrors = int.MaxValue; + [Fact] + public void OperationWithTwoVariablesThatHaveTheSameName() + { + // arrange + var context = ValidationUtils.CreateContext(); + context.MaxAllowedErrors = int.MaxValue; - DocumentNode query = Utf8GraphQLParser.Parse(@" + var query = Utf8GraphQLParser.Parse(@" query houseTrainedQuery($atOtherHomes: Boolean, $atOtherHomes: Boolean) { dog { isHouseTrained(atOtherHomes: $atOtherHomes) } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Single(context.Errors); - Assert.Collection(context.Errors, - t => Assert.Equal( - "A document containing operations that " + - "define more than one variable with the same " + - "name is invalid for execution.", t.Message)); - } + // assert + Assert.Single(context.Errors); + Assert.Collection(context.Errors, + t => Assert.Equal( + "A document containing operations that " + + "define more than one variable with the same " + + "name is invalid for execution.", t.Message)); + } - [Fact] - public void NoOperationHasVariablesThatShareTheSameName() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void NoOperationHasVariablesThatShareTheSameName() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query ($foo: Boolean = true, $bar: Boolean = false) { dog @skip(if: $foo) { isHouseTrained @@ -55,21 +55,21 @@ public void NoOperationHasVariablesThatShareTheSameName() } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void TwoOperationsThatShareVariableName() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void TwoOperationsThatShareVariableName() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query A($atOtherHomes: Boolean) { ...HouseTrainedFragment } @@ -84,13 +84,12 @@ public void TwoOperationsThatShareVariableName() } } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/VariablesAreInputTypesRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/VariablesAreInputTypesRuleTests.cs index 76f65007055..960bb8d27d4 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/VariablesAreInputTypesRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/VariablesAreInputTypesRuleTests.cs @@ -2,22 +2,22 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace HotChocolate.Validation +namespace HotChocolate.Validation; + +public class VariablesAreInputTypesRuleTests + : DocumentValidatorVisitorTestBase { - public class VariablesAreInputTypesRuleTests - : DocumentValidatorVisitorTestBase + public VariablesAreInputTypesRuleTests() + : base(builder => builder.AddVariableRules()) { - public VariablesAreInputTypesRuleTests() - : base(builder => builder.AddVariableRules()) - { - } + } - [Fact] - public void QueriesWithValidVariableTypes() - { - // arrange - IDocumentValidatorContext context = ValidationUtils.CreateContext(); - DocumentNode query = Utf8GraphQLParser.Parse(@" + [Fact] + public void QueriesWithValidVariableTypes() + { + // arrange + IDocumentValidatorContext context = ValidationUtils.CreateContext(); + var query = Utf8GraphQLParser.Parse(@" query takesBoolean($atOtherHomes: Boolean) { dog { isHouseTrained(atOtherHomes: $atOtherHomes) @@ -34,19 +34,19 @@ public void QueriesWithValidVariableTypes() booleanList(booleanListArg: $booleans) } "); - context.Prepare(query); + context.Prepare(query); - // act - Rule.Validate(context, query); + // act + Rule.Validate(context, query); - // assert - Assert.Empty(context.Errors); - } + // assert + Assert.Empty(context.Errors); + } - [Fact] - public void QueriesWithInvalidVariableTypes() - { - ExpectErrors(@" + [Fact] + public void QueriesWithInvalidVariableTypes() + { + ExpectErrors(@" query takesCat($cat: Cat) { # ... } @@ -63,6 +63,5 @@ public void QueriesWithInvalidVariableTypes() # ... } "); - } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Defer.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Defer.snap new file mode 100644 index 00000000000..c7f8512be03 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Defer.snap @@ -0,0 +1,125 @@ +[ + { + "Message": "If a label is passed, it must be unique within all other @defer and @stream directives in the document.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 5, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directive-Labels-Are-Unique", + "label": "a" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "InlineFragment", + "Location": { + "Start": 117, + "End": 207, + "Line": 5, + "Column": 17 + }, + "TypeCondition": null, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 121, + "End": 141, + "Line": 5, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 122, + "End": 128, + "Line": 5, + "Column": 22 + }, + "Value": "defer" + }, + "Arguments": [ + { + "Kind": "Argument", + "Location": { + "Start": 128, + "End": 139, + "Line": 5, + "Column": 28 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 128, + "End": 134, + "Line": 5, + "Column": 28 + }, + "Value": "label" + }, + "Value": { + "Kind": "StringValue", + "Location": { + "Start": 135, + "End": 139, + "Line": 5, + "Column": 35 + }, + "Value": "a", + "Block": false + } + } + ] + } + ], + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 140, + "End": 207, + "Line": 5, + "Column": 40 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": { + "Kind": "Name", + "Location": { + "Start": 162, + "End": 164, + "Line": 6, + "Column": 21 + }, + "Value": "b" + }, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 162, + "End": 193, + "Line": 6, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 165, + "End": 193, + "Line": 6, + "Column": 24 + }, + "Value": "__typename" + }, + "Directives": [] + } + ] + } + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Either_Stream_Or_Defer.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Either_Stream_Or_Defer.snap new file mode 100644 index 00000000000..23aba47fabe --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Either_Stream_Or_Defer.snap @@ -0,0 +1,137 @@ +[ + { + "Message": "If a label is passed, it must be unique within all other @defer and @stream directives in the document.", + "Code": null, + "Path": { + "Name": "b", + "Parent": { + "Parent": null, + "Depth": -1, + "IsRoot": true + }, + "Depth": 0, + "IsRoot": false + }, + "Locations": [ + { + "Line": 6, + "Column": 21 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directive-Labels-Are-Unique", + "label": "a" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 178, + "End": 248, + "Line": 6, + "Column": 48 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 204, + "End": 230, + "Line": 7, + "Column": 25 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 204, + "End": 230, + "Line": 7, + "Column": 25 + }, + "Value": "name" + }, + "Directives": [] + } + ] + }, + "Location": { + "Start": 151, + "End": 248, + "Line": 6, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 151, + "End": 159, + "Line": 6, + "Column": 21 + }, + "Value": "_types" + }, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 158, + "End": 179, + "Line": 6, + "Column": 28 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 159, + "End": 166, + "Line": 6, + "Column": 29 + }, + "Value": "stream" + }, + "Arguments": [ + { + "Kind": "Argument", + "Location": { + "Start": 166, + "End": 177, + "Line": 6, + "Column": 36 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 166, + "End": 172, + "Line": 6, + "Column": 36 + }, + "Value": "label" + }, + "Value": { + "Kind": "StringValue", + "Location": { + "Start": 173, + "End": 177, + "Line": 6, + "Column": 43 + }, + "Value": "a", + "Block": false + } + } + ] + } + ] + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Stream.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Stream.snap new file mode 100644 index 00000000000..bfdc0177b34 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Duplicate_On_Stream.snap @@ -0,0 +1,137 @@ +[ + { + "Message": "If a label is passed, it must be unique within all other @defer and @stream directives in the document.", + "Code": null, + "Path": { + "Name": "b", + "Parent": { + "Parent": null, + "Depth": -1, + "IsRoot": true + }, + "Depth": 0, + "IsRoot": false + }, + "Locations": [ + { + "Line": 8, + "Column": 21 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directive-Labels-Are-Unique", + "label": "a" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 233, + "End": 303, + "Line": 8, + "Column": 48 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 259, + "End": 285, + "Line": 9, + "Column": 25 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 259, + "End": 285, + "Line": 9, + "Column": 25 + }, + "Value": "name" + }, + "Directives": [] + } + ] + }, + "Location": { + "Start": 206, + "End": 303, + "Line": 8, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 206, + "End": 214, + "Line": 8, + "Column": 21 + }, + "Value": "_types" + }, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 213, + "End": 234, + "Line": 8, + "Column": 28 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 214, + "End": 221, + "Line": 8, + "Column": 29 + }, + "Value": "stream" + }, + "Arguments": [ + { + "Kind": "Argument", + "Location": { + "Start": 221, + "End": 232, + "Line": 8, + "Column": 36 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 221, + "End": 227, + "Line": 8, + "Column": 36 + }, + "Value": "label" + }, + "Value": { + "Kind": "StringValue", + "Location": { + "Start": 228, + "End": 232, + "Line": 8, + "Column": 43 + }, + "Value": "a", + "Block": false + } + } + ] + } + ] + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Is_Variable_On_Defer.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Is_Variable_On_Defer.snap new file mode 100644 index 00000000000..8ff9249c4ea --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectiveLabelsAreUniqueTests.Label_Is_Variable_On_Defer.snap @@ -0,0 +1,133 @@ +[ + { + "Message": "If a label for @defer or @stream is passed, it must not be a variable.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 2, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directive-Labels-Are-Unique", + "variable": "$a" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "InlineFragment", + "Location": { + "Start": 36, + "End": 125, + "Line": 2, + "Column": 17 + }, + "TypeCondition": null, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 40, + "End": 59, + "Line": 2, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 41, + "End": 47, + "Line": 2, + "Column": 22 + }, + "Value": "defer" + }, + "Arguments": [ + { + "Kind": "Argument", + "Location": { + "Start": 47, + "End": 57, + "Line": 2, + "Column": 28 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 47, + "End": 53, + "Line": 2, + "Column": 28 + }, + "Value": "label" + }, + "Value": { + "Kind": "Variable", + "Location": { + "Start": 54, + "End": 57, + "Line": 2, + "Column": 35 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 55, + "End": 57, + "Line": 2, + "Column": 36 + }, + "Value": "a" + } + } + } + ] + } + ], + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 58, + "End": 125, + "Line": 2, + "Column": 39 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": { + "Kind": "Name", + "Location": { + "Start": 80, + "End": 82, + "Line": 3, + "Column": 21 + }, + "Value": "a" + }, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 80, + "End": 111, + "Line": 3, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 83, + "End": 111, + "Line": 3, + "Column": 24 + }, + "Value": "__typename" + }, + "Directives": [] + } + ] + } + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Mutation_Root.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Mutation_Root.snap new file mode 100644 index 00000000000..76a9f194390 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Mutation_Root.snap @@ -0,0 +1,84 @@ +[ + { + "Message": "The defer and stream directives are not allowed to be used on root fields of the mutation or subscription type.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 2, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directives-Are-Used-On-Valid-Root-Field" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "InlineFragment", + "Location": { + "Start": 31, + "End": 121, + "Line": 2, + "Column": 17 + }, + "TypeCondition": null, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 35, + "End": 43, + "Line": 2, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 36, + "End": 43, + "Line": 2, + "Column": 22 + }, + "Value": "defer" + }, + "Arguments": [] + } + ], + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 42, + "End": 121, + "Line": 2, + "Column": 28 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 64, + "End": 107, + "Line": 3, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 64, + "End": 107, + "Line": 3, + "Column": 21 + }, + "Value": "disallowedSecondRootField" + }, + "Directives": [] + } + ] + } + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Mutation_Root_In_Nested_Fragment.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Mutation_Root_In_Nested_Fragment.snap new file mode 100644 index 00000000000..accc28430c7 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Mutation_Root_In_Nested_Fragment.snap @@ -0,0 +1,84 @@ +[ + { + "Message": "The defer and stream directives are not allowed to be used on root fields of the mutation or subscription type.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 10, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directives-Are-Used-On-Valid-Root-Field" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "InlineFragment", + "Location": { + "Start": 187, + "End": 277, + "Line": 10, + "Column": 17 + }, + "TypeCondition": null, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 191, + "End": 199, + "Line": 10, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 192, + "End": 199, + "Line": 10, + "Column": 22 + }, + "Value": "defer" + }, + "Arguments": [] + } + ], + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 198, + "End": 277, + "Line": 10, + "Column": 28 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 220, + "End": 263, + "Line": 11, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 220, + "End": 263, + "Line": 11, + "Column": 21 + }, + "Value": "disallowedSecondRootField" + }, + "Directives": [] + } + ] + } + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Subscriptions_Root.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Subscriptions_Root.snap new file mode 100644 index 00000000000..76a9f194390 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Subscriptions_Root.snap @@ -0,0 +1,84 @@ +[ + { + "Message": "The defer and stream directives are not allowed to be used on root fields of the mutation or subscription type.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 2, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directives-Are-Used-On-Valid-Root-Field" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "InlineFragment", + "Location": { + "Start": 31, + "End": 121, + "Line": 2, + "Column": 17 + }, + "TypeCondition": null, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 35, + "End": 43, + "Line": 2, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 36, + "End": 43, + "Line": 2, + "Column": 22 + }, + "Value": "defer" + }, + "Arguments": [] + } + ], + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 42, + "End": 121, + "Line": 2, + "Column": 28 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 64, + "End": 107, + "Line": 3, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 64, + "End": 107, + "Line": 3, + "Column": 21 + }, + "Value": "disallowedSecondRootField" + }, + "Directives": [] + } + ] + } + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Subscriptions_Root_In_Nested_Fragment.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Subscriptions_Root_In_Nested_Fragment.snap new file mode 100644 index 00000000000..accc28430c7 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Defer_On_Subscriptions_Root_In_Nested_Fragment.snap @@ -0,0 +1,84 @@ +[ + { + "Message": "The defer and stream directives are not allowed to be used on root fields of the mutation or subscription type.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 10, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directives-Are-Used-On-Valid-Root-Field" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "InlineFragment", + "Location": { + "Start": 187, + "End": 277, + "Line": 10, + "Column": 17 + }, + "TypeCondition": null, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 191, + "End": 199, + "Line": 10, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 192, + "End": 199, + "Line": 10, + "Column": 22 + }, + "Value": "defer" + }, + "Arguments": [] + } + ], + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 198, + "End": 277, + "Line": 10, + "Column": 28 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 220, + "End": 263, + "Line": 11, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 220, + "End": 263, + "Line": 11, + "Column": 21 + }, + "Value": "disallowedSecondRootField" + }, + "Directives": [] + } + ] + } + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Stream_On_Subscriptions_Root.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Stream_On_Subscriptions_Root.snap new file mode 100644 index 00000000000..f7308fb4075 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/DeferAndStreamDirectivesAreUsedOnValidRootFieldTests.Stream_On_Subscriptions_Root.snap @@ -0,0 +1,62 @@ +[ + { + "Message": "The defer and stream directives are not allowed to be used on root fields of the mutation or subscription type.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 2, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Defer-And-Stream-Directives-Are-Used-On-Valid-Root-Field" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 31, + "End": 62, + "Line": 2, + "Column": 17 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 31, + "End": 42, + "Line": 2, + "Column": 17 + }, + "Value": "listEvent" + }, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 41, + "End": 62, + "Line": 2, + "Column": 27 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 42, + "End": 62, + "Line": 2, + "Column": 28 + }, + "Value": "stream" + }, + "Arguments": [] + } + ] + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.Stream_Argument_Mismatch.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.Stream_Argument_Mismatch.snap new file mode 100644 index 00000000000..79cb160d661 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.Stream_Argument_Mismatch.snap @@ -0,0 +1,138 @@ +[ + { + "Message": "Encountered fields for the same object that cannot be merged.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 4, + "Column": 25 + }, + { + "Line": 9, + "Column": 25 + } + ], + "Extensions": { + "declaringTypeA": "__Type", + "declaringTypeB": "__Type", + "fieldA": "fields", + "fieldB": "fields", + "typeA": "[__Field!]", + "typeB": "[__Field!]", + "responseNameA": "fields", + "responseNameB": "fields", + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Field-Selection-Merging" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 316, + "End": 398, + "Line": 9, + "Column": 57 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 346, + "End": 376, + "Line": 10, + "Column": 29 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 346, + "End": 376, + "Line": 10, + "Column": 29 + }, + "Value": "name" + }, + "Directives": [] + } + ] + }, + "Location": { + "Start": 284, + "End": 398, + "Line": 9, + "Column": 25 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 284, + "End": 292, + "Line": 9, + "Column": 25 + }, + "Value": "fields" + }, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 291, + "End": 317, + "Line": 9, + "Column": 32 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 292, + "End": 299, + "Line": 9, + "Column": 33 + }, + "Value": "stream" + }, + "Arguments": [ + { + "Kind": "Argument", + "Location": { + "Start": 299, + "End": 315, + "Line": 9, + "Column": 40 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 299, + "End": 312, + "Line": 9, + "Column": 40 + }, + "Value": "initialCount" + }, + "Value": { + "Kind": "IntValue", + "Location": { + "Start": 313, + "End": 315, + "Line": 9, + "Column": 54 + }, + "Value": "2" + } + } + ] + } + ] + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.Stream_On_Some_Fields.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.Stream_On_Some_Fields.snap new file mode 100644 index 00000000000..7d7809f9929 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/FieldSelectionMergingRuleTests.Stream_On_Some_Fields.snap @@ -0,0 +1,87 @@ +[ + { + "Message": "Encountered fields for the same object that cannot be merged.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 4, + "Column": 25 + }, + { + "Line": 9, + "Column": 25 + } + ], + "Extensions": { + "declaringTypeA": "__Type", + "declaringTypeB": "__Type", + "fieldA": "fields", + "fieldB": "fields", + "typeA": "[__Field!]", + "typeB": "[__Field!]", + "responseNameA": "fields", + "responseNameB": "fields", + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Field-Selection-Merging" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": { + "Kind": "SelectionSet", + "Location": { + "Start": 291, + "End": 373, + "Line": 9, + "Column": 32 + }, + "Selections": [ + { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 321, + "End": 351, + "Line": 10, + "Column": 29 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 321, + "End": 351, + "Line": 10, + "Column": 29 + }, + "Value": "name" + }, + "Directives": [] + } + ] + }, + "Location": { + "Start": 284, + "End": 373, + "Line": 9, + "Column": 25 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 284, + "End": 292, + "Line": 9, + "Column": 25 + }, + "Value": "fields" + }, + "Directives": [] + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field.snap new file mode 100644 index 00000000000..14aa31b0716 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field.snap @@ -0,0 +1,62 @@ +[ + { + "Message": "@stream directive is only valid on list fields.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 2, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Stream-Directives-Are-Used-On-List-Fields" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 24, + "End": 56, + "Line": 2, + "Column": 17 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 24, + "End": 36, + "Line": 2, + "Column": 17 + }, + "Value": "__typename" + }, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 35, + "End": 56, + "Line": 2, + "Column": 28 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 36, + "End": 56, + "Line": 2, + "Column": 29 + }, + "Value": "stream" + }, + "Arguments": [] + } + ] + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field_1.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field_1.snap new file mode 100644 index 00000000000..14aa31b0716 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field_1.snap @@ -0,0 +1,62 @@ +[ + { + "Message": "@stream directive is only valid on list fields.", + "Code": null, + "Path": null, + "Locations": [ + { + "Line": 2, + "Column": 17 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Stream-Directives-Are-Used-On-List-Fields" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 24, + "End": 56, + "Line": 2, + "Column": 17 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 24, + "End": 36, + "Line": 2, + "Column": 17 + }, + "Value": "__typename" + }, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 35, + "End": 56, + "Line": 2, + "Column": 28 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 36, + "End": 56, + "Line": 2, + "Column": 29 + }, + "Value": "stream" + }, + "Arguments": [] + } + ] + } + } +] diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field_2.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field_2.snap new file mode 100644 index 00000000000..627721cb6fb --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/StreamDirectivesAreUsedOnListFieldsTests.Stream_On_String_Field_2.snap @@ -0,0 +1,71 @@ +[ + { + "Message": "@stream directive is only valid on list fields.", + "Code": null, + "Path": { + "Name": "__schema", + "Parent": { + "Parent": null, + "Depth": -1, + "IsRoot": true + }, + "Depth": 0, + "IsRoot": false + }, + "Locations": [ + { + "Line": 3, + "Column": 21 + } + ], + "Extensions": { + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Stream-Directives-Are-Used-On-List-Fields" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "Field", + "Alias": null, + "Arguments": [], + "Required": null, + "SelectionSet": null, + "Location": { + "Start": 55, + "End": 92, + "Line": 3, + "Column": 21 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 55, + "End": 68, + "Line": 3, + "Column": 21 + }, + "Value": "description" + }, + "Directives": [ + { + "Kind": "Directive", + "Location": { + "Start": 67, + "End": 92, + "Line": 3, + "Column": 33 + }, + "Name": { + "Kind": "Name", + "Location": { + "Start": 68, + "End": 92, + "Line": 3, + "Column": 34 + }, + "Value": "stream" + }, + "Arguments": [] + } + ] + } + } +] diff --git a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Objects_Types.snap b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Objects_Types.snap index 3e87a76198a..8e2a95f3cee 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Objects_Types.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Objects_Types.snap @@ -13,8 +13,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Scalar_Types.snap b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Scalar_Types.snap index 3024c1cc687..c3b42a7c2c4 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Scalar_Types.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Array_Filter_On_Scalar_Types.snap @@ -13,8 +13,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Objects_Types.snap b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Objects_Types.snap index 3e87a76198a..8e2a95f3cee 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Objects_Types.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Objects_Types.snap @@ -13,8 +13,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Scalar_Types.snap b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Scalar_Types.snap index 3024c1cc687..c3b42a7c2c4 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Scalar_Types.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Mongo.Tests/__snapshots__/ArrayFilterTests.Collection_Filter_On_Scalar_Types.snap @@ -13,8 +13,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/NoNullQueryFilterTests.Execute_Filter.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/NoNullQueryFilterTests.Execute_Filter.snap index 2d7adf3b521..57660d7f3d8 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/NoNullQueryFilterTests.Execute_Filter.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/NoNullQueryFilterTests.Execute_Filter.snap @@ -9,8 +9,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter.snap index ae3e8004e7f..33635fa2c5d 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter.snap @@ -9,8 +9,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter_With_Variables.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter_With_Variables.snap index ae3e8004e7f..33635fa2c5d 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter_With_Variables.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_DateTime_Filter_With_Variables.snap @@ -9,8 +9,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter.snap index 0aa45d705a2..0f113421539 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter.snap @@ -18,8 +18,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_As_Variable.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_As_Variable.snap index 0aa45d705a2..0f113421539 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_As_Variable.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_As_Variable.snap @@ -18,8 +18,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Comparable_In.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Comparable_In.snap index 091abe9d7f2..efe1ec7fe71 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Comparable_In.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Comparable_In.snap @@ -15,8 +15,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_And.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_And.snap index 25becc27fc1..993a04d9ffe 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_And.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_And.snap @@ -5,8 +5,10 @@ "Data": { "foos": [] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Null.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Null.snap index 2ef8268838f..f1056f5a41b 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Null.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Null.snap @@ -9,8 +9,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Or.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Or.snap index 1be5f2cba32..e9270952cfc 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Or.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Equals_Or.snap @@ -12,8 +12,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_In.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_In.snap index 817cb297925..fa083f82480 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_In.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_In.snap @@ -12,8 +12,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Is_Null.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Is_Null.snap index 962a4d82485..849127ad6f9 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Is_Null.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Is_Null.snap @@ -27,8 +27,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Not_Equals_Null.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Not_Equals_Null.snap index 97f1574f008..3ee5adbe667 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Not_Equals_Null.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Not_Equals_Null.snap @@ -24,8 +24,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_1.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_1.snap index 913d678a1aa..ac54c4b4055 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_1.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_1.snap @@ -10,8 +10,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_Null.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_Null.snap index 1c5900fdd09..2f88bafcabb 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_Null.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_Nullable_Equals_Null.snap @@ -30,8 +30,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_With_Variables.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_With_Variables.snap index 0aa45d705a2..0f113421539 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_With_Variables.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_Filter_With_Variables.snap @@ -18,8 +18,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_Array.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_Array.snap index 6b2e15429f8..059b02edad4 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_Array.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_Array.snap @@ -11,8 +11,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_InMemoryQueryable.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_InMemoryQueryable.snap index 6b2e15429f8..059b02edad4 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_InMemoryQueryable.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Execute_ObjectStringEqualWithNull_Expression_InMemoryQueryable.snap @@ -11,8 +11,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Infer_Filter_From_Field.snap b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Infer_Filter_From_Field.snap index 0aa45d705a2..0f113421539 100644 --- a/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Infer_Filter_From_Field.snap +++ b/src/HotChocolate/Filters/test/Types.Filters.Tests/__snapshots__/QueryableFilterTests.Infer_Filter_From_Field.snap @@ -18,8 +18,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsEnumerable.snap b/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsEnumerable.snap index 29ff9be7d22..13c7ed8f624 100644 --- a/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsEnumerable.snap +++ b/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsEnumerable.snap @@ -15,8 +15,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsQueryable.snap b/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsQueryable.snap index 29ff9be7d22..13c7ed8f624 100644 --- a/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsQueryable.snap +++ b/src/HotChocolate/Filters/test/Types.Sorting.Tests/__snapshots__/AsQueryable.snap @@ -15,8 +15,10 @@ } ] }, + "Items": null, "Errors": null, "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Integration.Tests/SchemaFirst/__snapshots__/SchemaIntegrationTests.MoviesSchemaIntegrationTests.snap b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Integration.Tests/SchemaFirst/__snapshots__/SchemaIntegrationTests.MoviesSchemaIntegrationTests.snap new file mode 100644 index 00000000000..381650b8aa3 --- /dev/null +++ b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Integration.Tests/SchemaFirst/__snapshots__/SchemaIntegrationTests.MoviesSchemaIntegrationTests.snap @@ -0,0 +1,298 @@ +MoviesSchema_Snapshot +--------------- +schema { + query: Query +} + +type Actor { + name: String! + actedIn: [Movie!]! +} + +type Movie { + title: String! + generes: [Actor!]! +} + +type Query { + movies(where: MovieFilterInput order: [MovieSortInput!]): [Movie!]! + actors(where: ActorFilterInput order: [ActorSortInput!]): [Actor!]! +} + +input ActorFilterInput { + and: [ActorFilterInput!] + or: [ActorFilterInput!] + name: StringOperationFilterInput + actedIn: ListFilterInputTypeOfMovieFilterInput +} + +input ActorSortInput { + name: SortEnumType +} + +input ListFilterInputTypeOfActorFilterInput { + all: ActorFilterInput + none: ActorFilterInput + some: ActorFilterInput + any: Boolean +} + +input ListFilterInputTypeOfMovieFilterInput { + all: MovieFilterInput + none: MovieFilterInput + some: MovieFilterInput + any: Boolean +} + +input MovieFilterInput { + and: [MovieFilterInput!] + or: [MovieFilterInput!] + title: StringOperationFilterInput + generes: ListFilterInputTypeOfActorFilterInput +} + +input MovieSortInput { + title: SortEnumType +} + +input StringOperationFilterInput { + and: [StringOperationFilterInput!] + or: [StringOperationFilterInput!] + eq: String + neq: String + contains: String + ncontains: String + in: [String] + nin: [String] + startsWith: String + nstartsWith: String + endsWith: String + nendsWith: String +} + +enum SortEnumType { + ASC + DESC +} + +"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`." +directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT + +"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`." +directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! = 0 "Streamed when true." if: Boolean) on FIELD +--------------- + +MoviesSchema_Actors_Query +--------------- +{ + "data": { + "actors": [ + { + "name": "Keanu Reeves", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Carrie-Anne Moss", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Laurence Fishburne", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Hugo Weaving", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Lilly Wachowski", + "actedIn": [] + }, + { + "name": "Lana Wachowski", + "actedIn": [] + }, + { + "name": "Joel Silver", + "actedIn": [] + }, + { + "name": "Emil Eifrem", + "actedIn": [ + { + "title": "The Matrix" + } + ] + } + ] + } +} +--------------- + +MoviesSchema_Name_StartsWith_Actors_Query +--------------- +{ + "data": { + "actors": [ + { + "name": "Keanu Reeves", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + } + ] + } +} +--------------- + +MoviesSchema_Movies_Query +--------------- +{ + "data": { + "movies": [ + { + "title": "The Matrix" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix Revolutions" + } + ] + } +} +--------------- + +MoviesSchema_Name_Desc_Sort_Actors_Query +--------------- +{ + "data": { + "actors": [ + { + "name": "Carrie-Anne Moss", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Emil Eifrem", + "actedIn": [ + { + "title": "The Matrix" + } + ] + }, + { + "name": "Hugo Weaving", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Joel Silver", + "actedIn": [] + }, + { + "name": "Keanu Reeves", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Lana Wachowski", + "actedIn": [] + }, + { + "name": "Laurence Fishburne", + "actedIn": [ + { + "title": "The Matrix Revolutions" + }, + { + "title": "The Matrix Reloaded" + }, + { + "title": "The Matrix" + } + ] + }, + { + "name": "Lilly Wachowski", + "actedIn": [] + } + ] + } +} +--------------- diff --git a/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Default_Items.snap b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Default_Items.snap new file mode 100644 index 00000000000..3f5dfecd6a4 --- /dev/null +++ b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Default_Items.snap @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "message": "The provided source is not supported for Neo4j paging", + "extensions": { + "code": "HC0025" + } + } + ], + "data": { + "root": null + } +} \ No newline at end of file diff --git a/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Take_2.snap b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Take_2.snap new file mode 100644 index 00000000000..3f5dfecd6a4 --- /dev/null +++ b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Take_2.snap @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "message": "The provided source is not supported for Neo4j paging", + "extensions": { + "code": "HC0025" + } + } + ], + "data": { + "root": null + } +} \ No newline at end of file diff --git a/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Take_2_After.snap b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Take_2_After.snap new file mode 100644 index 00000000000..3f5dfecd6a4 --- /dev/null +++ b/src/HotChocolate/Neo4J/test/HotChocolate.Data.Neo4J.Paging.Tests/Offset/__snapshots__/Neo4JOffsetPagingTests.Simple_StringList_Take_2_After.snap @@ -0,0 +1,13 @@ +{ + "errors": [ + { + "message": "The provided source is not supported for Neo4j paging", + "extensions": { + "code": "HC0025" + } + } + ], + "data": { + "root": null + } +} \ No newline at end of file diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap index b215a250601..d90a546a5e0 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap @@ -5,10 +5,12 @@ "Data": { "__typename": "Query" }, + "Items": null, "Errors": null, "Extensions": { "persistedDocument": true }, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap index 7aaebfa6d3e..d10e621bead 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.FileSystem.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap @@ -3,6 +3,7 @@ "Label": null, "Path": null, "Data": null, + "Items": null, "Errors": [ { "Message": "The query request contains no document.", @@ -17,6 +18,7 @@ } ], "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap index b215a250601..d90a546a5e0 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery.snap @@ -5,10 +5,12 @@ "Data": { "__typename": "Query" }, + "Items": null, "Errors": null, "Extensions": { "persistedDocument": true }, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_After_Expiration.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_After_Expiration.snap index 7aaebfa6d3e..d10e621bead 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_After_Expiration.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_After_Expiration.snap @@ -3,6 +3,7 @@ "Label": null, "Path": null, "Data": null, + "Items": null, "Errors": [ { "Message": "The query request contains no document.", @@ -17,6 +18,7 @@ } ], "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI.snap index b215a250601..d90a546a5e0 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI.snap @@ -5,10 +5,12 @@ "Data": { "__typename": "Query" }, + "Items": null, "Errors": null, "Extensions": { "persistedDocument": true }, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI_Default.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI_Default.snap index b215a250601..d90a546a5e0 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI_Default.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_ApplicationDI_Default.snap @@ -5,10 +5,12 @@ "Data": { "__typename": "Query" }, + "Items": null, "Errors": null, "Extensions": { "persistedDocument": true }, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_Before_Expiration.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_Before_Expiration.snap index b215a250601..d90a546a5e0 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_Before_Expiration.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_Before_Expiration.snap @@ -5,10 +5,12 @@ "Data": { "__typename": "Query" }, + "Items": null, "Errors": null, "Extensions": { "persistedDocument": true }, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap index 7aaebfa6d3e..d10e621bead 100644 --- a/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap +++ b/src/HotChocolate/PersistedQueries/test/PersistedQueries.Redis.Tests/__snapshots__/IntegrationTests.ExecutePersistedQuery_NotFound.snap @@ -3,6 +3,7 @@ "Label": null, "Path": null, "Data": null, + "Items": null, "Errors": [ { "Message": "The query request contains no document.", @@ -17,6 +18,7 @@ } ], "Extensions": null, + "Incremental": null, "ContextData": null, "HasNext": null } diff --git a/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_AST.snap b/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_AST.snap index 7d797b2ef97..b645a4b62d1 100644 --- a/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_AST.snap +++ b/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_AST.snap @@ -13,6 +13,7 @@ type Query { droid(id: String): Droid time: Long! evict: Boolean! + wait(m: Int!): Boolean! } type Mutation { diff --git a/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_SDL.snap b/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_SDL.snap index c015db5e5e2..5c59a5c59e5 100644 --- a/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_SDL.snap +++ b/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/__snapshots__/IntrospectionClientTests.Download_Schema_SDL.snap @@ -13,6 +13,7 @@ type Query { droid(id: String): Droid time: Long! evict: Boolean! + wait(m: Int!): Boolean! } type Mutation { diff --git a/src/StrawberryShake/Client/src/Core/StrawberryShake.Core.csproj b/src/StrawberryShake/Client/src/Core/StrawberryShake.Core.csproj index 7759e77dc20..cb0ae0d224e 100644 --- a/src/StrawberryShake/Client/src/Core/StrawberryShake.Core.csproj +++ b/src/StrawberryShake/Client/src/Core/StrawberryShake.Core.csproj @@ -46,8 +46,4 @@ - - - - diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs index 2f85eea80ae..96582ea0fcd 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/Analyzers/FieldCollector.cs @@ -222,7 +222,7 @@ public FieldCollector(ISchema schema, DocumentNode document) if (DoesTypeApply(fragment.TypeCondition, type)) { - var deferDirective = fragmentSpreadSyntax.Directives.GetDeferDirective(); + var deferDirective = fragmentSpreadSyntax.Directives.GetDeferDirectiveNode(); var nodes = new List(); var fragmentNode = new FragmentNode(fragment, nodes, deferDirective); fragmentNodes.Add(fragmentNode); @@ -247,7 +247,7 @@ public FieldCollector(ISchema schema, DocumentNode document) if (DoesTypeApply(fragment.TypeCondition, type)) { - var deferDirective = inlineFragmentSyntax.Directives.GetDeferDirective(); + var deferDirective = inlineFragmentSyntax.Directives.GetDeferDirectiveNode(); var nodes = new List(); var fragmentNode = new FragmentNode(fragment, nodes, deferDirective); fragmentNodes.Add(fragmentNode);