graphql 1.7.4 → 1.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/generators/graphql/core.rb +13 -3
- data/lib/generators/graphql/enum_generator.rb +1 -1
- data/lib/generators/graphql/function_generator.rb +4 -1
- data/lib/generators/graphql/install_generator.rb +3 -3
- data/lib/generators/graphql/interface_generator.rb +1 -1
- data/lib/generators/graphql/loader_generator.rb +4 -1
- data/lib/generators/graphql/mutation_generator.rb +3 -3
- data/lib/generators/graphql/object_generator.rb +1 -1
- data/lib/generators/graphql/type_generator.rb +3 -0
- data/lib/generators/graphql/union_generator.rb +1 -1
- data/lib/graphql/backtrace/inspect_result.rb +1 -1
- data/lib/graphql/backtrace/table.rb +2 -2
- data/lib/graphql/backtrace/tracer.rb +7 -1
- data/lib/graphql/base_type.rb +10 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +15 -0
- data/lib/graphql/execution/multiplex.rb +4 -0
- data/lib/graphql/language/parser.rb +595 -514
- data/lib/graphql/language/parser.y +21 -5
- data/lib/graphql/list_type.rb +4 -0
- data/lib/graphql/non_null_type.rb +5 -1
- data/lib/graphql/query.rb +3 -0
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +23 -0
- data/lib/graphql/subscriptions.rb +6 -0
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -4
- data/lib/graphql/subscriptions/serialize.rb +36 -10
- data/lib/graphql/tracing/scout_tracing.rb +5 -3
- data/lib/graphql/version.rb +1 -1
- data/spec/dummy/Gemfile +4 -2
- data/spec/dummy/config/application.rb +0 -1
- data/spec/generators/graphql/install_generator_spec.rb +7 -0
- data/spec/generators/graphql/mutation_generator_spec.rb +25 -2
- data/spec/generators/graphql/union_generator_spec.rb +14 -0
- data/spec/graphql/backtrace_spec.rb +21 -1
- data/spec/graphql/base_type_spec.rb +42 -0
- data/spec/graphql/execution/multiplex_spec.rb +48 -0
- data/spec/graphql/field_spec.rb +14 -2
- data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +23 -0
- data/spec/graphql/subscriptions/serialize_spec.rb +53 -0
- data/spec/graphql/subscriptions_spec.rb +9 -2
- data/spec/graphql/tracing/scout_tracing_spec.rb +17 -0
- metadata +23 -2
| @@ -78,8 +78,8 @@ rule | |
| 78 78 | 
             
                | LBRACKET type RBRACKET { return make_node(:ListType, of_type: val[1]) }
         | 
| 79 79 |  | 
| 80 80 | 
             
              default_value_opt:
         | 
| 81 | 
            -
                  /* none */ | 
| 82 | 
            -
                | EQUALS  | 
| 81 | 
            +
                  /* none */            { return nil }
         | 
| 82 | 
            +
                | EQUALS literal_value  { return val[1] }
         | 
| 83 83 |  | 
| 84 84 | 
             
              selection_set:
         | 
| 85 85 | 
             
                  LCURLY RCURLY                { return [] }
         | 
| @@ -176,17 +176,21 @@ rule | |
| 176 176 | 
             
              argument:
         | 
| 177 177 | 
             
                  name COLON input_value { return make_node(:Argument, name: val[0], value: val[2], position_source: val[0])}
         | 
| 178 178 |  | 
| 179 | 
            -
               | 
| 179 | 
            +
              literal_value:
         | 
| 180 180 | 
             
                  FLOAT       { return val[0].to_f }
         | 
| 181 181 | 
             
                | INT         { return val[0].to_i }
         | 
| 182 182 | 
             
                | STRING      { return val[0].to_s }
         | 
| 183 183 | 
             
                | TRUE        { return true }
         | 
| 184 184 | 
             
                | FALSE       { return false }
         | 
| 185 185 | 
             
                | null_value
         | 
