diff --git a/lib/graphql/schema/field.rb b/lib/graphql/schema/field.rb index 53e5113530..c7d043e44e 100644 --- a/lib/graphql/schema/field.rb +++ b/lib/graphql/schema/field.rb @@ -496,7 +496,13 @@ def calculate_complexity(query:, nodes:, child_complexity:) case defined_complexity when Proc arguments = query.arguments_for(nodes.first, self) - defined_complexity.call(query.context, arguments.keyword_arguments, child_complexity) + if arguments.is_a?(GraphQL::ExecutionError) + return child_complexity + elsif arguments.respond_to?(:keyword_arguments) + arguments = arguments.keyword_arguments + end + + defined_complexity.call(query.context, arguments, child_complexity) when Numeric defined_complexity + child_complexity else diff --git a/spec/graphql/analysis/ast/query_complexity_spec.rb b/spec/graphql/analysis/ast/query_complexity_spec.rb index 66742b9f1d..0654357765 100644 --- a/spec/graphql/analysis/ast/query_complexity_spec.rb +++ b/spec/graphql/analysis/ast/query_complexity_spec.rb @@ -8,7 +8,8 @@ GraphQL::Analysis::AST.analyze_multiplex(multiplex, [GraphQL::Analysis::AST::QueryComplexity]) } let(:variables) { {} } - let(:query) { GraphQL::Query.new(schema, query_string, variables: variables) } + let(:query_context) { {} } + let(:query) { GraphQL::Query.new(schema, query_string, context: query_context, variables: variables) } let(:multiplex) { GraphQL::Execution::Multiplex.new( schema: schema, @@ -377,10 +378,20 @@ class DoubleComplexity < GraphQL::Schema::Object class Query < GraphQL::Schema::Object field :complexity, SingleComplexity do - argument :int_value, Int, required: false + argument :int_value, Int, required: false, prepare: ->(val, ctx) { + if ctx[:raise_prepare_error] + raise GraphQL::ExecutionError, "Boom" + else + val + end + } complexity ->(ctx, args, child_complexity) { args[:int_value] + child_complexity } end + def complexity(int_value:) + { value: int_value } + end + field :inner_complexity, ComplexityInterface do argument :value, Int, required: false end @@ -390,7 +401,7 @@ class Query < GraphQL::Schema::Object orphan_types(DoubleComplexity) end - let(:query) { GraphQL::Query.new(complexity_schema, query_string) } + let(:query) { GraphQL::Query.new(complexity_schema, query_string, context: query_context) } let(:complexity_schema) { CustomComplexitySchema } let(:query_string) {%| { @@ -426,6 +437,18 @@ class Query < GraphQL::Schema::Object assert_equal 5, complexity end end + + describe "when prepare raises an error" do + let(:query_string) { "{ complexity(intValue: 3) { value } }"} + let(:query_context) { { raise_prepare_error: true } } + + it "handles it nicely" do + result = query.result + assert_equal ["Boom"], result["errors"].map { |e| e["message"] } + complexity = reduce_result.first + assert_equal 0.1, complexity + end + end end describe "custom complexities by complexity_for(...)" do