1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
# frozen_string_literal: true
require "spec_helper"
describe GraphQL::Pagination::Connections do
ITEMS = ConnectionAssertions::NAMES.map { |n| { name: n } }
class ArrayConnectionWithTotalCount < GraphQL::Pagination::ArrayConnection
def total_count
items.size
end
end
let(:base_schema) {
ConnectionAssertions.build_schema(
connection_class: GraphQL::Pagination::ArrayConnection,
total_count_connection_class: ArrayConnectionWithTotalCount,
get_items: -> { ITEMS }
)
}
# These wouldn't _work_, I just need to test `.wrap`
class SetConnection < GraphQL::Pagination::ArrayConnection; end
class HashConnection < GraphQL::Pagination::ArrayConnection; end
class OtherArrayConnection < GraphQL::Pagination::ArrayConnection; end
let(:schema) do
other_base_schema = Class.new(base_schema) do
connections.add(Set, SetConnection)
end
Class.new(other_base_schema) do
connections.add(Hash, HashConnection)
connections.add(Array, OtherArrayConnection)
end
end
it "returns connections by class, using inherited mappings and local overrides" do
field_defn = OpenStruct.new(has_max_page_size?: true, max_page_size: 10, has_default_page_size?: true, default_page_size: 5, type: GraphQL::Types::Relay::BaseConnection)
set_wrapper = schema.connections.wrap(field_defn, nil, Set.new([1,2,3]), {}, nil)
assert_instance_of SetConnection, set_wrapper
hash_wrapper = schema.connections.wrap(field_defn, nil, {1 => :a, 2 => :b}, {}, nil)
assert_instance_of HashConnection, hash_wrapper
array_wrapper = schema.connections.wrap(field_defn, nil, [1,2,3], {}, nil)
assert_instance_of OtherArrayConnection, array_wrapper
raw_value = schema.connections.wrap(field_defn, nil, GraphQL::Execution::Interpreter::RawValue.new([1,2,3]), {}, nil)
assert_instance_of GraphQL::Execution::Interpreter::RawValue, raw_value
end
it "uses cached wrappers" do
field_defn = OpenStruct.new(max_page_size: 10)
dummy_ctx = Class.new do
def namespace(some_key)
if some_key == :connections
{ all_wrappers: {} }
else
raise ArgumentError, "unsupported key: #{some_key.inspect}"
end
end
end
assert_raises GraphQL::Pagination::Connections::ImplementationMissingError do
schema.connections.wrap(field_defn, nil, Set.new([1,2,3]), {}, dummy_ctx.new)
end
end
# Simulate a schema with a `*Connection` type that _isn't_
# supposed to be a connection. Help debug, see https://github.com/rmosolgo/graphql-ruby/issues/2588
class ConnectionErrorTestSchema < GraphQL::Schema
class BadThing
def name
self.no_such_method # raise a NoMethodError
end
def inspect
"<BadThing!>"
end
end
class ThingConnection < GraphQL::Schema::Object
field :name, String, null: false
end
class Query < GraphQL::Schema::Object
field :things, [ThingConnection], null: false
def things
[{name: "thing1"}, {name: "thing2"}]
end
field :things2, [ThingConnection], null: false, connection: false
def things2
[
BadThing.new
]
end
end
query(Query)
end
it "raises a helpful error when it fails to implement a connection" do
err = assert_raises GraphQL::Execution::Interpreter::ListResultFailedError do
pp ConnectionErrorTestSchema.execute("{ things { name } }")
end
assert_includes err.message, "Failed to build a GraphQL list result for field `Query.things` at path `things`."
assert_includes err.message, "(GraphQL::Pagination::ArrayConnection) to implement `.each` to satisfy the GraphQL return type `[ThingConnection!]!`"
assert_includes err.message, "This field was treated as a Relay-style connection; add `connection: false` to the `field(...)` to disable this behavior."
end
it "lets unrelated NoMethodErrors bubble up" do
err = assert_raises NoMethodError do
ConnectionErrorTestSchema.execute("{ things2 { name } }")
end
expected_message = if RUBY_VERSION >= "3.3"
"undefined method `no_such_method' for an instance of ConnectionErrorTestSchema::BadThing"
else
"undefined method `no_such_method' for <BadThing!>"
end
assert_includes err.message, expected_message
end
it "uses a field's `max_page_size: nil` configuration" do
user_type = Class.new(GraphQL::Schema::Object) do
graphql_name 'User'
field :name, String, null: false
end
query_type = Class.new(GraphQL::Schema::Object) do
graphql_name 'Query'
field :users, user_type.connection_type, max_page_size: nil
def users
[{ name: 'Yoda' }, { name: 'Anakin' }, { name: 'Obi Wan' }]
end
end
schema = Class.new(GraphQL::Schema) do
# This value should be overriden by `max_page_size: nil` in the field definition above
default_max_page_size 2
query(query_type)
end
res = schema.execute(<<-GRAPHQL).to_h
{
users {
nodes {
name
}
}
}
GRAPHQL
assert_equal ["Yoda", "Anakin", "Obi Wan"], res['data']['users']['nodes'].map { |node| node['name'] }
end
class SingleNewConnectionSchema < GraphQL::Schema
class Query < GraphQL::Schema::Object
field :strings, GraphQL::Types::String.connection_type, null: false
def strings
GraphQL::Pagination::ArrayConnection.new(["a", "b", "c"])
end
end
query(Query)
end
it "works when new connections are not installed" do
res = SingleNewConnectionSchema.execute("{ strings(first: 2) { edges { node } } }")
assert_equal ["a", "b"], res["data"]["strings"]["edges"].map { |e| e["node"] }
end
end
|