| 186 | 
            -
                |  | 
| 186 | 
            +
                | enum_value
         | 
| 187 187 | 
             
                | list_value
         | 
| 188 | 
            +
                | object_literal_value
         | 
| 189 | 
            +
             | 
| 190 | 
            +
              input_value:
         | 
| 191 | 
            +
                | literal_value
         | 
| 192 | 
            +
                | variable
         | 
| 188 193 | 
             
                | object_value
         | 
| 189 | 
            -
                | enum_value
         | 
| 190 194 |  | 
| 191 195 | 
             
              null_value: NULL { return make_node(:NullValue, name: val[0], position_source: val[0]) }
         | 
| 192 196 | 
             
              variable: VAR_SIGN name { return make_node(:VariableIdentifier, name: val[1], position_source: val[0]) }
         | 
| @@ -210,6 +214,18 @@ rule | |
| 210 214 | 
             
              object_value_field:
         | 
| 211 215 | 
             
                  name COLON input_value { return make_node(:Argument, name: val[0], value: val[2], position_source: val[0])}
         | 
| 212 216 |  | 
| 217 | 
            +
              /* like the previous, but with literals only: */
         | 
| 218 | 
            +
              object_literal_value:
         | 
| 219 | 
            +
                  LCURLY RCURLY                           { return make_node(:InputObject, arguments: [], position_source: val[0])}
         | 
| 220 | 
            +
                | LCURLY object_literal_value_list RCURLY { return make_node(:InputObject, arguments: val[1], position_source: val[0])}
         | 
| 221 | 
            +
             | 
| 222 | 
            +
              object_literal_value_list:
         | 
| 223 | 
            +
                  object_literal_value_field                            { return [val[0]] }
         | 
| 224 | 
            +
                | object_literal_value_list object_literal_value_field  { val[0] << val[1] }
         | 
| 225 | 
            +
             | 
| 226 | 
            +
              object_literal_value_field:
         | 
| 227 | 
            +
                  name COLON literal_value { return make_node(:Argument, name: val[0], value: val[2], position_source: val[0])}
         | 
| 228 | 
            +
             | 
| 213 229 | 
             
              enum_value: enum_name { return make_node(:Enum, name: val[0], position_source: val[0]) }
         | 
| 214 230 |  | 
| 215 231 | 
             
              directives_list_opt:
         | 
    
        data/lib/graphql/list_type.rb
    CHANGED
    
    
| @@ -62,7 +62,7 @@ module GraphQL | |
| 62 62 | 
             
                  end
         | 
| 63 63 | 
             
                end
         | 
| 64 64 |  | 
| 65 | 
            -
                def_delegators :@of_type, :coerce_input, :coerce_result
         | 
| 65 | 
            +
                def_delegators :@of_type, :coerce_input, :coerce_result, :list?
         | 
| 66 66 |  | 
| 67 67 | 
             
                def kind
         | 
| 68 68 | 
             
                  GraphQL::TypeKinds::NON_NULL
         | 
| @@ -72,5 +72,9 @@ module GraphQL | |
| 72 72 | 
             
                  "#{of_type.to_s}!"
         | 
| 73 73 | 
             
                end
         | 
| 74 74 | 
             
                alias_method :inspect, :to_s
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def non_null?
         | 
| 77 | 
            +
                  true
         | 
| 78 | 
            +
                end
         | 
| 75 79 | 
             
              end
         | 
| 76 80 | 
             
            end
         | 
    
        data/lib/graphql/query.rb
    CHANGED
    
    
| @@ -24,6 +24,7 @@ module GraphQL | |
| 24 24 | 
             
                  GraphQL::StaticValidation::ArgumentsAreDefined,
         | 
| 25 25 | 
             
                  GraphQL::StaticValidation::ArgumentLiteralsAreCompatible,
         | 
| 26 26 | 
             
                  GraphQL::StaticValidation::RequiredArgumentsArePresent,
         | 
