diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-18 09:45:46 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-18 09:45:46 +0000 |
commit | a7b3560714b4d9cc4ab32dffcd1f74a284b93580 (patch) | |
tree | 7452bd5c3545c2fa67a28aa013835fb4fa071baf /spec/graphql/resolvers | |
parent | ee9173579ae56a3dbfe5afe9f9410c65bb327ca7 (diff) | |
download | gitlab-ce-a7b3560714b4d9cc4ab32dffcd1f74a284b93580.tar.gz |
Add latest changes from gitlab-org/gitlab@14-8-stable-eev14.8.0-rc42
Diffstat (limited to 'spec/graphql/resolvers')
9 files changed, 335 insertions, 54 deletions
diff --git a/spec/graphql/resolvers/ci/project_pipeline_counts_resolver_spec.rb b/spec/graphql/resolvers/ci/project_pipeline_counts_resolver_spec.rb new file mode 100644 index 00000000000..07b4a5509b2 --- /dev/null +++ b/spec/graphql/resolvers/ci/project_pipeline_counts_resolver_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Ci::ProjectPipelineCountsResolver do + include GraphqlHelpers + + let(:current_user) { create(:user) } + + let_it_be(:project) { create(:project, :private) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:failed_pipeline) { create(:ci_pipeline, :failed, project: project) } + let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) } + let_it_be(:ref_pipeline) { create(:ci_pipeline, project: project, ref: 'awesome-feature') } + let_it_be(:sha_pipeline) { create(:ci_pipeline, :running, project: project, sha: 'deadbeef') } + let_it_be(:on_demand_dast_scan) { create(:ci_pipeline, :success, project: project, source: 'ondemand_dast_scan') } + + before do + project.add_developer(current_user) + end + + describe '#resolve' do + it 'counts pipelines' do + expect(resolve_pipeline_counts).to have_attributes( + all: 6, + finished: 3, + running: 1, + pending: 2 + ) + end + + it 'counts by ref' do + expect(resolve_pipeline_counts(ref: "awesome-feature")).to have_attributes( + all: 1, + finished: 0, + running: 0, + pending: 1 + ) + end + + it 'counts by sha' do + expect(resolve_pipeline_counts(sha: "deadbeef")).to have_attributes( + all: 1, + finished: 0, + running: 1, + pending: 0 + ) + end + + it 'counts by source' do + expect(resolve_pipeline_counts(source: "ondemand_dast_scan")).to have_attributes( + all: 1, + finished: 1, + running: 0, + pending: 0 + ) + end + end + + def resolve_pipeline_counts(args = {}, context = { current_user: current_user }) + resolve(described_class, obj: project, args: args, ctx: context) + end +end diff --git a/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb new file mode 100644 index 00000000000..53b673e255b --- /dev/null +++ b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::Ci::RunnerJobsResolver do + include GraphqlHelpers + + let_it_be(:project) { create(:project, :repository) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:irrelevant_pipeline) { create(:ci_pipeline, project: project) } + + let!(:build_one) { create(:ci_build, :success, name: 'Build One', runner: runner, pipeline: pipeline) } + let!(:build_two) { create(:ci_build, :success, name: 'Build Two', runner: runner, pipeline: pipeline) } + let!(:build_three) { create(:ci_build, :failed, name: 'Build Three', runner: runner, pipeline: pipeline) } + let!(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline)} + + let(:args) { {} } + let(:runner) { create(:ci_runner, :project, projects: [project]) } + + subject { resolve_jobs(args) } + + describe '#resolve' do + context 'with authorized user', :enable_admin_mode do + let(:current_user) { create(:user, :admin) } + + context 'with statuses argument' do + let(:args) { { statuses: [Types::Ci::JobStatusEnum.coerce_isolated_input('SUCCESS')] } } + + it { is_expected.to contain_exactly(build_one, build_two) } + end + + context 'without statuses argument' do + it { is_expected.to contain_exactly(build_one, build_two, build_three) } + end + end + + context 'with unauthorized user' do + let(:current_user) { nil } + + it { is_expected.to be_nil } + end + end + + private + + def resolve_jobs(args = {}, context = { current_user: current_user }) + resolve(described_class, obj: runner, args: args, ctx: context) + end +end diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb index df6490df915..9251fbf24d9 100644 --- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb @@ -43,34 +43,99 @@ RSpec.describe Resolvers::Ci::RunnersResolver do # Only thing we can do is to verify that args from the resolver is correctly transformed to params of the Finder and we return the Finder's result back. describe 'Allowed query arguments' do let(:finder) { instance_double(::Ci::RunnersFinder) } - let(:args) do - { - active: true, - status: 'active', - type: :instance_type, - tag_list: ['active_runner'], - search: 'abc', - sort: :contacted_asc - } + + context 'with active filter' do + let(:args) do + { + active: true, + status: 'active', + type: :instance_type, + tag_list: ['active_runner'], + search: 'abc', + sort: :contacted_asc + } + end + + let(:expected_params) do + { + active: true, + status_status: 'active', + type_type: :instance_type, + tag_name: ['active_runner'], + preload: { tag_name: nil }, + search: 'abc', + sort: 'contacted_asc' + } + end + + it 'calls RunnersFinder with expected arguments' do + expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder) + allow(finder).to receive(:execute).once.and_return([:execute_return_value]) + + expect(subject.items.to_a).to eq([:execute_return_value]) + end + end + + context 'with both active and paused filter' do + let(:args) do + { + active: true, + paused: true + } + end + + let(:expected_params) do + { + active: false, + preload: { tag_name: nil } + } + end + + it 'calls RunnersFinder with expected arguments' do + expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder) + allow(finder).to receive(:execute).once.and_return([:execute_return_value]) + + expect(subject.items.to_a).to eq([:execute_return_value]) + end end - let(:expected_params) do - { - active: true, - status_status: 'active', - type_type: :instance_type, - tag_name: ['active_runner'], - preload: { tag_name: nil }, - search: 'abc', - sort: 'contacted_asc' - } + context 'with paused filter' do + let(:args) do + { paused: true } + end + + let(:expected_params) do + { + active: false, + preload: { tag_name: nil } + } + end + + it 'calls RunnersFinder with expected arguments' do + expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder) + allow(finder).to receive(:execute).once.and_return([:execute_return_value]) + + expect(subject.items.to_a).to eq([:execute_return_value]) + end end - it 'calls RunnersFinder with expected arguments' do - allow(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder) - allow(finder).to receive(:execute).once.and_return([:execute_return_value]) + context 'with neither paused or active filters' do + let(:args) do + {} + end + + let(:expected_params) do + { + preload: { tag_name: nil } + } + end + + it 'calls RunnersFinder with expected arguments' do + expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder) + allow(finder).to receive(:execute).once.and_return([:execute_return_value]) - expect(subject.items.to_a).to eq([:execute_return_value]) + expect(subject.items.to_a).to eq([:execute_return_value]) + end end end end diff --git a/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb b/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb index 9b54d466681..866f4ce7b5a 100644 --- a/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb +++ b/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do describe '#resolve' do let(:agent) { create(:cluster_agent) } - let(:user) { create(:user, maintainer_projects: [agent.project]) } + let(:user) { create(:user, developer_projects: [agent.project]) } let(:ctx) { Hash(current_user: user) } let!(:matching_token1) { create(:cluster_agent_token, agent: agent, last_used_at: 5.days.ago) } @@ -33,7 +33,11 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do end context 'user does not have permission' do - let(:user) { create(:user, developer_projects: [agent.project]) } + let(:user) { create(:user) } + + before do + agent.project.add_reporter(user) + end it { is_expected.to be_empty } end diff --git a/spec/graphql/resolvers/clusters/agents_resolver_spec.rb b/spec/graphql/resolvers/clusters/agents_resolver_spec.rb index 70f40748e1d..152d7fa22c4 100644 --- a/spec/graphql/resolvers/clusters/agents_resolver_spec.rb +++ b/spec/graphql/resolvers/clusters/agents_resolver_spec.rb @@ -15,10 +15,14 @@ RSpec.describe Resolvers::Clusters::AgentsResolver do describe '#resolve' do let_it_be(:project) { create(:project) } - let_it_be(:maintainer) { create(:user, maintainer_projects: [project]) } - let_it_be(:developer) { create(:user, developer_projects: [project]) } + let_it_be(:maintainer) { create(:user, developer_projects: [project]) } + let_it_be(:reporter) { create(:user) } let_it_be(:agents) { create_list(:cluster_agent, 2, project: project) } + before do + project.add_reporter(reporter) + end + let(:ctx) { { current_user: current_user } } subject { resolve_agents } @@ -32,7 +36,7 @@ RSpec.describe Resolvers::Clusters::AgentsResolver do end context 'the current user does not have access to clusters' do - let(:current_user) { developer } + let(:current_user) { reporter } it 'returns an empty result' do expect(subject).to be_empty diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb index 1d0eac30a23..e4eaeb9bc3c 100644 --- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb +++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb @@ -321,7 +321,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do end describe 'sorting' do - let(:mrs) do + let_it_be(:mrs) do [ merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4, merge_request_3, merge_request_2, merge_request_1 @@ -363,28 +363,44 @@ RSpec.describe Resolvers::MergeRequestsResolver do def merged_at(mr) nils_last(mr.metrics.merged_at) end + end + + context 'when sorting by closed at' do + before do + merge_request_1.metrics.update!(latest_closed_at: 10.days.ago) + merge_request_3.metrics.update!(latest_closed_at: 5.days.ago) + end + + it 'sorts merge requests ascending' do + expect(resolve_mr(project, sort: :closed_at_asc)) + .to match_array(mrs) + .and be_sorted(->(mr) { [closed_at(mr), -mr.id] }) + end + + it 'sorts merge requests descending' do + expect(resolve_mr(project, sort: :closed_at_desc)) + .to match_array(mrs) + .and be_sorted(->(mr) { [-closed_at(mr), -mr.id] }) + end + + def closed_at(mr) + nils_last(mr.metrics.latest_closed_at) + end + end + + context 'when sorting by title' do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:mr1) { create(:merge_request, :unique_branches, title: 'foo', source_project: project) } + let_it_be(:mr2) { create(:merge_request, :unique_branches, title: 'bar', source_project: project) } + let_it_be(:mr3) { create(:merge_request, :unique_branches, title: 'baz', source_project: project) } + let_it_be(:mr4) { create(:merge_request, :unique_branches, title: 'Baz 2', source_project: project) } + + it 'sorts issues ascending' do + expect(resolve_mr(project, sort: :title_asc).to_a).to eq [mr2, mr3, mr4, mr1] + end - context 'when sorting by closed at' do - before do - merge_request_1.metrics.update!(latest_closed_at: 10.days.ago) - merge_request_3.metrics.update!(latest_closed_at: 5.days.ago) - end - - it 'sorts merge requests ascending' do - expect(resolve_mr(project, sort: :closed_at_asc)) - .to match_array(mrs) - .and be_sorted(->(mr) { [closed_at(mr), -mr.id] }) - end - - it 'sorts merge requests descending' do - expect(resolve_mr(project, sort: :closed_at_desc)) - .to match_array(mrs) - .and be_sorted(->(mr) { [-closed_at(mr), -mr.id] }) - end - - def closed_at(mr) - nils_last(mr.metrics.latest_closed_at) - end + it 'sorts issues descending' do + expect(resolve_mr(project, sort: :title_desc).to_a).to eq [mr1, mr4, mr3, mr2] end end end diff --git a/spec/graphql/resolvers/package_details_resolver_spec.rb b/spec/graphql/resolvers/package_details_resolver_spec.rb index d6acb31d4e3..c8ee489a034 100644 --- a/spec/graphql/resolvers/package_details_resolver_spec.rb +++ b/spec/graphql/resolvers/package_details_resolver_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Resolvers::PackageDetailsResolver do include GraphqlHelpers let_it_be_with_reload(:project) { create(:project) } - let_it_be(:user) { project.owner } + let_it_be(:user) { project.first_owner } let_it_be(:package) { create(:composer_package, project: project) } describe '#resolve' do diff --git a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb index d48d4d8ae01..892dc641201 100644 --- a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb +++ b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb @@ -8,15 +8,16 @@ RSpec.describe Resolvers::PackagePipelinesResolver do let_it_be_with_reload(:package) { create(:package) } let_it_be(:pipelines) { create_list(:ci_pipeline, 3, project: package.project) } - let(:user) { package.project.owner } + let(:user) { package.project.first_owner } let(:args) { {} } describe '#resolve' do subject { resolve(described_class, obj: package, args: args, ctx: { current_user: user }) } before do - package.pipelines = pipelines - package.save! + pipelines.each do |pipeline| + create(:package_build_info, package: package, pipeline: pipeline) + end end it { is_expected.to contain_exactly(*pipelines) } diff --git a/spec/graphql/resolvers/recent_boards_resolver_spec.rb b/spec/graphql/resolvers/recent_boards_resolver_spec.rb new file mode 100644 index 00000000000..1afdcd42b4f --- /dev/null +++ b/spec/graphql/resolvers/recent_boards_resolver_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Resolvers::RecentBoardsResolver do + include GraphqlHelpers + + let_it_be(:user) { create(:user) } + + shared_examples_for 'group and project recent boards resolver' do + let_it_be(:board1) { create(:board, name: 'One', resource_parent: board_parent) } + let_it_be(:board2) { create(:board, name: 'Two', resource_parent: board_parent) } + + before do + [board1, board2].each { |board| visit_board(board, board_parent) } + end + + it 'calls ::Boards::VisitsFinder' do + expect_any_instance_of(::Boards::VisitsFinder) do |finder| + expect(finder).to receive(:latest) + end + + resolve_recent_boards + end + + it 'avoids N+1 queries' do + control = ActiveRecord::QueryRecorder.new { resolve_recent_boards } + + board3 = create(:board, resource_parent: board_parent) + visit_board(board3, board_parent) + + expect { resolve_recent_boards(args: {}) }.not_to exceed_query_limit(control) + end + + it 'returns most recent visited boards' do + expect(resolve_recent_boards).to match_array [board2, board1] + end + + it 'returns a set number of boards' do + stub_const('Board::RECENT_BOARDS_SIZE', 1) + + expect(resolve_recent_boards).to match_array [board2] + end + end + + describe '#resolve' do + context 'when there is no parent' do + let_it_be(:board_parent) { nil } + + it 'returns none if parent is nil' do + expect(resolve_recent_boards).to eq(Board.none) + end + end + + context 'when project boards' do + let_it_be(:board_parent) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) } + + it_behaves_like 'group and project recent boards resolver' + end + + context 'when group boards' do + let_it_be(:board_parent) { create(:group) } + + it_behaves_like 'group and project recent boards resolver' + end + end + + def resolve_recent_boards(args: {}) + resolve(described_class, obj: board_parent, args: args, ctx: { current_user: user }) + end + + def visit_board(board, parent) + if parent.is_a?(Group) + create(:board_group_recent_visit, group: parent, board: board, user: user) + else + create(:board_project_recent_visit, project: parent, board: board, user: user) + end + end +end |