Skip to content

Commit c87c355

Browse files
authored
1 parent 272cb4f commit c87c355

File tree

2 files changed

+202
-4
lines changed

2 files changed

+202
-4
lines changed

src/GraphQL.Tests/Utilities/SchemaBuilderTests.cs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,125 @@ directive @myDirective(
311311
});
312312
}
313313

314+
[Fact]
315+
public void custom_deprecation_on_type_field()
316+
{
317+
var definitions = @"
318+
type Query {
319+
stars: Int @deprecated(reason: ""a reason"")
320+
}
321+
";
322+
323+
var schema = Schema.For(definitions);
324+
schema.Initialize();
325+
326+
var type = schema.FindType("Query") as IObjectGraphType;
327+
type.ShouldNotBeNull();
328+
type.Fields.Count().ShouldBe(1);
329+
type.Fields.Single().DeprecationReason.ShouldBe("a reason");
330+
}
331+
332+
[Fact]
333+
public void default_deprecation_on_type_field()
334+
{
335+
var definitions = @"
336+
type Query {
337+
stars: Int @deprecated
338+
}
339+
";
340+
341+
var schema = Schema.For(definitions);
342+
schema.Initialize();
343+
344+
var type = schema.FindType("Query") as IObjectGraphType;
345+
type.ShouldNotBeNull();
346+
type.Fields.Count().ShouldBe(1);
347+
type.Fields.Single().DeprecationReason.ShouldBe("No longer supported");
348+
}
349+
350+
[Fact]
351+
public void default_deprecation_on_interface_field()
352+
{
353+
var definitions = @"
354+
interface Movie {
355+
stars: Int @deprecated
356+
}
357+
";
358+
359+
var schema = Schema.For(definitions);
360+
schema.Initialize();
361+
362+
var type = schema.FindType("Movie") as IInterfaceGraphType;
363+
type.ShouldNotBeNull();
364+
type.Fields.Count().ShouldBe(1);
365+
type.Fields.Single().DeprecationReason.ShouldBe("No longer supported");
366+
}
367+
368+
[Fact]
369+
public void deprecate_enum_value()
370+
{
371+
var definitions = @"
372+
enum PetKind {
373+
CAT @deprecated(reason: ""dogs rule"")
374+
DOG
375+
}
376+
";
377+
378+
var schema = Schema.For(definitions);
379+
schema.Initialize();
380+
381+
var type = schema.FindType("PetKind") as EnumerationGraphType;
382+
type.ShouldNotBeNull();
383+
384+
var cat = type.Values.Single(x => x.Name == "CAT");
385+
cat.DeprecationReason.ShouldBe("dogs rule");
386+
}
387+
388+
[Fact]
389+
public void default_deprecation_on_input_field()
390+
{
391+
var definitions = @"
392+
input MovieInput {
393+
stars: Int @deprecated
394+
}
395+
";
396+
397+
var schema = Schema.For(definitions);
398+
schema.Initialize();
399+
400+
var type = schema.FindType("MovieInput") as IInputObjectGraphType;
401+
type.ShouldNotBeNull();
402+
type.Fields.Count().ShouldBe(1);
403+
type.Fields.Single().DeprecationReason.ShouldBe("No longer supported");
404+
}
405+
406+
[Fact]
407+
public void deprecated_prefers_metadata_values()
408+
{
409+
var definitions = @"
410+
type Movie {
411+
movies: Int @deprecated
412+
}
413+
";
414+
415+
var schema = Schema.For(definitions, _ => _.Types.Include<Movie>());
416+
schema.Initialize();
417+
418+
var type = schema.FindType("Movie") as IObjectGraphType;
419+
type.ShouldNotBeNull();
420+
type.Fields.Count().ShouldBe(1);
421+
type.Fields.Single().DeprecationReason.ShouldBe("my reason");
422+
}
423+
424+
class Movie
425+
{
426+
[GraphQLMetadata("movies", DeprecationReason = "my reason")]
427+
public int Movies()
428+
{
429+
return 0;
430+
}
431+
}
432+
314433
class CustomScalarType : ScalarGraphType
315434
{
316435
public CustomScalarType()

src/GraphQL/Utilities/SchemaBuilder.cs

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,13 @@ protected virtual IObjectGraphType ToObjectGraphType(GraphQLObjectTypeDefinition
161161
var type = new ObjectGraphType();
162162
type.Name = astType.Name.Value;
163163
type.Description = typeConfig.Description;
164-
type.DeprecationReason = typeConfig.DeprecationReason;
165164
type.IsTypeOf = typeConfig.IsTypeOfFunc;
166165

166+
ApplyDeprecatedDirective(astType.Directives, reason =>
167+
{
168+
type.DeprecationReason = typeConfig.DeprecationReason ?? reason;
169+
});
170+
167171
CopyMetadata(type, typeConfig);
168172

169173
var fields = astType.Fields.Select(f => ToFieldType(type.Name, f));
@@ -189,7 +193,6 @@ protected virtual FieldType ToFieldType(string parentTypeName, GraphQLFieldDefin
189193
var field = new FieldType();
190194
field.Name = fieldDef.Name.Value;
191195
field.Description = fieldConfig.Description;
192-
field.DeprecationReason = fieldConfig.DeprecationReason;
193196
field.ResolvedType = ToGraphType(fieldDef.Type);
194197
field.Resolver = fieldConfig.Resolver;
195198

@@ -198,16 +201,50 @@ protected virtual FieldType ToFieldType(string parentTypeName, GraphQLFieldDefin
198201
var args = fieldDef.Arguments.Select(ToArguments);
199202
field.Arguments = new QueryArguments(args);
200203

204+
ApplyDeprecatedDirective(fieldDef.Directives, reason =>
205+
{
206+
field.DeprecationReason = fieldConfig.DeprecationReason ?? reason;
207+
});
208+
201209
return field;
202210
}
203211

204-
protected virtual FieldType ToFieldType(GraphQLInputValueDefinition inputDef)
212+
private static string DeprecatedDefaultValue = DirectiveGraphType.Deprecated.Arguments.Find("reason").DefaultValue.ToString();
213+
private void ApplyDeprecatedDirective(IEnumerable<GraphQLDirective> directives, Action<string> apply)
214+
{
215+
var deprecated = directives.Directive("deprecated");
216+
217+
if(deprecated != null)
218+
{
219+
var arg = deprecated.Arguments.Argument("reason");
220+
var value = "";
221+
222+
if(arg != null)
223+
{
224+
value = ToValue(arg.Value).ToString();
225+
}
226+
227+
if(string.IsNullOrWhiteSpace(value))
228+
{
229+
value = DeprecatedDefaultValue;
230+
}
231+
232+
apply(value);
233+
}
234+
}
235+
236+
protected virtual FieldType ToFieldType(string parentTypeName, GraphQLInputValueDefinition inputDef)
205237
{
206238
var field = new FieldType();
207239
field.Name = inputDef.Name.Value;
208240
field.ResolvedType = ToGraphType(inputDef.Type);
209241
field.DefaultValue = ToValue(inputDef.DefaultValue);
210242

243+
ApplyDeprecatedDirective(inputDef.Directives, reason =>
244+
{
245+
field.DeprecationReason = reason;
246+
});
247+
211248
return field;
212249
}
213250

@@ -220,6 +257,11 @@ protected virtual InterfaceGraphType ToInterfaceType(GraphQLInterfaceTypeDefinit
220257
type.Description = typeConfig.Description;
221258
type.ResolveType = typeConfig.ResolveType;
222259

260+
ApplyDeprecatedDirective(interfaceDef.Directives, reason =>
261+
{
262+
type.DeprecationReason = typeConfig.DeprecationReason ?? reason;
263+
});
264+
223265
CopyMetadata(type, typeConfig);
224266

225267
var fields = interfaceDef.Fields.Select(f => ToFieldType(type.Name, f));
@@ -237,6 +279,11 @@ protected virtual UnionGraphType ToUnionType(GraphQLUnionTypeDefinition unionDef
237279
type.Description = typeConfig.Description;
238280
type.ResolveType = typeConfig.ResolveType;
239281

282+
ApplyDeprecatedDirective(unionDef.Directives, reason =>
283+
{
284+
type.DeprecationReason = typeConfig.DeprecationReason ?? reason;
285+
});
286+
240287
CopyMetadata(type, typeConfig);
241288

242289
var possibleTypes = unionDef.Types.Select(x => GetType(x.Name.Value));
@@ -248,8 +295,13 @@ protected virtual InputObjectGraphType ToInputObjectType(GraphQLInputObjectTypeD
248295
{
249296
var type = new InputObjectGraphType();
250297
type.Name = inputDef.Name.Value;
251-
var fields = inputDef.Fields.Select(ToFieldType);
252298

299+
ApplyDeprecatedDirective(inputDef.Directives, reason =>
300+
{
301+
type.DeprecationReason = reason;
302+
});
303+
304+
var fields = inputDef.Fields.Select(x => ToFieldType(type.Name, x));
253305
fields.Apply(f => type.AddField(f));
254306

255307
return type;
@@ -259,6 +311,12 @@ protected virtual EnumerationGraphType ToEnumerationType(GraphQLEnumTypeDefiniti
259311
{
260312
var type = new EnumerationGraphType();
261313
type.Name = enumDef.Name.Value;
314+
315+
ApplyDeprecatedDirective(enumDef.Directives, reason =>
316+
{
317+
type.DeprecationReason = reason;
318+
});
319+
262320
var values = enumDef.Values.Select(ToEnumValue);
263321
values.Apply(type.AddValue);
264322
return type;
@@ -292,6 +350,12 @@ private EnumValueDefinition ToEnumValue(GraphQLEnumValueDefinition valDef)
292350
var val = new EnumValueDefinition();
293351
val.Value = valDef.Name.Value;
294352
val.Name = valDef.Name.Value;
353+
354+
ApplyDeprecatedDirective(valDef.Directives, reason =>
355+
{
356+
val.DeprecationReason = reason;
357+
});
358+
295359
return val;
296360
}
297361

@@ -413,4 +477,19 @@ protected virtual void CopyMetadata(IProvideMetadata target, IProvideMetadata so
413477
});
414478
}
415479
}
480+
481+
internal static class SchemaExtensions
482+
{
483+
public static GraphQLDirective Directive(this IEnumerable<GraphQLDirective> directives, string name)
484+
{
485+
return directives?.FirstOrDefault(
486+
x => string.Equals(x.Name.Value, name, StringComparison.OrdinalIgnoreCase));
487+
}
488+
489+
public static GraphQLArgument Argument(this IEnumerable<GraphQLArgument> arguments, string name)
490+
{
491+
return arguments?.FirstOrDefault(
492+
x => string.Equals(x.Name.Value, name, StringComparison.OrdinalIgnoreCase));
493+
}
494+
}
416495
}

0 commit comments

Comments
 (0)