debian-mirror-gitlab/spec/graphql/resolvers/base_resolver_spec.rb

285 lines
7.5 KiB
Ruby
Raw Normal View History

2019-07-07 11:18:12 +05:30
# frozen_string_literal: true
require 'spec_helper'
2020-07-28 23:09:34 +05:30
RSpec.describe Resolvers::BaseResolver do
2019-07-07 11:18:12 +05:30
include GraphqlHelpers
let(:resolver) do
Class.new(described_class) do
2021-01-29 00:20:46 +05:30
argument :test, ::GraphQL::INT_TYPE, required: false
type [::GraphQL::INT_TYPE], null: true
def resolve(test: 100)
2020-01-01 13:55:28 +05:30
process(object)
2021-01-29 00:20:46 +05:30
[test, test]
2019-07-07 11:18:12 +05:30
end
2020-01-01 13:55:28 +05:30
def process(obj); end
2019-07-07 11:18:12 +05:30
end
end
2019-12-26 22:10:19 +05:30
let(:last_resolver) do
Class.new(described_class) do
2021-01-29 00:20:46 +05:30
type [::GraphQL::INT_TYPE], null: true
2019-12-26 22:10:19 +05:30
def resolve(**args)
[1, 2]
end
end
end
2021-01-29 00:20:46 +05:30
describe '.singular_type' do
subject { resolver.singular_type }
context 'for a connection of scalars' do
let(:resolver) do
Class.new(described_class) do
type ::GraphQL::INT_TYPE.connection_type, null: true
end
end
it { is_expected.to eq(::GraphQL::INT_TYPE) }
end
context 'for a connection of objects' do
let(:object) do
Class.new(::Types::BaseObject) do
graphql_name 'Foo'
end
end
let(:resolver) do
conn = object.connection_type
Class.new(described_class) do
type conn, null: true
end
end
it { is_expected.to eq(object) }
end
context 'for a list type' do
let(:resolver) do
Class.new(described_class) do
type [::GraphQL::STRING_TYPE], null: true
end
end
it { is_expected.to eq(::GraphQL::STRING_TYPE) }
end
context 'for a scalar type' do
let(:resolver) do
Class.new(described_class) do
type ::GraphQL::BOOLEAN_TYPE, null: true
end
end
it { is_expected.to eq(::GraphQL::BOOLEAN_TYPE) }
end
end
2019-07-07 11:18:12 +05:30
describe '.single' do
it 'returns a subclass from the resolver' do
expect(resolver.single.superclass).to eq(resolver)
end
2021-01-29 00:20:46 +05:30
it 'has the correct (singular) type' do
expect(resolver.single.type).to eq(::GraphQL::INT_TYPE)
end
2019-07-07 11:18:12 +05:30
it 'returns the same subclass every time' do
expect(resolver.single.object_id).to eq(resolver.single.object_id)
end
it 'returns a resolver that gives the first result from the original resolver' do
result = resolve(resolver.single, args: { test: 1 })
2021-01-29 00:20:46 +05:30
expect(result).to eq(1)
end
end
describe '.when_single' do
let(:resolver) do
Class.new(described_class) do
type [::GraphQL::INT_TYPE], null: true
when_single do
argument :foo, ::GraphQL::INT_TYPE, required: true
end
def resolve(foo: 1)
[foo * foo] # rubocop: disable Lint/BinaryOperatorWithIdenticalOperands
end
end
end
it 'does not apply the block to the resolver' do
expect(resolver.field_options).to include(
arguments: be_empty
)
result = resolve(resolver)
expect(result).to eq([1])
end
it 'applies the block to the single version of the resolver' do
expect(resolver.single.field_options).to include(
arguments: match('foo' => an_instance_of(::Types::BaseArgument))
)
result = resolve(resolver.single, args: { foo: 7 })
expect(result).to eq(49)
end
context 'multiple when_single blocks' do
let(:resolver) do
Class.new(described_class) do
type [::GraphQL::INT_TYPE], null: true
when_single do
argument :foo, ::GraphQL::INT_TYPE, required: true
end
when_single do
argument :bar, ::GraphQL::INT_TYPE, required: true
end
def resolve(foo: 1, bar: 2)
[foo * bar]
end
end
end
it 'applies both blocks to the single version of the resolver' do
expect(resolver.single.field_options).to include(
arguments: match('foo' => ::Types::BaseArgument, 'bar' => ::Types::BaseArgument)
)
result = resolve(resolver.single, args: { foo: 7, bar: 5 })
expect(result).to eq(35)
end
end
context 'inheritance' do
let(:subclass) do
Class.new(resolver) do
when_single do
argument :inc, ::GraphQL::INT_TYPE, required: true
end
def resolve(foo:, inc:)
super(foo: foo + inc)
end
end
end
it 'applies both blocks to the single version of the resolver' do
expect(resolver.single.field_options).to include(
arguments: match('foo' => ::Types::BaseArgument)
)
expect(subclass.single.field_options).to include(
arguments: match('foo' => ::Types::BaseArgument, 'inc' => ::Types::BaseArgument)
)
result = resolve(subclass.single, args: { foo: 7, inc: 1 })
expect(result).to eq(64)
end
2019-07-07 11:18:12 +05:30
end
end
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
context 'when the resolver returns early' do
let(:resolver) do
Class.new(described_class) do
2021-01-29 00:20:46 +05:30
type [::GraphQL::STRING_TYPE], null: true
2020-06-23 00:09:42 +05:30
def ready?(**args)
2021-01-29 00:20:46 +05:30
[false, %w[early return]]
2020-06-23 00:09:42 +05:30
end
def resolve(**args)
raise 'Should not get here'
end
end
end
it 'runs correctly in our test framework' do
expect(resolve(resolver)).to contain_exactly('early', 'return')
end
it 'single selects the first early return value' do
expect(resolve(resolver.single)).to eq('early')
end
it 'last selects the last early return value' do
expect(resolve(resolver.last)).to eq('return')
end
end
2019-12-26 22:10:19 +05:30
describe '.last' do
it 'returns a subclass from the resolver' do
2020-06-23 00:09:42 +05:30
expect(last_resolver.last.ancestors).to include(last_resolver)
2019-12-26 22:10:19 +05:30
end
it 'returns the same subclass every time' do
expect(last_resolver.last.object_id).to eq(last_resolver.last.object_id)
end
it 'returns a resolver that gives the last result from the original resolver' do
result = resolve(last_resolver.last)
expect(result).to eq(2)
end
end
2019-09-04 21:01:54 +05:30
context 'when field is a connection' do
it 'increases complexity based on arguments' do
field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: described_class, null: false, max_page_size: 1)
2019-07-31 22:56:46 +05:30
2019-09-04 21:01:54 +05:30
expect(field.to_graphql.complexity.call({}, { sort: 'foo' }, 1)).to eq 3
expect(field.to_graphql.complexity.call({}, { search: 'foo' }, 1)).to eq 7
end
2019-07-31 22:56:46 +05:30
2019-09-04 21:01:54 +05:30
it 'does not increase complexity when filtering by iids' do
field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: described_class, null: false, max_page_size: 100)
2019-07-31 22:56:46 +05:30
2019-09-04 21:01:54 +05:30
expect(field.to_graphql.complexity.call({}, { sort: 'foo' }, 1)).to eq 6
expect(field.to_graphql.complexity.call({}, { sort: 'foo', iid: 1 }, 1)).to eq 3
expect(field.to_graphql.complexity.call({}, { sort: 'foo', iids: [1, 2, 3] }, 1)).to eq 3
end
2019-07-31 22:56:46 +05:30
end
2020-01-01 13:55:28 +05:30
describe '#object' do
let_it_be(:user) { create(:user) }
it 'returns object' do
expect_next_instance_of(resolver) do |r|
expect(r).to receive(:process).with(user)
end
resolve(resolver, obj: user)
end
context 'when object is a presenter' do
it 'returns presented object' do
expect_next_instance_of(resolver) do |r|
expect(r).to receive(:process).with(user)
end
resolve(resolver, obj: UserPresenter.new(user))
end
end
end
2021-02-22 17:27:13 +05:30
describe '#offset_pagination' do
let(:instance) { resolver_instance(resolver) }
2021-03-11 19:13:27 +05:30
it 'is sugar for OffsetPaginatedRelation.new' do
expect(instance.offset_pagination(User.none)).to be_a(::Gitlab::Graphql::Pagination::OffsetPaginatedRelation)
2021-02-22 17:27:13 +05:30
end
end
2019-07-07 11:18:12 +05:30
end