diff --git a/lib/graphql/schema.rb b/lib/graphql/schema.rb index 7c61856bd2..37e54d6225 100644 --- a/lib/graphql/schema.rb +++ b/lib/graphql/schema.rb @@ -1304,10 +1304,8 @@ def type_error(type_error, ctx) execution_error.path = ctx[:current_path] ctx.errors << execution_error - when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError + when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError raise type_error - when GraphQL::IntegerDecodingError - nil end end diff --git a/lib/graphql/types/float.rb b/lib/graphql/types/float.rb index 7551899ed5..914ac48315 100644 --- a/lib/graphql/types/float.rb +++ b/lib/graphql/types/float.rb @@ -6,11 +6,21 @@ class Float < GraphQL::Schema::Scalar description "Represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point)." def self.coerce_input(value, _ctx) - value.is_a?(Numeric) ? value.to_f : nil + if value.is_a?(Numeric) + value.to_f + else + raise GraphQL::CoercionError, "Float cannot represent non numeric value: #{value.inspect}" + end end def self.coerce_result(value, _ctx) - value.to_f + coerced_value = Float(value, exception: false) + + if coerced_value.nil? || !coerced_value.finite? + raise GraphQL::CoercionError, "Float cannot represent non numeric value: #{value.inspect}" + end + + coerced_value end default_scalar true diff --git a/lib/graphql/types/int.rb b/lib/graphql/types/int.rb index e9ec3d5531..7b7eb8dc61 100644 --- a/lib/graphql/types/int.rb +++ b/lib/graphql/types/int.rb @@ -15,18 +15,17 @@ def self.coerce_input(value, ctx) if value >= MIN && value <= MAX value else - err = GraphQL::IntegerDecodingError.new(value) - ctx.schema.type_error(err, ctx) + raise GraphQL::CoercionError.new("Int cannot represent non 32-bit signed integer value: #{value.inspect}") end end def self.coerce_result(value, ctx) - value = value.to_i - if value >= MIN && value <= MAX + value = Integer(value, exception: false) + + if value && (value >= MIN && value <= MAX) value else - err = GraphQL::IntegerEncodingError.new(value, context: ctx) - ctx.schema.type_error(err, ctx) + raise GraphQL::CoercionError.new("Int cannot represent non 32-bit signed integer value: #{value.inspect}") end end diff --git a/spec/graphql/types/float_spec.rb b/spec/graphql/types/float_spec.rb index ba2b802880..04ecc84be6 100644 --- a/spec/graphql/types/float_spec.rb +++ b/spec/graphql/types/float_spec.rb @@ -11,9 +11,40 @@ end it "rejects other types" do - assert_nil GraphQL::Types::Float.coerce_isolated_input("55") - assert_nil GraphQL::Types::Float.coerce_isolated_input(true) - assert_nil GraphQL::Types::Float.coerce_isolated_input(enum) + assert_raises(GraphQL::CoercionError) do + GraphQL::Types::Float.coerce_isolated_input("55") + end + + assert_raises(GraphQL::CoercionError) do + GraphQL::Types::Float.coerce_isolated_input(true) + end + + assert_raises(GraphQL::CoercionError) do + GraphQL::Types::Float.coerce_isolated_input(enum) + end + end + end + + describe "coerce_result" do + it "coercess ints and floats" do + err_ctx = GraphQL::Query.new(Dummy::Schema, "{ __typename }").context + + assert_equal 1.0, GraphQL::Types::Float.coerce_result(1, err_ctx) + assert_equal 1.0, GraphQL::Types::Float.coerce_result("1", err_ctx) + assert_equal 1.0, GraphQL::Types::Float.coerce_result("1.0", err_ctx) + assert_equal 6.1, GraphQL::Types::Float.coerce_result(6.1, err_ctx) + end + + it "rejects other types" do + err_ctx = GraphQL::Query.new(Dummy::Schema, "{ __typename }").context + + assert_raises(GraphQL::CoercionError) do + GraphQL::Types::Float.coerce_result("foo", err_ctx) + end + + assert_raises(GraphQL::CoercionError) do + GraphQL::Types::Float.coerce_result(1.0 / 0, err_ctx) + end end end end diff --git a/spec/graphql/types/int_spec.rb b/spec/graphql/types/int_spec.rb index 1145ece0de..1a07d580b3 100644 --- a/spec/graphql/types/int_spec.rb +++ b/spec/graphql/types/int_spec.rb @@ -13,8 +13,14 @@ assert_nil GraphQL::Types::Int.coerce_isolated_input("55") assert_nil GraphQL::Types::Int.coerce_isolated_input(true) assert_nil GraphQL::Types::Int.coerce_isolated_input(6.1) - assert_nil GraphQL::Types::Int.coerce_isolated_input(2**31) - assert_nil GraphQL::Types::Int.coerce_isolated_input(-(2**31 + 1)) + + assert_raises(GraphQL::CoercionError) do + GraphQL::Types::Int.coerce_isolated_input(2**31) + end + + assert_raises(GraphQL::CoercionError) do + GraphQL::Types::Int.coerce_isolated_input(-(2**31 + 1)) + end end describe "handling boundaries" do @@ -26,21 +32,16 @@ assert_equal(-(2**31), GraphQL::Types::Int.coerce_result(-(2**31), context)) end - it "replaces values, if configured to do so" do - assert_equal Dummy::Schema::MAGIC_INT_COERCE_VALUE, GraphQL::Types::Int.coerce_result(99**99, context) - end - it "raises on values out of bounds" do err_ctx = GraphQL::Query.new(Dummy::Schema, "{ __typename }").context - assert_raises(GraphQL::IntegerEncodingError) { GraphQL::Types::Int.coerce_result(2**31, err_ctx) } - err = assert_raises(GraphQL::IntegerEncodingError) { GraphQL::Types::Int.coerce_result(-(2**31 + 1), err_ctx) } - assert_equal "Integer out of bounds: -2147483649. Consider using ID or GraphQL::Types::BigInt instead.", err.message + assert_raises(GraphQL::CoercionError) { GraphQL::Types::Int.coerce_result(2**31, err_ctx) } + err = assert_raises(GraphQL::CoercionError) { GraphQL::Types::Int.coerce_result(-(2**31 + 1), err_ctx) } + assert_equal "Int cannot represent non 32-bit signed integer value: -2147483649", err.message - err = assert_raises GraphQL::IntegerEncodingError do + err = assert_raises GraphQL::CoercionError do Dummy::Schema.execute("{ hugeInteger }") end - expected_err = "Integer out of bounds: 2147483648 @ hugeInteger (Query.hugeInteger). Consider using ID or GraphQL::Types::BigInt instead." - assert_equal expected_err, err.message + assert_equal "Int cannot represent non 32-bit signed integer value: 2147483648", err.message end end end diff --git a/spec/support/dummy/schema.rb b/spec/support/dummy/schema.rb index 0fbcb6c7f1..441cf2c600 100644 --- a/spec/support/dummy/schema.rb +++ b/spec/support/dummy/schema.rb @@ -557,17 +557,6 @@ def self.resolve_type(type, obj, ctx) -> { Schema.types[obj.class.name.split("::").last] } end - # This is used to confirm that the hook is called: - MAGIC_INT_COERCE_VALUE = -1 - - def self.type_error(err, ctx) - if err.is_a?(GraphQL::IntegerEncodingError) && err.integer_value == 99**99 - MAGIC_INT_COERCE_VALUE - else - super - end - end - use GraphQL::Dataloader lazy_resolve(Proc, :call)