| 27 | 
            +
                  GraphQL::StaticValidation::VariableNamesAreUnique,
         | 
| 27 28 | 
             
                  GraphQL::StaticValidation::VariablesAreInputTypes,
         | 
| 28 29 | 
             
                  GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped,
         | 
| 29 30 | 
             
                  GraphQL::StaticValidation::VariablesAreUsedAndDefined,
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module GraphQL
         | 
| 3 | 
            +
              module StaticValidation
         | 
| 4 | 
            +
                class VariableNamesAreUnique
         | 
| 5 | 
            +
                  include GraphQL::StaticValidation::Message::MessageHelper
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def validate(context)
         | 
| 8 | 
            +
                    context.visitor[GraphQL::Language::Nodes::OperationDefinition] << ->(node, parent) {
         | 
| 9 | 
            +
                      var_defns = node.variables
         | 
| 10 | 
            +
                      if var_defns.any?
         | 
| 11 | 
            +
                        vars_by_name = Hash.new { |h, k| h[k] = [] }
         | 
| 12 | 
            +
                        var_defns.each { |v| vars_by_name[v.name] << v }
         | 
| 13 | 
            +
                        vars_by_name.each do |name, defns|
         | 
| 14 | 
            +
                          if defns.size > 1
         | 
| 15 | 
            +
                            context.errors << message("There can only be one variable named \"#{name}\"", defns, context: context)
         | 
| 16 | 
            +
                          end
         | 
| 17 | 
            +
                        end
         | 
| 18 | 
            +
                      end
         | 
| 19 | 
            +
                    }
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require "securerandom"
         | 
| 2 3 | 
             
            require "graphql/subscriptions/event"
         | 
| 3 4 | 
             
            require "graphql/subscriptions/instrumentation"
         | 
| 4 5 | 
             
            require "graphql/subscriptions/serialize"
         | 
| @@ -133,5 +134,10 @@ module GraphQL | |
| 133 134 | 
             
                def write_subscription(query, events)
         | 
| 134 135 | 
             
                  raise NotImplementedError
         | 
| 135 136 | 
             
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                # @return [String] A new unique identifier for a subscription
         | 
| 139 | 
            +
                def build_id
         | 
| 140 | 
            +
                  SecureRandom.uuid
         | 
| 141 | 
            +
                end
         | 
| 136 142 | 
             
              end
         | 
| 137 143 | 
             
            end
         | 
| @@ -1,6 +1,4 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            require "securerandom"
         | 
| 3 | 
            -
             | 
| 4 2 | 
             
            module GraphQL
         | 
| 5 3 | 
             
              class Subscriptions
         | 
| 6 4 | 
             
                # A subscriptions implementation that sends data
         | 
| @@ -41,7 +39,7 @@ module GraphQL | |
| 41 39 | 
             
                #       })
         | 
| 42 40 | 
             
                #
         | 
| 43 41 | 
             
                #       payload = {
         | 
| 44 | 
            -
                #         result: result.to_h,
         | 
| 42 | 
            +
                #         result: result.subscription? ? nil : result.to_h,
         | 
| 45 43 | 
             
                #         more: result.subscription?,
         | 
| 46 44 | 
             
                #       }
         | 
| 47 45 | 
             
                #
         | 
| @@ -93,7 +91,7 @@ module GraphQL | |
| 93 91 | 
             
                  # and re-evaluate the query locally.
         | 
| 94 92 | 
             
                  def write_subscription(query, events)
         | 
| 95 93 | 
             
                    channel = query.context[:channel]
         | 
| 96 | 
            -
                    subscription_id = query.context[:subscription_id] ||=  | 
| 94 | 
            +
                    subscription_id = query.context[:subscription_id] ||= build_id
         | 
| 97 95 | 
             
                    stream = query.context[:action_cable_stream] ||= SUBSCRIPTION_PREFIX + subscription_id
         | 
| 98 96 | 
             
                    channel.stream_from(stream)
         | 
