Incorrect handling of enum input value coercions

Open
#5,499 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
graphql, ruby
Domain
api

Research direction

Start with the supplied tests, especially test_reports_validation_errors_with_enums_ast and test_reports_validation_errors_with_enum_variables, then trace GraphQL::Query validation and enum input coercion. Done means enum coercion errors invalidate the query before field execution, with validation or variable errors matching the intended behavior shown in the examples.

Written by the indexing model from the issue text.

Description

Describe the bug

Input coercion errors raised by leaf types are pretty spotty on validating correctly. I've included a complete test suite below, but the summary is:

  • Enum types don't call coerce_input during validation. Therefore, the query is incorrectly valid, this input does not block execution, and the error manifests as a field execution error. Right error, wrong time.
  • Scalars DO call coerce_input, and will statically invalidate the query to prevent it from executing. When this happens via variables, we get a good error message. When it happens via AST, not so much.
class GraphQLRubyTest < Minitest::Test
  class TestSchema < GraphQL::Schema
    class MyScalar < GraphQL::Schema::Scalar
      def self.coerce_input(value, ctx = nil)
        raise GraphQL::ExecutionError.new("boom")
      end
    end

    class MyEnum < GraphQL::Schema::Enum
      def self.coerce_input(value, ctx = nil)
        raise GraphQL::ExecutionError.new("boom")
      end

      value "BOOM"
    end

    class Query < GraphQL::Schema::Object
      field :scalar, String do |f|
        f.argument :input, MyScalar, required: true
      end

      field :enum, String do |f|
        f.argument :input, MyEnum, required: true
      end
    end

    query(Query)
  end

  def test_reports_validation_errors_with_scalar_ast
    query = ::GraphQL::Query.new(TestSchema, "{ scalar(input: 1) }")
    query.result.to_h

    # This is sort of the right error, but is missing a bunch of relevant information
    # {"errors" => [{"message" => "boom"}]}

    # This works...
    refute query.valid?
  end

  def test_reports_validation_errors_with_scalar_variables
    query = ::GraphQL::Query.new(TestSchema, "query($input: MyScalar!) { scalar(input: $input) }", variables: { input: 1 })
    query.result.to_h

    # This is the correct error
    # {"errors" => [{
    #   "message" => "Variable $input of type MyScalar! was provided invalid value",
    #   "locations" => [{"line" => 1, "column" => 7}],
    #   "extensions" => {"value" => 1, "problems" => [{"path" => [], "explanation" => "boom"}]},
    # }]}

    # This works...
    refute query.valid?
  end

  def test_reports_validation_errors_with_enums_ast
    query = ::GraphQL::Query.new(TestSchema, "{ enum(input: BOOM) }")
    query.result.to_h

    # This is a field execution error, it should have been a variable error that blocked execution
    # {"errors" => [{"message" => "boom", "locations" => [{"line" => 1, "column" => 3}], "path" => ["enum"]}], "data" => {"enum" => nil}}

    # This fails... query is valid?
    refute query.valid?
  end

  def test_reports_validation_errors_with_enum_variables
    query = ::GraphQL::Query.new(TestSchema, "query($input: MyEnum!) { enum(input: $input) }", variables: { input: "BOOM" })
    query.result.to_h

    # This is a field execution error, it should have been a variable error that blocked execution
    # {"errors" => [{"message" => "boom", "locations" => [{"line" => 1, "column" => 26}], "path" => ["enum"]}], "data" => {"enum" => nil}}

    # This fails... query is valid?
    refute query.valid?
  end
end
Dominant language
Ruby
Stars
5.4k
Forks
1.4k
Avg merge
23h 19m
Merged PRs (30d)
28

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rmosolgo/graphql-ruby

All issues in rmosolgo/graphql-ruby

Similar issues

More Ruby issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.