diff options
Diffstat (limited to 'spec/support/shared_examples/requests')
11 files changed, 336 insertions, 77 deletions
diff --git a/spec/support/shared_examples/requests/admin_mode_shared_examples.rb b/spec/support/shared_examples/requests/admin_mode_shared_examples.rb new file mode 100644 index 00000000000..07fde7d3f35 --- /dev/null +++ b/spec/support/shared_examples/requests/admin_mode_shared_examples.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true +RSpec.shared_examples 'GET request permissions for admin mode' do + it_behaves_like 'GET request permissions for admin mode when user' + it_behaves_like 'GET request permissions for admin mode when admin' +end + +RSpec.shared_examples 'PUT request permissions for admin mode' do |params| + it_behaves_like 'PUT request permissions for admin mode when user', params + it_behaves_like 'PUT request permissions for admin mode when admin', params +end + +RSpec.shared_examples 'POST request permissions for admin mode' do |params| + it_behaves_like 'POST request permissions for admin mode when user', params + it_behaves_like 'POST request permissions for admin mode when admin', params +end + +RSpec.shared_examples 'DELETE request permissions for admin mode' do + it_behaves_like 'DELETE request permissions for admin mode when user' + it_behaves_like 'DELETE request permissions for admin mode when admin' +end + +RSpec.shared_examples 'GET request permissions for admin mode when user' do + subject { get api(path, current_user, admin_mode: admin_mode) } + + let_it_be(:current_user) { create(:user) } + + it_behaves_like 'admin mode on', true, :forbidden + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples 'GET request permissions for admin mode when admin' do + subject { get api(path, current_user, admin_mode: admin_mode) } + + let_it_be(:current_user) { create(:admin) } + + it_behaves_like 'admin mode on', true, :ok + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples 'PUT request permissions for admin mode when user' do |params| + subject { put api(path, current_user, admin_mode: admin_mode), params: params } + + let_it_be(:current_user) { create(:user) } + + it_behaves_like 'admin mode on', true, :forbidden + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples 'PUT request permissions for admin mode when admin' do |params| + subject { put api(path, current_user, admin_mode: admin_mode), params: params } + + let_it_be(:current_user) { create(:admin) } + + it_behaves_like 'admin mode on', true, :ok + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples 'POST request permissions for admin mode when user' do |params| + subject { post api(path, current_user, admin_mode: admin_mode), params: params } + + let_it_be(:current_user) { create(:user) } + + it_behaves_like 'admin mode on', true, :forbidden + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples 'POST request permissions for admin mode when admin' do |params| + subject { post api(path, current_user, admin_mode: admin_mode), params: params } + + let_it_be(:current_user) { create(:admin) } + + it_behaves_like 'admin mode on', true, :created + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples 'DELETE request permissions for admin mode when user' do + subject { delete api(path, current_user, admin_mode: admin_mode) } + + let_it_be(:current_user) { create(:user) } + + it_behaves_like 'admin mode on', true, :forbidden + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples 'DELETE request permissions for admin mode when admin' do + subject { delete api(path, current_user, admin_mode: admin_mode) } + + let_it_be(:current_user) { create(:admin) } + + it_behaves_like 'admin mode on', true, :no_content + it_behaves_like 'admin mode on', false, :forbidden +end + +RSpec.shared_examples "admin mode on" do |admin_mode, status| + let_it_be(:admin_mode) { admin_mode } + + it_behaves_like 'returning response status', status +end diff --git a/spec/support/shared_examples/requests/api/debian_common_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_common_shared_examples.rb index 2ba42b8e8fa..e0225070986 100644 --- a/spec/support/shared_examples/requests/api/debian_common_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/debian_common_shared_examples.rb @@ -15,9 +15,3 @@ RSpec.shared_examples 'rejects Debian access with unknown container id' do |anon end end end - -RSpec.shared_examples 'Debian API FIPS mode' do - context 'when FIPS mode is enabled', :fips_mode do - it_behaves_like 'returning response status', :not_found - end -end diff --git a/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb index f13ac05591c..5cd63c33936 100644 --- a/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb @@ -3,8 +3,6 @@ RSpec.shared_examples 'Debian distributions GET request' do |status, body = nil| and_body = body.nil? ? '' : ' and expected body' - it_behaves_like 'Debian API FIPS mode' - it "returns #{status}#{and_body}" do subject @@ -19,8 +17,6 @@ end RSpec.shared_examples 'Debian distributions PUT request' do |status, body| and_body = body.nil? ? '' : ' and expected body' - it_behaves_like 'Debian API FIPS mode' - if status == :success it 'updates distribution', :aggregate_failures do expect(::Packages::Debian::UpdateDistributionService).to receive(:new).with(distribution, api_params.except(:codename)).and_call_original @@ -53,8 +49,6 @@ end RSpec.shared_examples 'Debian distributions DELETE request' do |status, body| and_body = body.nil? ? '' : ' and expected body' - it_behaves_like 'Debian API FIPS mode' - if status == :success it 'updates distribution', :aggregate_failures do expect { subject } diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb index 14a83d2889b..6d29076da0f 100644 --- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb @@ -3,8 +3,6 @@ RSpec.shared_examples 'Debian packages GET request' do |status, body = nil| and_body = body.nil? ? '' : ' and expected body' - it_behaves_like 'Debian API FIPS mode' - it "returns #{status}#{and_body}" do subject @@ -19,11 +17,8 @@ end RSpec.shared_examples 'Debian packages upload request' do |status, body = nil| and_body = body.nil? ? '' : ' and expected body' - it_behaves_like 'Debian API FIPS mode' - if status == :created it 'creates package files', :aggregate_failures do - expect(::Packages::Debian::FindOrCreateIncomingService).to receive(:new).with(container, user).and_call_original expect(::Packages::Debian::CreatePackageFileService).to receive(:new).with(package: be_a(Packages::Package), current_user: be_an(User), params: be_an(Hash)).and_call_original if file_name.end_with? '.changes' @@ -32,10 +27,23 @@ RSpec.shared_examples 'Debian packages upload request' do |status, body = nil| expect(::Packages::Debian::ProcessChangesWorker).not_to receive(:perform_async) end - expect { subject } + if extra_params[:distribution] + expect(::Packages::Debian::FindOrCreateIncomingService).not_to receive(:new) + expect(::Packages::Debian::ProcessPackageFileWorker).to receive(:perform_async) + + expect { subject } + .to change { container.packages.debian.count }.by(1) + .and not_change { container.packages.debian.where(name: 'incoming').count } + .and change { container.package_files.count }.by(1) + else + expect(::Packages::Debian::FindOrCreateIncomingService).to receive(:new).with(container, user).and_call_original + expect(::Packages::Debian::ProcessPackageFileWorker).not_to receive(:perform_async) + + expect { subject } .to change { container.packages.debian.count }.by(1) .and change { container.packages.debian.where(name: 'incoming').count }.by(1) .and change { container.package_files.count }.by(1) + end expect(response).to have_gitlab_http_status(status) expect(response.media_type).to eq('text/plain') diff --git a/spec/support/shared_examples/requests/api/graphql/ci/sorted_paginated_variables_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/ci/sorted_paginated_variables_shared_examples.rb new file mode 100644 index 00000000000..306310c9e9c --- /dev/null +++ b/spec/support/shared_examples/requests/api/graphql/ci/sorted_paginated_variables_shared_examples.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# Requires `current_user`, `data_path`, `variables`, and `pagination_query(params)` bindings +RSpec.shared_examples 'sorted paginated variables' do + subject(:expected_ordered_variables) { ordered_variables.map { |var| var.to_global_id.to_s } } + + context 'when sorted by key ascending' do + let(:ordered_variables) { variables.sort_by(&:key) } + + it_behaves_like 'sorted paginated query' do + let(:sort_param) { :KEY_ASC } + let(:first_param) { 2 } + let(:all_records) { expected_ordered_variables } + end + end + + context 'when sorted by key descending' do + let(:ordered_variables) { variables.sort_by(&:key).reverse } + + it_behaves_like 'sorted paginated query' do + let(:sort_param) { :KEY_DESC } + let(:first_param) { 2 } + let(:all_records) { expected_ordered_variables } + end + end +end diff --git a/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb index d4af9e570d1..6c8b792bf92 100644 --- a/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb @@ -5,7 +5,7 @@ RSpec.shared_examples 'graphql issue list request spec' do let(:fields) do <<~QUERY nodes { - #{all_graphql_fields_for('issues'.classify)} + #{all_graphql_fields_for('issues'.classify, excluded: ['relatedMergeRequests'])} } QUERY end @@ -683,6 +683,28 @@ RSpec.shared_examples 'graphql issue list request spec' do end end + context 'when selecting `related_merge_requests`' do + let(:fields) do + <<~QUERY + nodes { + relatedMergeRequests { + nodes { + id + } + } + } + QUERY + end + + it 'limits the field to 1 execution' do + post_query + + expect_graphql_errors_to_include( + '"relatedMergeRequests" field can be requested only for 1 Issue(s) at a time.' + ) + end + end + it 'includes a web_url' do post_query diff --git a/spec/support/shared_examples/requests/api/graphql/releases_and_group_releases_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/releases_and_group_releases_shared_examples.rb new file mode 100644 index 00000000000..b40cf6daea9 --- /dev/null +++ b/spec/support/shared_examples/requests/api/graphql/releases_and_group_releases_shared_examples.rb @@ -0,0 +1,164 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'correct total count' do + let(:data) { graphql_data.dig(resource_type.to_s, 'releases') } + + before do + create_list(:release, 2, project: project) + + post_query + end + + it 'returns the total count' do + expect(data['count']).to eq(project.releases.count) + end +end + +RSpec.shared_examples 'full access to all repository-related fields' do + describe 'repository-related fields' do + before do + post_query + end + + it 'returns data for fields that are protected in private projects' do + expected_sources = release.sources.map do |s| + { 'url' => s.url } + end + + expected_evidences = release.evidences.map do |e| + { 'sha' => e.sha } + end + expect(data).to eq( + 'tagName' => release.tag, + 'tagPath' => project_tag_path(project, release.tag), + 'name' => release.name, + 'commit' => { + 'sha' => release.commit.sha + }, + 'assets' => { + 'count' => release.assets_count, + 'sources' => { + 'nodes' => expected_sources + } + }, + 'evidences' => { + 'nodes' => expected_evidences + }, + 'links' => { + 'selfUrl' => project_release_url(project, release), + 'openedMergeRequestsUrl' => project_merge_requests_url(project, opened_url_params), + 'mergedMergeRequestsUrl' => project_merge_requests_url(project, merged_url_params), + 'closedMergeRequestsUrl' => project_merge_requests_url(project, closed_url_params), + 'openedIssuesUrl' => project_issues_url(project, opened_url_params), + 'closedIssuesUrl' => project_issues_url(project, closed_url_params) + } + ) + end + end + + it_behaves_like 'correct total count' +end + +RSpec.shared_examples 'no access to any repository-related fields' do + describe 'repository-related fields' do + before do + post_query + end + + it 'does not return data for fields that expose repository information' do + tag_name = release.tag + release_name = release.name + expect(data).to eq( + 'tagName' => tag_name, + 'tagPath' => nil, + 'name' => release_name, + 'commit' => nil, + 'assets' => { + 'count' => release.assets_count(except: [:sources]), + 'sources' => { + 'nodes' => [] + } + }, + 'evidences' => { + 'nodes' => [] + }, + 'links' => { + 'closedIssuesUrl' => nil, + 'closedMergeRequestsUrl' => nil, + 'mergedMergeRequestsUrl' => nil, + 'openedIssuesUrl' => nil, + 'openedMergeRequestsUrl' => nil, + 'selfUrl' => project_release_url(project, release) + } + ) + end + end + + it_behaves_like 'correct total count' +end + +RSpec.shared_examples 'access to editUrl' do + # editUrl is tested separately because its permissions + # are slightly different than other release fields + let(:query) do + graphql_query_for(resource_type, { fullPath: resource.full_path }, + %( + releases { + nodes { + links { + editUrl + } + } + } + )) + end + + before do + post_query + end + + it 'returns editUrl' do + expect(data).to eq( + 'links' => { + 'editUrl' => edit_project_release_url(project, release) + } + ) + end +end + +RSpec.shared_examples 'no access to editUrl' do + let(:query) do + graphql_query_for(resource_type, { fullPath: resource.full_path }, + %( + releases { + nodes { + links { + editUrl + } + } + } + )) + end + + before do + post_query + end + + it 'does not return editUrl' do + expect(data).to eq( + 'links' => { + 'editUrl' => nil + } + ) + end +end + +RSpec.shared_examples 'no access to any release data' do + before do + post_query + end + + it 'returns nil' do + expect(data).to eq(nil) + end +end diff --git a/spec/support/shared_examples/requests/api/hooks_shared_examples.rb b/spec/support/shared_examples/requests/api/hooks_shared_examples.rb index d666a754d9f..f2002de4b55 100644 --- a/spec/support/shared_examples/requests/api/hooks_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/hooks_shared_examples.rb @@ -128,7 +128,8 @@ RSpec.shared_examples 'web-hook API endpoints' do |prefix| get api(hook_uri, user) expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to include('alert_status' => 'disabled') + + expect(json_response).to include('alert_status' => 'disabled') unless hook.executable? end end @@ -142,10 +143,13 @@ RSpec.shared_examples 'web-hook API endpoints' do |prefix| get api(hook_uri, user) expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to include( - 'alert_status' => 'temporarily_disabled', - 'disabled_until' => hook.disabled_until.iso8601(3) - ) + + unless hook.executable? + expect(json_response).to include( + 'alert_status' => 'temporarily_disabled', + 'disabled_until' => hook.disabled_until.iso8601(3) + ) + end end end end diff --git a/spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb b/spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb index fcde3b65b4f..f06a80375e8 100644 --- a/spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb @@ -1,40 +1,5 @@ # frozen_string_literal: true -RSpec.shared_examples 'issuable anonymous search' do - context 'with anonymous user' do - context 'with disable_anonymous_search disabled' do - before do - stub_feature_flags(disable_anonymous_search: false) - end - - it 'returns issuables matching given search string for title' do - get api(url), params: { scope: 'all', search: issuable.title } - - expect_paginated_array_response(result) - end - - it 'returns issuables matching given search string for description' do - get api(url), params: { scope: 'all', search: issuable.description } - - expect_paginated_array_response(result) - end - end - - context 'with disable_anonymous_search enabled' do - before do - stub_feature_flags(disable_anonymous_search: true) - end - - it "returns 422 error" do - get api(url), params: { scope: 'all', search: issuable.title } - - expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(json_response['message']).to eq('User must be authenticated to use search') - end - end - end -end - RSpec.shared_examples 'issuable API rate-limited search' do it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do let(:current_user) { user } @@ -49,20 +14,4 @@ RSpec.shared_examples 'issuable API rate-limited search' do get api(url), params: { scope: 'all', search: issuable.title } end end - - context 'when rate_limit_issuable_searches is disabled', :freeze_time, :clean_gitlab_redis_rate_limiting do - before do - stub_feature_flags(rate_limit_issuable_searches: false) - - allow(Gitlab::ApplicationRateLimiter).to receive(:threshold) - .with(:search_rate_limit_unauthenticated).and_return(1) - end - - it 'does not enforce the rate limit' do - get api(url), params: { scope: 'all', search: issuable.title } - get api(url), params: { scope: 'all', search: issuable.title } - - expect(response).to have_gitlab_http_status(:ok) - end - end end diff --git a/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb b/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb index 381583ff2a9..86a1fd76d09 100644 --- a/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb @@ -142,7 +142,7 @@ RSpec.shared_examples 'time tracking endpoints' do |issuable_name| if issuable_name == 'issue' it 'calls update service without :use_specialized_service param' do expect(::Issues::UpdateService).to receive(:new).with( - project: project, + container: project, current_user: user, params: { spend_time: { duration: 3600, summary: 'summary', user_id: user.id } }) diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb index 82ed6eb4c95..3f457890f35 100644 --- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb +++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb @@ -382,7 +382,7 @@ RSpec.shared_examples 'tracking when dry-run mode is set' do end def reset_rack_attack - Rack::Attack.reset! + Gitlab::Redis::RateLimiting.with(&:flushdb) Rack::Attack.clear_configuration Gitlab::RackAttack.configure(Rack::Attack) end |