diff options
Diffstat (limited to 'spec/graphql/types')
-rw-r--r-- | spec/graphql/types/global_id_type_spec.rb | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/spec/graphql/types/global_id_type_spec.rb b/spec/graphql/types/global_id_type_spec.rb index 4df51dc8d1b..37f59770817 100644 --- a/spec/graphql/types/global_id_type_spec.rb +++ b/spec/graphql/types/global_id_type_spec.rb @@ -3,6 +3,10 @@ require 'spec_helper' RSpec.describe Types::GlobalIDType do + include ::Gitlab::Graphql::Laziness + include GraphqlHelpers + include GlobalIDDeprecationHelpers + let_it_be(:project) { create(:project) } let(:gid) { project.to_global_id } @@ -97,6 +101,142 @@ RSpec.describe Types::GlobalIDType do expect { type.coerce_isolated_input(invalid_gid) } .to raise_error(GraphQL::CoercionError, /does not represent an instance of Project/) end + + context 'with a deprecation' do + around(:all) do |example| + # Unset all previously memoized GlobalIDTypes to allow us to define one + # that will use the constants stubbed in the `before` block. + previous_id_types = Types::GlobalIDType.instance_variable_get(:@id_types) + Types::GlobalIDType.instance_variable_set(:@id_types, {}) + + example.run + ensure + Types::GlobalIDType.instance_variable_set(:@id_types, previous_id_types) + end + + before do + deprecation = Gitlab::GlobalId::Deprecations::Deprecation.new(old_model_name: 'OldIssue', new_model_name: 'Issue', milestone: '10.0') + + stub_global_id_deprecations(deprecation) + end + + let_it_be(:issue) { create(:issue) } + + let!(:type) { ::Types::GlobalIDType[::Issue] } + let(:deprecated_gid) { Gitlab::GlobalId.build(model_name: 'OldIssue', id: issue.id) } + let(:deprecating_gid) { Gitlab::GlobalId.build(model_name: 'Issue', id: issue.id) } + + it 'appends the description with a deprecation notice for the old Global ID' do + expect(type.to_graphql.description).to include('The older format `"gid://gitlab/OldIssue/1"` was deprecated in 10.0') + end + + describe 'coercing input against the type (parsing the Global ID string when supplied as an argument)' do + subject(:result) { type.coerce_isolated_input(gid.to_s) } + + context 'when passed the deprecated Global ID' do + let(:gid) { deprecated_gid } + + it 'changes the model_name to the new model name' do + expect(result.model_name).to eq('Issue') + end + + it 'changes the model_class to the new model class' do + expect(result.model_class).to eq(Issue) + end + + it 'can find the correct resource' do + expect(result.find).to eq(issue) + end + + it 'can find the correct resource loaded through GitlabSchema' do + expect(force(GitlabSchema.object_from_id(result, expected_class: Issue))).to eq(issue) + end + end + + context 'when passed the Global ID that is deprecating another' do + let(:gid) { deprecating_gid } + + it 'works as normal' do + expect(result).to have_attributes( + model_class: Issue, + model_name: 'Issue', + find: issue, + to_s: gid.to_s + ) + end + end + end + + describe 'coercing the result against the type (producing the Global ID string when used in a field)' do + context 'when passed the deprecated Global ID' do + let(:gid) { deprecated_gid } + + it 'works, but does not result in matching the new Global ID', :aggregate_failures do + # Note, this would normally never happen in real life as the object being parsed + # by the field would not produce the GlobalID of the deprecated model. This test + # proves that it is technically possible for the deprecated GlobalID to be + # considered parsable for the type, as opposed to raising a `GraphQL::CoercionError`. + expect(type.coerce_isolated_result(gid)).not_to eq(issue.to_global_id.to_s) + expect(type.coerce_isolated_result(gid)).to eq(gid.to_s) + end + end + + context 'when passed the Global ID that is deprecating another' do + let(:gid) { deprecating_gid } + + it 'works as normal' do + expect(type.coerce_isolated_result(gid)).to eq(issue.to_global_id.to_s) + end + end + end + + describe 'executing against the schema' do + let(:query_result) do + context = { current_user: issue.project.owner } + variables = { 'id' => gid } + + run_with_clean_state(query, context: context, variables: variables).to_h + end + + shared_examples 'a query that works with old and new GIDs' do + let(:query) do + <<-GQL + query($id: #{argument_name}!) { + issue(id: $id) { + id + } + } + GQL + end + + subject { query_result.dig('data', 'issue', 'id') } + + context 'when the argument value is the new GID' do + let(:gid) { Gitlab::GlobalId.build(model_name: 'Issue', id: issue.id) } + + it { is_expected.to be_present } + end + + context 'when the argument value is the old GID' do + let(:gid) { Gitlab::GlobalId.build(model_name: 'OldIssue', id: issue.id) } + + it { is_expected.to be_present } + end + end + + context 'when the query signature includes the old type name' do + let(:argument_name) { 'OldIssueID' } + + it_behaves_like 'a query that works with old and new GIDs' + end + + context 'when the query signature includes the new type name' do + let(:argument_name) { 'IssueID' } + + it_behaves_like 'a query that works with old and new GIDs' + end + end + end end describe 'a parameterized type with a namespace' do @@ -231,4 +371,10 @@ RSpec.describe Types::GlobalIDType do end end end + + describe '.model_name_to_graphql_name' do + it 'returns a graphql name for the given model name' do + expect(described_class.model_name_to_graphql_name('DesignManagement::Design')).to eq('DesignManagementDesignID') + end + end end |