Skip to content

Commit

Permalink
Fixed DefaultTypeInspector ignored ScopedStateAttribute (#3568)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib committed Apr 22, 2021
1 parent 19cfba2 commit 4b9be94
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;

#nullable enable

namespace HotChocolate
{
[AttributeUsage(AttributeTargets.Parameter)]
public class ScopedStateAttribute
: Attribute
public class ScopedStateAttribute : Attribute
{
public ScopedStateAttribute()
{
Expand All @@ -15,6 +16,6 @@ public ScopedStateAttribute(string key)
Key = key;
}

public string Key { get; }
public string? Key { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static class ResolverContextExtensions
throw String_NullOrEmpty(nameof(name));
}

if (context.ContextData.TryGetValue(name, out object? value) &&
if (context.ContextData.TryGetValue(name, out var value) &&
value is T casted)
{
return casted;
Expand All @@ -47,7 +47,7 @@ public static class ResolverContextExtensions
throw String_NullOrEmpty(nameof(name));
}

if (context.ScopedContextData.TryGetValue(name, out object? value) &&
if (context.ScopedContextData.TryGetValue(name, out var value) &&
value is T casted)
{
return casted;
Expand All @@ -70,7 +70,7 @@ public static class ResolverContextExtensions
throw String_NullOrEmpty(nameof(name));
}

if (context.LocalContextData.TryGetValue(name, out object? value) &&
if (context.LocalContextData.TryGetValue(name, out var value) &&
value is T casted)
{
return casted;
Expand Down Expand Up @@ -153,7 +153,7 @@ public static class ResolverContextExtensions
throw new ArgumentNullException(nameof(createValue));
}

if (context.ContextData.TryGetValue(name, out object? value) &&
if (context.ContextData.TryGetValue(name, out var value) &&
value is T casted)
{
return casted;
Expand Down Expand Up @@ -187,7 +187,7 @@ public static class ResolverContextExtensions
throw new ArgumentNullException(nameof(createValue));
}

if (context.ScopedContextData.TryGetValue(name, out object? value) &&
if (context.ScopedContextData.TryGetValue(name, out var value) &&
value is T casted)
{
return casted;
Expand Down Expand Up @@ -221,7 +221,7 @@ public static class ResolverContextExtensions
throw new ArgumentNullException(nameof(createValue));
}

if (context.LocalContextData.TryGetValue(name, out object? value) &&
if (context.LocalContextData.TryGetValue(name, out var value) &&
value is T casted)
{
return casted;
Expand Down Expand Up @@ -285,16 +285,16 @@ public static class ResolverContextExtensions
context.LocalContextData = context.LocalContextData.Remove(name);
}

public static T GetEventMessage<T>(this IResolverContext context)
public static T GetEventMessage<T>(this IResolverContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}

if (context.ScopedContextData.TryGetValue(
WellKnownContextData.EventMessage,
out object? value) && value is { })
WellKnownContextData.EventMessage,
out var value) && value is { })
{
if(value is T casted)
{
Expand All @@ -307,4 +307,4 @@ public static T GetEventMessage<T>(this IResolverContext context)
throw EventMessage_NotFound();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public static async ValueTask<object> AwaitTaskHelper<T>(Task<T> task)
bool hasDefaultValue,
TContextData defaultValue)
{
if (contextData.TryGetValue(key, out object value))
if (contextData.TryGetValue(key, out var value))
{
if (value is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ private static bool HasConfiguration(ICustomAttributeProvider element)
element.IsDefined(typeof(ServiceAttribute), true) ||
element.IsDefined(typeof(GlobalStateAttribute), true) ||
element.IsDefined(typeof(ScopedServiceAttribute), true) ||
element.IsDefined(typeof(ScopedStateAttribute), true) ||
element.IsDefined(typeof(LocalStateAttribute), true) ||
element.IsDefined(typeof(DescriptorAttribute), true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace HotChocolate.Execution
public class ScopedContextDataTests
{
[Fact]
public async Task ScopedContextDataIsPassedAllongCorrectly()
public async Task ScopedContextDataIsPassedAlongCorrectly()
{
// arrange
ISchema schema = Schema.Create(
Expand All @@ -26,10 +26,10 @@ type Level2
foo: String
}
",
c => c.Use(next => context =>
c => c.Use(_ => context =>
{
if (context.ScopedContextData
.TryGetValue("field", out object o)
.TryGetValue("field", out var o)
&& o is string s)
{
s += "/" + context.Field.Name;
Expand All @@ -44,7 +44,7 @@ type Level2
context.Result = s;
return default(ValueTask);
return default;
}));

IRequestExecutor executor = schema.MakeExecutable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using HotChocolate.Execution;
using HotChocolate.Language;
using HotChocolate.Tests;
using HotChocolate.Types;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;

Expand Down Expand Up @@ -1461,6 +1464,17 @@ public async Task Compile_SetLocalState_Generic()
Assert.Equal("abc", resolverContext.LocalContextData["foo"]);
}

[Fact]
public async Task SchemaIntegrationTest()
{
await new ServiceCollection()
.AddGraphQL()
.AddQueryType<Resolvers>()
.ModifyOptions(o => o.SortFieldsByName = true)
.BuildSchemaAsync()
.MatchSnapshotAsync();
}

public class Resolvers
{
public Task<object> ObjectTaskResolver() =>
Expand All @@ -1478,6 +1492,7 @@ public class Resolvers

public string StringResolverWithArg(string a) => a;

[GraphQLIgnore]
public string StringValueNodeResolverWithArg(StringValueNode a) => a.Value;

public string OptionalStringResolverWithArg(Optional<string> a) => a.Value;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
schema {
query: Resolvers
}

type Resolvers {
globalState: String
globalStateNullable: String!
globalStateWithDefault: String
globalStateWithDefaultAbc: String
globalStateWithKey: String
localState: String
localStateWithDefault: String
localStateWithDefaultAbc: String
localStateWithKey: String
optionalStringResolverWithArg(a: String): String
resolverWithCancellationToken: String
resolverWithDocument: Boolean!
resolverWithFieldSelection: Boolean!
resolverWithObjectField: Boolean!
resolverWithObjectType: Boolean!
resolverWithOperationDefinition: Boolean!
resolverWithOutputField: Boolean!
resolverWithResolverContext: Boolean!
resolverWithSchema: Boolean!
resolverWithService: Boolean!
resolveWithContextData: String
resolveWithContextDataDefault: String
resolveWithScopedContextData: String
resolveWithScopedContextDataDefault: String
scopedState: String
scopedStateNullable: String!
scopedStateWithDefault: String
scopedStateWithDefaultAbc: String
scopedStateWithKey: String
setGlobalState: String
setGlobalStateGeneric: String
setLocalState: String
setLocalStateGeneric: String
setScopedState: String
setScopedStateGeneric: String
stringProp: String
stringResolver: String
stringResolverWithArg(a: String): String
stringTaskResolver: String
stringTaskResolverProp: String
stringTaskResolverWithArg(a: String): String
}

"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("Deferred when true." if: Boolean "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) 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("Streamed when true." if: Boolean! "The initial elements that shall be send down to the consumer." initialCount: Int! "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) on FIELD

0 comments on commit 4b9be94

Please sign in to comment.