| 99 97 | 
             
                    @subscriptions[subscription_id] = query
         | 
| @@ -12,21 +12,13 @@ module GraphQL | |
| 12 12 | 
             
                  # @return [Object] An object equivalent to the one passed to {.dump}
         | 
| 13 13 | 
             
                  def load(str)
         | 
| 14 14 | 
             
                    parsed_obj = JSON.parse(str)
         | 
| 15 | 
            -
                     | 
| 16 | 
            -
                      GlobalID::Locator.locate(parsed_obj[GLOBALID_KEY])
         | 
| 17 | 
            -
                    else
         | 
| 18 | 
            -
                      parsed_obj
         | 
| 19 | 
            -
                    end
         | 
| 15 | 
            +
                    load_value(parsed_obj)
         | 
| 20 16 | 
             
                  end
         | 
| 21 17 |  | 
| 22 18 | 
             
                  # @param obj [Object] Some subscription-related data to dump
         | 
| 23 19 | 
             
                  # @return [String] The stringified object
         | 
| 24 20 | 
             
                  def dump(obj)
         | 
| 25 | 
            -
                     | 
| 26 | 
            -
                      JSON.dump(GLOBALID_KEY => obj.to_gid_param)
         | 
| 27 | 
            -
                    else
         | 
| 28 | 
            -
                      JSON.generate(obj, quirks_mode: true)
         | 
| 29 | 
            -
                    end
         | 
| 21 | 
            +
                    JSON.generate(dump_value(obj), quirks_mode: true)
         | 
| 30 22 | 
             
                  end
         | 
| 31 23 |  | 
| 32 24 | 
             
                  # This is for turning objects into subscription scopes.
         | 
| @@ -47,6 +39,40 @@ module GraphQL | |
| 47 39 | 
             
                      obj.to_s
         | 
| 48 40 | 
             
                    end
         | 
| 49 41 | 
             
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  class << self
         | 
| 44 | 
            +
                    private
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    # @param value [Object] A parsed JSON object
         | 
| 47 | 
            +
                    # @return [Object] An object that load Global::Identification recursive
         | 
| 48 | 
            +
                    def load_value(value)
         | 
| 49 | 
            +
                      if value.is_a?(Array)
         | 
| 50 | 
            +
                        value.map{|item| load_value(item)}
         | 
| 51 | 
            +
                      elsif value.is_a?(Hash)
         | 
| 52 | 
            +
                        if value.size == 1 && value.key?(GLOBALID_KEY)
         | 
| 53 | 
            +
                          GlobalID::Locator.locate(value[GLOBALID_KEY])
         | 
| 54 | 
            +
                        else
         | 
| 55 | 
            +
                          Hash[value.map{|k, v| [k, load_value(v)]}]
         | 
| 56 | 
            +
                        end
         | 
| 57 | 
            +
                      else
         | 
| 58 | 
            +
                        value
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    # @param obj [Object] Some subscription-related data to dump
         | 
| 63 | 
            +
                    # @return [Object] The object that converted Global::Identification
         | 
| 64 | 
            +
                    def dump_value(obj)
         | 
| 65 | 
            +
                      if obj.is_a?(Array)
         | 
| 66 | 
            +
                        obj.map{|item| dump_value(item)}
         | 
| 67 | 
            +
                      elsif obj.is_a?(Hash)
         | 
| 68 | 
            +
                        Hash[obj.map{|k, v| [k, dump_value(v)]}]
         | 
| 69 | 
            +
                      elsif obj.respond_to?(:to_gid_param)
         | 
| 70 | 
            +
                        {GLOBALID_KEY => obj.to_gid_param}
         | 
| 71 | 
            +
                      else
         | 
| 72 | 
            +
                        obj
         | 
| 73 | 
            +
                      end
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                  end
         | 
| 50 76 | 
             
                end
         | 
| 51 77 | 
             
              end
         | 
