graphql-client/test/test_client_errors.rb

371 строка
10 KiB
Ruby

# frozen_string_literal: true
require "graphql"
require "graphql/client"
require "minitest/autorun"
class TestClientErrors < MiniTest::Test
class FooType < GraphQL::Schema::Object
field :nullable_error, String, null: true
def nullable_error
raise GraphQL::ExecutionError, "b00m"
end
field :nonnullable_error, String, null: false
def nonnullable_error
raise GraphQL::ExecutionError, "b00m"
end
end
class QueryType < GraphQL::Schema::Object
field :version, Int, null: false
def version
1
end
field :node, FooType, null: true
def node
GraphQL::ExecutionError.new("missing node")
end
field :nodes, [FooType, null: true], null: false
def nodes
[GraphQL::ExecutionError.new("missing node"), {}]
end
field :nullable_error, String, null: true
def nullable_error
raise GraphQL::ExecutionError, "b00m"
end
field :nonnullable_error, String, null: false
def nonnullable_error
raise GraphQL::ExecutionError, "b00m"
end
field :foo, FooType, null: false
def foo
{}
end
field :foos, [FooType], null: true
def foos
[{}, {}]
end
end
class Schema < GraphQL::Schema
query(QueryType)
if defined?(GraphQL::Execution::Interpreter)
use GraphQL::Execution::Interpreter
use GraphQL::Analysis::AST
end
end
module Temp
end
def setup
@client = GraphQL::Client.new(schema: Schema, execute: Schema)
end
def teardown
Temp.constants.each do |sym|
Temp.send(:remove_const, sym)
end
end
def test_normalize_error_path
actual = {
"data" => nil,
"errors" => [
{
"message" => "error"
}
]
}
GraphQL::Client::Errors.normalize_error_paths(actual["data"], actual["errors"])
expected = {
"data" => nil,
"errors" => [
{
"message" => "error",
"normalizedPath" => %w(data)
}
]
}
assert_equal expected, actual
actual = {
"data" => {
"node" => nil
},
"errors" => [
{
"message" => "error",
"path" => %w(node)
}
]
}
GraphQL::Client::Errors.normalize_error_paths(actual["data"], actual["errors"])
expected = {
"data" => {
"node" => nil
},
"errors" => [
{
"message" => "error",
"path" => %w(node),
"normalizedPath" => %w(data node)
}
]
}
assert_equal expected, actual
actual = {
"data" => nil,
"errors" => [
{
"message" => "error",
"path" => %w(node projects owner)
}
]
}
GraphQL::Client::Errors.normalize_error_paths(actual["data"], actual["errors"])
expected = {
"data" => nil,
"errors" => [
{
"message" => "error",
"path" => %w(node projects owner),
"normalizedPath" => %w(data)
}
]
}
assert_equal expected, actual
actual = {
"data" => {
"node" => nil
},
"errors" => [
{
"message" => "error",
"path" => %w(node projects owner)
}
]
}
GraphQL::Client::Errors.normalize_error_paths(actual["data"], actual["errors"])
expected = {
"data" => {
"node" => nil
},
"errors" => [
{
"message" => "error",
"path" => %w(node projects owner),
"normalizedPath" => %w(data node)
}
]
}
assert_equal expected, actual
end
def test_filter_nested_errors_by_path
raw_errors = [
{
"message" => "1",
"normalizedPath" => %w(node id)
},
{
"message" => "2",
"normalizedPath" => %w(node owner name)
},
{
"message" => "3",
"normalizedPath" => ["node", "repositories", 0, "name"]
},
{
"message" => "4",
"normalizedPath" => ["version"]
}
]
errors = GraphQL::Client::Errors.new(raw_errors, [], true)
assert_equal 4, errors.count
assert_equal({ "node" => %w(1 2 3), "version" => ["4"] }, errors.messages.to_h)
errors = GraphQL::Client::Errors.new(raw_errors, ["node"], true)
assert_equal 3, errors.count
assert_equal({ "id" => ["1"], "owner" => ["2"], "repositories" => ["3"] }, errors.messages.to_h)
errors = GraphQL::Client::Errors.new(raw_errors, ["version"], true)
assert_empty errors
end
def test_filter_direct_errors_by_path
raw_errors = [
{
"message" => "1",
"normalizedPath" => %w(node id)
},
{
"message" => "2",
"normalizedPath" => %w(node owner name)
},
{
"message" => "3",
"normalizedPath" => ["node", "repositories", 0, "name"]
},
{
"message" => "4",
"normalizedPath" => ["version"]
}
]
errors = GraphQL::Client::Errors.new(raw_errors, [], false)
assert_equal 1, errors.count
assert_equal({ "version" => ["4"] }, errors.messages.to_h)
errors = GraphQL::Client::Errors.new(raw_errors, ["node"], false)
assert_equal 1, errors.count
assert_equal({ "id" => ["1"] }, errors.messages.to_h)
errors = GraphQL::Client::Errors.new(raw_errors, %w(node owner), false)
assert_equal 1, errors.count
assert_equal({ "name" => ["2"] }, errors.messages.to_h)
errors = GraphQL::Client::Errors.new(raw_errors, ["node", "repositories", 0], false)
assert_equal 1, errors.count
assert_equal({ "name" => ["3"] }, errors.messages.to_h)
errors = GraphQL::Client::Errors.new(raw_errors, ["version"], false)
assert_empty errors
end
def test_errors_collection
Temp.const_set :Query, @client.parse("{ nullableError }")
assert response = @client.query(Temp::Query)
assert_nil response.data.nullable_error
assert_equal false, response.data.errors.empty?
assert_equal false, response.data.errors.blank?
assert_equal 1, response.data.errors.size
assert_equal 1, response.data.errors.count
assert_equal true, response.data.errors.include?(:nullableError)
assert_equal true, response.data.errors.include?("nullableError")
assert_equal true, response.data.errors.include?(:nullable_error)
assert_equal true, response.data.errors[:nullableError].any?
assert_equal true, response.data.errors["nullableError"].any?
assert_equal true, response.data.errors[:nullable_error].any?
assert_equal false, response.data.errors.include?(:missingError)
assert_equal false, response.data.errors.include?("missingError")
assert_equal false, response.data.errors.include?(:missing_error)
assert_equal false, response.data.errors[:missingError].any?
assert_equal false, response.data.errors["missingError"].any?
assert_equal false, response.data.errors[:missing_error].any?
assert_equal "b00m", response.data.errors[:nullableError][0]
assert_equal "b00m", response.data.errors[:nullable_error][0]
assert_equal "b00m", response.data.errors.messages["nullableError"][0]
detail = {
"message" => "b00m",
"locations" => [{ "line" => 1, "column" => 3 }],
"path" => %w(nullableError),
"normalizedPath" => %w(data nullableError)
}
assert_equal(detail, response.data.errors.details["nullableError"][0])
assert_equal [%w(nullableError b00m)], response.data.errors.each.to_a
assert_equal ["nullableError"], response.data.errors.keys
assert_equal [["b00m"]], response.data.errors.values
assert_equal({
"data" => {
"nullableError" => nil
},
"errors" => [
{
"message" => "b00m",
"locations" => [{"line" => 1, "column" => 3}],
"path" => ["nullableError"]
}
]
}, response.to_h)
end
def test_nested_errors
Temp.const_set :Query, @client.parse("{ foo { nullableError } }")
assert response = @client.query(Temp::Query)
assert response.data.foo
assert_empty response.data.errors
assert_equal "b00m", response.data.errors.all["foo"][0]
assert_nil response.data.foo.nullable_error
assert_equal "b00m", response.data.foo.errors["nullableError"][0]
assert_equal "b00m", response.data.foo.errors.all["nullableError"][0]
end
def test_nonnullable_root_error
Temp.const_set :Query, @client.parse("{ version, nonnullableError }")
assert response = @client.query(Temp::Query)
assert_nil response.data
refute_empty response.errors
assert_equal "b00m", response.errors[:data][0]
assert_equal "b00m", response.errors.all[:data][0]
end
def test_nonnullable_nested_error
Temp.const_set :Query, @client.parse("{ version, foo { nonnullableError } }")
assert response = @client.query(Temp::Query)
assert_nil response.data
refute_empty response.errors
assert_equal "b00m", response.errors[:data][0]
assert_equal "b00m", response.errors.all[:data][0]
end
def test_collection_errors
Temp.const_set :Query, @client.parse("{ foos { nullableError } }")
assert response = @client.query(Temp::Query)
assert response.data.foos
assert_empty response.data.errors
assert_equal "b00m", response.data.errors.all["foos"][0]
assert_equal "b00m", response.data.errors.all["foos"][1]
assert_nil response.data.foos[0].nullable_error
assert_equal "b00m", response.data.foos[0].errors["nullableError"][0]
assert_equal "b00m", response.data.foos[0].errors.all["nullableError"][0]
end
def test_node_errors
Temp.const_set :Query, @client.parse("{ node { __typename } nodes { __typename } }")
assert response = @client.query(Temp::Query)
assert_nil response.data.node
# This list-error handling behavior is broken for class-based schemas that don't use the interpreter.
# The fix is an `.is_a?` check in `proxy_to_depth` in member_instrumentation.rb
if defined?(GraphQL::Execution::Interpreter)
assert_nil response.data.nodes[0]
end
assert response.data.nodes[1]
assert_equal "Foo", response.data.nodes[1].__typename
refute_empty response.data.errors
assert_equal "missing node", response.data.errors["node"][0]
# This error isn't added in class-based schemas + `Execution::Execute`, same bug as above
if defined?(GraphQL::Execution::Interpreter)
assert_equal "missing node", response.data.nodes.errors[0][0]
end
end
end