diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 13:49:51 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 13:49:51 +0000 |
commit | 71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e (patch) | |
tree | 6a2d93ef3fb2d353bb7739e4b57e6541f51cdd71 /spec/graphql/resolvers | |
parent | a7253423e3403b8c08f8a161e5937e1488f5f407 (diff) | |
download | gitlab-ce-71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e.tar.gz |
Add latest changes from gitlab-org/gitlab@15-9-stable-eev15.9.0-rc42
Diffstat (limited to 'spec/graphql/resolvers')
12 files changed, 366 insertions, 166 deletions
diff --git a/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb b/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb index 59ece15b745..92f4d3dd8e8 100644 --- a/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/job_token_scope_resolver_spec.rb @@ -23,18 +23,18 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do it 'returns the same project in the allow list of projects for the Ci Job Token when scope is not enabled' do allow(project).to receive(:ci_outbound_job_token_scope_enabled?).and_return(false) - expect(resolve_scope.all_projects).to contain_exactly(project) + expect(resolve_scope.outbound_projects).to contain_exactly(project) end it 'returns the same project in the allow list of projects for the Ci Job Token' do - expect(resolve_scope.all_projects).to contain_exactly(project) + expect(resolve_scope.outbound_projects).to contain_exactly(project) end context 'when another projects gets added to the allow list' do let!(:link) { create(:ci_job_token_project_scope_link, source_project: project) } it 'returns both projects' do - expect(resolve_scope.all_projects).to contain_exactly(project, link.target_project) + expect(resolve_scope.outbound_projects).to contain_exactly(project, link.target_project) end end @@ -44,7 +44,7 @@ RSpec.describe Resolvers::Ci::JobTokenScopeResolver do end it 'resolves projects' do - expect(resolve_scope.all_projects).to contain_exactly(project) + expect(resolve_scope.outbound_projects).to contain_exactly(project) end end end diff --git a/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb index 1d1fb4a9967..da6a84cec44 100644 --- a/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runner_platforms_resolver_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Resolvers::Ci::RunnerPlatformsResolver, feature_category: :runner expect(resolve_subject).to contain_exactly( hash_including(name: :linux), hash_including(name: :osx), hash_including(name: :windows), hash_including(name: :docker), - hash_including(name: :kubernetes) + hash_including(name: :kubernetes), hash_including(name: :aws) ) end end diff --git a/spec/graphql/resolvers/ci/variables_resolver_spec.rb b/spec/graphql/resolvers/ci/variables_resolver_spec.rb new file mode 100644 index 00000000000..16b72e8cb7f --- /dev/null +++ b/spec/graphql/resolvers/ci/variables_resolver_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Ci::VariablesResolver, feature_category: :pipeline_authoring do + include GraphqlHelpers + + describe '#resolve' do + let_it_be(:user) { create(:user) } + let_it_be(:args) { {} } + let_it_be(:obj) { nil } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project) } + + let_it_be(:ci_instance_variables) do + [ + create(:ci_instance_variable, key: 'a'), + create(:ci_instance_variable, key: 'b') + ] + end + + let_it_be(:ci_group_variables) do + [ + create(:ci_group_variable, group: group, key: 'a'), + create(:ci_group_variable, group: group, key: 'b') + ] + end + + let_it_be(:ci_project_variables) do + [ + create(:ci_variable, project: project, key: 'a'), + create(:ci_variable, project: project, key: 'b') + ] + end + + subject(:resolve_variables) { resolve(described_class, obj: obj, ctx: { current_user: user }, args: args) } + + context 'when parent object is nil' do + context 'when user is authorized', :enable_admin_mode do + let_it_be(:user) { create(:admin) } + + it "returns the instance's variables" do + expect(resolve_variables.items.to_a).to match_array(ci_instance_variables) + end + end + + context 'when user is not authorized' do + it "returns nil" do + expect(resolve_variables).to be_nil + end + end + end + + context 'when parent object is a Group' do + let_it_be(:obj) { group } + + it "returns the group's variables" do + expect(resolve_variables.items.to_a).to match_array(ci_group_variables) + end + end + + context 'when parent object is a Project' do + let_it_be(:obj) { project } + + it "returns the project's variables" do + expect(resolve_variables.items.to_a).to match_array(ci_project_variables) + end + end + end +end diff --git a/spec/graphql/resolvers/data_transfer_resolver_spec.rb b/spec/graphql/resolvers/data_transfer_resolver_spec.rb new file mode 100644 index 00000000000..f5a088dc1c3 --- /dev/null +++ b/spec/graphql/resolvers/data_transfer_resolver_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::DataTransferResolver, feature_category: :source_code_management do + include GraphqlHelpers + + describe '.source' do + context 'with base DataTransferResolver' do + it 'raises NotImplementedError' do + expect { described_class.source }.to raise_error ::NotImplementedError + end + end + + context 'with projects DataTransferResolver' do + let(:source) { described_class.project.source } + + it 'outputs "Project"' do + expect(source).to eq 'Project' + end + end + + context 'with groups DataTransferResolver' do + let(:source) { described_class.group.source } + + it 'outputs "Group"' do + expect(source).to eq 'Group' + end + end + end +end diff --git a/spec/graphql/resolvers/group_releases_resolver_spec.rb b/spec/graphql/resolvers/group_releases_resolver_spec.rb new file mode 100644 index 00000000000..73386870030 --- /dev/null +++ b/spec/graphql/resolvers/group_releases_resolver_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::GroupReleasesResolver, feature_category: :release_orchestration do + include GraphqlHelpers + + let_it_be(:today) { Time.now } + let_it_be(:yesterday) { today - 1.day } + let_it_be(:tomorrow) { today + 1.day } + + let_it_be(:group) { create(:group, :private) } + let_it_be(:project) { create(:project, :private, namespace: group) } + let_it_be(:release_v1) do + create(:release, project: project, tag: 'v1.0.0', released_at: yesterday, created_at: tomorrow) + end + + let_it_be(:release_v2) do + create(:release, project: project, tag: 'v2.0.0', released_at: today, created_at: yesterday) + end + + let_it_be(:release_v3) do + create(:release, project: project, tag: 'v3.0.0', released_at: tomorrow, created_at: today) + end + + let_it_be(:developer) { create(:user) } + let_it_be(:public_user) { create(:user) } + + let(:args) { { sort: :released_at_desc } } + let(:all_releases) { [release_v1, release_v2, release_v3] } + + before do + group.add_member(developer, :owner) + project.add_developer(developer) + end + + describe '#resolve' do + it_behaves_like 'releases and group releases resolver' + end + + private + + def resolve_releases + context = { current_user: current_user } + resolve(described_class, obj: group, args: args, ctx: context, arg_style: :internal) + end +end diff --git a/spec/graphql/resolvers/groups_resolver_spec.rb b/spec/graphql/resolvers/groups_resolver_spec.rb index e53ca674163..9d1ad46ed0e 100644 --- a/spec/graphql/resolvers/groups_resolver_spec.rb +++ b/spec/graphql/resolvers/groups_resolver_spec.rb @@ -2,131 +2,42 @@ require 'spec_helper' -RSpec.describe Resolvers::GroupsResolver do +RSpec.describe Resolvers::GroupsResolver, feature_category: :subgroups do include GraphqlHelpers describe '#resolve' do - let_it_be(:group) { create(:group, name: 'public-group') } - let_it_be(:private_group) { create(:group, :private, name: 'private-group') } - let_it_be(:subgroup1) { create(:group, parent: group, name: 'Subgroup') } - let_it_be(:subgroup2) { create(:group, parent: subgroup1, name: 'Test Subgroup 2') } - let_it_be(:private_subgroup1) { create(:group, :private, parent: private_group, name: 'Subgroup1') } - let_it_be(:private_subgroup2) { create(:group, :private, parent: private_subgroup1, name: 'Subgroup2') } let_it_be(:user) { create(:user) } + let_it_be(:public_group) { create(:group, name: 'public-group') } + let_it_be(:private_group) { create(:group, :private, name: 'private-group') } - before_all do - private_group.add_developer(user) - end + let(:params) { {} } - shared_examples 'access to all public descendant groups' do - it 'returns all public descendant groups of the parent group ordered by ASC name' do - is_expected.to eq([subgroup1, subgroup2]) - end - end + subject { resolve(described_class, args: params, ctx: { current_user: user }) } - shared_examples 'access to all public subgroups' do - it 'returns all public subgroups of the parent group' do - is_expected.to contain_exactly(subgroup1) - end + it 'includes public groups' do + expect(subject).to contain_exactly(public_group) end - shared_examples 'returning empty results' do - it 'returns empty results' do - is_expected.to be_empty - end + it 'includes accessible private groups' do + private_group.add_developer(user) + expect(subject).to contain_exactly(public_group, private_group) end - context 'when parent group is public' do - subject { resolve(described_class, obj: group, args: params, ctx: { current_user: current_user }) } - - context 'when `include_parent_descendants` is false' do - let(:params) { { include_parent_descendants: false } } - - context 'when user is not logged in' do - let(:current_user) { nil } - - it_behaves_like 'access to all public subgroups' - end + describe 'ordering' do + let_it_be(:other_group) { create(:group, name: 'other-group') } - context 'when user is logged in' do - let(:current_user) { user } - - it_behaves_like 'access to all public subgroups' - end - end - - context 'when `include_parent_descendants` is true' do - let(:params) { { include_parent_descendants: true } } - - context 'when user is not logged in' do - let(:current_user) { nil } - - it_behaves_like 'access to all public descendant groups' - end - - context 'when user is logged in' do - let(:current_user) { user } - - it_behaves_like 'access to all public descendant groups' - - context 'with owned argument set as true' do - before do - subgroup1.add_owner(current_user) - params[:owned] = true - end - - it 'returns only descendant groups owned by the user' do - is_expected.to contain_exactly(subgroup1) - end - end - - context 'with search argument' do - it 'returns only descendant groups with matching name or path' do - params[:search] = 'Test' - is_expected.to contain_exactly(subgroup2) - end - end - end + it 'orders by name ascending' do + expect(subject.map(&:name)).to eq(%w[other-group public-group]) end end - context 'when parent group is private' do - subject { resolve(described_class, obj: private_group, args: params, ctx: { current_user: current_user }) } - - context 'when `include_parent_descendants` is true' do - let(:params) { { include_parent_descendants: true } } - - context 'when user is not logged in' do - let(:current_user) { nil } - - it_behaves_like 'returning empty results' - end - - context 'when user is logged in' do - let(:current_user) { user } - - it 'returns all private descendant groups' do - is_expected.to contain_exactly(private_subgroup1, private_subgroup2) - end - end - end - - context 'when `include_parent_descendants` is false' do - let(:params) { { include_parent_descendants: false } } - - context 'when user is not logged in' do - let(:current_user) { nil } - - it_behaves_like 'returning empty results' - end + context 'with `search` argument' do + let_it_be(:other_group) { create(:group, name: 'other-group') } - context 'when user is logged in' do - let(:current_user) { user } + let(:params) { { search: 'oth' } } - it 'returns private subgroups' do - is_expected.to contain_exactly(private_subgroup1) - end - end + it 'filters groups by name' do + expect(subject).to contain_exactly(other_group) end end end diff --git a/spec/graphql/resolvers/nested_groups_resolver_spec.rb b/spec/graphql/resolvers/nested_groups_resolver_spec.rb new file mode 100644 index 00000000000..e58edc3fd4b --- /dev/null +++ b/spec/graphql/resolvers/nested_groups_resolver_spec.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::NestedGroupsResolver, feature_category: :subgroups do + include GraphqlHelpers + + describe '#resolve' do + let_it_be(:group) { create(:group, name: 'public-group') } + let_it_be(:private_group) { create(:group, :private, name: 'private-group') } + let_it_be(:subgroup1) { create(:group, parent: group, name: 'Subgroup') } + let_it_be(:subgroup2) { create(:group, parent: subgroup1, name: 'Test Subgroup 2') } + let_it_be(:private_subgroup1) { create(:group, :private, parent: private_group, name: 'Subgroup1') } + let_it_be(:private_subgroup2) { create(:group, :private, parent: private_subgroup1, name: 'Subgroup2') } + let_it_be(:user) { create(:user) } + + before_all do + private_group.add_developer(user) + end + + shared_examples 'access to all public descendant groups' do + it 'returns all public descendant groups of the parent group ordered by ASC name' do + is_expected.to eq([subgroup1, subgroup2]) + end + end + + shared_examples 'access to all public subgroups' do + it 'returns all public subgroups of the parent group' do + is_expected.to contain_exactly(subgroup1) + end + end + + shared_examples 'returning empty results' do + it 'returns empty results' do + is_expected.to be_empty + end + end + + context 'when parent group is public' do + subject { resolve(described_class, obj: group, args: params, ctx: { current_user: current_user }) } + + context 'when `include_parent_descendants` is false' do + let(:params) { { include_parent_descendants: false } } + + context 'when user is not logged in' do + let(:current_user) { nil } + + it_behaves_like 'access to all public subgroups' + end + + context 'when user is logged in' do + let(:current_user) { user } + + it_behaves_like 'access to all public subgroups' + end + end + + context 'when `include_parent_descendants` is true' do + let(:params) { { include_parent_descendants: true } } + + context 'when user is not logged in' do + let(:current_user) { nil } + + it_behaves_like 'access to all public descendant groups' + end + + context 'when user is logged in' do + let(:current_user) { user } + + it_behaves_like 'access to all public descendant groups' + + context 'with owned argument set as true' do + before do + subgroup1.add_owner(current_user) + params[:owned] = true + end + + it 'returns only descendant groups owned by the user' do + is_expected.to contain_exactly(subgroup1) + end + end + + context 'with search argument' do + it 'returns only descendant groups with matching name or path' do + params[:search] = 'Test' + is_expected.to contain_exactly(subgroup2) + end + end + end + end + end + + context 'when parent group is private' do + subject { resolve(described_class, obj: private_group, args: params, ctx: { current_user: current_user }) } + + context 'when `include_parent_descendants` is true' do + let(:params) { { include_parent_descendants: true } } + + context 'when user is not logged in' do + let(:current_user) { nil } + + it_behaves_like 'returning empty results' + end + + context 'when user is logged in' do + let(:current_user) { user } + + it 'returns all private descendant groups' do + is_expected.to contain_exactly(private_subgroup1, private_subgroup2) + end + end + end + + context 'when `include_parent_descendants` is false' do + let(:params) { { include_parent_descendants: false } } + + context 'when user is not logged in' do + let(:current_user) { nil } + + it_behaves_like 'returning empty results' + end + + context 'when user is logged in' do + let(:current_user) { user } + + it 'returns private subgroups' do + is_expected.to contain_exactly(private_subgroup1) + end + end + end + end + end +end diff --git a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb index b95bab41e3e..6af2f56cef4 100644 --- a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb +++ b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::Projects::JiraProjectsResolver do +RSpec.describe Resolvers::Projects::JiraProjectsResolver, feature_category: :integrations do include GraphqlHelpers specify do diff --git a/spec/graphql/resolvers/releases_resolver_spec.rb b/spec/graphql/resolvers/releases_resolver_spec.rb index 6ba9a6c33a1..58f6257c946 100644 --- a/spec/graphql/resolvers/releases_resolver_spec.rb +++ b/spec/graphql/resolvers/releases_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::ReleasesResolver do +RSpec.describe Resolvers::ReleasesResolver, feature_category: :release_orchestration do include GraphqlHelpers let_it_be(:today) { Time.now } @@ -24,60 +24,28 @@ RSpec.describe Resolvers::ReleasesResolver do end describe '#resolve' do - context 'when the user does not have access to the project' do - let(:current_user) { public_user } + it_behaves_like 'releases and group releases resolver' - it 'returns an empty array' do - expect(resolve_releases).to be_empty - end - end - - context "when the user has full access to the project's releases" do + describe 'when order_by is created_at' do let(:current_user) { developer } - it 'returns all releases associated to the project' do - expect(resolve_releases).to match_array(all_releases) - end - - describe 'sorting behavior' do - context 'with sort: :released_at_desc' do - let(:args) { { sort: :released_at_desc } } - - it 'returns the releases ordered by released_at in descending order' do - expect(resolve_releases.to_a) - .to match_array(all_releases) - .and be_sorted(:released_at, :desc) - end - end - - context 'with sort: :released_at_asc' do - let(:args) { { sort: :released_at_asc } } - - it 'returns the releases ordered by released_at in ascending order' do - expect(resolve_releases.to_a) - .to match_array(all_releases) - .and be_sorted(:released_at, :asc) - end - end - - context 'with sort: :created_desc' do - let(:args) { { sort: :created_desc } } + context 'with sort: desc' do + let(:args) { { sort: :created_desc } } - it 'returns the releases ordered by created_at in descending order' do - expect(resolve_releases.to_a) - .to match_array(all_releases) - .and be_sorted(:created_at, :desc) - end + it 'returns the releases ordered by created_at in descending order' do + expect(resolve_releases.to_a) + .to match_array(all_releases) + .and be_sorted(:created_at, :desc) end + end - context 'with sort: :created_asc' do - let(:args) { { sort: :created_asc } } + context 'with sort: asc' do + let(:args) { { sort: :created_asc } } - it 'returns the releases ordered by created_at in ascending order' do - expect(resolve_releases.to_a) - .to match_array(all_releases) - .and be_sorted(:created_at, :asc) - end + it 'returns the releases ordered by created_at in ascending order' do + expect(resolve_releases.to_a) + .to match_array(all_releases) + .and be_sorted(:created_at, :asc) end end end diff --git a/spec/graphql/resolvers/saved_reply_resolver_spec.rb b/spec/graphql/resolvers/saved_reply_resolver_spec.rb new file mode 100644 index 00000000000..f1cb0ca5214 --- /dev/null +++ b/spec/graphql/resolvers/saved_reply_resolver_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::SavedReplyResolver, feature_category: :user_profile do + include GraphqlHelpers + + let_it_be(:current_user) { create(:user) } + let_it_be(:saved_reply) { create(:saved_reply, user: current_user) } + + describe 'feature flag disabled' do + before do + stub_feature_flags(saved_replies: false) + end + + it 'does not return saved reply' do + expect(resolve_saved_reply).to be_nil + end + end + + describe 'feature flag enabled' do + it 'returns users saved reply' do + expect(resolve_saved_reply).to eq(saved_reply) + end + + it 'returns nil when saved reply is not found' do + expect(resolve_saved_reply({ id: 'gid://gitlab/Users::SavedReply/100' })).to be_nil + end + + it 'returns nil when saved reply is another users' do + other_users_saved_reply = create(:saved_reply, user: create(:user)) + + expect(resolve_saved_reply({ id: other_users_saved_reply.to_global_id })).to be_nil + end + end + + def resolve_saved_reply(args = { id: saved_reply.to_global_id }) + resolve(described_class, args: args, ctx: { current_user: current_user }) + end +end diff --git a/spec/graphql/resolvers/users/participants_resolver_spec.rb b/spec/graphql/resolvers/users/participants_resolver_spec.rb index 27c3b9643ce..224213d1521 100644 --- a/spec/graphql/resolvers/users/participants_resolver_spec.rb +++ b/spec/graphql/resolvers/users/participants_resolver_spec.rb @@ -115,8 +115,8 @@ RSpec.describe Resolvers::Users::ParticipantsResolver do create(:award_emoji, name: 'thumbsup', awardable: public_note) # 1 extra query per source (3 emojis + 2 notes) to fetch participables collection - # 1 extra query to load work item widgets collection - expect { query.call }.not_to exceed_query_limit(control_count).with_threshold(6) + # 2 extra queries to load work item widgets collection + expect { query.call }.not_to exceed_query_limit(control_count).with_threshold(7) end it 'does not execute N+1 for system note metadata relation' do diff --git a/spec/graphql/resolvers/work_items_resolver_spec.rb b/spec/graphql/resolvers/work_items_resolver_spec.rb index d89ccc7f806..6da62e3adb7 100644 --- a/spec/graphql/resolvers/work_items_resolver_spec.rb +++ b/spec/graphql/resolvers/work_items_resolver_spec.rb @@ -101,7 +101,7 @@ RSpec.describe Resolvers::WorkItemsResolver do end it 'batches queries that only include IIDs', :request_store do - result = batch_sync(max_queries: 7) do + result = batch_sync(max_queries: 8) do [item1, item2] .map { |item| resolve_items(iid: item.iid.to_s) } .flat_map(&:to_a) @@ -111,7 +111,7 @@ RSpec.describe Resolvers::WorkItemsResolver do end it 'finds a specific item with iids', :request_store do - result = batch_sync(max_queries: 7) do + result = batch_sync(max_queries: 8) do resolve_items(iids: [item1.iid]).to_a end |