diff --git a/src/HotChocolate/Core/src/Abstractions/IExecutable.cs b/src/HotChocolate/Core/src/Abstractions/IExecutable.cs new file mode 100644 index 00000000000..34bf6a02b72 --- /dev/null +++ b/src/HotChocolate/Core/src/Abstractions/IExecutable.cs @@ -0,0 +1,12 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace HotChocolate +{ + public interface IExecutable + { + ValueTask ExecuteAsync(CancellationToken cancellationToken); + + string Print(); + } +} diff --git a/src/HotChocolate/Core/src/Abstractions/IExecutable~1.cs b/src/HotChocolate/Core/src/Abstractions/IExecutable~1.cs new file mode 100644 index 00000000000..fbe7a0df091 --- /dev/null +++ b/src/HotChocolate/Core/src/Abstractions/IExecutable~1.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace HotChocolate +{ + public interface IExecutable : IExecutable + { + new ValueTask> ExecuteAsync(CancellationToken cancellationToken); + } +} diff --git a/src/HotChocolate/Core/src/Execution/Processing/ResolverTask.cs b/src/HotChocolate/Core/src/Execution/Processing/ResolverTask.cs index d03b6abfd99..54260923ae9 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/ResolverTask.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/ResolverTask.cs @@ -66,6 +66,10 @@ private async ValueTask ExecuteResolverPipelineAsync() switch (_context.Result) { + case IExecutable executable: + _context.Result = await executable.ExecuteAsync(_context.RequestAborted); + break; + case IQueryable queryable: _context.Result = await Task.Run(() => { diff --git a/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Helper.cs b/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Helper.cs index 095c5465896..72931324be9 100644 --- a/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Helper.cs +++ b/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Helper.cs @@ -166,7 +166,8 @@ public static bool IsSupportedCollectionInterface(Type type) || typeDefinition == typeof(ImmutableList<>) || typeDefinition == typeof(ImmutableQueue<>) || typeDefinition == typeof(ImmutableStack<>) - || typeDefinition == typeof(ImmutableHashSet<>)) + || typeDefinition == typeof(ImmutableHashSet<>) + || typeDefinition == typeof(IExecutable<>)) { return true; } diff --git a/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Members.cs b/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Members.cs index 026c9f24a5d..90c5a506c0f 100644 --- a/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Members.cs +++ b/src/HotChocolate/Core/src/Types/Internal/ExtendedType.Members.cs @@ -40,7 +40,8 @@ public static ExtendedMethodInfo FromMethod(MethodInfo method, TypeCache cache) method, () => Rewrite( CreateExtendedType(context, helper.GetFlags(method), method.ReturnType), - method, cache)); + method, + cache)); ParameterInfo[] parameters = method.GetParameters(); var parameterTypes = new Dictionary(); @@ -203,6 +204,7 @@ public static ExtendedMethodInfo FromMethod(MethodInfo method, TypeCache cache) state = flags[0]; } } + return state; } } diff --git a/src/HotChocolate/Core/src/Types/Internal/ExtendedType.SystemType.cs b/src/HotChocolate/Core/src/Types/Internal/ExtendedType.SystemType.cs index 1a513799c76..d13fc99df33 100644 --- a/src/HotChocolate/Core/src/Types/Internal/ExtendedType.SystemType.cs +++ b/src/HotChocolate/Core/src/Types/Internal/ExtendedType.SystemType.cs @@ -20,7 +20,7 @@ private static ExtendedType FromTypeInternal(Type type, TypeCache cache) && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { Type inner = type.GetGenericArguments()[0]; - + return new ExtendedType( inner, ExtendedTypeKind.Runtime, @@ -50,7 +50,7 @@ private static ExtendedType FromTypeInternal(Type type, TypeCache cache) } public static IReadOnlyList GetGenericArguments( - Type type, + Type type, TypeCache cache) { if (type.IsGenericType) diff --git a/src/HotChocolate/Core/test/Execution.Tests/CodeFirstTests.cs b/src/HotChocolate/Core/test/Execution.Tests/CodeFirstTests.cs index 9c9c0c7d977..e42c2661a84 100644 --- a/src/HotChocolate/Core/test/Execution.Tests/CodeFirstTests.cs +++ b/src/HotChocolate/Core/test/Execution.Tests/CodeFirstTests.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Linq; +using System.Threading; using System.Threading.Tasks; using HotChocolate.Execution; using HotChocolate.Resolvers; @@ -43,6 +45,22 @@ public async Task ExecuteOneFieldQueryWithMethod() result.MatchSnapshot(); } + [Fact] + public async Task ExecuteOneFieldQueryWithQuery() + { + // arrange + var schema = Schema.Create( + c => c.RegisterType()); + + // act + IExecutionResult result = + await schema.MakeExecutable().ExecuteAsync("{ query }"); + + // assert + Assert.Null(result.Errors); + result.MatchSnapshot(); + } + [Fact] public async Task ExecuteWithUnionType() { @@ -51,13 +69,16 @@ public async Task ExecuteWithUnionType() // act IExecutionResult result = - await schema.MakeExecutable().ExecuteAsync( - @"{ - fooOrBar { - ... on Bar { nameBar } - ... on Foo { nameFoo } + await schema.MakeExecutable() + .ExecuteAsync( + @" + { + fooOrBar { + ... on Bar { nameBar } + ... on Foo { nameFoo } + } } - }"); + "); // assert Assert.Null(result.Errors); @@ -263,6 +284,11 @@ public string GetTest() return "Hello World!"; } + public IExecutable GetQuery() + { + return MockQuery.From("foo", "bar"); + } + public string TestProp => "Hello World!"; } @@ -285,6 +311,7 @@ public class QueryTypeWithMethod { descriptor.Name("Query"); descriptor.Field(t => t.GetTest()).Name("test"); + descriptor.Field(t => t.GetQuery()).Name("query"); } } @@ -434,5 +461,32 @@ public class DogType .Type>(); } } + + public class MockQuery : IExecutable + { + private readonly IReadOnlyList _list; + + private MockQuery(IEnumerable list) + { + _list = list.ToArray(); + } + + async ValueTask IExecutable.ExecuteAsync(CancellationToken cancellationToken) + { + return await ExecuteAsync(cancellationToken); + } + + public ValueTask> ExecuteAsync(CancellationToken cancellationToken) + { + return new ValueTask>(_list); + } + + public string Print() + { + return _list.ToString(); + } + + public static MockQuery From(params T[] items) => new MockQuery(items); + } } } diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Field_Based_Optimizers.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Field_Based_Optimizers.snap deleted file mode 100644 index b768114f5bc..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Field_Based_Optimizers.snap +++ /dev/null @@ -1,18 +0,0 @@ -{ - ... on Query { - root { - ... on Foo { - bar { - ... on Bar { - text - baz @_internal { - ... on Baz { - text @_internal - } - } - } - } - } - } - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited.snap deleted file mode 100644 index 455eeecf475..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited.snap +++ /dev/null @@ -1,16 +0,0 @@ -query foo($v: Boolean) { - ... on Query { - hero(episode: EMPIRE) { - ... on Human { - name @include(if: $v) - id - height @include(if: $v) - } - ... on Droid { - name @include(if: $v) - id - height @include(if: $v) - } - } - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_2.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_2.snap deleted file mode 100644 index 2683f5d8d1d..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_2.snap +++ /dev/null @@ -1,16 +0,0 @@ -query foo($v: Boolean, $q: Boolean) { - ... on Query { - hero(episode: EMPIRE) { - ... on Human { - name @include(if: $q) - id - height @include(if: $v) - } - ... on Droid { - name @include(if: $q) - id - height @include(if: $v) - } - } - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_3.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_3.snap deleted file mode 100644 index 65e23a43199..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Object_Field_Visibility_Is_Correctly_Inherited_3.snap +++ /dev/null @@ -1,12 +0,0 @@ -query foo($v: Boolean, $q: Boolean) { - ... on Query { - hero(episode: EMPIRE) @include(if: $v) { - ... on Human { - name @include(if: $q) - } - ... on Droid { - name @include(if: $q) - } - } - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Prepare_Fragment_Definition.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Prepare_Fragment_Definition.snap deleted file mode 100644 index bc679f1ab1d..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Prepare_Fragment_Definition.snap +++ /dev/null @@ -1,14 +0,0 @@ -{ - ... on Query { - hero(episode: EMPIRE) { - ... on Human { - name - homePlanet - } - ... on Droid { - name - primaryFunction - } - } - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Prepare_Inline_Fragment.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Prepare_Inline_Fragment.snap deleted file mode 100644 index bc679f1ab1d..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Prepare_Inline_Fragment.snap +++ /dev/null @@ -1,14 +0,0 @@ -{ - ... on Query { - hero(episode: EMPIRE) { - ... on Human { - name - homePlanet - } - ... on Droid { - name - primaryFunction - } - } - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Reuse_Selection.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Reuse_Selection.snap deleted file mode 100644 index 5f48a964030..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/OperationCompilerTests.Reuse_Selection.snap +++ /dev/null @@ -1,36 +0,0 @@ -query Hero($episode: Episode, $withFriends: Boolean!) { - ... on Query { - hero(episode: $episode) { - ... on Human { - name - friends @include(if: $withFriends) { - ... on CharacterConnection { - nodes @include(if: $withFriends) { - ... on Human { - id @include(if: $withFriends) - } - ... on Droid { - id @include(if: $withFriends) - } - } - } - } - } - ... on Droid { - name - friends @include(if: $withFriends) { - ... on CharacterConnection { - nodes @include(if: $withFriends) { - ... on Human { - id @include(if: $withFriends) - } - ... on Droid { - id @include(if: $withFriends) - } - } - } - } - } - } - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/ResultHelperTests.BuildResult_SimpleResultSet_SnapshotMatches.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/ResultHelperTests.BuildResult_SimpleResultSet_SnapshotMatches.snap deleted file mode 100644 index 769cd361886..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/ResultHelperTests.BuildResult_SimpleResultSet_SnapshotMatches.snap +++ /dev/null @@ -1,5 +0,0 @@ -{ - "data": { - "abc": "def" - } -} diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_ReviewInput_Variable_With_Dictionary.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_ReviewInput_Variable_With_Dictionary.snap deleted file mode 100644 index dd91f5e3fe1..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_ReviewInput_Variable_With_Dictionary.snap +++ /dev/null @@ -1 +0,0 @@ -{ stars: 5 } diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_ReviewInput_Variable_With_Review_Object.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_ReviewInput_Variable_With_Review_Object.snap deleted file mode 100644 index a729e82ec41..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_ReviewInput_Variable_With_Review_Object.snap +++ /dev/null @@ -1 +0,0 @@ -{ stars: 5, commentary: null } diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_String_Variable_With_Default_Where_Plain_Value_Is_Provided.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_String_Variable_With_Default_Where_Plain_Value_Is_Provided.snap deleted file mode 100644 index 5f4269fe6dd..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Coerce_Nullable_String_Variable_With_Default_Where_Plain_Value_Is_Provided.snap +++ /dev/null @@ -1 +0,0 @@ -"xyz" diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Input_Field_Has_Different_Properties_Than_Defined.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Input_Field_Has_Different_Properties_Than_Defined.snap deleted file mode 100644 index c9550aabfd2..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Input_Field_Has_Different_Properties_Than_Defined.snap +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "Message": "Variable `abc` got an invalid value.", - "Code": "EXEC_INVALID_TYPE", - "Path": null, - "Locations": null, - "Extensions": { - "code": "EXEC_INVALID_TYPE", - "variable": "abc" - }, - "Exception": null - } -] diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_PlainValue_Is_Null_On_Non_Null_Variable.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_PlainValue_Is_Null_On_Non_Null_Variable.snap deleted file mode 100644 index ce5cb5dc04b..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_PlainValue_Is_Null_On_Non_Null_Variable.snap +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "Message": "Variable `abc` is required.", - "Code": "EXEC_NON_NULL_VIOLATION", - "Path": null, - "Locations": null, - "Extensions": { - "code": "EXEC_NON_NULL_VIOLATION", - "variable": "abc" - }, - "Exception": null - } -] diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_PlainValue_Type_Does_Not_Match_Variable_Type.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_PlainValue_Type_Does_Not_Match_Variable_Type.snap deleted file mode 100644 index c9550aabfd2..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_PlainValue_Type_Does_Not_Match_Variable_Type.snap +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "Message": "Variable `abc` got an invalid value.", - "Code": "EXEC_INVALID_TYPE", - "Path": null, - "Locations": null, - "Extensions": { - "code": "EXEC_INVALID_TYPE", - "variable": "abc" - }, - "Exception": null - } -] diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Value_Is_Null_On_Non_Null_Variable.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Value_Is_Null_On_Non_Null_Variable.snap deleted file mode 100644 index ce5cb5dc04b..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Value_Is_Null_On_Non_Null_Variable.snap +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "Message": "Variable `abc` is required.", - "Code": "EXEC_NON_NULL_VIOLATION", - "Path": null, - "Locations": null, - "Extensions": { - "code": "EXEC_NON_NULL_VIOLATION", - "variable": "abc" - }, - "Exception": null - } -] diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Value_Type_Does_Not_Match_Variable_Type.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Value_Type_Does_Not_Match_Variable_Type.snap deleted file mode 100644 index c9550aabfd2..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Error_When_Value_Type_Does_Not_Match_Variable_Type.snap +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "Message": "Variable `abc` got an invalid value.", - "Code": "EXEC_INVALID_TYPE", - "Path": null, - "Locations": null, - "Extensions": { - "code": "EXEC_INVALID_TYPE", - "variable": "abc" - }, - "Exception": null - } -] diff --git a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Variable_Type_Is_Not_An_Input_Type.snap b/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Variable_Type_Is_Not_An_Input_Type.snap deleted file mode 100644 index 9edc6374ead..00000000000 --- a/src/HotChocolate/Core/test/Execution.Tests/Utilities/__snapshots__/VariableCoercionHelperTests.Variable_Type_Is_Not_An_Input_Type.snap +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "Message": "Variable `abc` is not an input type.", - "Code": "EXEC_NON_NULL_VIOLATION", - "Path": null, - "Locations": null, - "Extensions": { - "code": "EXEC_NON_NULL_VIOLATION", - "variable": "abc", - "type": "Human" - }, - "Exception": null - } -] diff --git a/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/CodeFirstTests.ExecuteOneFieldQueryWithQuery.snap b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/CodeFirstTests.ExecuteOneFieldQueryWithQuery.snap new file mode 100644 index 00000000000..f9bb2f97588 --- /dev/null +++ b/src/HotChocolate/Core/test/Execution.Tests/__snapshots__/CodeFirstTests.ExecuteOneFieldQueryWithQuery.snap @@ -0,0 +1,14 @@ +{ + "Label": null, + "Path": null, + "Data": { + "query": [ + "foo", + "bar" + ] + }, + "Errors": null, + "Extensions": null, + "ContextData": null, + "HasNext": null +} diff --git a/src/HotChocolate/Core/test/Types.Tests/Internal/ExtendedTypeTests.cs b/src/HotChocolate/Core/test/Types.Tests/Internal/ExtendedTypeTests.cs index 169e2c6bc85..050b70a47e8 100644 --- a/src/HotChocolate/Core/test/Types.Tests/Internal/ExtendedTypeTests.cs +++ b/src/HotChocolate/Core/test/Types.Tests/Internal/ExtendedTypeTests.cs @@ -301,6 +301,7 @@ public void IsEqual_Object_Byte_String_False() [InlineData(typeof(IEnumerable), "IEnumerable", "String")] [InlineData(typeof(IReadOnlyCollection), "IReadOnlyCollection", "String")] [InlineData(typeof(IReadOnlyList), "IReadOnlyList", "String")] + [InlineData(typeof(IExecutable), "IExecutable", "String")] [InlineData(typeof(string[]), "[String]", "String")] [InlineData( typeof(Task>), @@ -328,6 +329,7 @@ public void SupportedListTypes(Type type, string listTypeName, string elementTyp [InlineData(typeof(CustomStringList2))] [InlineData(typeof(ImmutableArray))] [InlineData(typeof(IEnumerable))] + [InlineData(typeof(IExecutable))] [InlineData(typeof(Task>))] [InlineData(typeof(ValueTask>))] [Theory] @@ -345,10 +347,10 @@ public void ChangeNullability_From_ElementType(Type listType) } [Fact] - public void NullableOptionalNullableString() + public void NullableOptionalNullableString() { // arrange - MethodInfo member = + MethodInfo member = typeof(Nullability).GetMethod(nameof(Nullability.NullableOptionalNullableString))!; // act @@ -359,10 +361,10 @@ public void NullableOptionalNullableString() } [Fact] - public void OptionalNullableOptionalNullableString() + public void OptionalNullableOptionalNullableString() { // arrange - MethodInfo member = + MethodInfo member = typeof(Nullability) .GetMethod(nameof(Nullability.OptionalNullableOptionalNullableString))!; @@ -373,6 +375,20 @@ public void OptionalNullableOptionalNullableString() Assert.Equal("Optional>!", type.ToString()); } + [Fact] + public void From_IExecutableScalar() + { + // arrange + // act + ExtendedType dict = ExtendedType.FromType( + typeof(IExecutable), + _cache); + + // assert + Assert.True(dict.IsList); + Assert.True(dict.IsArrayOrList); + } + private class CustomStringList1 : List { @@ -394,11 +410,11 @@ private class CustomStringList3 #nullable enable public class Nullability - { - public Nullable> NullableOptionalNullableString() => + { + public Nullable> NullableOptionalNullableString() => throw new NotImplementedException(); - public Optional>> OptionalNullableOptionalNullableString() => + public Optional>> OptionalNullableOptionalNullableString() => throw new NotImplementedException(); } diff --git a/src/HotChocolate/Core/test/Types.Tests/Internal/TypeInfoTests.cs b/src/HotChocolate/Core/test/Types.Tests/Internal/TypeInfoTests.cs index 6505d463c90..04a27c2e1ba 100644 --- a/src/HotChocolate/Core/test/Types.Tests/Internal/TypeInfoTests.cs +++ b/src/HotChocolate/Core/test/Types.Tests/Internal/TypeInfoTests.cs @@ -60,6 +60,9 @@ public class TypeInfoTests [InlineData(typeof(IAsyncEnumerable), "[String]")] [InlineData(typeof(IEnumerable), "[String]")] [InlineData(typeof(IQueryable), "[String]")] + [InlineData(typeof(IExecutable), "[String]")] + [InlineData(typeof(IExecutable), "[String!]")] + [InlineData(typeof(IExecutable), "[String]")] [Theory] public void CreateTypeInfoFromRuntimeType( Type clrType, @@ -84,6 +87,7 @@ public class TypeInfoTests [InlineData(typeof(IEnumerable), "[String]")] [InlineData(typeof(IReadOnlyCollection), "[String]")] [InlineData(typeof(IReadOnlyList), "[String]")] + [InlineData(typeof(IExecutable), "[String]")] [InlineData(typeof(string[]), "[String]")] [Theory] public void SupportedListTypes(Type clrType, string expectedTypeName) @@ -152,6 +156,61 @@ public void NullableListNonNullElement() Assert.Equal("[String!]", typeInfo.CreateType(new StringType()).Print()); } + [Fact] + public void NonNullQueryNonNullElement() + { + // arrange + MethodInfo methodInfo = + typeof(Nullability).GetMethod(nameof(Nullability.NonNullQueryNonNullElement)); + + // act + var typeInfo = TypeInfo.Create(_typeInspector.GetReturnType(methodInfo!), _cache); + + // assert + Assert.Equal("[String!]!", typeInfo.CreateType(new StringType()).Print()); + } + + [Fact] + public void NonNullQueryNullableElement() + { + // arrange + MethodInfo methodInfo = + typeof(Nullability).GetMethod(nameof(Nullability.NonNullQueryNullableElement)); + + // act + var typeInfo = TypeInfo.Create(_typeInspector.GetReturnType(methodInfo!), _cache); + + // assert + Assert.Equal("[String]!", typeInfo.CreateType(new StringType()).Print()); + } + + [Fact] + public void NullableQueryNullableElement() + { + // arrange + MethodInfo methodInfo = + typeof(Nullability).GetMethod(nameof(Nullability.NullableQueryNullableElement)); + + // act + var typeInfo = TypeInfo.Create(_typeInspector.GetReturnType(methodInfo!), _cache); + + // assert + Assert.Equal("[String]", typeInfo.CreateType(new StringType()).Print()); + } + + [Fact] + public void NullableQueryNonNullElement() + { + // arrange + MethodInfo methodInfo = + typeof(Nullability).GetMethod(nameof(Nullability.NullableQueryNonNullElement)); + + // act + var typeInfo = TypeInfo.Create(_typeInspector.GetReturnType(methodInfo!), _cache); + + // assert + Assert.Equal("[String!]", typeInfo.CreateType(new StringType()).Print()); + } [Fact] public void NonNullCollectionNonNullElement() { @@ -538,6 +597,14 @@ public class Nullability public ICollection? NullableCollectionNonNullElement() => default; + public IExecutable NonNullQueryNonNullElement() => default!; + + public IExecutable NonNullQueryNullableElement() => default!; + + public IExecutable? NullableQueryNullableElement() => default; + + public IExecutable? NullableQueryNonNullElement() => default; + public string[] NonNullArrayNonNullElement() => default!; public string?[] NonNullArrayNullableElement() => default!; @@ -549,7 +616,7 @@ public class Nullability public List?>? NestedList() => default; public Optional OptionalNullableString() => default; - + public Nullable> NullableOptionalNullableString() => default; }