Skip to content

Commit

Permalink
Fixed deprecation handling. (#876)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Jun 26, 2019
1 parent e55c6c1 commit 3529e78
Show file tree
Hide file tree
Showing 72 changed files with 786 additions and 121 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- The parent method on the resolver context now uses the converters if the source object type does not align with the requested type.
- Aligned the deprecation handling with the GraphQL spec. [#876](https://github.com/ChilliCream/hotchocolate/pull/876)

## [9.0.4] - 2019-06-16

Expand Down
33 changes: 14 additions & 19 deletions src/Core/Abstractions/AttributeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,36 +114,31 @@ public static string GetGraphQLDescription(
return null;
}

public static string GetGraphQLDeprecationReason(
this ICustomAttributeProvider attributeProvider)
public static bool IsDeprecated(
this ICustomAttributeProvider attributeProvider,
out string reason)
{
var deprecatedAttribute = GetAttributeIfDefined<GraphQLDeprecatedAttribute>(
attributeProvider
);
var deprecatedAttribute =
GetAttributeIfDefined<GraphQLDeprecatedAttribute>(
attributeProvider);

if (deprecatedAttribute != null)
{
return deprecatedAttribute.DeprecationReason;
reason = deprecatedAttribute.DeprecationReason;
return true;
}

var obsoleteAttribute = GetAttributeIfDefined<ObsoleteAttribute>(
attributeProvider
);
attributeProvider);

if (obsoleteAttribute != null)
{
if (string.IsNullOrEmpty(obsoleteAttribute.Message))
{
// TODO : resources
return "This field is no longer supported.";
}
else
{
return obsoleteAttribute.Message;
}
reason = obsoleteAttribute.Message;
return true;
}

return null;
reason = null;
return false;
}

private static string GetFromType(Type type)
Expand Down Expand Up @@ -179,7 +174,7 @@ private static TAttribute GetAttributeIfDefined<TAttribute>(ICustomAttributeProv
where TAttribute : Attribute
{
Type attributeType = typeof(TAttribute);

if (attributeProvider.IsDefined(attributeType, false))
{
return (TAttribute)attributeProvider
Expand Down
3 changes: 2 additions & 1 deletion src/Core/Abstractions/InternalsVisibleTo.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("HotChocolate.Types")]
[assembly: InternalsVisibleTo("HotChocolate.Core")]
[assembly: InternalsVisibleTo("HotChocolate.Types")]
[assembly: InternalsVisibleTo("HotChocolate.Stitching")]
[assembly: InternalsVisibleTo("HotChocolate.Abstractions.Tests")]
[assembly: InternalsVisibleTo("HotChocolate.Core.Tests")]
[assembly: InternalsVisibleTo("HotChocolate.Types.Tests")]
1 change: 1 addition & 0 deletions src/Core/Abstractions/WellKnownDirectives.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ internal static class WellKnownDirectives
public const string IfArgument = "if";
public const string Deprecated = "deprecated";
public const string DeprecationReasonArgument = "reason";
public const string DeprecationDefaultReason = "No longer supported";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace HotChocolate.Execution
{
public class ErrorbehaviorTests
public class ErrorBehaviourTests
{
[Fact]
public async Task SyntaxError()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,25 @@
"onOperation": false,
"onFragment": false,
"onField": false
},
{
"name": "deprecated",
"description": "The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema,such as deprecated fields on a type or deprecated enum values.",
"args": [
{
"name": "reason",
"description": "Deprecations include a reason for why it is deprecated, which is formatted using Markdown syntax (as specified by CommonMark).",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": "\"No longer supported\""
}
],
"onOperation": false,
"onFragment": false,
"onField": false
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,25 @@
"onOperation": false,
"onFragment": false,
"onField": false
},
{
"name": "deprecated",
"description": "The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema,such as deprecated fields on a type or deprecated enum values.",
"args": [
{
"name": "reason",
"description": "Deprecations include a reason for why it is deprecated, which is formatted using Markdown syntax (as specified by CommonMark).",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": "\"No longer supported\""
}
],
"onOperation": false,
"onFragment": false,
"onField": false
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Query {

input FooFilter {
AND: [FooFilter!]
bar: Boolean @Bar(qux: null)
bar: Boolean @Bar
OR: [FooFilter!]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Query {

input FooFilter {
AND: [FooFilter!]
bar: Boolean @Bar(qux: null)
bar: Boolean @Bar
OR: [FooFilter!]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ input FooFilter {
barFloat_not_in: [Float!]
barFloat_not_lt: Float
barFloat_not_lte: Float
barInt: Int @Bar(baz: null)
barInt: Int @Bar
barLong: Long
barLong_gt: Long
barLong_gte: Long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ input FooFilter {
barFloat_not_in: [Float!]
barFloat_not_lt: Float
barFloat_not_lte: Float
barInt: Int @Bar(baz: null)
barInt: Int @Bar
barLong: Long
barLong_gt: Long
barLong_gte: Long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Query {

input FooFilter {
AND: [FooFilter!]
bar: String @Bar(baz: null)
bar: String @Bar
OR: [FooFilter!]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Query {

input FooFilter {
AND: [FooFilter!]
bar: String @Bar(baz: null)
bar: String @Bar
OR: [FooFilter!]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"None: HotChocolate.Types.CostDirective": "None: HotChocolate.Types.CostDirectiveType",
"None: System.String": "None: HotChocolate.Types.StringType",
"None: System.Boolean": "None: HotChocolate.Types.BooleanType",
"None: HotChocolate.Types.DeprecatedDirective": "None: HotChocolate.Types.DeprecatedDirectiveType",
"None: System.Int32": "None: HotChocolate.Types.IntType",
"None: HotChocolate.Types.MultiplierPathString": "None: HotChocolate.Types.MultiplierPathType",
"Output: HotChocolate.TypeRegistrarTests.Foo": "Output: HotChocolate.Types.ObjectType<HotChocolate.TypeRegistrarTests.Foo>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"HotChocolate.Types.CostDirectiveType": "HotChocolate.Types.CostDirective",
"HotChocolate.Types.StringType": "System.String",
"HotChocolate.Types.BooleanType": "System.Boolean",
"HotChocolate.Types.DeprecatedDirectiveType": "HotChocolate.Types.DeprecatedDirective",
"HotChocolate.Types.IntType": "System.Int32",
"HotChocolate.Types.MultiplierPathType": "HotChocolate.Types.MultiplierPathString",
"HotChocolate.Types.ObjectType<HotChocolate.TypeRegistrarTests.Foo>": "HotChocolate.TypeRegistrarTests.Foo",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"Output: HotChocolate.TypeRegistrarTests.Foo": "Output: HotChocolate.TypeRegistrarTests.FooType",
"None: System.String": "None: HotChocolate.Types.StringType",
"None: System.Boolean": "None: HotChocolate.Types.BooleanType",
"None: HotChocolate.Types.DeprecatedDirective": "None: HotChocolate.Types.DeprecatedDirectiveType",
"None: System.Int32": "None: HotChocolate.Types.IntType",
"None: HotChocolate.Types.MultiplierPathString": "None: HotChocolate.Types.MultiplierPathType",
"Output: HotChocolate.TypeRegistrarTests.Bar": "Output: HotChocolate.TypeRegistrarTests.BarType"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"HotChocolate.TypeRegistrarTests.FooType": "HotChocolate.TypeRegistrarTests.Foo",
"HotChocolate.Types.StringType": "System.String",
"HotChocolate.Types.BooleanType": "System.Boolean",
"HotChocolate.Types.DeprecatedDirectiveType": "HotChocolate.Types.DeprecatedDirective",
"HotChocolate.Types.IntType": "System.Int32",
"HotChocolate.Types.MultiplierPathType": "HotChocolate.Types.MultiplierPathString",
"HotChocolate.TypeRegistrarTests.BarType": "HotChocolate.TypeRegistrarTests.Bar"
Expand Down
74 changes: 74 additions & 0 deletions src/Core/Types.Tests/Types/InterfaceTypeExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
Expand Down Expand Up @@ -29,6 +30,7 @@ public void InterfaceTypeExtension_AddField()
Assert.True(type.Fields.ContainsField("test"));
}

[Obsolete]
[Fact]
public void InterfaceTypeExtension_DepricateField()
{
Expand All @@ -53,6 +55,78 @@ public void InterfaceTypeExtension_DepricateField()
Assert.Equal("Foo", type.Fields["description"].DeprecationReason);
}

[Fact]
public void InterfaceTypeExtension_Deprecate_With_Reason()
{
// arrange
FieldResolverDelegate resolver =
ctx => Task.FromResult<object>(null);

// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<DummyQuery>()
.AddType<FooType>()
.AddType(new InterfaceTypeExtension(d => d
.Name("Foo")
.Field("description")
.Type<StringType>()
.Deprecated("Foo")))
.Create();

// assert
InterfaceType type = schema.GetType<InterfaceType>("Foo");
Assert.True(type.Fields["description"].IsDeprecated);
Assert.Equal("Foo", type.Fields["description"].DeprecationReason);
}

[Fact]
public void InterfaceTypeExtension_Deprecate_Without_Reason()
{
// arrange
FieldResolverDelegate resolver =
ctx => Task.FromResult<object>(null);

// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<DummyQuery>()
.AddType<FooType>()
.AddType(new InterfaceTypeExtension(d => d
.Name("Foo")
.Field("description")
.Type<StringType>()
.Deprecated()))
.Create();

// assert
InterfaceType type = schema.GetType<InterfaceType>("Foo");
Assert.True(type.Fields["description"].IsDeprecated);
Assert.Equal(
WellKnownDirectives.DeprecationDefaultReason,
type.Fields["description"].DeprecationReason);
}

[Fact]
public void InterfaceTypeExtension_Deprecated_Directive_Is_Serialized()
{
// arrange
FieldResolverDelegate resolver =
ctx => Task.FromResult<object>(null);

// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<DummyQuery>()
.AddType<FooType>()
.AddType(new InterfaceTypeExtension(d => d
.Name("Foo")
.Field("description")
.Type<StringType>()
.Deprecated()))
.Create();

// assert
schema.ToString().MatchSnapshot();
}

[Fact]
public void InterfaceTypeExtension_SetTypeContextData()
{
Expand Down
53 changes: 52 additions & 1 deletion src/Core/Types.Tests/Types/ObjectTypeExtensionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ public void ObjectTypeExtension_AddMiddleware()
executor.Execute("{ description }").MatchSnapshot();
}

[Obsolete]
[Fact]
public void ObjectTypeExtension_DepricateField()
public void ObjectTypeExtension_DeprecateField_Obsolete()
{
// arrange
FieldResolverDelegate resolver =
Expand All @@ -122,6 +123,56 @@ public void ObjectTypeExtension_DepricateField()
Assert.Equal("Foo", type.Fields["description"].DeprecationReason);
}

[Fact]
public void ObjectTypeExtension_DepricateField_With_Reason()
{
// arrange
FieldResolverDelegate resolver =
ctx => Task.FromResult<object>(null);

// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<FooType>()
.AddType(new ObjectTypeExtension(d => d
.Name("Foo")
.Field("description")
.Type<StringType>()
.Deprecated("Foo")))
.Create();

// assert
ObjectType type = schema.GetType<ObjectType>("Foo");
Assert.True(type.Fields["description"].IsDeprecated);
Assert.Equal("Foo", type.Fields["description"].DeprecationReason);
schema.ToString().MatchSnapshot();
}

[Fact]
public void ObjectTypeExtension_DepricateField_Without_Reason()
{
// arrange
FieldResolverDelegate resolver =
ctx => Task.FromResult<object>(null);

// act
ISchema schema = SchemaBuilder.New()
.AddQueryType<FooType>()
.AddType(new ObjectTypeExtension(d => d
.Name("Foo")
.Field("description")
.Type<StringType>()
.Deprecated()))
.Create();

// assert
ObjectType type = schema.GetType<ObjectType>("Foo");
Assert.True(type.Fields["description"].IsDeprecated);
Assert.Equal(
WellKnownDirectives.DeprecationDefaultReason,
type.Fields["description"].DeprecationReason);
schema.ToString().MatchSnapshot();
}

[Fact]
public void ObjectTypeExtension_SetTypeContextData()
{
Expand Down
Loading

0 comments on commit 3529e78

Please sign in to comment.