diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 12:08:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 12:08:42 +0300 |
commit | b76ae638462ab0f673e5915986070518dd3f9ad3 (patch) | |
tree | bdab0533383b52873be0ec0eb4d3c66598ff8b91 /spec/requests/api/graphql | |
parent | 434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff) |
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'spec/requests/api/graphql')
18 files changed, 537 insertions, 29 deletions
diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb index 10f05efa1b8..e6362fdde88 100644 --- a/spec/requests/api/graphql/ci/jobs_spec.rb +++ b/spec/requests/api/graphql/ci/jobs_spec.rb @@ -117,14 +117,19 @@ RSpec.describe 'Query.project.pipeline' do ) end - it 'avoids N+1 queries' do - control_count = ActiveRecord::QueryRecorder.new do - post_graphql(query, current_user: user, variables: first_n.with(1)) + it 'does not generate N+1 queries', :request_store, :use_sql_query_cache do + post_graphql(query, current_user: user) + + control = ActiveRecord::QueryRecorder.new(skip_cached: false) do + post_graphql(query, current_user: user) end + create(:ci_build, name: 'test-a', pipeline: pipeline) + create(:ci_build, name: 'test-b', pipeline: pipeline) + expect do - post_graphql(query, current_user: user, variables: first_n.with(3)) - end.not_to exceed_query_limit(control_count) + post_graphql(query, current_user: user) + end.not_to exceed_all_query_limit(control) end end end @@ -137,11 +142,19 @@ RSpec.describe 'Query.project.pipeline' do query { project(fullPath: "#{project.full_path}") { pipeline(iid: "#{pipeline.iid}") { - jobs { + stages { nodes { - artifacts { + groups{ nodes { - downloadPath + jobs { + nodes { + artifacts { + nodes { + downloadPath + } + } + } + } } } } @@ -158,7 +171,7 @@ RSpec.describe 'Query.project.pipeline' do post_graphql(query, current_user: user) - job_data = graphql_data.dig('project', 'pipeline', 'jobs', 'nodes').first + job_data = graphql_data_at(:project, :pipeline, :stages, :nodes, :groups, :nodes, :jobs, :nodes).first expect(job_data.dig('artifacts', 'nodes').count).to be(2) end end @@ -169,7 +182,7 @@ RSpec.describe 'Query.project.pipeline' do post_graphql(query, current_user: user) - job_data = graphql_data.dig('project', 'pipeline', 'jobs', 'nodes').first + job_data = graphql_data_at(:project, :pipeline, :stages, :nodes, :groups, :nodes, :jobs, :nodes).first expect(job_data['artifacts']).to be_nil end end diff --git a/spec/requests/api/graphql/ci/runner_spec.rb b/spec/requests/api/graphql/ci/runner_spec.rb index cdd46ca4ecc..74547196445 100644 --- a/spec/requests/api/graphql/ci/runner_spec.rb +++ b/spec/requests/api/graphql/ci/runner_spec.rb @@ -52,14 +52,14 @@ RSpec.describe 'Query.runner(id)' do 'version' => runner.version, 'shortSha' => runner.short_sha, 'revision' => runner.revision, - 'locked' => runner.locked, + 'locked' => false, 'active' => runner.active, 'status' => runner.status.to_s.upcase, 'maximumTimeout' => runner.maximum_timeout, 'accessLevel' => runner.access_level.to_s.upcase, 'runUntagged' => runner.run_untagged, 'ipAddress' => runner.ip_address, - 'runnerType' => 'INSTANCE_TYPE', + 'runnerType' => runner.instance_type? ? 'INSTANCE_TYPE' : 'PROJECT_TYPE', 'jobCount' => 0, 'projectCount' => nil ) @@ -109,6 +109,40 @@ RSpec.describe 'Query.runner(id)' do end end + describe 'for project runner' do + using RSpec::Parameterized::TableSyntax + + where(is_locked: [true, false]) + + with_them do + let(:project_runner) do + create(:ci_runner, :project, description: 'Runner 3', contacted_at: 1.day.ago, active: false, locked: is_locked, + version: 'adfe157', revision: 'b', ip_address: '10.10.10.10', access_level: 1, run_untagged: true) + end + + let(:query) do + wrap_fields(query_graphql_path(query_path, all_graphql_fields_for('CiRunner'))) + end + + let(:query_path) do + [ + [:runner, { id: project_runner.to_global_id.to_s }] + ] + end + + it 'retrieves correct locked value' do + post_graphql(query, current_user: user) + + runner_data = graphql_data_at(:runner) + + expect(runner_data).to match a_hash_including( + 'id' => "gid://gitlab/Ci::Runner/#{project_runner.id}", + 'locked' => is_locked + ) + end + end + end + describe 'for inactive runner' do it_behaves_like 'runner details fetch', :inactive_instance_runner end diff --git a/spec/requests/api/graphql/current_user_query_spec.rb b/spec/requests/api/graphql/current_user_query_spec.rb index dc832b42fa5..086a57094ca 100644 --- a/spec/requests/api/graphql/current_user_query_spec.rb +++ b/spec/requests/api/graphql/current_user_query_spec.rb @@ -5,8 +5,15 @@ require 'spec_helper' RSpec.describe 'getting project information' do include GraphqlHelpers + let(:fields) do + <<~GRAPHQL + name + namespace { id } + GRAPHQL + end + let(:query) do - graphql_query_for('currentUser', {}, 'name') + graphql_query_for('currentUser', {}, fields) end subject { graphql_data['currentUser'] } @@ -20,7 +27,7 @@ RSpec.describe 'getting project information' do it_behaves_like 'a working graphql query' - it { is_expected.to include('name' => current_user.name) } + it { is_expected.to include('name' => current_user.name, 'namespace' => { 'id' => current_user.namespace.to_global_id.to_s }) } end context 'when there is no current_user' do diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb index b6bbf8d5dd2..fd0ee5d52b9 100644 --- a/spec/requests/api/graphql/group_query_spec.rb +++ b/spec/requests/api/graphql/group_query_spec.rb @@ -8,11 +8,11 @@ RSpec.describe 'getting group information' do include GraphqlHelpers include UploadHelpers - let(:user1) { create(:user, can_create_group: false) } - let(:user2) { create(:user) } - let(:admin) { create(:admin) } - let(:public_group) { create(:group, :public) } - let(:private_group) { create(:group, :private) } + let_it_be(:user1) { create(:user, can_create_group: false) } + let_it_be(:user2) { create(:user) } + let_it_be(:admin) { create(:admin) } + let_it_be(:private_group) { create(:group, :private) } + let_it_be(:public_group) { create(:group, :public) } # similar to the API "GET /groups/:id" describe "Query group(fullPath)" do @@ -78,6 +78,7 @@ RSpec.describe 'getting group information' do expect(graphql_data['group']['parentId']).to eq(group1.parent_id) expect(graphql_data['group']['issues']['nodes'].count).to eq(1) expect(graphql_data['group']['issues']['nodes'][0]['iid']).to eq(issue.iid.to_s) + expect(graphql_data['group']['sharedRunnersSetting']).to eq(group1.shared_runners_setting.upcase) end it "does not return a non existing group" do @@ -105,6 +106,20 @@ RSpec.describe 'getting group information' do expect { post_multiplex(queries, current_user: admin) } .to issue_same_number_of_queries_as { post_graphql(group_query(group1), current_user: admin) } end + + context "when querying group's descendant groups" do + let_it_be(:subgroup1) { create(:group, parent: public_group) } + let_it_be(:subgroup2) { create(:group, parent: subgroup1) } + + let(:descendants) { [subgroup1, subgroup2] } + + it 'returns all descendant groups user has access to' do + post_graphql(group_query(public_group), current_user: admin) + + names = graphql_data['group']['descendantGroups']['nodes'].map { |n| n['name'] } + expect(names).to match_array(descendants.map(&:name)) + end + end end context "when authenticated as admin" do diff --git a/spec/requests/api/graphql/mutations/ci/job_cancel_spec.rb b/spec/requests/api/graphql/mutations/ci/job_cancel_spec.rb new file mode 100644 index 00000000000..ee0f0a9bccb --- /dev/null +++ b/spec/requests/api/graphql/mutations/ci/job_cancel_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe "JobCancel" do + include GraphqlHelpers + + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } + let_it_be(:job) { create(:ci_build, pipeline: pipeline, name: 'build') } + + let(:mutation) do + variables = { + id: job.to_global_id.to_s + } + graphql_mutation(:job_cancel, variables, + <<-QL + errors + job { + id + } + QL + ) + end + + let(:mutation_response) { graphql_mutation_response(:job_cancel) } + + it 'returns an error if the user is not allowed to cancel the job' do + project.add_developer(user) + post_graphql_mutation(mutation, current_user: user) + + expect(graphql_errors).not_to be_empty + end + + it 'cancels a job' do + job_id = ::Gitlab::GlobalId.build(job, id: job.id).to_s + project.add_maintainer(user) + post_graphql_mutation(mutation, current_user: user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['job']['id']).to eq(job_id) + expect(job.reload.status).to eq('canceled') + end +end diff --git a/spec/requests/api/graphql/mutations/ci/job_unschedule_spec.rb b/spec/requests/api/graphql/mutations/ci/job_unschedule_spec.rb new file mode 100644 index 00000000000..4ddc019a2b5 --- /dev/null +++ b/spec/requests/api/graphql/mutations/ci/job_unschedule_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'JobUnschedule' do + include GraphqlHelpers + + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } + let_it_be(:job) { create(:ci_build, :scheduled, pipeline: pipeline, name: 'build') } + + let(:mutation) do + variables = { + id: job.to_global_id.to_s + } + graphql_mutation(:job_unschedule, variables, + <<-QL + errors + job { + id + } + QL + ) + end + + let(:mutation_response) { graphql_mutation_response(:job_unschedule) } + + it 'returns an error if the user is not allowed to unschedule the job' do + project.add_developer(user) + + post_graphql_mutation(mutation, current_user: user) + + expect(graphql_errors).not_to be_empty + expect(job.reload.status).to eq('scheduled') + end + + it 'unschedules a job' do + project.add_maintainer(user) + + job_id = ::Gitlab::GlobalId.build(job, id: job.id).to_s + post_graphql_mutation(mutation, current_user: user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['job']['id']).to eq(job_id) + expect(job.reload.status).to eq('manual') + end +end diff --git a/spec/requests/api/graphql/mutations/groups/update_spec.rb b/spec/requests/api/graphql/mutations/groups/update_spec.rb new file mode 100644 index 00000000000..b9dfb8e37ab --- /dev/null +++ b/spec/requests/api/graphql/mutations/groups/update_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'GroupUpdate' do + include GraphqlHelpers + + let_it_be(:user) { create(:user) } + let_it_be_with_reload(:group) { create(:group) } + + let(:variables) do + { + full_path: group.full_path, + shared_runners_setting: 'DISABLED_WITH_OVERRIDE' + } + end + + let(:mutation) { graphql_mutation(:group_update, variables) } + + context 'when unauthorized' do + shared_examples 'unauthorized' do + it 'returns an error' do + post_graphql_mutation(mutation, current_user: user) + + expect(graphql_errors).not_to be_empty + end + end + + context 'when not a group member' do + it_behaves_like 'unauthorized' + end + + context 'when a non-admin group member' do + before do + group.add_developer(user) + end + + it_behaves_like 'unauthorized' + end + end + + context 'when authorized' do + before do + group.add_owner(user) + end + + it 'updates shared runners settings' do + post_graphql_mutation(mutation, current_user: user) + + expect(response).to have_gitlab_http_status(:success) + expect(graphql_errors).to be_nil + expect(group.reload.shared_runners_setting).to eq(variables[:shared_runners_setting].downcase) + end + + context 'when bad arguments are provided' do + let(:variables) { { full_path: '', shared_runners_setting: 'INVALID' } } + + it 'returns the errors' do + post_graphql_mutation(mutation, current_user: user) + + expect(graphql_errors).not_to be_empty + expect(group.reload.shared_runners_setting).to eq('enabled') + end + end + end +end diff --git a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb index ea5be9f9852..72e47a98373 100644 --- a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb @@ -68,7 +68,7 @@ RSpec.describe 'Setting Due Date of an issue' do it 'returns an error' do post_graphql_mutation(mutation, current_user: current_user) - expect(graphql_errors).to include(a_hash_including('message' => /Argument dueDate must be provided/)) + expect(graphql_errors).to include(a_hash_including('message' => /Arguments must be provided: dueDate/)) end end diff --git a/spec/requests/api/graphql/mutations/issues/update_spec.rb b/spec/requests/api/graphql/mutations/issues/update_spec.rb index b3e1ab62e54..c3aaf090703 100644 --- a/spec/requests/api/graphql/mutations/issues/update_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/update_spec.rb @@ -8,6 +8,8 @@ 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_it_be(:label1) { create(:label, project: project) } + let_it_be(:label2) { create(:label, project: project) } let(:input) do { @@ -20,7 +22,9 @@ RSpec.describe 'Update of an existing issue' do } end - let(:mutation) { graphql_mutation(:update_issue, input.merge(project_path: project.full_path, locked: true)) } + let(:extra_params) { { project_path: project.full_path, locked: true } } + let(:input_params) { input.merge(extra_params) } + let(:mutation) { graphql_mutation(:update_issue, input_params) } let(:mutation_response) { graphql_mutation_response(:update_issue) } context 'the user is not allowed to update issue' do @@ -39,5 +43,82 @@ RSpec.describe 'Update of an existing issue' do expect(mutation_response['issue']).to include(input) expect(mutation_response['issue']).to include('discussionLocked' => true) end + + context 'setting labels' do + let(:mutation) do + graphql_mutation(:update_issue, input_params) do + <<~QL + issue { + labels { + nodes { + id + } + } + } + errors + QL + end + end + + context 'reset labels' do + let(:input_params) { input.merge(extra_params).merge({ labelIds: [label1.id, label2.id] }) } + + it 'resets labels' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(json_response['errors']).to be_nil + expect(mutation_response['issue']['labels']).to include({ "nodes" => [{ "id" => label1.to_global_id.to_s }, { "id" => label2.to_global_id.to_s }] }) + end + + context 'reset labels and add labels' do + let(:input_params) { input.merge(extra_params).merge({ labelIds: [label1.id], addLabelIds: [label2.id] }) } + + it 'returns error for mutually exclusive arguments' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(json_response['errors'].first['message']).to eq('labelIds is mutually exclusive with any of addLabelIds or removeLabelIds') + expect(mutation_response).to be_nil + end + end + + context 'reset labels and remove labels' do + let(:input_params) { input.merge(extra_params).merge({ labelIds: [label1.id], removeLabelIds: [label2.id] }) } + + it 'returns error for mutually exclusive arguments' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(json_response['errors'].first['message']).to eq('labelIds is mutually exclusive with any of addLabelIds or removeLabelIds') + expect(mutation_response).to be_nil + end + end + + context 'with global label ids' do + let(:input_params) { input.merge(extra_params).merge({ labelIds: [label1.to_global_id.to_s, label2.to_global_id.to_s] }) } + + it 'resets labels' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(json_response['errors']).to be_nil + expect(mutation_response['issue']['labels']).to include({ "nodes" => [{ "id" => label1.to_global_id.to_s }, { "id" => label2.to_global_id.to_s }] }) + end + end + end + + context 'add and remove labels' do + let(:input_params) { input.merge(extra_params).merge({ addLabelIds: [label1.id], removeLabelIds: [label2.id] }) } + + it 'returns error for mutually exclusive arguments' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(json_response['errors']).to be_nil + expect(mutation_response['issue']['labels']).to include({ "nodes" => [{ "id" => label1.to_global_id.to_s }] }) + end + end + end end end diff --git a/spec/requests/api/graphql/mutations/packages/destroy_file_spec.rb b/spec/requests/api/graphql/mutations/packages/destroy_file_spec.rb new file mode 100644 index 00000000000..7be629f8f4b --- /dev/null +++ b/spec/requests/api/graphql/mutations/packages/destroy_file_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Destroying a package file' do + using RSpec::Parameterized::TableSyntax + + include GraphqlHelpers + + let_it_be_with_reload(:package) { create(:maven_package) } + let_it_be(:user) { create(:user) } + + let(:project) { package.project } + let(:id) { package.package_files.first.to_global_id.to_s } + + let(:query) do + <<~GQL + errors + GQL + end + + let(:params) { { id: id } } + let(:mutation) { graphql_mutation(:destroy_package_file, params, query) } + let(:mutation_response) { graphql_mutation_response(:destroyPackageFile) } + + shared_examples 'destroying the package file' do + it 'destroy the package file' do + expect { mutation_request }.to change { ::Packages::PackageFile.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 file' do + expect(::Packages::PackageFile) + .not_to receive(:destroy) + + expect { mutation_request }.not_to change { ::Packages::PackageFile.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 file' + :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::PackageFile/5555' } } + + it_behaves_like 'denying the mutation request' + end + + context 'when an error occures' do + let(:error_messages) { ['some error'] } + + before do + project.add_maintainer(user) + end + + it 'returns the errors in the response' do + allow_next_found_instance_of(::Packages::PackageFile) do |package_file| + allow(package_file).to receive(:destroy).and_return(false) + allow(package_file).to receive_message_chain(:errors, :full_messages).and_return(error_messages) + end + + mutation_request + + expect(mutation_response['errors']).to eq(error_messages) + end + end + end +end 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 43d846cb297..77fd6cddc09 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 @@ -58,7 +58,7 @@ RSpec.describe 'Mark snippet as spam' do end it 'marks snippet as spam' do - expect_next(Spam::MarkAsSpamService, target: snippet) + expect_next(Spam::AkismetMarkAsSpamService, target: snippet) .to receive(:execute).and_return(true) post_graphql_mutation(mutation, current_user: current_user) diff --git a/spec/requests/api/graphql/packages/nuget_spec.rb b/spec/requests/api/graphql/packages/nuget_spec.rb index 1de16009684..ba8d2ca42d2 100644 --- a/spec/requests/api/graphql/packages/nuget_spec.rb +++ b/spec/requests/api/graphql/packages/nuget_spec.rb @@ -6,8 +6,11 @@ RSpec.describe 'nuget package details' do include_context 'package details setup' let_it_be(:package) { create(:nuget_package, :with_metadatum, project: project) } + let_it_be(:dependency_link) { create(:packages_dependency_link, :with_nuget_metadatum, package: package) } let(:metadata) { query_graphql_fragment('NugetMetadata') } + let(:dependency_link_response) { graphql_data_at(:package, :dependency_links, :nodes, 0) } + let(:dependency_response) { graphql_data_at(:package, :dependency_links, :nodes, 0, :dependency) } subject { post_graphql(query, current_user: user) } @@ -26,4 +29,34 @@ RSpec.describe 'nuget package details' do 'iconUrl' => package.nuget_metadatum.icon_url ) end + + it 'has dependency links' do + expect(dependency_link_response).to include( + 'id' => global_id_of(dependency_link), + 'dependencyType' => dependency_link.dependency_type.upcase + ) + + expect(dependency_response).to include( + 'id' => global_id_of(dependency_link.dependency), + 'name' => dependency_link.dependency.name, + 'versionPattern' => dependency_link.dependency.version_pattern + ) + end + + it 'avoids N+1 queries' do + first_user = create(:user) + second_user = create(:user) + + control_count = ActiveRecord::QueryRecorder.new do + post_graphql(query, current_user: first_user) + end + + create_list(:packages_dependency_link, 10, :with_nuget_metadatum, package: package) + + expect do + post_graphql(query, current_user: second_user) + end.not_to exceed_query_limit(control_count) + + expect(response).to have_gitlab_http_status(:ok) + end end 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 05a98a9dd9c..29896c16f5b 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 @@ -40,7 +40,7 @@ RSpec.describe 'getting Alert Management Alert Issue' do context 'with gitlab alert' do before do - create(:alert_management_alert, :with_issue, project: project, payload: payload) + create(:alert_management_alert, :with_incident, project: project, payload: payload) end it 'includes the correct alert issue payload data' do @@ -57,7 +57,7 @@ RSpec.describe 'getting Alert Management Alert Issue' do context 'with gitlab alert' do before do - create(:alert_management_alert, :with_issue, project: project, payload: payload) + create(:alert_management_alert, :with_incident, project: project, payload: payload) end it 'avoids N+1 queries' 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 14fabaaf032..40a3281d3b7 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 @@ -7,7 +7,7 @@ RSpec.describe 'getting a detailed sentry error' do let_it_be(:project) { create(:project, :repository) } 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_it_be(:sentry_detailed_error) { build(:error_tracking_sentry_detailed_error) } let(:sentry_gid) { sentry_detailed_error.to_global_id.to_s } let(:fields) do 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 e71e5a48ddc..80376f56ee8 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 @@ -16,7 +16,7 @@ RSpec.describe 'sentry errors requests' do end describe 'getting a detailed sentry error' do - let_it_be(:sentry_detailed_error) { build(:detailed_error_tracking_error) } + let_it_be(:sentry_detailed_error) { build(:error_tracking_sentry_detailed_error) } let(:sentry_gid) { sentry_detailed_error.to_global_id.to_s } @@ -97,7 +97,7 @@ RSpec.describe 'sentry errors requests' do end describe 'getting an errors list' do - let_it_be(:sentry_error) { build(:error_tracking_error) } + let_it_be(:sentry_error) { build(:error_tracking_sentry_error) } let_it_be(:pagination) do { 'next' => { 'cursor' => '2222' }, @@ -193,7 +193,7 @@ RSpec.describe 'sentry errors requests' do end describe 'getting a stack trace' do - let_it_be(:sentry_stack_trace) { build(:error_tracking_error_event) } + let_it_be(:sentry_stack_trace) { build(:error_tracking_sentry_error_event) } let(:sentry_gid) { global_id_of(Gitlab::ErrorTracking::DetailedError.new(id: 1)) } diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb index dd9d44136e5..ff0d7ecceb5 100644 --- a/spec/requests/api/graphql/project/issues_spec.rb +++ b/spec/requests/api/graphql/project/issues_spec.rb @@ -323,7 +323,7 @@ RSpec.describe 'getting an issue list for a project' do it 'avoids N+1 queries' do control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) } - create(:alert_management_alert, :with_issue, project: project) + create(:alert_management_alert, :with_incident, project: project) expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control) end @@ -476,6 +476,17 @@ RSpec.describe 'getting an issue list for a project' do include_examples 'N+1 query check' end + context 'when requesting `merge_requests_count`' do + let(:requested_fields) { [:merge_requests_count] } + + before do + create_list(:merge_requests_closing_issues, 2, issue: issue_a) + create_list(:merge_requests_closing_issues, 3, issue: issue_b) + end + + include_examples 'N+1 query check' + end + context 'when requesting `timelogs`' do let(:requested_fields) { 'timelogs { nodes { timeSpent } }' } diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb index 7fc1ef05fa7..1b0405be09c 100644 --- a/spec/requests/api/graphql/project/merge_requests_spec.rb +++ b/spec/requests/api/graphql/project/merge_requests_spec.rb @@ -422,6 +422,46 @@ RSpec.describe 'getting merge request listings nested in a project' do end end end + + context 'when sorting by closed_at DESC' do + let(:sort_param) { :CLOSED_AT_DESC } + let(:expected_results) do + [ + merge_request_b, + merge_request_d, + merge_request_c, + merge_request_e, + merge_request_a + ].map { |mr| global_id_of(mr) } + end + + before do + five_days_ago = 5.days.ago + + merge_request_d.metrics.update!(latest_closed_at: five_days_ago) + + # same merged_at, the second order column will decide (merge_request.id) + merge_request_c.metrics.update!(latest_closed_at: five_days_ago) + + merge_request_b.metrics.update!(latest_closed_at: 1.day.ago) + end + + it_behaves_like 'sorted paginated query' do + let(:first_param) { 2 } + end + + context 'when last parameter is given' do + let(:params) { graphql_args(sort: sort_param, last: 2) } + let(:page_info) { nil } + + it 'takes the last 2 records' do + query = pagination_query(params) + post_graphql(query, current_user: current_user) + + expect(results.map { |item| item["id"] }).to eq(expected_results.last(2)) + end + end + end end context 'when only the count is requested' do diff --git a/spec/requests/api/graphql/project/repository_spec.rb b/spec/requests/api/graphql/project/repository_spec.rb index bddd300e27f..8810f2fa3d5 100644 --- a/spec/requests/api/graphql/project/repository_spec.rb +++ b/spec/requests/api/graphql/project/repository_spec.rb @@ -83,4 +83,26 @@ RSpec.describe 'getting a repository in a project' do expect(graphql_data['project']['repository']).to be_nil end end + + context 'when paginated tree requested' do + let(:fields) do + %( + paginatedTree { + nodes { + trees { + nodes { + path + } + } + } + } + ) + end + + it 'returns paginated tree' do + post_graphql(query, current_user: current_user) + + expect(graphql_data['project']['repository']['paginatedTree']).to be_present + end + end end |