From 9c57080d3c4392f123b253ec5ba2403918ed32fb Mon Sep 17 00:00:00 2001 From: Joel Turkel Date: Mon, 29 Mar 2021 13:54:45 -0400 Subject: [PATCH] Introspection support for deprecated directive arguments --- lib/graphql/introspection.rb | 2 +- lib/graphql/introspection/directive_type.rb | 10 +++- .../introspection/directive_type_spec.rb | 56 +++++++++++++++++++ .../schema/build_from_definition_spec.rb | 2 + spec/graphql/schema/printer_spec.rb | 4 +- 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/lib/graphql/introspection.rb b/lib/graphql/introspection.rb index 0f3ea73f60..921e550172 100644 --- a/lib/graphql/introspection.rb +++ b/lib/graphql/introspection.rb @@ -17,7 +17,7 @@ def self.query(include_deprecated_args: false) name description locations - args { + args#{include_deprecated_args ? '(includeDeprecated: true)' : ''} { ...InputValue } } diff --git a/lib/graphql/introspection/directive_type.rb b/lib/graphql/introspection/directive_type.rb index 0df00fef1b..d2d332a85e 100644 --- a/lib/graphql/introspection/directive_type.rb +++ b/lib/graphql/introspection/directive_type.rb @@ -12,13 +12,17 @@ class DirectiveType < Introspection::BaseObject field :name, String, null: false, method: :graphql_name field :description, String, null: true field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false - field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false + field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do + argument :include_deprecated, Boolean, required: false, default_value: false + end field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation? field :on_fragment, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_fragment? field :on_field, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_field? - def args - @context.warden.arguments(@object) + def args(include_deprecated:) + args = @context.warden.arguments(@object) + args = args.reject(&:deprecation_reason) unless include_deprecated + args end end end diff --git a/spec/graphql/introspection/directive_type_spec.rb b/spec/graphql/introspection/directive_type_spec.rb index 3bfec39854..c12f221812 100644 --- a/spec/graphql/introspection/directive_type_spec.rb +++ b/spec/graphql/introspection/directive_type_spec.rb @@ -18,6 +18,15 @@ } |} + let(:directive_with_deprecated_arg) do + Class.new(GraphQL::Schema::Directive) do + graphql_name "customTransform" + locations GraphQL::Schema::Directive::FIELD + argument :old_way, String, required: false, deprecation_reason: "Use the newWay" + argument :new_way, String, required: false + end + end + let(:schema) { Class.new(Dummy::Schema) } let(:result) { schema.execute(query_string) } before do @@ -63,4 +72,51 @@ }} assert_equal(expected, result) end + + it "hides deprecated arguments by default" do + schema.directive(directive_with_deprecated_arg) + result = schema.execute <<-GRAPHQL + { + __schema { + directives { + name + args { + name + } + } + } + } + GRAPHQL + + directive_result = result["data"]["__schema"]["directives"].find { |d| d["name"] == "customTransform" } + expected = [ + {"name" => "newWay"} + ] + assert_equal(expected, directive_result["args"]) + end + + it "can expose deprecated arguments" do + schema.directive(directive_with_deprecated_arg) + result = schema.execute <<-GRAPHQL + { + __schema { + directives { + name + args(includeDeprecated: true) { + name + isDeprecated + deprecationReason + } + } + } + } + GRAPHQL + + directive_result = result["data"]["__schema"]["directives"].find { |d| d["name"] == "customTransform" } + expected = [ + {"name" => "oldWay", "isDeprecated" => true, "deprecationReason" => "Use the newWay"}, + {"name" => "newWay", "isDeprecated" => false, "deprecationReason" => nil} + ] + assert_equal(expected, directive_result["args"]) + end end diff --git a/spec/graphql/schema/build_from_definition_spec.rb b/spec/graphql/schema/build_from_definition_spec.rb index 9ee433293c..a02ece8dd3 100644 --- a/spec/graphql/schema/build_from_definition_spec.rb +++ b/spec/graphql/schema/build_from_definition_spec.rb @@ -785,6 +785,8 @@ def assert_schema_and_compare_output(definition) it 'supports @deprecated' do schema = <<-SCHEMA +directive @directiveWithDeprecatedArg(deprecatedArg: Boolean @deprecated(reason: "Don't use me!")) on OBJECT + enum MyEnum { OLD_VALUE @deprecated OTHER_VALUE @deprecated(reason: "Terrible reasons") diff --git a/spec/graphql/schema/printer_spec.rb b/spec/graphql/schema/printer_spec.rb index 2794e49aae..d951392766 100644 --- a/spec/graphql/schema/printer_spec.rb +++ b/spec/graphql/schema/printer_spec.rb @@ -152,7 +152,7 @@ class Subscription < GraphQL::Schema::Object to the executor. """ type __Directive { - args: [__InputValue!]! + args(includeDeprecated: Boolean = false): [__InputValue!]! description: String locations: [__DirectiveLocation!]! name: String! @@ -858,6 +858,8 @@ class OddlyNamedQuery < GraphQL::Schema::Object directive @customDirective on FIELD_DEFINITION +directive @directiveWithDeprecatedArg(deprecatedArg: Boolean @deprecated(reason: "Don't use me!")) on OBJECT + directive @intDir(a: Int!) on INPUT_FIELD_DEFINITION directive @someDirective on OBJECT