2019-03-27 20:02:25 +00:00
# frozen_string_literal: true
require 'spec_helper'
2020-06-24 09:08:32 +00:00
RSpec . describe Types :: BaseField do
2019-03-27 20:02:25 +00:00
context 'when considering complexity' do
2019-05-06 21:24:19 +00:00
let ( :resolver ) do
Class . new ( described_class ) do
2019-05-31 16:46:16 +00:00
def self . resolver_complexity ( args , child_complexity : )
2019-05-06 21:24:19 +00:00
2 if args [ :foo ]
end
def self . complexity_multiplier ( args )
0 . 01
end
end
end
2019-03-27 20:02:25 +00:00
it 'defaults to 1' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true )
expect ( field . to_graphql . complexity ) . to eq 1
end
2019-06-16 10:12:56 +00:00
describe '#base_complexity' do
context 'with no gitaly calls' do
it 'defaults to 1' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true )
expect ( field . base_complexity ) . to eq 1
end
end
context 'with a gitaly call' do
it 'adds 1 to the default value' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true , calls_gitaly : true )
expect ( field . base_complexity ) . to eq 2
end
end
end
2019-03-27 20:02:25 +00:00
it 'has specified value' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true , complexity : 12 )
expect ( field . to_graphql . complexity ) . to eq 12
end
2019-05-06 21:24:19 +00:00
2020-02-26 09:08:47 +00:00
context 'when field has a resolver' do
context 'when a valid complexity is already set' do
let ( :field ) { described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE . connection_type , resolver_class : resolver , complexity : 2 , max_page_size : 100 , null : true ) }
it 'uses this complexity' do
expect ( field . to_graphql . complexity ) . to eq 2
end
end
2019-06-04 22:52:06 +00:00
context 'and is a connection' do
let ( :field ) { described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE . connection_type , resolver_class : resolver , max_page_size : 100 , null : true ) }
2019-05-06 21:24:19 +00:00
2019-06-04 22:52:06 +00:00
it 'sets complexity depending on arguments for resolvers' do
expect ( field . to_graphql . complexity . call ( { } , { } , 2 ) ) . to eq 4
expect ( field . to_graphql . complexity . call ( { } , { first : 50 } , 2 ) ) . to eq 3
end
2019-05-06 21:24:19 +00:00
2019-06-04 22:52:06 +00:00
it 'sets complexity depending on number load limits for resolvers' do
expect ( field . to_graphql . complexity . call ( { } , { first : 1 } , 2 ) ) . to eq 2
expect ( field . to_graphql . complexity . call ( { } , { first : 1 , foo : true } , 2 ) ) . to eq 4
end
end
2019-05-06 21:24:19 +00:00
2019-06-04 22:52:06 +00:00
context 'and is not a connection' do
it 'sets complexity as normal' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , resolver_class : resolver , max_page_size : 100 , null : true )
expect ( field . to_graphql . complexity . call ( { } , { } , 2 ) ) . to eq 2
expect ( field . to_graphql . complexity . call ( { } , { first : 50 } , 2 ) ) . to eq 2
end
end
2019-05-06 21:24:19 +00:00
end
2019-06-16 10:12:56 +00:00
context 'calls_gitaly' do
context 'for fields with a resolver' do
it 'adds 1 if true' do
2019-06-28 01:24:47 +00:00
with_gitaly_field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , resolver_class : resolver , null : true , calls_gitaly : true )
without_gitaly_field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , resolver_class : resolver , null : true )
base_result = without_gitaly_field . to_graphql . complexity . call ( { } , { } , 2 )
2019-06-16 10:12:56 +00:00
2019-06-28 01:24:47 +00:00
expect ( with_gitaly_field . to_graphql . complexity . call ( { } , { } , 2 ) ) . to eq base_result + 1
2019-06-16 10:12:56 +00:00
end
end
context 'for fields without a resolver' do
it 'adds 1 if true' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true , calls_gitaly : true )
expect ( field . to_graphql . complexity ) . to eq 2
end
end
it 'defaults to false' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true )
expect ( field . base_complexity ) . to eq Types :: BaseField :: DEFAULT_COMPLEXITY
end
2019-07-02 05:32:44 +00:00
context 'with declared constant complexity value' do
it 'has complexity set to that constant' do
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true , complexity : 12 )
2019-06-16 10:12:56 +00:00
2019-07-02 05:32:44 +00:00
expect ( field . to_graphql . complexity ) . to eq 12
end
it 'does not raise an error even with Gitaly calls' do
allow ( Gitlab :: GitalyClient ) . to receive ( :get_request_count ) . and_return ( [ 0 , 1 ] )
field = described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , null : true , complexity : 12 )
expect ( field . to_graphql . complexity ) . to eq 12
end
2019-06-16 10:12:56 +00:00
end
end
2020-01-30 21:08:47 +00:00
describe '#visible?' do
context 'and has a feature_flag' do
let ( :flag ) { :test_feature }
let ( :field ) { described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , feature_flag : flag , null : false ) }
let ( :context ) { { } }
2020-09-21 12:09:34 +00:00
before do
skip_feature_flags_yaml_validation
end
2021-07-12 15:09:19 +00:00
it 'checks YAML definition for default_enabled' do
# Exception is indicative of a check for YAML definition
expect { field . visible? ( context ) } . to raise_error ( Feature :: InvalidFeatureFlagError , / The feature flag YAML definition for ' #{ flag } ' does not exist / )
2020-01-30 21:08:47 +00:00
end
2021-07-12 15:09:19 +00:00
context 'skipping YAML check' do
before do
skip_default_enabled_yaml_check
end
it 'returns false if the feature is not enabled' do
stub_feature_flags ( flag = > false )
expect ( field . visible? ( context ) ) . to eq ( false )
end
it 'returns true if the feature is enabled' do
expect ( field . visible? ( context ) ) . to eq ( true )
end
2020-01-30 21:08:47 +00:00
end
end
end
2020-03-19 12:09:33 +00:00
end
2020-01-30 21:08:47 +00:00
2020-03-19 12:09:33 +00:00
describe '#description' do
context 'feature flag given' do
2020-12-11 15:10:04 +00:00
let ( :field ) { described_class . new ( name : 'test' , type : GraphQL :: STRING_TYPE , feature_flag : flag , null : false , description : 'Test description.' ) }
2020-03-19 12:09:33 +00:00
let ( :flag ) { :test_flag }
2020-01-30 21:08:47 +00:00
2020-03-19 12:09:33 +00:00
it 'prepends the description' do
2021-07-19 15:09:40 +00:00
expect ( field . description ) . to start_with 'Test description. Available only when feature flag `test_flag` is enabled.'
2020-03-19 12:09:33 +00:00
end
2020-01-30 21:08:47 +00:00
2020-03-19 12:09:33 +00:00
context 'falsey feature_flag values' do
using RSpec :: Parameterized :: TableSyntax
2020-01-30 21:08:47 +00:00
2021-07-19 15:09:40 +00:00
where ( :flag , :feature_value , :default_enabled ) do
'' | false | false
'' | true | false
nil | false | true
nil | true | false
2020-03-19 12:09:33 +00:00
end
2020-01-30 21:08:47 +00:00
2020-03-19 12:09:33 +00:00
with_them do
it 'returns the correct description' do
2020-12-11 15:10:04 +00:00
expect ( field . description ) . to eq ( 'Test description.' )
2020-01-30 21:08:47 +00:00
end
end
end
2021-07-19 15:09:40 +00:00
context 'with different default_enabled values' do
using RSpec :: Parameterized :: TableSyntax
where ( :feature_value , :default_enabled , :expected_description ) do
disabled_ff_description = " Test description. Available only when feature flag `test_flag` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. "
enabled_ff_description = " Test description. Available only when feature flag `test_flag` is enabled. This flag is enabled by default. "
false | false | disabled_ff_description
true | false | disabled_ff_description
false | true | enabled_ff_description
true | true | enabled_ff_description
end
with_them do
before do
stub_feature_flags ( " #{ flag } " : feature_value )
allow ( Feature :: Definition ) . to receive ( :has_definition? ) . with ( flag ) . and_return ( true )
allow ( Feature :: Definition ) . to receive ( :default_enabled? ) . and_return ( default_enabled )
end
it 'returns the correct availability in the description' do
expect ( field . description ) . to eq expected_description
end
end
end
2020-01-30 21:08:47 +00:00
end
2019-03-27 20:02:25 +00:00
end
2020-03-20 09:09:22 +00:00
2020-09-14 15:09:28 +00:00
include_examples 'Gitlab-style deprecations' do
def subject ( args = { } )
2020-03-20 09:09:22 +00:00
base_args = { name : 'test' , type : GraphQL :: STRING_TYPE , null : true }
described_class . new ( ** base_args . merge ( args ) )
end
it 'interacts well with the `feature_flag` property' do
2020-09-14 15:09:28 +00:00
field = subject (
2020-04-06 03:09:23 +00:00
deprecated : { milestone : '1.10' , reason : 'Deprecation reason' } ,
2020-12-11 15:10:04 +00:00
description : 'Field description.' ,
2020-03-20 09:09:22 +00:00
feature_flag : 'foo_flag'
)
2021-07-19 15:09:40 +00:00
expect ( field . description ) . to start_with ( 'Field description. Available only when feature flag `foo_flag` is enabled.' )
expect ( field . description ) . to end_with ( 'Deprecated in 1.10: Deprecation reason.' )
2020-03-20 09:09:22 +00:00
end
end
2019-03-27 20:02:25 +00:00
end