diff options
Diffstat (limited to 'spec/controllers/projects')
18 files changed, 448 insertions, 363 deletions
diff --git a/spec/controllers/projects/alerting/notifications_controller_spec.rb b/spec/controllers/projects/alerting/notifications_controller_spec.rb index b3feeb7c07b..5ce2950f95f 100644 --- a/spec/controllers/projects/alerting/notifications_controller_spec.rb +++ b/spec/controllers/projects/alerting/notifications_controller_spec.rb @@ -16,9 +16,6 @@ RSpec.describe Projects::Alerting::NotificationsController do end shared_examples 'process alert payload' do |notify_service_class| - let(:alert_1) { build(:alert_management_alert, project: project) } - let(:alert_2) { build(:alert_management_alert, project: project) } - let(:service_response) { ServiceResponse.success(payload: { alerts: [alert_1, alert_2] }) } let(:notify_service) { instance_double(notify_service_class, execute: service_response) } before do @@ -35,11 +32,14 @@ RSpec.describe Projects::Alerting::NotificationsController do it 'responds with the alert data' do make_request - expect(json_response).to contain_exactly( - { 'iid' => alert_1.iid, 'title' => alert_1.title }, - { 'iid' => alert_2.iid, 'title' => alert_2.title } - ) - expect(response).to have_gitlab_http_status(:ok) + if service_response.payload.present? + expect(json_response).to contain_exactly( + { 'iid' => alert_1.iid, 'title' => alert_1.title }, + { 'iid' => alert_2.iid, 'title' => alert_2.title } + ) + end + + expect(response).to have_gitlab_http_status(service_response.http_status) end it 'does not pass excluded parameters to the notify service' do @@ -146,6 +146,9 @@ RSpec.describe Projects::Alerting::NotificationsController do context 'with generic alert payload' do it_behaves_like 'process alert payload', Projects::Alerting::NotifyService do + let(:alert_1) { build(:alert_management_alert, project: project) } + let(:alert_2) { build(:alert_management_alert, project: project) } + let(:service_response) { ServiceResponse.success(payload: { alerts: [alert_1, alert_2] }) } let(:payload) { { title: 'Alert title' } } end end @@ -154,6 +157,7 @@ RSpec.describe Projects::Alerting::NotificationsController do include PrometheusHelpers it_behaves_like 'process alert payload', Projects::Prometheus::Alerts::NotifyService do + let(:service_response) { ServiceResponse.success(http_status: :created) } let(:payload) { prometheus_alert_payload } end end diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb index f79a2c6a6d0..00efd7d7b56 100644 --- a/spec/controllers/projects/artifacts_controller_spec.rb +++ b/spec/controllers/projects/artifacts_controller_spec.rb @@ -30,28 +30,10 @@ RSpec.describe Projects::ArtifactsController do stub_feature_flags(artifacts_management_page: true) end - it 'sets the artifacts variable' do + it 'renders the page' do subject - expect(assigns(:artifacts)).to contain_exactly(*project.job_artifacts) - end - - it 'sets the total size variable' do - subject - - expect(assigns(:total_size)).to eq(project.job_artifacts.total_size) - end - - describe 'pagination' do - before do - stub_const("#{described_class}::MAX_PER_PAGE", 1) - end - - it 'paginates artifacts' do - subject - - expect(assigns(:artifacts)).to contain_exactly(project.reload.job_artifacts.last) - end + expect(response).to have_gitlab_http_status(:ok) end end @@ -65,18 +47,6 @@ RSpec.describe Projects::ArtifactsController do expect(response).to have_gitlab_http_status(:no_content) end - - it 'does not set the artifacts variable' do - subject - - expect(assigns(:artifacts)).to eq(nil) - end - - it 'does not set the total size variable' do - subject - - expect(assigns(:total_size)).to eq(nil) - end end end @@ -183,12 +153,17 @@ RSpec.describe Projects::ArtifactsController do end context 'when file is stored remotely' do + let(:cdn_config) {} + before do - stub_artifacts_object_storage + stub_artifacts_object_storage(cdn: cdn_config) create(:ci_job_artifact, :remote_store, :codequality, job: job) + allow(Gitlab::ApplicationContext).to receive(:push).and_call_original end it 'sends the codequality report' do + expect(Gitlab::ApplicationContext).to receive(:push).with(artifact: an_instance_of(Ci::JobArtifact)).and_call_original + expect(controller).to receive(:redirect_to).and_call_original download_artifact(file_type: file_type) @@ -201,6 +176,30 @@ RSpec.describe Projects::ArtifactsController do download_artifact(file_type: file_type, proxy: true) end end + + context 'when Google CDN is configured' do + let(:cdn_config) do + { + 'provider' => 'Google', + 'url' => 'https://cdn.example.org', + 'key_name' => 'some-key', + 'key' => Base64.urlsafe_encode64(SecureRandom.hex) + } + end + + before do + request.env['action_dispatch.remote_ip'] = '18.245.0.42' + end + + it 'redirects to a Google CDN request' do + expect(Gitlab::ApplicationContext).to receive(:push).with(artifact: an_instance_of(Ci::JobArtifact)).and_call_original + expect(Gitlab::ApplicationContext).to receive(:push).with(artifact_used_cdn: true).and_call_original + + download_artifact(file_type: file_type) + + expect(response.redirect_url).to start_with("https://cdn.example.org/") + end + end end end end @@ -228,8 +227,9 @@ RSpec.describe Projects::ArtifactsController do expect(response).to have_gitlab_http_status(:forbidden) expect(response.body).to include( 'You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. ' \ - 'To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. ' \ - 'If you need to view this job log, a project maintainer or owner must add you to the project with developer permissions or higher.' + 'To disable debug trace, set the 'CI_DEBUG_TRACE' and 'CI_DEBUG_SERVICES' variables to 'false' ' \ + 'in your pipeline configuration or CI/CD settings. If you must view this job log, a project maintainer or owner must ' \ + 'add you to the project with developer permissions or higher.' ) end end diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 16a43bae674..5927f20df97 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -76,7 +76,7 @@ RSpec.describe Projects::EnvironmentsController do it 'handles search option properly' do get :index, params: environment_params(format: :json, search: 'staging/r') - expect(environments.map { |env| env['name'] } ).to contain_exactly('staging/review-1', 'staging/review-2') + expect(environments.map { |env| env['name'] }).to contain_exactly('staging/review-1', 'staging/review-2') expect(json_response['available_count']).to eq 2 expect(json_response['stopped_count']).to eq 1 end @@ -84,7 +84,7 @@ RSpec.describe Projects::EnvironmentsController do it 'ignores search option if is shorter than a minimum' do get :index, params: environment_params(format: :json, search: 'st') - expect(environments.map { |env| env['name'] } ).to contain_exactly('production', + expect(environments.map { |env| env['name'] }).to contain_exactly('production', 'staging/review-1', 'staging/review-2') expect(json_response['available_count']).to eq 3 @@ -233,7 +233,7 @@ RSpec.describe Projects::EnvironmentsController do search: 'staging-1.0/z' }, format: :json) - expect(environments.map { |env| env['name'] } ).to eq(['staging-1.0/zzz']) + expect(environments.map { |env| env['name'] }).to eq(['staging-1.0/zzz']) expect(json_response['available_count']).to eq 1 expect(json_response['stopped_count']).to eq 0 end @@ -705,7 +705,7 @@ RSpec.describe Projects::EnvironmentsController do expect(json_response).to have_key('all_dashboards') expect(json_response['all_dashboards']).to be_an_instance_of(Array) - expect(json_response['all_dashboards']).to all( include('path', 'default', 'display_name') ) + expect(json_response['all_dashboards']).to all(include('path', 'default', 'display_name')) end end diff --git a/spec/controllers/projects/hooks_controller_spec.rb b/spec/controllers/projects/hooks_controller_spec.rb index ba7b712964c..18f16937505 100644 --- a/spec/controllers/projects/hooks_controller_spec.rb +++ b/spec/controllers/projects/hooks_controller_spec.rb @@ -29,6 +29,22 @@ RSpec.describe Projects::HooksController do { namespace_id: project.namespace, project_id: project, id: hook.id } end + context 'with an existing token' do + hook_params = { + token: WebHook::SECRET_MASK, + url: "http://example.com" + } + + it 'does not change a token' do + expect do + post :update, params: params.merge({ hook: hook_params }) + end.not_to change { hook.reload.token } + + expect(response).to have_gitlab_http_status(:found) + expect(flash[:alert]).to be_blank + end + end + it 'adds, updates and deletes URL variables' do hook.update!(url_variables: { 'a' => 'bar', 'b' => 'woo' }) @@ -106,8 +122,9 @@ RSpec.describe Projects::HooksController do it 'sets all parameters' do hook_params = { enable_ssl_verification: true, - token: "TEST TOKEN", - url: "http://example.com", + token: 'TEST TOKEN', + url: 'http://example.com', + branch_filter_strategy: 'regex', push_events: true, tag_push_events: true, @@ -124,13 +141,39 @@ RSpec.describe Projects::HooksController do url_variables: [{ key: 'token', value: 'some secret value' }] } - post :create, params: { namespace_id: project.namespace, project_id: project, hook: hook_params } + params = { namespace_id: project.namespace, project_id: project, hook: hook_params } + + expect { post :create, params: params }.to change(ProjectHook, :count).by(1) + + project_hook = ProjectHook.order_id_desc.take + + expect(project_hook).to have_attributes( + **hook_params.merge(url_variables: { 'token' => 'some secret value' }) + ) + expect(response).to have_gitlab_http_status(:found) + expect(flash[:alert]).to be_blank + end + + it 'ignores branch_filter_strategy when flag is disabled' do + stub_feature_flags(enhanced_webhook_support_regex: false) + hook_params = { + url: 'http://example.com', + branch_filter_strategy: 'regex', + push_events: true + } + params = { namespace_id: project.namespace, project_id: project, hook: hook_params } + + expect { post :create, params: params }.to change(ProjectHook, :count).by(1) + + project_hook = ProjectHook.order_id_desc.take + + expect(project_hook).to have_attributes( + url: 'http://example.com', + branch_filter_strategy: 'wildcard' + ) expect(response).to have_gitlab_http_status(:found) expect(flash[:alert]).to be_blank - expect(ProjectHook.count).to eq(1) - expect(ProjectHook.first).to have_attributes(hook_params.except(:url_variables)) - expect(ProjectHook.first).to have_attributes(url_variables: { 'token' => 'some secret value' }) end it 'alerts the user if the new hook is invalid' do @@ -186,7 +229,7 @@ RSpec.describe Projects::HooksController do context 'when the hook fails completely' do before do allow_next(::TestHooks::ProjectService) - .to receive(:execute).and_return({ message: 'All is woe' }) + .to receive(:execute).and_return(ServiceResponse.error(message: 'All is woe')) end it 'informs the user' do @@ -204,7 +247,7 @@ RSpec.describe Projects::HooksController do it 'prevents making test requests' do expect_next_instance_of(TestHooks::ProjectService) do |service| - expect(service).to receive(:execute).and_return(http_status: 200) + expect(service).to receive(:execute).and_return(ServiceResponse.success(payload: { http_status: 200 })) end 2.times { post :test, params: { namespace_id: project.namespace, project_id: project, id: hook } } diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 0c3795540e0..8f26be442a7 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -168,75 +168,56 @@ RSpec.describe Projects::IssuesController do let_it_be(:task) { create(:issue, :task, project: project) } - context 'when work_items feature flag is enabled' do - shared_examples 'redirects to show work item page' do - it 'redirects to work item page' do - expect(response).to redirect_to(project_work_items_path(project, task.id, query)) - end - end - - context 'show action' do - let(:query) { { query: 'any' } } - + shared_examples 'redirects to show work item page' do + context 'when use_iid_in_work_items_path feature flag is disabled' do before do - get :show, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query } + stub_feature_flags(use_iid_in_work_items_path: false) end - it_behaves_like 'redirects to show work item page' - end - - context 'edit action' do - let(:query) { { query: 'any' } } + it 'redirects to work item page' do + make_request - before do - get :edit, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query } + expect(response).to redirect_to(project_work_items_path(project, task.id, query)) end - - it_behaves_like 'redirects to show work item page' end - context 'update action' do - before do - put :update, params: { namespace_id: project.namespace, project_id: project, id: task.iid, issue: { title: 'New title' } } - end + it 'redirects to work item page using iid' do + make_request - it_behaves_like 'redirects to show work item page' + expect(response).to redirect_to(project_work_items_path(project, task.iid, query.merge(iid_path: true))) end end - context 'when work_items feature flag is disabled' do - before do - stub_feature_flags(work_items: false) - end + context 'show action' do + let(:query) { { query: 'any' } } - shared_examples 'renders 404' do - it 'renders 404 for show action' do - expect(response).to have_gitlab_http_status(:not_found) + it_behaves_like 'redirects to show work item page' do + subject(:make_request) do + get :show, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query } end end + end - context 'show action' do - before do - get :show, params: { namespace_id: project.namespace, project_id: project, id: task.iid } - end - - it_behaves_like 'renders 404' - end + context 'edit action' do + let(:query) { { query: 'any' } } - context 'edit action' do - before do - get :edit, params: { namespace_id: project.namespace, project_id: project, id: task.iid } + it_behaves_like 'redirects to show work item page' do + subject(:make_request) do + get :edit, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query } end - - it_behaves_like 'renders 404' end + end - context 'update action' do - before do - put :update, params: { namespace_id: project.namespace, project_id: project, id: task.iid, issue: { title: 'New title' } } + context 'update action' do + it_behaves_like 'redirects to show work item page' do + subject(:make_request) do + put :update, params: { + namespace_id: project.namespace, + project_id: project, + id: task.iid, + issue: { title: 'New title' } + } end - - it_behaves_like 'renders 404' end end end @@ -1107,6 +1088,24 @@ RSpec.describe Projects::IssuesController do end end + context 'when trying to create a objective' do + it 'defaults to issue type' do + issue = post_new_issue(issue_type: 'objective') + + expect(issue.issue_type).to eq('issue') + expect(issue.work_item_type.base_type).to eq('issue') + end + end + + context 'when trying to create a key_result' do + it 'defaults to issue type' do + issue = post_new_issue(issue_type: 'key_result') + + expect(issue.issue_type).to eq('issue') + expect(issue.work_item_type.base_type).to eq('issue') + end + end + context 'when create service return an unrecoverable error with http_status' do let(:http_status) { 403 } @@ -1291,7 +1290,7 @@ RSpec.describe Projects::IssuesController do let!(:last_spam_log) { spam_logs.last } def post_verified_issue - post_new_issue({}, { spam_log_id: last_spam_log.id, 'g-recaptcha-response': 'abc123' } ) + post_new_issue({}, { spam_log_id: last_spam_log.id, 'g-recaptcha-response': 'abc123' }) end before do @@ -1311,7 +1310,7 @@ RSpec.describe Projects::IssuesController do it 'does not mark spam log as recaptcha_verified when it does not belong to current_user' do spam_log = create(:spam_log) - expect { post_new_issue({}, { spam_log_id: spam_log.id, 'g-recaptcha-response': true } ) } + expect { post_new_issue({}, { spam_log_id: spam_log.id, 'g-recaptcha-response': true }) } .not_to change { last_spam_log.recaptcha_verified } end end @@ -1709,19 +1708,6 @@ RSpec.describe Projects::IssuesController do expect(response).to redirect_to(project_issues_path(project)) expect(controller).to set_flash[:notice].to match(/\AYour CSV export has started/i) end - - context 'when work_items is disabled' do - before do - stub_feature_flags(work_items: false) - end - - it 'does not include tasks in CSV export' do - expect(IssuableExportCsvWorker).to receive(:perform_async) - .with(:issue, viewer.id, project.id, hash_including('issue_types' => Issue::TYPES_FOR_LIST.excluding('task'))) - - request_csv - end - end end context 'when not logged in' do diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index 556dd23c135..3dc89365530 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -660,6 +660,38 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do end end end + + context 'when CI_DEBUG_SERVICES enabled' do + let!(:variable) { create(:ci_instance_variable, key: 'CI_DEBUG_SERVICES', value: 'true') } + + context 'with proper permissions on a project' do + let(:user) { developer } + + before do + sign_in(user) + end + + it 'returns response ok' do + get_trace + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'without proper permissions for debug logging' do + let(:user) { guest } + + before do + sign_in(user) + end + + it 'returns response forbidden' do + get_trace + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + end end context 'when job has a live trace' do @@ -1184,36 +1216,51 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" end - context 'when CI_DEBUG_TRACE enabled' do - before do - create(:ci_instance_variable, key: 'CI_DEBUG_TRACE', value: 'true') + context 'when CI_DEBUG_TRACE and/or CI_DEBUG_SERVICES are enabled' do + using RSpec::Parameterized::TableSyntax + where(:ci_debug_trace, :ci_debug_services) do + 'true' | 'true' + 'true' | 'false' + 'false' | 'true' + 'false' | 'false' end - context 'with proper permissions for debug logging on a project' do - let(:user) { developer } - + with_them do before do - sign_in(user) + create(:ci_instance_variable, key: 'CI_DEBUG_TRACE', value: ci_debug_trace) + create(:ci_instance_variable, key: 'CI_DEBUG_SERVICES', value: ci_debug_services) end - it 'returns response ok' do - response = subject + context 'with proper permissions for debug logging on a project' do + let(:user) { developer } - expect(response).to have_gitlab_http_status(:ok) - end - end + before do + sign_in(user) + end - context 'without proper permissions for debug logging on a project' do - let(:user) { reporter } + it 'returns response ok' do + response = subject - before do - sign_in(user) + expect(response).to have_gitlab_http_status(:ok) + end end - it 'returns response forbidden' do - response = subject + context 'without proper permissions for debug logging on a project' do + let(:user) { reporter } - expect(response).to have_gitlab_http_status(:forbidden) + before do + sign_in(user) + end + + it 'returns response forbidden if dev mode enabled' do + response = subject + + if ci_debug_trace == 'true' || ci_debug_services == 'true' + expect(response).to have_gitlab_http_status(:forbidden) + else + expect(response).to have_gitlab_http_status(:ok) + end + end end end end @@ -1380,7 +1427,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do { 'Channel' => { 'Subprotocols' => ["terminal.gitlab.com"], - 'Url' => 'wss://localhost/proxy/build/default_port/', + 'Url' => 'wss://gitlab.example.com/proxy/build/default_port/', 'Header' => { 'Authorization' => [nil] }, @@ -1536,7 +1583,8 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_return(nil) expect(job.runner_session_url).to start_with('https://') - expect(Gitlab::Workhorse).to receive(:channel_websocket).with(a_hash_including(url: "wss://localhost/proxy/build/default_port/")) + expect(Gitlab::Workhorse).to receive(:channel_websocket) + .with(a_hash_including(url: "wss://gitlab.example.com/proxy/build/default_port/")) make_request end diff --git a/spec/controllers/projects/learn_gitlab_controller_spec.rb b/spec/controllers/projects/learn_gitlab_controller_spec.rb index 2d00fcbccf3..a93da82d948 100644 --- a/spec/controllers/projects/learn_gitlab_controller_spec.rb +++ b/spec/controllers/projects/learn_gitlab_controller_spec.rb @@ -34,8 +34,15 @@ RSpec.describe Projects::LearnGitlabController do it { is_expected.to have_gitlab_http_status(:not_found) } end - it_behaves_like 'tracks assignment and records the subject', :invite_for_help_continuous_onboarding, :namespace do - subject { project.namespace } + context 'with invite_for_help_continuous_onboarding experiment' do + it 'tracks the assignment', :experiment do + stub_experiments(invite_for_help_continuous_onboarding: true) + + expect(experiment(:invite_for_help_continuous_onboarding)) + .to track(:assignment).with_context(namespace: project.namespace).on_next_instance + + action + end end end end diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb index 367781c0e76..613d82efd06 100644 --- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb @@ -213,7 +213,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do commit: nil, latest_diff: true, only_context_commits: false, - allow_tree_conflicts: true, + merge_conflicts_in_diff: true, merge_ref_head_diff: false } end @@ -281,7 +281,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do commit: nil, latest_diff: true, only_context_commits: false, - allow_tree_conflicts: true, + merge_conflicts_in_diff: true, merge_ref_head_diff: nil } end @@ -303,7 +303,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do commit: merge_request.diff_head_commit, latest_diff: nil, only_context_commits: false, - allow_tree_conflicts: true, + merge_conflicts_in_diff: true, merge_ref_head_diff: nil } end @@ -329,7 +329,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do commit: nil, latest_diff: true, only_context_commits: false, - allow_tree_conflicts: false, + merge_conflicts_in_diff: false, merge_ref_head_diff: nil } end @@ -488,7 +488,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do commit: nil, diff_view: :inline, merge_ref_head_diff: nil, - allow_tree_conflicts: true, + merge_conflicts_in_diff: true, pagination_data: { total_pages: nil }.merge(pagination_data) @@ -616,7 +616,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do it_behaves_like 'serializes diffs with expected arguments' do let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20).merge(allow_tree_conflicts: false) } + let(:expected_options) { collection_arguments(total_pages: 20).merge(merge_conflicts_in_diff: false) } end it_behaves_like 'successful request' diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index a41abd8c16d..026cf19bde5 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe Projects::MergeRequestsController do include ProjectForksHelper include Gitlab::Routing + using RSpec::Parameterized::TableSyntax let_it_be_with_refind(:project) { create(:project, :repository) } let_it_be_with_reload(:project_public_with_private_builds) { create(:project, :repository, :public, :builds_private) } @@ -708,12 +709,14 @@ RSpec.describe Projects::MergeRequestsController do end describe 'GET commits' do - def go(format: 'html') + def go(page: nil, per_page: 1, format: 'html') get :commits, params: { namespace_id: project.namespace.to_param, project_id: project, - id: merge_request.iid + id: merge_request.iid, + page: page, + per_page: per_page }, format: format end @@ -723,6 +726,27 @@ RSpec.describe Projects::MergeRequestsController do expect(response).to render_template('projects/merge_requests/_commits') expect(json_response).to have_key('html') + expect(json_response).to have_key('next_page') + expect(json_response['next_page']).to eq(2) + end + + describe 'pagination' do + where(:page, :next_page) do + 1 | 2 + 2 | 3 + 3 | nil + end + + with_them do + it "renders the commits for page #{params[:page]}" do + go format: 'json', page: page, per_page: 10 + + expect(response).to render_template('projects/merge_requests/_commits') + expect(json_response).to have_key('html') + expect(json_response).to have_key('next_page') + expect(json_response['next_page']).to eq(next_page) + end + end end end @@ -1756,7 +1780,7 @@ RSpec.describe Projects::MergeRequestsController do end it 'renders MergeRequest as JSON' do - expect(json_response.keys).to include('id', 'iid', 'title', 'has_ci', 'merge_status', 'can_be_merged', 'current_user') + expect(json_response.keys).to include('id', 'iid', 'title', 'has_ci', 'current_user') end end @@ -1790,7 +1814,7 @@ RSpec.describe Projects::MergeRequestsController do it 'renders MergeRequest as JSON' do subject - expect(json_response.keys).to include('id', 'iid', 'title', 'has_ci', 'merge_status', 'can_be_merged', 'current_user') + expect(json_response.keys).to include('id', 'iid', 'title', 'has_ci', 'current_user') end end diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index b132c0b5a69..f66e4b133ca 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -20,23 +20,11 @@ RSpec.describe Projects::PipelinesController do end shared_examples 'the show page' do |param| - it 'redirects to pipeline path with param' do + it 'renders the show template' do get param, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - expect(response).to redirect_to(pipeline_path(pipeline, tab: param)) - end - - context 'when the FF pipeline_tabs_vue is disabled' do - before do - stub_feature_flags(pipeline_tabs_vue: false) - end - - it 'renders the show template' do - get param, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template :show - end + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show end end @@ -311,14 +299,15 @@ RSpec.describe Projects::PipelinesController do stub_application_setting(auto_devops_enabled: false) end - def action - get :index, params: { namespace_id: project.namespace, project_id: project } - end + context 'with runners_availability_section experiment' do + it 'tracks the assignment', :experiment do + stub_experiments(runners_availability_section: true) - subject { project.namespace } + expect(experiment(:runners_availability_section)) + .to track(:assignment).with_context(namespace: project.namespace).on_next_instance - context 'runners_availability_section experiment' do - it_behaves_like 'tracks assignment and records the subject', :runners_availability_section, :namespace + get :index, params: { namespace_id: project.namespace, project_id: project } + end end end @@ -710,37 +699,25 @@ RSpec.describe Projects::PipelinesController do describe 'GET failures' do let(:pipeline) { create(:ci_pipeline, project: project) } - context 'with ff `pipeline_tabs_vue` disabled' do + context 'with failed jobs' do before do - stub_feature_flags(pipeline_tabs_vue: false) + create(:ci_build, :failed, pipeline: pipeline, name: 'hello') end - context 'with failed jobs' do - before do - create(:ci_build, :failed, pipeline: pipeline, name: 'hello') - end - - it 'shows the page' do - get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template :show - end - end - - context 'without failed jobs' do - it 'redirects to the main pipeline page' do - get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + it 'shows the page' do + get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - expect(response).to redirect_to(pipeline_path(pipeline)) - end + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show end end - it 'redirects to the pipeline page with `failures` query param' do - get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + context 'without failed jobs' do + it 'redirects to the main pipeline page' do + get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } - expect(response).to redirect_to(pipeline_path(pipeline, tab: 'failures')) + expect(response).to redirect_to(pipeline_path(pipeline)) + end end end diff --git a/spec/controllers/projects/product_analytics_controller_spec.rb b/spec/controllers/projects/product_analytics_controller_spec.rb deleted file mode 100644 index 47f1d96c70b..00000000000 --- a/spec/controllers/projects/product_analytics_controller_spec.rb +++ /dev/null @@ -1,95 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Projects::ProductAnalyticsController do - let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } - - before(:all) do - project.add_maintainer(user) - end - - before do - sign_in(user) - stub_feature_flags(product_analytics: true) - end - - describe 'GET #index' do - it 'renders index with 200 status code' do - get :index, params: project_params - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template(:index) - end - - context 'with an anonymous user' do - before do - sign_out(user) - end - - it 'redirects to sign-in page' do - get :index, params: project_params - - expect(response).to redirect_to(new_user_session_path) - end - end - - context 'feature flag disabled' do - before do - stub_feature_flags(product_analytics: false) - end - - it 'returns not found' do - get :index, params: project_params - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - describe 'GET #test' do - it 'renders test with 200 status code' do - get :test, params: project_params - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template(:test) - end - end - - describe 'GET #setup' do - it 'renders setup with 200 status code' do - get :setup, params: project_params - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template(:setup) - end - end - - describe 'GET #graphs' do - it 'renders graphs with 200 status code' do - get :graphs, params: project_params - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template(:graphs) - end - - context 'feature flag disabled' do - before do - stub_feature_flags(product_analytics: false) - end - - it 'returns not found' do - get :graphs, params: project_params - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - private - - def project_params(opts = {}) - opts.reverse_merge(namespace_id: project.namespace, project_id: project) - end -end diff --git a/spec/controllers/projects/prometheus/alerts_controller_spec.rb b/spec/controllers/projects/prometheus/alerts_controller_spec.rb index 2c2c8180143..09b9f25c0c6 100644 --- a/spec/controllers/projects/prometheus/alerts_controller_spec.rb +++ b/spec/controllers/projects/prometheus/alerts_controller_spec.rb @@ -56,7 +56,7 @@ RSpec.describe Projects::Prometheus::AlertsController do describe 'POST #notify' do let(:alert_1) { build(:alert_management_alert, :prometheus, project: project) } let(:alert_2) { build(:alert_management_alert, :prometheus, project: project) } - let(:service_response) { ServiceResponse.success(payload: { alerts: [alert_1, alert_2] }) } + let(:service_response) { ServiceResponse.success(http_status: :created) } let(:notify_service) { instance_double(Projects::Prometheus::Alerts::NotifyService, execute: service_response) } before do @@ -68,17 +68,12 @@ RSpec.describe Projects::Prometheus::AlertsController do .and_return(notify_service) end - it 'returns ok if notification succeeds' do + it 'returns created if notification succeeds' do expect(notify_service).to receive(:execute).and_return(service_response) post :notify, params: project_params, session: { as: :json } - expect(json_response).to contain_exactly( - { 'iid' => alert_1.iid, 'title' => alert_1.title }, - { 'iid' => alert_2.iid, 'title' => alert_2.title } - ) - - expect(response).to have_gitlab_http_status(:ok) + expect(response).to have_gitlab_http_status(:created) end it 'returns unprocessable entity if notification fails' do diff --git a/spec/controllers/projects/registry/repositories_controller_spec.rb b/spec/controllers/projects/registry/repositories_controller_spec.rb index a5faaaf5969..f4f5c182850 100644 --- a/spec/controllers/projects/registry/repositories_controller_spec.rb +++ b/spec/controllers/projects/registry/repositories_controller_spec.rb @@ -103,10 +103,11 @@ RSpec.describe Projects::Registry::RepositoriesController do stub_container_registry_tags(repository: :any, tags: []) end - it 'schedules a job to delete a repository' do - expect(DeleteContainerRepositoryWorker).to receive(:perform_async).with(user.id, repository.id) + it 'marks the repository as delete_scheduled' do + expect(DeleteContainerRepositoryWorker).not_to receive(:perform_async).with(user.id, repository.id) - delete_repository(repository) + expect { delete_repository(repository) } + .to change { repository.reload.status }.from(nil).to('delete_scheduled') expect(repository.reload).to be_delete_scheduled expect(response).to have_gitlab_http_status(:no_content) @@ -119,6 +120,22 @@ RSpec.describe Projects::Registry::RepositoriesController do expect_snowplow_event(category: anything, action: 'delete_repository') end + + context 'with container_registry_delete_repository_with_cron_worker disabled' do + before do + stub_feature_flags(container_registry_delete_repository_with_cron_worker: false) + end + + it 'schedules a job to delete a repository' do + expect(DeleteContainerRepositoryWorker).to receive(:perform_async).with(user.id, repository.id) + + expect { delete_repository(repository) } + .to change { repository.reload.status }.from(nil).to('delete_scheduled') + + expect(repository.reload).to be_delete_scheduled + expect(response).to have_gitlab_http_status(:no_content) + end + end end end end @@ -137,7 +154,7 @@ RSpec.describe Projects::Registry::RepositoriesController do end end - def go_to_index(format: :html, params: {} ) + def go_to_index(format: :html, params: {}) get :index, params: params.merge({ namespace_id: project.namespace, project_id: project diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb index b307bb357fa..2afd080344d 100644 --- a/spec/controllers/projects/releases_controller_spec.rb +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -112,7 +112,7 @@ RSpec.describe Projects::ReleasesController do it "returns the project's releases as JSON, ordered by released_at" do get_index - expect(json_response.map { |release| release["id"] } ).to eq([release_2.id, release_1.id]) + expect(json_response.map { |release| release["id"] }).to eq([release_2.id, release_1.id]) end it_behaves_like 'common access controls' diff --git a/spec/controllers/projects/runners_controller_spec.rb b/spec/controllers/projects/runners_controller_spec.rb index 57d1695b842..1066c4ec9f6 100644 --- a/spec/controllers/projects/runners_controller_spec.rb +++ b/spec/controllers/projects/runners_controller_spec.rb @@ -25,7 +25,7 @@ RSpec.describe Projects::RunnersController do new_desc = runner.description.swapcase expect do - post :update, params: params.merge(runner: { description: new_desc } ) + post :update, params: params.merge(runner: { description: new_desc }) end.to change { runner.ensure_runner_queue_value } runner.reload diff --git a/spec/controllers/projects/settings/integrations_controller_spec.rb b/spec/controllers/projects/settings/integrations_controller_spec.rb index b76269f6f93..2b23f177a9d 100644 --- a/spec/controllers/projects/settings/integrations_controller_spec.rb +++ b/spec/controllers/projects/settings/integrations_controller_spec.rb @@ -334,6 +334,23 @@ RSpec.describe Projects::Settings::IntegrationsController do ) end end + + context 'with chat notification integration' do + let_it_be(:integration) { project.create_microsoft_teams_integration(webhook: 'http://webhook.com') } + let(:message) { 'Microsoft Teams notifications settings saved and active.' } + + it_behaves_like 'integration update' + + context 'with masked token' do + let(:integration_params) { { active: true, webhook: '************' } } + + it_behaves_like 'integration update' + + it 'does not update the webhook' do + expect(integration.reload.webhook).to eq('http://webhook.com') + end + end + end end describe 'as JSON' do diff --git a/spec/controllers/projects/settings/repository_controller_spec.rb b/spec/controllers/projects/settings/repository_controller_spec.rb index 22287fea82c..ea50ff6caa0 100644 --- a/spec/controllers/projects/settings/repository_controller_spec.rb +++ b/spec/controllers/projects/settings/repository_controller_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe Projects::Settings::RepositoryController do let(:project) { create(:project_empty_repo, :public) } let(:user) { create(:user) } + let(:base_params) { { namespace_id: project.namespace, project_id: project } } before do project.add_maintainer(user) @@ -13,7 +14,7 @@ RSpec.describe Projects::Settings::RepositoryController do describe 'GET show' do it 'renders show with 200 status code' do - get :show, params: { namespace_id: project.namespace, project_id: project } + get :show, params: base_params expect(response).to have_gitlab_http_status(:ok) expect(response).to render_template(:show) @@ -29,7 +30,7 @@ RSpec.describe Projects::Settings::RepositoryController do .with(project, user, anything) .and_return(status: :success) - put :cleanup, params: { namespace_id: project.namespace, project_id: project, project: { bfg_object_map: object_map } } + put :cleanup, params: base_params.merge({ project: { bfg_object_map: object_map } }) expect(response).to redirect_to project_settings_repository_path(project) end @@ -41,7 +42,7 @@ RSpec.describe Projects::Settings::RepositoryController do .with(project, user, anything) .and_return(status: :error, message: 'error message') - put :cleanup, params: { namespace_id: project.namespace, project_id: project, project: { bfg_object_map: object_map } } + put :cleanup, params: base_params.merge({ project: { bfg_object_map: object_map } }) expect(controller).to set_flash[:alert].to('error message') expect(response).to redirect_to project_settings_repository_path(project) @@ -50,83 +51,138 @@ RSpec.describe Projects::Settings::RepositoryController do end describe 'POST create_deploy_token' do - context 'when ajax_new_deploy_token feature flag is disabled for the project' do - before do - stub_feature_flags(ajax_new_deploy_token: false) + let(:good_deploy_token_params) do + { + name: 'name', + expires_at: 1.day.from_now.to_s, + username: 'deployer', + read_repository: '1', + deploy_token_type: DeployToken.deploy_token_types[:project_type] + } + end + + let(:request_params) { base_params.merge({ deploy_token: deploy_token_params }) } + + subject { post :create_deploy_token, params: request_params, format: :json } + + context('a good request') do + let(:deploy_token_params) { good_deploy_token_params } + let(:expected_response) do + { + 'id' => be_a(Integer), + 'name' => deploy_token_params[:name], + 'username' => deploy_token_params[:username], + 'expires_at' => Time.zone.parse(deploy_token_params[:expires_at]), + 'token' => be_a(String), + 'expired' => false, + 'revoked' => false, + 'scopes' => deploy_token_params.inject([]) do |scopes, kv| + key, value = kv + key.to_s.start_with?('read_') && value.to_i != 0 ? scopes << key.to_s : scopes + end + } end - it_behaves_like 'a created deploy token' do - let(:entity) { project } - let(:create_entity_params) { { namespace_id: project.namespace, project_id: project } } - let(:deploy_token_type) { DeployToken.deploy_token_types[:project_type] } + it 'creates the deploy token' do + subject + + expect(response).to have_gitlab_http_status(:created) + expect(response).to match_response_schema('public_api/v4/deploy_token') + expect(json_response).to match(expected_response) end end - context 'when ajax_new_deploy_token feature flag is enabled for the project' do - let(:good_deploy_token_params) do - { - name: 'name', - expires_at: 1.day.from_now.to_s, - username: 'deployer', - read_repository: '1', - deploy_token_type: DeployToken.deploy_token_types[:project_type] - } + context('a bad request') do + let(:deploy_token_params) { good_deploy_token_params.except(:read_repository) } + let(:expected_response) { { 'message' => "Scopes can't be blank" } } + + it 'does not create the deploy token' do + subject + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response).to match(expected_response) end + end - let(:request_params) do - { - namespace_id: project.namespace.to_param, - project_id: project.to_param, - deploy_token: deploy_token_params - } + context('an invalid request') do + let(:deploy_token_params) { good_deploy_token_params.except(:name) } + + it 'raises a validation error' do + expect { subject }.to raise_error(ActiveRecord::StatementInvalid) end + end + end - subject { post :create_deploy_token, params: request_params, format: :json } - - context('a good request') do - let(:deploy_token_params) { good_deploy_token_params } - let(:expected_response) do - { - 'id' => be_a(Integer), - 'name' => deploy_token_params[:name], - 'username' => deploy_token_params[:username], - 'expires_at' => Time.zone.parse(deploy_token_params[:expires_at]), - 'token' => be_a(String), - 'expired' => false, - 'revoked' => false, - 'scopes' => deploy_token_params.inject([]) do |scopes, kv| - key, value = kv - key.to_s.start_with?('read_') && value.to_i != 0 ? scopes << key.to_s : scopes - end - } + describe 'PUT update' do + let(:project) { create(:project, :repository) } + + context 'when updating default branch' do + let!(:previous_default_branch) { project.default_branch } + + let(:new_default_branch) { 'feature' } + let(:request_params) { base_params.merge({ project: project_params_attributes }) } + + subject { put :update, params: request_params } + + context('with a good request') do + let(:project_params_attributes) { { default_branch: new_default_branch } } + + it "updates default branch and redirect to project_settings_repository_path" do + expect do + subject + end.to change { + Project.find(project.id).default_branch # refind to reset the default branch cache + }.from(previous_default_branch).to(new_default_branch) + + expect(response).to redirect_to project_settings_repository_path(project) + expect(controller).to set_flash[:notice].to("Project settings were successfully updated.") end + end - it 'creates the deploy token' do - subject + context('with a bad input') do + let(:project_params_attributes) { { default_branch: 'non_existent_branch' } } - expect(response).to have_gitlab_http_status(:created) - expect(response).to match_response_schema('public_api/v4/deploy_token') - expect(json_response).to match(expected_response) + it "does not update default branch and shows an alert" do + expect do + subject + end.not_to change { + Project.find(project.id).default_branch # refind to reset the default branch cache + } + + expect(response).to redirect_to project_settings_repository_path(project) + expect(controller).to set_flash[:alert].to("Could not set the default branch") end end + end + + context 'when updating branch names template from issues' do + let(:branch_name_template) { 'feat/GL-%{id}-%{title}' } - context('a bad request') do - let(:deploy_token_params) { good_deploy_token_params.except(:read_repository) } - let(:expected_response) { { 'message' => "Scopes can't be blank" } } + let(:request_params) { base_params.merge({ project: project_params_attributes }) } - it 'does not create the deploy token' do + subject { put :update, params: request_params } + + context('with a good request') do + let(:project_params_attributes) { { issue_branch_template: branch_name_template } } + + it "updates issue_branch_template and redirect to project_settings_repository_path" do subject - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response).to match(expected_response) + expect(response).to redirect_to project_settings_repository_path(project) + expect(controller).to set_flash[:notice].to("Project settings were successfully updated.") + expect(project.reload.issue_branch_template).to eq(branch_name_template) end end - context('an invalid request') do - let(:deploy_token_params) { good_deploy_token_params.except(:name) } + context('with a bad input') do + let(:project_params_attributes) { { issue_branch_template: 'a' * 260 } } + + it "updates issue_branch_template and redirect to project_settings_repository_path" do + subject - it 'raises a validation error' do - expect { subject }.to raise_error(ActiveRecord::StatementInvalid) + expect(response).to redirect_to project_settings_repository_path(project) + expect(controller).to set_flash[:alert].to("Project setting issue branch template is too long (maximum is 255 characters)") + expect(project.reload.issue_branch_template).to eq(nil) end end end diff --git a/spec/controllers/projects/starrers_controller_spec.rb b/spec/controllers/projects/starrers_controller_spec.rb index 8d03600cd58..2148f495c31 100644 --- a/spec/controllers/projects/starrers_controller_spec.rb +++ b/spec/controllers/projects/starrers_controller_spec.rb @@ -6,6 +6,7 @@ RSpec.describe Projects::StarrersController do let(:user_1) { create(:user, name: 'John') } let(:user_2) { create(:user, name: 'Michael') } let(:private_user) { create(:user, name: 'Michael Douglas', private_profile: true) } + let(:blocked_user) { create(:user, state: 'blocked') } let(:admin) { create(:user, admin: true) } let(:project) { create(:project, :public) } @@ -13,6 +14,7 @@ RSpec.describe Projects::StarrersController do user_1.toggle_star(project) user_2.toggle_star(project) private_user.toggle_star(project) + blocked_user.toggle_star(project) end describe 'GET index' do @@ -61,6 +63,10 @@ RSpec.describe Projects::StarrersController do expect(user_ids).to contain_exactly(user_1.id, user_2.id) end + it 'non-active users are not visible' do + expect(user_ids).not_to include(blocked_user.id) + end + include_examples 'starrers counts' end |