diff options
Diffstat (limited to 'spec/requests/api/graphql')
63 files changed, 517 insertions, 121 deletions
diff --git a/spec/requests/api/graphql/boards/board_lists_query_spec.rb b/spec/requests/api/graphql/boards/board_lists_query_spec.rb index cd94ce91071..2d52cddcacc 100644 --- a/spec/requests/api/graphql/boards/board_lists_query_spec.rb +++ b/spec/requests/api/graphql/boards/board_lists_query_spec.rb @@ -66,6 +66,7 @@ RSpec.describe 'get board lists' do describe 'sorting and pagination' do let_it_be(:current_user) { user } + let(:data_path) { [board_parent_type, :boards, :nodes, 0, :lists] } def pagination_query(params) diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb index 3fb89d6e815..10f05efa1b8 100644 --- a/spec/requests/api/graphql/ci/jobs_spec.rb +++ b/spec/requests/api/graphql/ci/jobs_spec.rb @@ -38,9 +38,15 @@ RSpec.describe 'Query.project.pipeline' do name groups { nodes { + detailedStatus { + id + } name jobs { nodes { + detailedStatus { + id + } name needs { nodes { #{all_graphql_fields_for('CiBuildNeed')} } diff --git a/spec/requests/api/graphql/ci/pipelines_spec.rb b/spec/requests/api/graphql/ci/pipelines_spec.rb index f207636283f..6587061094d 100644 --- a/spec/requests/api/graphql/ci/pipelines_spec.rb +++ b/spec/requests/api/graphql/ci/pipelines_spec.rb @@ -229,6 +229,7 @@ RSpec.describe 'Query.project(fullPath).pipelines' do let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } let_it_be(:upstream_project) { create(:project, :repository, :public) } let_it_be(:upstream_pipeline) { create(:ci_pipeline, project: upstream_project, user: user) } + let(:upstream_pipelines_graphql_data) { graphql_data.dig(*%w[project pipelines nodes]).first['upstream'] } let(:query) do diff --git a/spec/requests/api/graphql/ci/runner_spec.rb b/spec/requests/api/graphql/ci/runner_spec.rb index e1f84d23209..cdd46ca4ecc 100644 --- a/spec/requests/api/graphql/ci/runner_spec.rb +++ b/spec/requests/api/graphql/ci/runner_spec.rb @@ -5,25 +5,25 @@ require 'spec_helper' RSpec.describe 'Query.runner(id)' do include GraphqlHelpers - let_it_be(:user) { create_default(:user, :admin) } + let_it_be(:user) { create(:user, :admin) } - let_it_be(:active_runner) do + let_it_be(:active_instance_runner) do create(:ci_runner, :instance, description: 'Runner 1', contacted_at: 2.hours.ago, active: true, version: 'adfe156', revision: 'a', locked: true, ip_address: '127.0.0.1', maximum_timeout: 600, access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true) end - let_it_be(:inactive_runner) do + let_it_be(:inactive_instance_runner) do create(:ci_runner, :instance, description: 'Runner 2', contacted_at: 1.day.ago, active: false, version: 'adfe157', revision: 'b', ip_address: '10.10.10.10', access_level: 1, run_untagged: true) end def get_runner(id) case id - when :active_runner - active_runner - when :inactive_runner - inactive_runner + when :active_instance_runner + active_instance_runner + when :inactive_instance_runner + inactive_instance_runner end end @@ -59,7 +59,9 @@ RSpec.describe 'Query.runner(id)' do 'accessLevel' => runner.access_level.to_s.upcase, 'runUntagged' => runner.run_untagged, 'ipAddress' => runner.ip_address, - 'runnerType' => 'INSTANCE_TYPE' + 'runnerType' => 'INSTANCE_TYPE', + 'jobCount' => 0, + 'projectCount' => nil ) expect(runner_data['tagList']).to match_array runner.tag_list end @@ -84,38 +86,113 @@ RSpec.describe 'Query.runner(id)' do end describe 'for active runner' do - it_behaves_like 'runner details fetch', :active_runner + it_behaves_like 'runner details fetch', :active_instance_runner + + context 'when tagList is not requested' do + let(:query) do + wrap_fields(query_graphql_path(query_path, 'id')) + end + + let(:query_path) do + [ + [:runner, { id: active_instance_runner.to_global_id.to_s }] + ] + end + + it 'does not retrieve tagList' do + post_graphql(query, current_user: user) + + runner_data = graphql_data_at(:runner) + expect(runner_data).not_to be_nil + expect(runner_data).not_to include('tagList') + end + end end describe 'for inactive runner' do - it_behaves_like 'runner details fetch', :inactive_runner + it_behaves_like 'runner details fetch', :inactive_instance_runner + end + + describe 'for multiple runners' do + let_it_be(:project1) { create(:project, :test_repo) } + let_it_be(:project2) { create(:project, :test_repo) } + let_it_be(:project_runner1) { create(:ci_runner, :project, projects: [project1, project2], description: 'Runner 1') } + let_it_be(:project_runner2) { create(:ci_runner, :project, projects: [], description: 'Runner 2') } + + let!(:job) { create(:ci_build, runner: project_runner1) } + + context 'requesting project and job counts' do + let(:query) do + %( + query { + projectRunner1: runner(id: "#{project_runner1.to_global_id}") { + projectCount + jobCount + } + projectRunner2: runner(id: "#{project_runner2.to_global_id}") { + projectCount + jobCount + } + activeInstanceRunner: runner(id: "#{active_instance_runner.to_global_id}") { + projectCount + jobCount + } + } + ) + end + + before do + project_runner2.projects.clear + + post_graphql(query, current_user: user) + end + + it 'retrieves expected fields' do + runner1_data = graphql_data_at(:project_runner1) + runner2_data = graphql_data_at(:project_runner2) + runner3_data = graphql_data_at(:active_instance_runner) + + expect(runner1_data).to match a_hash_including( + 'jobCount' => 1, + 'projectCount' => 2) + expect(runner2_data).to match a_hash_including( + 'jobCount' => 0, + 'projectCount' => 0) + expect(runner3_data).to match a_hash_including( + 'jobCount' => 0, + 'projectCount' => nil) + end + end end describe 'by regular user' do - let(:user) { create_default(:user) } + let(:user) { create(:user) } - it_behaves_like 'retrieval by unauthorized user', :active_runner + it_behaves_like 'retrieval by unauthorized user', :active_instance_runner end describe 'by unauthenticated user' do let(:user) { nil } - it_behaves_like 'retrieval by unauthorized user', :active_runner + it_behaves_like 'retrieval by unauthorized user', :active_instance_runner end describe 'Query limits' do def runner_query(runner) <<~SINGLE runner(id: "#{runner.to_global_id}") { - #{all_graphql_fields_for('CiRunner')} + #{all_graphql_fields_for('CiRunner', excluded: excluded_fields)} } SINGLE end + # Currently excluding a known N+1 issue, see https://gitlab.com/gitlab-org/gitlab/-/issues/334759 + let(:excluded_fields) { %w[jobCount] } + let(:single_query) do <<~QUERY { - active: #{runner_query(active_runner)} + active: #{runner_query(active_instance_runner)} } QUERY end @@ -123,8 +200,8 @@ RSpec.describe 'Query.runner(id)' do let(:double_query) do <<~QUERY { - active: #{runner_query(active_runner)} - inactive: #{runner_query(inactive_runner)} + active: #{runner_query(active_instance_runner)} + inactive: #{runner_query(inactive_instance_runner)} } QUERY end diff --git a/spec/requests/api/graphql/current_user_todos_spec.rb b/spec/requests/api/graphql/current_user_todos_spec.rb index b657f15d0e9..7f37abba74a 100644 --- a/spec/requests/api/graphql/current_user_todos_spec.rb +++ b/spec/requests/api/graphql/current_user_todos_spec.rb @@ -10,6 +10,7 @@ RSpec.describe 'A Todoable that implements the CurrentUserTodos interface' do let_it_be(:todoable) { create(:issue, project: project) } let_it_be(:done_todo) { create(:todo, state: :done, target: todoable, user: current_user) } let_it_be(:pending_todo) { create(:todo, state: :pending, target: todoable, user: current_user) } + let(:state) { 'null' } let(:todoable_response) do diff --git a/spec/requests/api/graphql/issue_status_counts_spec.rb b/spec/requests/api/graphql/issue_status_counts_spec.rb index 3d8817c3bc5..89ecbf44b10 100644 --- a/spec/requests/api/graphql/issue_status_counts_spec.rb +++ b/spec/requests/api/graphql/issue_status_counts_spec.rb @@ -9,6 +9,7 @@ RSpec.describe 'getting Issue counts by status' do let_it_be(:issue_opened) { create(:issue, project: project) } let_it_be(:issue_closed) { create(:issue, :closed, project: project) } let_it_be(:other_project_issue) { create(:issue) } + let(:params) { {} } let(:fields) do diff --git a/spec/requests/api/graphql/metrics/dashboard_query_spec.rb b/spec/requests/api/graphql/metrics/dashboard_query_spec.rb index e01f59ee6a0..1b84acff0e2 100644 --- a/spec/requests/api/graphql/metrics/dashboard_query_spec.rb +++ b/spec/requests/api/graphql/metrics/dashboard_query_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Getting Metrics Dashboard' do include GraphqlHelpers let_it_be(:current_user) { create(:user) } + let(:project) { create(:project) } let(:environment) { create(:environment, project: project) } diff --git a/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb b/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb index b8cde32877b..1692cfbcf84 100644 --- a/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb +++ b/spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Deleting Sidekiq jobs', :clean_gitlab_redis_queues do include GraphqlHelpers let_it_be(:admin) { create(:admin) } + let(:queue) { 'authorized_projects' } let(:variables) { { user: admin.username, queue_name: queue } } diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb index cd5cefa0a9a..fcef7b4e3ec 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Setting assignees of an alert' do let_it_be(:project) { create(:project) } let_it_be(:current_user) { create(:user) } let_it_be(:alert) { create(:alert_management_alert, project: project) } + let(:input) { { assignee_usernames: [current_user.username] } } let(:mutation) do diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb index cd423d7764a..48307964345 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/todo/create_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Creating a todo for the alert' do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } + let(:alert) { create(:alert_management_alert, project: project) } let(:mutation) do diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb index ff55656a2ae..802d8d6c5a1 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/update_alert_status_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Setting the status of an alert' do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } + let(:alert) { create(:alert_management_alert, project: project) } let(:input) { { status: 'ACKNOWLEDGED' } } diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb index e594d67aab4..ff93da2153f 100644 --- a/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/create_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Creating a new HTTP Integration' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } + let(:variables) do { project_path: project.full_path, diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb index 0ef61ae0d5b..4c359d9b357 100644 --- a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/create_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Creating a new Prometheus Integration' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } + let(:variables) do { project_path: project.full_path, @@ -42,7 +43,7 @@ RSpec.describe 'Creating a new Prometheus Integration' do it 'creates a new integration' do post_graphql_mutation(mutation, current_user: current_user) - new_integration = ::PrometheusService.last! + new_integration = ::Integrations::Prometheus.last! integration_response = mutation_response['integration'] expect(response).to have_gitlab_http_status(:success) diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb index d8d0ace5981..31053c50cac 100644 --- a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Resetting a token on an existing Prometheus Integration' do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } - let_it_be(:integration) { create(:prometheus_service, project: project) } + let_it_be(:integration) { create(:prometheus_integration, project: project) } let(:mutation) do variables = { diff --git a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb index 6c4a647a353..ad26ec118d7 100644 --- a/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/prometheus_integration/update_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Updating an existing Prometheus Integration' do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } - let_it_be(:integration) { create(:prometheus_service, project: project) } + let_it_be(:integration) { create(:prometheus_integration, project: project) } let(:mutation) do variables = { diff --git a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb index b39062f2e71..fdf5503a3a2 100644 --- a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb +++ b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Adding an AwardEmoji' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } let_it_be(:awardable) { create(:note, project: project) } + let(:emoji_name) { 'thumbsup' } let(:mutation) do variables = { diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb index 170e7ff3b44..6b26e37e30c 100644 --- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb +++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Toggling an AwardEmoji' do let_it_be(:current_user) { create(:user) } let_it_be(:project, reload: true) { create(:project) } let_it_be(:awardable) { create(:note, project: project) } + let(:emoji_name) { 'thumbsup' } let(:mutation) do variables = { diff --git a/spec/requests/api/graphql/mutations/boards/create_spec.rb b/spec/requests/api/graphql/mutations/boards/create_spec.rb index c5f981262ea..22d05f36f0f 100644 --- a/spec/requests/api/graphql/mutations/boards/create_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/create_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe Mutations::Boards::Create do let_it_be(:parent) { create(:project) } + let(:project_path) { parent.full_path } let(:params) do { diff --git a/spec/requests/api/graphql/mutations/branches/create_spec.rb b/spec/requests/api/graphql/mutations/branches/create_spec.rb index fc09f57a389..6a098002963 100644 --- a/spec/requests/api/graphql/mutations/branches/create_spec.rb +++ b/spec/requests/api/graphql/mutations/branches/create_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Creation of a new branch' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project, :public, :empty_repo) } + let(:input) { { project_path: project.full_path, name: new_branch, ref: ref } } let(:new_branch) { 'new_branch' } let(:ref) { 'master' } @@ -34,11 +35,12 @@ RSpec.describe 'Creation of a new branch' do end context 'when ref is not correct' do + err_msg = 'Failed to create branch \'another_branch\': invalid reference name \'unknown\'' let(:new_branch) { 'another_branch' } let(:ref) { 'unknown' } it_behaves_like 'a mutation that returns errors in the response', - errors: ['Invalid reference name: unknown'] + errors: [err_msg] end end end diff --git a/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb b/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb index 0d7571d91ca..05f6804a208 100644 --- a/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb @@ -5,7 +5,10 @@ require 'spec_helper' RSpec.describe 'CiCdSettingsUpdate' do include GraphqlHelpers - let_it_be(:project) { create(:project, keep_latest_artifact: true, ci_job_token_scope_enabled: true) } + let_it_be(:project) do + create(:project, keep_latest_artifact: true, ci_job_token_scope_enabled: true) + .tap(&:save!) + end let(:variables) do { diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb new file mode 100644 index 00000000000..b53a7ddde32 --- /dev/null +++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_project_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'CiJobTokenScopeAddProject' do + include GraphqlHelpers + + let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) } + let_it_be(:target_project) { create(:project) } + + let(:variables) do + { + project_path: project.full_path, + target_project_path: target_project.full_path + } + end + + let(:mutation) do + graphql_mutation(:ci_job_token_scope_add_project, variables) do + <<~QL + errors + ciJobTokenScope { + projects { + nodes { + path + } + } + } + QL + end + end + + let(:mutation_response) { graphql_mutation_response(:ci_job_token_scope_add_project) } + + context 'when unauthorized' do + let(:current_user) { create(:user) } + + context 'when not a maintainer' do + before do + project.add_developer(current_user) + end + + it 'has graphql errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(graphql_errors).not_to be_empty + end + end + end + + context 'when authorized' do + let_it_be(:current_user) { project.owner } + + before do + target_project.add_developer(current_user) + end + + it 'adds the target project to the job token scope' do + expect do + post_graphql_mutation(mutation, current_user: current_user) + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response.dig('ciJobTokenScope', 'projects', 'nodes')).not_to be_empty + end.to change { Ci::JobToken::Scope.new(project).includes?(target_project) }.from(false).to(true) + end + + context 'when invalid target project is provided' do + before do + variables[:target_project_path] = 'unknown/project' + end + + it 'has mutation errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response['errors']).to contain_exactly(Ci::JobTokenScope::EditScopeValidations::TARGET_PROJECT_UNAUTHORIZED_OR_UNFOUND) + end + end + end +end diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb new file mode 100644 index 00000000000..f1f42b00ada --- /dev/null +++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/remove_project_spec.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'CiJobTokenScopeRemoveProject' do + include GraphqlHelpers + + let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) } + let_it_be(:target_project) { create(:project) } + + let_it_be(:link) do + create(:ci_job_token_project_scope_link, + source_project: project, + target_project: target_project) + end + + let(:variables) do + { + project_path: project.full_path, + target_project_path: target_project.full_path + } + end + + let(:mutation) do + graphql_mutation(:ci_job_token_scope_remove_project, variables) do + <<~QL + errors + ciJobTokenScope { + projects { + nodes { + path + } + } + } + QL + end + end + + let(:mutation_response) { graphql_mutation_response(:ci_job_token_scope_remove_project) } + + context 'when unauthorized' do + let(:current_user) { create(:user) } + + context 'when not a maintainer' do + before do + project.add_developer(current_user) + end + + it 'has graphql errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(graphql_errors).not_to be_empty + end + end + end + + context 'when authorized' do + let_it_be(:current_user) { project.owner } + + before do + target_project.add_guest(current_user) + end + + it 'removes the target project from the job token scope' do + expect do + post_graphql_mutation(mutation, current_user: current_user) + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response.dig('ciJobTokenScope', 'projects', 'nodes')).not_to be_empty + end.to change { Ci::JobToken::Scope.new(project).includes?(target_project) }.from(true).to(false) + end + + context 'when invalid target project is provided' do + before do + variables[:target_project_path] = 'unknown/project' + end + + it 'has mutation errors' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response['errors']).to contain_exactly(Ci::JobTokenScope::EditScopeValidations::TARGET_PROJECT_UNAUTHORIZED_OR_UNFOUND) + end + end + end +end diff --git a/spec/requests/api/graphql/mutations/commits/create_spec.rb b/spec/requests/api/graphql/mutations/commits/create_spec.rb index 375d4f10b40..619cba99c4e 100644 --- a/spec/requests/api/graphql/mutations/commits/create_spec.rb +++ b/spec/requests/api/graphql/mutations/commits/create_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Creation of a new commit' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project, :public, :repository) } + let(:input) { { project_path: project.full_path, branch: branch, message: message, actions: actions } } let(:branch) { 'master' } let(:message) { 'Commit message' } diff --git a/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb b/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb index 23e8e366483..0156142dc6f 100644 --- a/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb +++ b/spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb @@ -53,6 +53,7 @@ RSpec.describe 'Updating the container expiration policy' do RSpec.shared_examples 'rejecting invalid regex for' do |field_name| context "for field #{field_name}" do let_it_be(:invalid_regex) { '*production' } + let(:params) do { :project_path => project.full_path, diff --git a/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb b/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb index 450996bf76b..632a934cd95 100644 --- a/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb +++ b/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Toggling the resolve status of a discussion' do let_it_be(:project) { create(:project, :public, :repository) } let_it_be(:noteable) { create(:merge_request, source_project: project) } + let(:discussion) do create(:diff_note_on_merge_request, noteable: noteable, project: project).to_discussion end diff --git a/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb b/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb index f25a49291a6..3771ae0746e 100644 --- a/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb +++ b/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb @@ -13,6 +13,7 @@ RSpec.describe 'Update Environment Canary Ingress', :clean_gitlab_redis_cache do let_it_be(:deployment) { create(:deployment, :success, environment: environment, project: project) } let_it_be(:maintainer) { create(:user) } let_it_be(:developer) { create(:user) } + let(:environment_id) { environment.to_global_id.to_s } let(:weight) { 25 } let(:actor) { developer } diff --git a/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb b/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb index 4989d096925..435ed0f9eb2 100644 --- a/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Setting an issue as locked' do let_it_be(:current_user) { create(:user) } let_it_be(:issue) { create(:issue) } let_it_be(:project) { issue.project } + let(:input) { { locked: true } } let(:mutation) do diff --git a/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb index 96fd2368765..41997f151a2 100644 --- a/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Setting severity level of an incident' do include GraphqlHelpers let_it_be(:user) { create(:user) } + let(:incident) { create(:incident) } let(:project) { incident.project } let(:input) { { severity: 'CRITICAL' } } diff --git a/spec/requests/api/graphql/mutations/issues/update_spec.rb b/spec/requests/api/graphql/mutations/issues/update_spec.rb index adfa2a2bc08..b3e1ab62e54 100644 --- a/spec/requests/api/graphql/mutations/issues/update_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/update_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Update of an existing issue' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project, :public) } let_it_be(:issue) { create(:issue, project: project) } + let(:input) do { 'iid' => issue.iid.to_s, diff --git a/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb b/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb index 00b93984f98..45cc70f09fd 100644 --- a/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb +++ b/spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Importing Jira Users' do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } + let(:importer) { instance_double(JiraImport::UsersImporter) } let(:project_path) { project.full_path } let(:start_at) { 7 } diff --git a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb index e7124512ef1..b14305281af 100644 --- a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb +++ b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Starting a Jira Import' do let_it_be(:user) { create(:user) } let_it_be(:project, reload: true) { create(:project) } + let(:jira_project_key) { 'AA' } let(:project_path) { project.full_path } @@ -80,17 +81,17 @@ RSpec.describe 'Starting a Jira Import' do end end - context 'when project has no Jira service' do + context 'when project has no Jira integration' do it_behaves_like 'a mutation that returns errors in the response', errors: ['Jira integration not configured.'] end - context 'when when project has Jira service' do - let!(:service) { create(:jira_service, project: project) } + context 'when when project has Jira integration' do + let!(:service) { create(:jira_integration, project: project) } before do project.reload - stub_jira_service_test + stub_jira_integration_test end context 'when issues feature are disabled' do diff --git a/spec/requests/api/graphql/mutations/labels/create_spec.rb b/spec/requests/api/graphql/mutations/labels/create_spec.rb index 28284408306..d19411f6c1d 100644 --- a/spec/requests/api/graphql/mutations/labels/create_spec.rb +++ b/spec/requests/api/graphql/mutations/labels/create_spec.rb @@ -61,6 +61,7 @@ RSpec.describe Mutations::Labels::Create do context 'when creating a project label' do let_it_be(:parent) { create(:project) } + let(:extra_params) { { project_path: parent.full_path } } it_behaves_like 'labels create mutation' @@ -68,6 +69,7 @@ RSpec.describe Mutations::Labels::Create do context 'when creating a group label' do let_it_be(:parent) { create(:group) } + let(:extra_params) { { group_path: parent.full_path } } it_behaves_like 'labels create mutation' diff --git a/spec/requests/api/graphql/mutations/merge_requests/accept_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/accept_spec.rb index 2725b33d528..19a7c72ba80 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/accept_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/accept_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'accepting a merge request', :request_store do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project, :public, :repository) } + let!(:merge_request) { create(:merge_request, source_project: project) } let(:input) do { diff --git a/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb index bf759521dc0..3a4508489a1 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Creation of a new merge request' do include GraphqlHelpers let_it_be(:current_user) { create(:user) } + let(:project) { create(:project, :public, :repository) } let(:input) do { diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb index a63116e2b94..dec9afd1310 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/set_assignees_spec.rb @@ -68,7 +68,7 @@ RSpec.describe 'Setting assignees of a merge request', :assume_throttled do context 'when the current user does not have permission to add assignees' do let(:current_user) { create(:user) } - let(:db_query_limit) { 28 } + let(:db_query_limit) { 27 } it 'does not change the assignees' do project.add_guest(current_user) @@ -80,7 +80,7 @@ RSpec.describe 'Setting assignees of a merge request', :assume_throttled do end context 'with assignees already assigned' do - let(:db_query_limit) { 46 } + let(:db_query_limit) { 39 } before do merge_request.assignees = [assignee2] @@ -96,7 +96,7 @@ RSpec.describe 'Setting assignees of a merge request', :assume_throttled do end context 'when passing an empty list of assignees' do - let(:db_query_limit) { 32 } + let(:db_query_limit) { 31 } let(:input) { { assignee_usernames: [] } } before do @@ -115,7 +115,7 @@ RSpec.describe 'Setting assignees of a merge request', :assume_throttled do context 'when passing append as true' do let(:mode) { Types::MutationOperationModeEnum.enum[:append] } let(:input) { { assignee_usernames: [assignee2.username], operation_mode: mode } } - let(:db_query_limit) { 22 } + let(:db_query_limit) { 21 } before do # In CE, APPEND is a NOOP as you can't have multiple assignees @@ -135,7 +135,7 @@ RSpec.describe 'Setting assignees of a merge request', :assume_throttled do end context 'when passing remove as true' do - let(:db_query_limit) { 32 } + let(:db_query_limit) { 31 } let(:mode) { Types::MutationOperationModeEnum.enum[:remove] } let(:input) { { assignee_usernames: [assignee.username], operation_mode: mode } } let(:expected_result) { [] } diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb index 2a39757e103..5bc3c68cf26 100644 --- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb +++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb @@ -9,6 +9,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create do let_it_be(:project) { create(:project, :private, :repository) } let_it_be(:environment) { create(:environment, project: project) } let_it_be(:cluster) { create(:cluster, projects: [project]) } + let(:dashboard_path) { 'config/prometheus/common_metrics.yml' } let(:starting_at) { Time.current.iso8601 } let(:ending_at) { 1.hour.from_now.iso8601 } diff --git a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb index 202e7e7c333..d335642d321 100644 --- a/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb +++ b/spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb @@ -126,6 +126,7 @@ RSpec.describe 'Updating the package settings' do context 'without existing package settings' do let_it_be(:namespace, reload: true) { create(:group) } + let(:package_settings) { namespace.package_settings } where(:user_role, :shared_examples_name) do diff --git a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb index b5aaf304812..8f3ae9f26f6 100644 --- a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Adding a DiffNote' do include GraphqlHelpers let_it_be(:current_user) { create(:user) } + let(:noteable) { create(:merge_request, source_project: project, target_project: project) } let(:project) { create(:project, :repository) } let(:diff_refs) { noteable.diff_refs } diff --git a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb index 0e5744fb64f..8f2438cb741 100644 --- a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Adding an image DiffNote' do include GraphqlHelpers let_it_be(:current_user) { create(:user) } + let(:noteable) { create(:merge_request, source_project: project, target_project: project) } let(:project) { create(:project, :repository) } let(:diff_refs) { noteable.diff_refs } diff --git a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb index 8dd8ed361ba..87c752393ea 100644 --- a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Adding a Note' do include GraphqlHelpers let_it_be(:current_user) { create(:user) } + let(:noteable) { create(:merge_request, source_project: project, target_project: project) } let(:project) { create(:project) } let(:discussion) { nil } diff --git a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb index 4efa7f9d509..89e3a71280f 100644 --- a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Repositioning an ImageDiffNote' do let_it_be(:noteable) { create(:merge_request) } let_it_be(:project) { noteable.project } + let(:note) { create(:image_diff_note_on_merge_request, noteable: noteable, project: project) } let(:new_position) { { x: 10 } } let(:current_user) { project.creator } diff --git a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb index 1ce09881fde..cfd0b34b815 100644 --- a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb @@ -26,6 +26,7 @@ RSpec.describe 'Updating an image DiffNote' do let_it_be(:updated_height) { 100 } let_it_be(:updated_x) { 5 } let_it_be(:updated_y) { 10 } + let(:updated_position) do { width: updated_width, diff --git a/spec/requests/api/graphql/mutations/packages/destroy_spec.rb b/spec/requests/api/graphql/mutations/packages/destroy_spec.rb new file mode 100644 index 00000000000..e5ced419ecf --- /dev/null +++ b/spec/requests/api/graphql/mutations/packages/destroy_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Destroying a package' do + using RSpec::Parameterized::TableSyntax + + include GraphqlHelpers + + let_it_be_with_reload(:package) { create(:package) } + let_it_be(:user) { create(:user) } + + let(:project) { package.project } + let(:id) { package.to_global_id.to_s } + + let(:query) do + <<~GQL + errors + GQL + end + + let(:params) { { id: id } } + let(:mutation) { graphql_mutation(:destroy_package, params, query) } + let(:mutation_response) { graphql_mutation_response(:destroyPackage) } + + shared_examples 'destroying the package' do + it 'destroy the package' do + expect(::Packages::DestroyPackageService) + .to receive(:new).with(container: package, current_user: user).and_call_original + + expect { mutation_request }.to change { ::Packages::Package.count }.by(-1) + end + + it_behaves_like 'returning response status', :success + end + + shared_examples 'denying the mutation request' do + it 'does not destroy the package' do + expect(::Packages::DestroyPackageService) + .not_to receive(:new).with(container: package, current_user: user) + + expect { mutation_request }.not_to change { ::Packages::Package.count } + + expect(mutation_response).to be_nil + end + + it_behaves_like 'returning response status', :success + end + + describe 'post graphql mutation' do + subject(:mutation_request) { post_graphql_mutation(mutation, current_user: user) } + + context 'with valid id' do + where(:user_role, :shared_examples_name) do + :maintainer | 'destroying the package' + :developer | 'denying the mutation request' + :reporter | 'denying the mutation request' + :guest | 'denying the mutation request' + :anonymous | 'denying the mutation request' + end + + with_them do + before do + project.send("add_#{user_role}", user) unless user_role == :anonymous + end + + it_behaves_like params[:shared_examples_name] + end + end + + context 'with invalid id' do + let(:params) { { id: 'gid://gitlab/Packages::Package/5555' } } + + it_behaves_like 'denying the mutation request' + end + + context 'when an error occures' do + before do + project.add_maintainer(user) + end + + it 'returns the errors in the response' do + allow_next_found_instance_of(::Packages::Package) do |package| + allow(package).to receive(:destroy!).and_raise(StandardError) + end + + mutation_request + + expect(mutation_response['errors']).to eq(['Failed to remove the package']) + end + end + end +end diff --git a/spec/requests/api/graphql/mutations/releases/delete_spec.rb b/spec/requests/api/graphql/mutations/releases/delete_spec.rb index 3710f118bf4..40063156609 100644 --- a/spec/requests/api/graphql/mutations/releases/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/releases/delete_spec.rb @@ -55,7 +55,7 @@ RSpec.describe 'Deleting a release' do end context 'when the current user has access to update releases' do - let(:current_user) { maintainer } + let(:current_user) { developer } it 'deletes the release' do expect { delete_release }.to change { Release.count }.by(-1) @@ -105,12 +105,6 @@ RSpec.describe 'Deleting a release' do end context "when the current user doesn't have access to update releases" do - context 'when the current user is a Developer' do - let(:current_user) { developer } - - it_behaves_like 'unauthorized or not found error' - end - context 'when the current user is a Reporter' do let(:current_user) { reporter } diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb index 214c804c519..9a3cea3ca14 100644 --- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb @@ -17,7 +17,6 @@ RSpec.describe 'Creating a Snippet' do let(:actions) { [{ action: action }.merge(file_1), { action: action }.merge(file_2)] } let(:project_path) { nil } let(:uploaded_files) { nil } - let(:spam_mutation_vars) { {} } let(:mutation_vars) do { description: description, @@ -26,7 +25,7 @@ RSpec.describe 'Creating a Snippet' do project_path: project_path, uploaded_files: uploaded_files, blob_actions: actions - }.merge(spam_mutation_vars) + } end let(:mutation) do @@ -77,21 +76,6 @@ RSpec.describe 'Creating a Snippet' do expect(mutation_response['snippet']).to be_nil end - - context 'when snippet_spam flag is disabled' do - before do - stub_feature_flags(snippet_spam: false) - end - - it 'passes disable_spam_action_service param to service' do - expect(::Snippets::CreateService) - .to receive(:new) - .with(project: anything, current_user: anything, params: hash_including(disable_spam_action_service: true)) - .and_call_original - - subject - end - end end shared_examples 'creates snippet' do @@ -101,8 +85,8 @@ RSpec.describe 'Creating a Snippet' do end.to change { Snippet.count }.by(1) snippet = Snippet.last - created_file_1 = snippet.repository.blob_at('HEAD', file_1[:filePath]) - created_file_2 = snippet.repository.blob_at('HEAD', file_2[:filePath]) + created_file_1 = snippet.repository.blob_at(snippet.default_branch, file_1[:filePath]) + created_file_2 = snippet.repository.blob_at(snippet.default_branch, file_2[:filePath]) expect(created_file_1.data).to match(file_1[:content]) expect(created_file_2.data).to match(file_2[:content]) @@ -121,15 +105,6 @@ RSpec.describe 'Creating a Snippet' do it_behaves_like 'snippet edit usage data counters' it_behaves_like 'a mutation which can mutate a spammable' do - let(:captcha_response) { 'abc123' } - let(:spam_log_id) { 1234 } - let(:spam_mutation_vars) do - { - captcha_response: captcha_response, - spam_log_id: spam_log_id - } - end - let(:service) { Snippets::CreateService } end end @@ -190,7 +165,7 @@ RSpec.describe 'Creating a Snippet' do it do expect(::Snippets::CreateService).to receive(:new) - .with(project: nil, current_user: user, params: hash_including(files: expected_value)) + .with(project: nil, current_user: user, params: hash_including(files: expected_value), spam_params: instance_of(::Spam::SpamParams)) .and_return(double(execute: creation_response)) subject diff --git a/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb b/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb index 4d499310591..43d846cb297 100644 --- a/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/mark_as_spam_spec.rb @@ -10,6 +10,7 @@ RSpec.describe 'Mark snippet as spam' do let_it_be(:other_user) { create(:user) } let_it_be(:snippet) { create(:personal_snippet) } let_it_be(:user_agent_detail) { create(:user_agent_detail, subject: snippet) } + let(:current_user) { snippet.author } let(:snippet_gid) { snippet.to_global_id.to_s } diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb index 77efb786dcb..eb7e6f840fe 100644 --- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb @@ -9,6 +9,7 @@ RSpec.describe 'Updating a Snippet' do let_it_be(:original_description) { 'Initial description' } let_it_be(:original_title) { 'Initial title' } let_it_be(:original_file_name) { 'Initial file_name' } + let(:updated_content) { 'Updated content' } let(:updated_description) { 'Updated description' } let(:updated_title) { 'Updated_title' } @@ -16,7 +17,6 @@ RSpec.describe 'Updating a Snippet' do let(:updated_file) { 'CHANGELOG' } let(:deleted_file) { 'README' } let(:snippet_gid) { GitlabSchema.id_from_object(snippet).to_s } - let(:spam_mutation_vars) { {} } let(:mutation_vars) do { id: snippet_gid, @@ -27,7 +27,7 @@ RSpec.describe 'Updating a Snippet' do { action: :update, filePath: updated_file, content: updated_content }, { action: :delete, filePath: deleted_file } ] - }.merge(spam_mutation_vars) + } end let(:mutation) do @@ -82,21 +82,6 @@ RSpec.describe 'Updating a Snippet' do end end - context 'when snippet_spam flag is disabled' do - before do - stub_feature_flags(snippet_spam: false) - end - - it 'passes disable_spam_action_service param to service' do - expect(::Snippets::UpdateService) - .to receive(:new) - .with(project: anything, current_user: anything, params: hash_including(disable_spam_action_service: true)) - .and_call_original - - subject - end - end - context 'when there are ActiveRecord validation errors' do let(:updated_title) { '' } @@ -125,15 +110,6 @@ RSpec.describe 'Updating a Snippet' do end it_behaves_like 'a mutation which can mutate a spammable' do - let(:captcha_response) { 'abc123' } - let(:spam_log_id) { 1234 } - let(:spam_mutation_vars) do - { - captcha_response: captcha_response, - spam_log_id: spam_log_id - } - end - let(:service) { Snippets::UpdateService } end @@ -164,6 +140,7 @@ RSpec.describe 'Updating a Snippet' do describe 'ProjectSnippet' do let_it_be(:project) { create(:project, :private) } + let(:snippet) do create(:project_snippet, :private, diff --git a/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb b/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb index cb67a60ebe4..716983f01d2 100644 --- a/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb +++ b/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Create a user callout' do include GraphqlHelpers let_it_be(:current_user) { create(:user) } + let(:feature_name) { ::UserCallout.feature_names.each_key.first } let(:input) do diff --git a/spec/requests/api/graphql/namespace/package_settings_spec.rb b/spec/requests/api/graphql/namespace/package_settings_spec.rb index 6af098e902f..42fd07dbdc7 100644 --- a/spec/requests/api/graphql/namespace/package_settings_spec.rb +++ b/spec/requests/api/graphql/namespace/package_settings_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'getting namespace package settings in a namespace' do let_it_be(:package_settings) { create(:namespace_package_setting) } let_it_be(:namespace) { package_settings.namespace } let_it_be(:current_user) { namespace.owner } + let(:package_settings_response) { graphql_data.dig('namespace', 'packageSettings') } let(:fields) { all_graphql_fields_for('PackageSettings') } diff --git a/spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb index 9724de4fedb..05a98a9dd9c 100644 --- a/spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'getting Alert Management Alert Issue' do let_it_be(:project) { create(:project) } let_it_be(:current_user) { create(:user) } + let(:payload) { {} } let(:query) { 'avg(metric) > 1.0' } diff --git a/spec/requests/api/graphql/project/alert_management/alert_status_counts_spec.rb b/spec/requests/api/graphql/project/alert_management/alert_status_counts_spec.rb index 9fbf5aaa41f..ecd93d169d3 100644 --- a/spec/requests/api/graphql/project/alert_management/alert_status_counts_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/alert_status_counts_spec.rb @@ -9,6 +9,7 @@ RSpec.describe 'getting Alert Management Alert counts by status' do let_it_be(:alert_resolved) { create(:alert_management_alert, :resolved, project: project) } let_it_be(:alert_triggered) { create(:alert_management_alert, project: project) } let_it_be(:other_project_alert) { create(:alert_management_alert) } + let(:params) { {} } let(:fields) do diff --git a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb index 0e029aee9e8..1793d4961eb 100644 --- a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'getting Alert Management Integrations' do let_it_be(:project) { create(:project, :repository) } let_it_be(:current_user) { create(:user) } - let_it_be(:prometheus_service) { create(:prometheus_service, project: project) } + let_it_be(:prometheus_integration) { create(:prometheus_integration, project: project) } let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) } let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) } let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) } @@ -53,15 +53,15 @@ RSpec.describe 'getting Alert Management Integrations' do end context 'when no extra params given' do - let(:http_integration) { integrations.first } - let(:prometheus_integration) { integrations.second } + let(:http_integration_response) { integrations.first } + let(:prometheus_integration_response) { integrations.second } it_behaves_like 'a working graphql query' it { expect(integrations.size).to eq(2) } it 'returns the correct properties of the integrations' do - expect(http_integration).to include( + expect(http_integration_response).to include( 'id' => global_id_of(active_http_integration), 'type' => 'HTTP', 'name' => active_http_integration.name, @@ -71,14 +71,14 @@ RSpec.describe 'getting Alert Management Integrations' do 'apiUrl' => nil ) - expect(prometheus_integration).to include( - 'id' => global_id_of(prometheus_service), + expect(prometheus_integration_response).to include( + 'id' => global_id_of(prometheus_integration), 'type' => 'PROMETHEUS', 'name' => 'Prometheus', - 'active' => prometheus_service.manual_configuration?, + 'active' => prometheus_integration.manual_configuration?, 'token' => project_alerting_setting.token, 'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json", - 'apiUrl' => prometheus_service.api_url + 'apiUrl' => prometheus_integration.api_url ) end end @@ -104,7 +104,7 @@ RSpec.describe 'getting Alert Management Integrations' do end context 'when Prometheus Integration ID is given' do - let(:params) { { id: global_id_of(prometheus_service) } } + let(:params) { { id: global_id_of(prometheus_integration) } } it_behaves_like 'a working graphql query' @@ -112,13 +112,13 @@ RSpec.describe 'getting Alert Management Integrations' do it 'returns the correct properties of the Prometheus Integration' do expect(integrations.first).to include( - 'id' => global_id_of(prometheus_service), + 'id' => global_id_of(prometheus_integration), 'type' => 'PROMETHEUS', 'name' => 'Prometheus', - 'active' => prometheus_service.manual_configuration?, + 'active' => prometheus_integration.manual_configuration?, 'token' => project_alerting_setting.token, 'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json", - 'apiUrl' => prometheus_service.api_url + 'apiUrl' => prometheus_integration.api_url ) end end diff --git a/spec/requests/api/graphql/project/base_service_spec.rb b/spec/requests/api/graphql/project/base_service_spec.rb index af462c4a639..5dc0f55db88 100644 --- a/spec/requests/api/graphql/project/base_service_spec.rb +++ b/spec/requests/api/graphql/project/base_service_spec.rb @@ -7,9 +7,9 @@ RSpec.describe 'query Jira service' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } - let_it_be(:jira_service) { create(:jira_service, project: project) } + let_it_be(:jira_integration) { create(:jira_integration, project: project) } let_it_be(:bugzilla_integration) { create(:bugzilla_integration, project: project) } - let_it_be(:redmine_service) { create(:redmine_service, project: project) } + let_it_be(:redmine_integration) { create(:redmine_integration, project: project) } let(:query) do %( diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb index b2b42137acf..14fabaaf032 100644 --- a/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb +++ b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'getting a detailed sentry error' do let_it_be(:project_setting) { create(:project_error_tracking_setting, project: project) } let_it_be(:current_user) { project.owner } let_it_be(:sentry_detailed_error) { build(:detailed_error_tracking_error) } + let(:sentry_gid) { sentry_detailed_error.to_global_id.to_s } let(:fields) do <<~QUERY diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb index c7d327a62af..e71e5a48ddc 100644 --- a/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb +++ b/spec/requests/api/graphql/project/error_tracking/sentry_errors_request_spec.rb @@ -17,6 +17,7 @@ RSpec.describe 'sentry errors requests' do describe 'getting a detailed sentry error' do let_it_be(:sentry_detailed_error) { build(:detailed_error_tracking_error) } + let(:sentry_gid) { sentry_detailed_error.to_global_id.to_s } let(:detailed_fields) do @@ -193,6 +194,7 @@ RSpec.describe 'sentry errors requests' do describe 'getting a stack trace' do let_it_be(:sentry_stack_trace) { build(:error_tracking_error_event) } + let(:sentry_gid) { global_id_of(Gitlab::ErrorTracking::DetailedError.new(id: 1)) } let(:stack_trace_fields) do diff --git a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb index decab900a43..def41efddde 100644 --- a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb +++ b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Getting designs related to an issue' do let_it_be(:design) { create(:design, :with_smaller_image_versions, versions_count: 1) } let_it_be(:current_user) { design.project.owner } + let(:design_query) do <<~NODE designs { @@ -124,6 +125,7 @@ RSpec.describe 'Getting designs related to an issue' do context 'with versions' do let_it_be(:version) { design.versions.take } + let(:design_query) do <<~NODE designs { @@ -165,6 +167,7 @@ RSpec.describe 'Getting designs related to an issue' do let_it_be(:issue) { design.issue } let_it_be(:second_design, reload: true) { create(:design, :with_smaller_image_versions, issue: issue, versions_count: 1) } let_it_be(:deleted_design) { create(:design, :with_versions, issue: issue, deleted: true, versions_count: 1) } + let(:all_versions) { issue.design_versions.ordered.reverse } let(:design_query) do <<~NODE diff --git a/spec/requests/api/graphql/project/jira_service_spec.rb b/spec/requests/api/graphql/project/jira_service_spec.rb index 905a669bf0d..64e9e04ae44 100644 --- a/spec/requests/api/graphql/project/jira_service_spec.rb +++ b/spec/requests/api/graphql/project/jira_service_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'query Jira service' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } - let_it_be(:jira_service) { create(:jira_service, project: project) } + let_it_be(:jira_integration) { create(:jira_integration, project: project) } let(:query) do %( diff --git a/spec/requests/api/graphql/project/pipeline_spec.rb b/spec/requests/api/graphql/project/pipeline_spec.rb index 0a5bcc7a965..cb6755640a9 100644 --- a/spec/requests/api/graphql/project/pipeline_spec.rb +++ b/spec/requests/api/graphql/project/pipeline_spec.rb @@ -8,9 +8,9 @@ RSpec.describe 'getting pipeline information nested in a project' do let_it_be(:project) { create(:project, :repository, :public) } let_it_be(:pipeline) { create(:ci_pipeline, project: project) } let_it_be(:current_user) { create(:user) } - let_it_be(:build_job) { create(:ci_build, :trace_with_sections, name: 'build-a', pipeline: pipeline) } - let_it_be(:failed_build) { create(:ci_build, :failed, name: 'failed-build', pipeline: pipeline) } - let_it_be(:bridge) { create(:ci_bridge, name: 'ci-bridge-example', pipeline: pipeline) } + let_it_be(:build_job) { create(:ci_build, :trace_with_sections, name: 'build-a', pipeline: pipeline, stage_idx: 0, stage: 'build') } + let_it_be(:failed_build) { create(:ci_build, :failed, name: 'failed-build', pipeline: pipeline, stage_idx: 0, stage: 'build') } + let_it_be(:bridge) { create(:ci_bridge, name: 'ci-bridge-example', pipeline: pipeline, stage_idx: 0, stage: 'build') } let(:path) { %i[project pipeline] } let(:pipeline_graphql_data) { graphql_data_at(*path) } @@ -79,16 +79,6 @@ RSpec.describe 'getting pipeline information nested in a project' do end end - private - - def build_query_to_find_pipeline_shas(*pipelines) - pipeline_fields = pipelines.map.each_with_index do |pipeline, idx| - "pipeline#{idx}: pipeline(iid: \"#{pipeline.iid}\") { sha }" - end.join(' ') - - graphql_query_for('project', { 'fullPath' => project.full_path }, pipeline_fields) - end - context 'when enough data is requested' do let(:fields) do query_graphql_field(:jobs, nil, @@ -282,4 +272,69 @@ RSpec.describe 'getting pipeline information nested in a project' do end end end + + context 'N+1 queries on stages jobs' do + let(:depth) { 5 } + let(:fields) do + <<~FIELDS + stages { + nodes { + name + groups { + nodes { + name + jobs { + nodes { + name + needs { + nodes { + name + } + } + status: detailedStatus { + tooltip + hasDetails + detailsPath + action { + buttonTitle + path + title + } + } + } + } + } + } + } + } + FIELDS + end + + it 'does not generate N+1 queries', :request_store, :use_sql_query_cache do + # warm up + post_graphql(query, current_user: current_user) + + control = ActiveRecord::QueryRecorder.new(skip_cached: false) do + post_graphql(query, current_user: current_user) + end + + create(:ci_build, name: 'test-a', pipeline: pipeline, stage_idx: 1, stage: 'test') + create(:ci_build, name: 'test-b', pipeline: pipeline, stage_idx: 1, stage: 'test') + create(:ci_build, name: 'deploy-a', pipeline: pipeline, stage_idx: 2, stage: 'deploy') + + expect do + post_graphql(query, current_user: current_user) + end.not_to exceed_all_query_limit(control) + end + end + + private + + def build_query_to_find_pipeline_shas(*pipelines) + pipeline_fields = pipelines.map.each_with_index do |pipeline, idx| + "pipeline#{idx}: pipeline(iid: \"#{pipeline.iid}\") { sha }" + end.join(' ') + + graphql_query_for('project', { 'fullPath' => project.full_path }, pipeline_fields) + end end diff --git a/spec/requests/api/graphql/project/project_pipeline_statistics_spec.rb b/spec/requests/api/graphql/project/project_pipeline_statistics_spec.rb index 7d157563f5f..39a68d98d84 100644 --- a/spec/requests/api/graphql/project/project_pipeline_statistics_spec.rb +++ b/spec/requests/api/graphql/project/project_pipeline_statistics_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'rendering project pipeline statistics' do include GraphqlHelpers let_it_be(:project) { create(:project) } + let(:user) { create(:user) } let(:fields) do diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb index 54375d4de1d..e44a7efb354 100644 --- a/spec/requests/api/graphql/project_query_spec.rb +++ b/spec/requests/api/graphql/project_query_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'getting project information' do let_it_be(:group) { create(:group) } let_it_be(:project, reload: true) { create(:project, :repository, group: group) } let_it_be(:current_user) { create(:user) } + let(:project_fields) { all_graphql_fields_for('project'.to_s.classify, max_depth: 1) } let(:query) do diff --git a/spec/requests/api/graphql/query_spec.rb b/spec/requests/api/graphql/query_spec.rb index 6bd0703c121..ecc7fffaef7 100644 --- a/spec/requests/api/graphql/query_spec.rb +++ b/spec/requests/api/graphql/query_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Query' do let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:issue, project: project) } let_it_be(:developer) { create(:user) } + let(:current_user) { developer } describe '.designManagement' do @@ -15,6 +16,7 @@ RSpec.describe 'Query' do let_it_be(:version) { create(:design_version, issue: issue) } let_it_be(:design) { version.designs.first } + let(:query_result) { graphql_data.dig(*path) } let(:query) { graphql_query_for(:design_management, nil, dm_fields) } diff --git a/spec/requests/api/graphql/user/starred_projects_query_spec.rb b/spec/requests/api/graphql/user/starred_projects_query_spec.rb index 6cb02068f2a..a8c087d1fbf 100644 --- a/spec/requests/api/graphql/user/starred_projects_query_spec.rb +++ b/spec/requests/api/graphql/user/starred_projects_query_spec.rb @@ -60,6 +60,7 @@ RSpec.describe 'Getting starredProjects of the user' do context 'the current user is a member of a private project the user starred' do let_it_be(:other_user) { create(:user) } + let(:current_user) { other_user } before do diff --git a/spec/requests/api/graphql/user_query_spec.rb b/spec/requests/api/graphql/user_query_spec.rb index 60520906e87..59b805bb25b 100644 --- a/spec/requests/api/graphql/user_query_spec.rb +++ b/spec/requests/api/graphql/user_query_spec.rb @@ -402,6 +402,7 @@ RSpec.describe 'getting user information' do context 'we request the groupMemberships' do let_it_be(:membership_a) { create(:group_member, user: user) } + let(:group_memberships) { graphql_data_at(:user, :group_memberships, :nodes) } let(:user_fields) { 'groupMemberships { nodes { id } }' } @@ -424,6 +425,7 @@ RSpec.describe 'getting user information' do context 'we request the projectMemberships' do let_it_be(:membership_a) { create(:project_member, user: user) } + let(:project_memberships) { graphql_data_at(:user, :project_memberships, :nodes) } let(:user_fields) { 'projectMemberships { nodes { id } }' } |