| 52 78 | 
             
            end
         | 
| @@ -3,9 +3,6 @@ | |
| 3 3 | 
             
            module GraphQL
         | 
| 4 4 | 
             
              module Tracing
         | 
| 5 5 | 
             
                class ScoutTracing < PlatformTracing
         | 
| 6 | 
            -
                  if defined?(ScoutApm)
         | 
| 7 | 
            -
                    include ScoutApm::Tracer
         | 
| 8 | 
            -
                  end
         | 
| 9 6 | 
             
                  INSTRUMENT_OPTS = { scope: true }
         | 
| 10 7 |  | 
| 11 8 | 
             
                  self.platform_keys = {
         | 
| @@ -19,6 +16,11 @@ module GraphQL | |
| 19 16 | 
             
                    "execute_query_lazy" => "execute.graphql",
         | 
| 20 17 | 
             
                  }
         | 
| 21 18 |  | 
| 19 | 
            +
                  def initialize
         | 
| 20 | 
            +
                    self.class.include ScoutApm::Tracer
         | 
| 21 | 
            +
                    super
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 22 24 | 
             
                  def platform_trace(platform_key, key, data)
         | 
| 23 25 | 
             
                    self.class.instrument("GraphQL", platform_key, INSTRUMENT_OPTS) do
         | 
| 24 26 | 
             
                      yield
         | 
    
        data/lib/graphql/version.rb
    CHANGED
    
    
    
        data/spec/dummy/Gemfile
    CHANGED
    
    | @@ -1,10 +1,12 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            +
            source 'https://rubygems.org'
         | 
| 3 | 
            +
             | 
| 2 4 | 
             
            gem 'rails'
         | 
| 3 5 | 
             
            gem 'puma'
         | 
| 4 6 | 
             
            gem 'capybara'
         | 
| 5 7 | 
             
            gem 'selenium-webdriver'
         | 
| 6 | 
            -
            gem 'graphql', path: File.expand_path( | 
| 8 | 
            +
            gem 'graphql', path: File.expand_path('../../', __dir__)
         | 
| 7 9 |  | 
| 8 10 | 
             
            group :development do
         | 
| 9 | 
            -
              gem  | 
| 11 | 
            +
              gem 'listen'
         | 
| 10 12 | 
             
            end
         | 
| @@ -10,7 +10,6 @@ require "action_view/railtie" | |
| 10 10 | 
             
            require "action_cable/engine"
         | 
| 11 11 | 
             
            require "sprockets/railtie"
         | 
| 12 12 | 
             
            require "rails/test_unit/railtie"
         | 
| 13 | 
            -
            require "puma"
         | 
| 14 13 |  | 
| 15 14 | 
             
            # Require the gems listed in Gemfile, including any gems
         | 
| 16 15 | 
             
            # you've limited to :test, :development, or :production.
         | 
| @@ -64,6 +64,13 @@ RUBY | |
| 64 64 | 
             
                assert_file "app/controllers/graphql_controller.rb", EXPECTED_GRAPHQLS_CONTROLLER
         | 
| 65 65 | 
             
              end
         | 
| 66 66 |  | 
| 67 | 
            +
              test "it allows for a user-specified install directory" do
         | 
| 68 | 
            +
                run_generator(["--directory", "app/mydirectory"])
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                assert_file "app/mydirectory/types/.keep"
         | 
| 71 | 
            +
                assert_file "app/mydirectory/mutations/.keep"
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
             | 
| 67 74 | 
             
              test "it generates graphql-batch and relay boilerplate" do
         | 
| 68 75 | 
             
                run_generator(["--batch", "--relay"])
         | 
| 69 76 | 
             
                assert_file "app/graphql/loaders/.keep"
         | 
| @@ -7,7 +7,7 @@ class GraphQLGeneratorsMutationGeneratorTest < BaseGeneratorTest | |
| 7 7 |  | 
| 8 8 | 
             
              destination File.expand_path("../../../tmp/dummy", File.dirname(__FILE__))
         | 
| 9 9 |  | 
| 10 | 
            -
              setup  | 
| 10 | 
            +
              def setup(directory = "app/graphql")
         | 
| 11 11 | 
             
                prepare_destination
         | 
| 12 12 | 
             
                FileUtils.cd(File.expand_path("../../../tmp", File.dirname(__FILE__))) do
         | 
| 13 13 | 
             
                  `rm -rf dummy`
         | 
| @@ -15,11 +15,12 @@ class GraphQLGeneratorsMutationGeneratorTest < BaseGeneratorTest | |
| 15 15 | 
             
                end
         | 
| 16 16 |  | 
| 17 17 | 
             
                FileUtils.cd(destination_root) do
         | 
| 18 | 
            -
                  `rails g graphql:install`
         | 
| 18 | 
            +
                  `rails g graphql:install --directory #{directory}`
         | 
| 19 19 | 
             
                end
         | 
| 20 20 | 
             
              end
         | 
| 21 21 |  | 
| 22 22 | 
             
              test "it generates an empty resolver by name" do
         | 
| 23 | 
            +
                setup
         | 
| 23 24 | 
             
                run_generator(["UpdateName"])
         | 
| 24 25 |  | 
| 25 26 | 
             
                expected_content = <<-RUBY
         | 
| @@ -39,4 +40,26 @@ RUBY | |
| 39 40 |  | 
| 40 41 | 
             
                assert_file "app/graphql/mutations/update_name.rb", expected_content
         | 
| 41 42 | 
             
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              test "it allows for user-specified directory" do
         | 
| 45 | 
            +
                setup "app/mydirectory"
         | 
| 46 | 
            +
                run_generator(["UpdateName", "--directory", "app/mydirectory"])
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                expected_content = <<-RUBY
         | 
| 49 | 
            +
            Mutations::UpdateName = GraphQL::Relay::Mutation.define do
         | 
| 50 | 
            +
              name "UpdateName"
         | 
| 51 | 
            +
              # TODO: define return fields
         | 
| 52 | 
            +
              # return_field :post, Types::PostType
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              # TODO: define arguments
         | 
| 55 | 
            +
              # input_field :name, !types.String
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              resolve ->(obj, args, ctx) {
         | 
| 58 | 
            +
                # TODO: define resolve function
         | 
| 59 | 
            +
              }
         | 
| 60 | 
            +
            end
         | 
| 61 | 
            +
            RUBY
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                assert_file "app/mydirectory/mutations/update_name.rb", expected_content
         | 
| 64 | 
            +
              end
         | 
| 42 65 | 
             
            end
         | 
| @@ -47,4 +47,18 @@ RUBY | |
| 47 47 | 
             
                  assert_file "app/graphql/types/winged_creature_type.rb", expected_content
         | 
| 48 48 | 
             
                end
         | 
| 49 49 | 
             
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              test "it accepts a user-specified directory" do
         | 
| 52 | 
            +
                command = ["WingedCreature", "--directory", "app/mydirectory"]
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                expected_content = <<-RUBY
         | 
| 55 | 
            +
            Types::WingedCreatureType = GraphQL::UnionType.define do
         | 
| 56 | 
            +
              name "WingedCreature"
         | 
| 57 | 
            +
            end
         | 
| 58 | 
            +
            RUBY
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                prepare_destination
         | 
| 61 | 
            +
                run_generator(command)
         | 
| 62 | 
            +
                assert_file "app/mydirectory/types/winged_creature_type.rb", expected_content
         | 
| 63 | 
            +
              end
         | 
| 50 64 | 
             
            end
         | 
| @@ -21,6 +21,15 @@ describe GraphQL::Backtrace do | |
| 21 21 | 
             
                def inspect; nil; end
         | 
| 22 22 | 
             
              end
         | 
| 23 23 |  | 
| 24 | 
            +
              class ErrorInstrumentation
         | 
| 25 | 
            +
                def self.before_query(_query)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def self.after_query(query)
         | 
| 29 | 
            +
                  raise "Instrumentation Boom"
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 24 33 | 
             
              let(:resolvers) {
         | 
| 25 34 | 
             
                {
         | 
| 26 35 | 
             
                  "Query" => {
         | 
| @@ -113,7 +122,7 @@ describe GraphQL::Backtrace do | |
| 113 122 | 
             
                  assert_includes err.message, rendered_table
         | 
| 114 123 | 
             
                  # The message includes the original error message
         | 
| 115 124 | 
             
                  assert_includes err.message, "This is broken: Boom"
         | 
| 116 | 
            -
                  assert_includes err.message, "spec/graphql/backtrace_spec.rb: | 
| 125 | 
            +
                  assert_includes err.message, "spec/graphql/backtrace_spec.rb:42", "It includes the original backtrace"
         | 
| 117 126 | 
             
                  assert_includes err.message, "more lines"
         | 
| 118 127 | 
             
                end
         | 
| 119 128 |  | 
| @@ -165,6 +174,17 @@ describe GraphQL::Backtrace do | |
| 165 174 |  | 
| 166 175 | 
             
                  assert_includes(err.message, rendered_table)
         | 
| 167 176 | 
             
                end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
             | 
| 179 | 
            +
                it "raises original exception instead of a TracedError when error does not occur during resolving" do
         | 
| 180 | 
            +
                  instrumentation_schema = schema.redefine do
         | 
| 181 | 
            +
                    instrument(:query, ErrorInstrumentation)
         | 
| 182 | 
            +
                  end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                  assert_raises(RuntimeError) {
         | 
| 185 | 
            +
                    instrumentation_schema.execute(GraphQL::Introspection::INTROSPECTION_QUERY, context: { backtrace: true })
         | 
| 186 | 
            +
                  }
         | 
| 187 | 
            +
                end
         | 
| 168 188 | 
             
              end
         | 
| 169 189 |  | 
| 170 190 | 
             
              # This will get brittle when execution code moves between files
         | 
| @@ -82,4 +82,46 @@ TYPE | |
| 82 82 | 
             
                  assert_equal expected.chomp, post_type.to_definition(schema)
         | 
| 83 83 | 
             
                end
         | 
| 84 84 | 
             
              end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              describe 'non_null?' do
         | 
| 87 | 
            +
                let(:type) do
         | 
| 88 | 
            +
                  GraphQL::EnumType.define do
         | 
| 89 | 
            +
                    name "Hello"
         | 
| 90 | 
            +
                    value 'WORLD'
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                it "returns false for nullable types" do
         | 
| 95 | 
            +
                  assert_equal(type.non_null?, false)
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                it "returns true for non-nulls" do
         | 
| 99 | 
            +
                  assert_equal(type.to_non_null_type.non_null?, true)
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                it "returns false for a nullable list of non-nulls" do
         | 
| 103 | 
            +
                  assert_equal(type.to_non_null_type.to_list_type.non_null?, false)
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
              describe 'list?' do
         | 
| 108 | 
            +
                let(:type) do
         | 
| 109 | 
            +
                  GraphQL::EnumType.define do
         | 
| 110 | 
            +
                    name "Hello"
         | 
| 111 | 
            +
                    value 'WORLD'
         | 
| 112 | 
            +
                  end
         | 
| 113 | 
            +
                end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                it "returns false for non-list types" do
         | 
| 116 | 
            +
                  assert_equal(type.list?, false)
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                it "returns true for lists" do
         | 
| 120 | 
            +
                  assert_equal(type.to_list_type.list?, true)
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                it "returns true for a non-nullable list" do
         | 
| 124 | 
            +
                  assert_equal(type.to_list_type.to_non_null_type.list?, true)
         | 
| 125 | 
            +
                end
         | 
| 126 | 
            +
              end
         | 
| 85 127 | 
             
            end
         |