diff options
Diffstat (limited to 'spec/controllers/projects')
93 files changed, 1742 insertions, 779 deletions
diff --git a/spec/controllers/projects/alert_management_controller_spec.rb b/spec/controllers/projects/alert_management_controller_spec.rb index b84376db33d..6a1952f949b 100644 --- a/spec/controllers/projects/alert_management_controller_spec.rb +++ b/spec/controllers/projects/alert_management_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::AlertManagementController do +RSpec.describe Projects::AlertManagementController do let_it_be(:project) { create(:project) } let_it_be(:role) { :developer } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/alerting/notifications_controller_spec.rb b/spec/controllers/projects/alerting/notifications_controller_spec.rb index 9d26c2278b1..33fd73c762a 100644 --- a/spec/controllers/projects/alerting/notifications_controller_spec.rb +++ b/spec/controllers/projects/alerting/notifications_controller_spec.rb @@ -2,90 +2,101 @@ require 'spec_helper' -describe Projects::Alerting::NotificationsController do +RSpec.describe Projects::Alerting::NotificationsController do let_it_be(:project) { create(:project) } let_it_be(:environment) { create(:environment, project: project) } describe 'POST #create' do - let(:service_response) { ServiceResponse.success } - let(:notify_service) { instance_double(Projects::Alerting::NotifyService, execute: service_response) } - around do |example| ForgeryProtection.with_forgery_protection { example.run } end - before do - allow(Projects::Alerting::NotifyService).to receive(:new).and_return(notify_service) - end + shared_examples 'process alert payload' do |notify_service_class| + let(:service_response) { ServiceResponse.success } + let(:notify_service) { instance_double(notify_service_class, execute: service_response) } - def make_request(body = {}) - post :create, params: project_params, body: body.to_json, as: :json - end + before do + allow(notify_service_class).to receive(:new).and_return(notify_service) + end - context 'when notification service succeeds' do - let(:payload) do - { - title: 'Alert title', - hosts: 'https://gitlab.com' - } + def make_request + post :create, params: project_params, body: payload.to_json, as: :json end - let(:permitted_params) { ActionController::Parameters.new(payload).permit! } + context 'when notification service succeeds' do + let(:permitted_params) { ActionController::Parameters.new(payload).permit! } - it 'responds with ok' do - make_request + it 'responds with ok' do + make_request - expect(response).to have_gitlab_http_status(:ok) - end + expect(response).to have_gitlab_http_status(:ok) + end - it 'does not pass excluded parameters to the notify service' do - make_request(payload) + it 'does not pass excluded parameters to the notify service' do + make_request - expect(Projects::Alerting::NotifyService) - .to have_received(:new) - .with(project, nil, permitted_params) + expect(notify_service_class) + .to have_received(:new) + .with(project, nil, permitted_params) + end end - end - context 'when notification service fails' do - let(:service_response) { ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized) } + context 'when notification service fails' do + let(:service_response) { ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized) } - it 'responds with the service response' do - make_request + it 'responds with the service response' do + make_request - expect(response).to have_gitlab_http_status(:unauthorized) + expect(response).to have_gitlab_http_status(:unauthorized) + end end - end - context 'bearer token' do - context 'when set' do - it 'extracts bearer token' do - request.headers['HTTP_AUTHORIZATION'] = 'Bearer some token' + context 'bearer token' do + context 'when set' do + it 'extracts bearer token' do + request.headers['HTTP_AUTHORIZATION'] = 'Bearer some token' - expect(notify_service).to receive(:execute).with('some token') + expect(notify_service).to receive(:execute).with('some token') - make_request - end + make_request + end - it 'pass nil if cannot extract a non-bearer token' do - request.headers['HTTP_AUTHORIZATION'] = 'some token' + it 'pass nil if cannot extract a non-bearer token' do + request.headers['HTTP_AUTHORIZATION'] = 'some token' - expect(notify_service).to receive(:execute).with(nil) + expect(notify_service).to receive(:execute).with(nil) - make_request + make_request + end end - end - context 'when missing' do - it 'passes nil' do - expect(notify_service).to receive(:execute).with(nil) + context 'when missing' do + it 'passes nil' do + expect(notify_service).to receive(:execute).with(nil) - make_request + make_request + end end end end + + context 'generic alert payload' do + it_behaves_like 'process alert payload', Projects::Alerting::NotifyService do + let(:payload) { { title: 'Alert title' } } + end + end + + context 'Prometheus alert payload' do + include PrometheusHelpers + + it_behaves_like 'process alert payload', Projects::Prometheus::Alerts::NotifyService do + let(:payload) { prometheus_alert_payload } + end + end end + private + def project_params(opts = {}) opts.reverse_merge(namespace_id: project.namespace, project_id: project) end diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb index 4c815a5b40c..69ab9873b90 100644 --- a/spec/controllers/projects/artifacts_controller_spec.rb +++ b/spec/controllers/projects/artifacts_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ArtifactsController do +RSpec.describe Projects::ArtifactsController do include RepoHelpers let(:user) { project.owner } @@ -371,10 +371,9 @@ describe Projects::ArtifactsController do end context 'when the artifact is zip' do - let!(:artifact) { create(:ci_job_artifact, :lsif, job: job, file_path: Rails.root.join("spec/fixtures/#{file_name}")) } + let!(:artifact) { create(:ci_job_artifact, :lsif, job: job) } let(:path) { 'lsif/main.go.json' } - let(:file_name) { 'lsif.json.zip' } - let(:archive_matcher) { file_name } + let(:archive_matcher) { 'lsif.json.zip' } let(:query_params) { super().merge(file_type: :lsif, path: path) } it_behaves_like 'a valid file' do diff --git a/spec/controllers/projects/autocomplete_sources_controller_spec.rb b/spec/controllers/projects/autocomplete_sources_controller_spec.rb index d35192b2ccb..865b31a28d7 100644 --- a/spec/controllers/projects/autocomplete_sources_controller_spec.rb +++ b/spec/controllers/projects/autocomplete_sources_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::AutocompleteSourcesController do +RSpec.describe Projects::AutocompleteSourcesController do let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, namespace: group) } let_it_be(:issue) { create(:issue, project: project) } diff --git a/spec/controllers/projects/avatars_controller_spec.rb b/spec/controllers/projects/avatars_controller_spec.rb index 54c2397625f..16e9c845307 100644 --- a/spec/controllers/projects/avatars_controller_spec.rb +++ b/spec/controllers/projects/avatars_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::AvatarsController do +RSpec.describe Projects::AvatarsController do let_it_be(:project) { create(:project, :repository) } before do diff --git a/spec/controllers/projects/badges_controller_spec.rb b/spec/controllers/projects/badges_controller_spec.rb index 4ae29ba7f54..7e7a630921f 100644 --- a/spec/controllers/projects/badges_controller_spec.rb +++ b/spec/controllers/projects/badges_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::BadgesController do +RSpec.describe Projects::BadgesController do let(:project) { pipeline.project } let!(:pipeline) { create(:ci_empty_pipeline) } let(:user) { create(:user) } @@ -54,7 +54,7 @@ describe Projects::BadgesController do context 'when style param is set to `flat`' do it 'renders the `flat` badge layout' do - get_badge(badge_type, 'flat') + get_badge(badge_type, style: 'flat') expect(response).to render_template('projects/badges/badge') end @@ -62,7 +62,7 @@ describe Projects::BadgesController do context 'when style param is set to an invalid type' do it 'renders the `flat` (default) badge layout' do - get_badge(badge_type, 'xxx') + get_badge(badge_type, style: 'xxx') expect(response).to render_template('projects/badges/badge') end @@ -70,7 +70,7 @@ describe Projects::BadgesController do context 'when style param is set to `flat-square`' do it 'renders the `flat-square` badge layout' do - get_badge(badge_type, 'flat-square') + get_badge(badge_type, style: 'flat-square') expect(response).to render_template('projects/badges/badge_flat-square') end @@ -102,12 +102,37 @@ describe Projects::BadgesController do end it 'defaults to project permissions' do - get_badge(:coverage) + get_badge(badge_type) expect(response).to have_gitlab_http_status(:not_found) end end end + + context 'customization' do + render_views + + before do + project.add_maintainer(user) + sign_in(user) + end + + context 'when key_text param is used' do + it 'sets custom key text' do + get_badge(badge_type, key_text: 'custom key text') + + expect(response.body).to include('custom key text') + end + end + + context 'when key_width param is used' do + it 'sets custom key width' do + get_badge(badge_type, key_width: '123') + + expect(response.body).to include('123') + end + end + end end describe '#pipeline' do @@ -118,13 +143,12 @@ describe Projects::BadgesController do it_behaves_like 'a badge resource', :coverage end - def get_badge(badge, style = nil) + def get_badge(badge, args = {}) params = { namespace_id: project.namespace.to_param, project_id: project, - ref: pipeline.ref, - style: style - } + ref: pipeline.ref + }.merge(args.slice(:style, :key_text, :key_width)) get badge, params: params, format: :svg end diff --git a/spec/controllers/projects/blame_controller_spec.rb b/spec/controllers/projects/blame_controller_spec.rb index ac8394e3cd4..bf475f6135a 100644 --- a/spec/controllers/projects/blame_controller_spec.rb +++ b/spec/controllers/projects/blame_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::BlameController do +RSpec.describe Projects::BlameController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index ad04c6e61e8..9fee97f938c 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::BlobController do +RSpec.describe Projects::BlobController do include ProjectForksHelper let(:project) { create(:project, :public, :repository) } @@ -378,6 +378,22 @@ describe Projects::BlobController do expect(response).to redirect_to(after_delete_path) end + + context 'when a validation failure occurs' do + let(:failure_path) { project_blob_path(project, default_params[:id]) } + + render_views + + it 'redirects to a valid page' do + expect_next_instance_of(Files::DeleteService) do |instance| + expect(instance).to receive(:validate!).and_raise(Commits::CreateService::ValidationError, "validation error") + end + + delete :destroy, params: default_params + + expect(response).to redirect_to(failure_path) + end + end end context 'if deleted file is the last one in a subdirectory' do diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb index 6634801939b..dad932f9cdf 100644 --- a/spec/controllers/projects/boards_controller_spec.rb +++ b/spec/controllers/projects/boards_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::BoardsController do +RSpec.describe Projects::BoardsController do let(:project) { create(:project) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 174d8904481..625fc5bddda 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -2,14 +2,13 @@ require 'spec_helper' -describe Projects::BranchesController do +RSpec.describe Projects::BranchesController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:developer) { create(:user) } before do - project.add_maintainer(user) - project.add_developer(user) + project.add_developer(developer) allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz']) allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0']) @@ -21,7 +20,7 @@ describe Projects::BranchesController do context "on creation of a new branch" do before do - sign_in(user) + sign_in(developer) post :create, params: { @@ -80,7 +79,7 @@ describe Projects::BranchesController do let(:issue) { create(:issue, project: project) } before do - sign_in(user) + sign_in(developer) end it 'redirects' do @@ -97,7 +96,7 @@ describe Projects::BranchesController do end it 'posts a system note' do - expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, "1-feature-branch", branch_project: project) + expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, developer, "1-feature-branch", branch_project: project) post :create, params: { @@ -136,14 +135,14 @@ describe Projects::BranchesController do context 'user can update issue' do before do - confidential_issue_project.add_reporter(user) + confidential_issue_project.add_reporter(developer) end context 'issue is under the specified project' do let(:issue) { create(:issue, project: confidential_issue_project) } it 'posts a system note' do - expect(SystemNoteService).to receive(:new_issue_branch).with(issue, confidential_issue_project, user, "1-feature-branch", branch_project: project) + expect(SystemNoteService).to receive(:new_issue_branch).with(issue, confidential_issue_project, developer, "1-feature-branch", branch_project: project) create_branch_with_confidential_issue_project end @@ -264,7 +263,7 @@ describe Projects::BranchesController do describe 'POST create with JSON format' do before do - sign_in(user) + sign_in(developer) end context 'with valid params' do @@ -305,7 +304,7 @@ describe Projects::BranchesController do render_views before do - sign_in(user) + sign_in(developer) end it 'returns 303' do @@ -325,7 +324,7 @@ describe Projects::BranchesController do render_views before do - sign_in(user) + sign_in(developer) post :destroy, format: format, @@ -436,7 +435,7 @@ describe Projects::BranchesController do context 'when user is allowed to push' do before do - sign_in(user) + sign_in(developer) end it 'redirects to branches' do @@ -454,7 +453,7 @@ describe Projects::BranchesController do context 'when user is not allowed to push' do before do - sign_in(developer) + sign_in(user) end it 'responds with status 404' do @@ -469,7 +468,7 @@ describe Projects::BranchesController do render_views before do - sign_in(user) + sign_in(developer) end context 'when rendering a JSON format' do @@ -487,6 +486,82 @@ describe Projects::BranchesController do end end + context 'when a branch has multiple pipelines' do + it 'chooses the latest to determine status' do + sha = project.repository.create_file(developer, generate(:branch), 'content', message: 'message', branch_name: 'master') + create(:ci_pipeline, + project: project, + user: developer, + ref: "master", + sha: sha, + status: :running, + created_at: 6.months.ago) + create(:ci_pipeline, + project: project, + user: developer, + ref: "master", + sha: sha, + status: :success, + created_at: 2.months.ago) + + get :index, + format: :html, + params: { + namespace_id: project.namespace, + project_id: project, + state: 'all' + } + + expect(controller.instance_variable_get(:@branch_pipeline_statuses)["master"].group).to eq("success") + end + end + + context 'when multiple branches exist' do + it 'all relevant commit statuses are received' do + master_sha = project.repository.create_file(developer, generate(:branch), 'content', message: 'message', branch_name: 'master') + create(:ci_pipeline, + project: project, + user: developer, + ref: "master", + sha: master_sha, + status: :running, + created_at: 6.months.ago) + test_sha = project.repository.create_file(developer, generate(:branch), 'content', message: 'message', branch_name: 'test') + create(:ci_pipeline, + project: project, + user: developer, + ref: "test", + sha: test_sha, + status: :success, + created_at: 2.months.ago) + + get :index, + format: :html, + params: { + namespace_id: project.namespace, + project_id: project, + state: 'all' + } + + expect(controller.instance_variable_get(:@branch_pipeline_statuses)["master"].group).to eq("running") + expect(controller.instance_variable_get(:@branch_pipeline_statuses)["test"].group).to eq("success") + end + end + + context 'when a branch contains no pipelines' do + it 'no commit statuses are received' do + get :index, + format: :html, + params: { + namespace_id: project.namespace, + project_id: project, + state: 'all' + } + + expect(controller.instance_variable_get(:@branch_pipeline_statuses)).to be_blank + end + end + # We need :request_store because Gitaly only counts the queries whenever # `RequestStore.active?` in GitalyClient.enforce_gitaly_request_limits # And the main goal of this test is making sure TooManyInvocationsError @@ -564,7 +639,7 @@ describe Projects::BranchesController do describe 'GET diverging_commit_counts' do before do - sign_in(user) + sign_in(developer) end it 'returns the commit counts behind and ahead of default branch' do diff --git a/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb b/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb index ac31045678f..252ad6ec9c4 100644 --- a/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb +++ b/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb @@ -2,34 +2,27 @@ require 'spec_helper' -describe Projects::Ci::DailyBuildGroupReportResultsController do +RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do describe 'GET index' do let(:project) { create(:project, :public, :repository) } let(:ref_path) { 'refs/heads/master' } let(:param_type) { 'coverage' } let(:start_date) { '2019-12-10' } let(:end_date) { '2020-03-09' } - - def create_daily_coverage(group_name, coverage, date) - create( - :ci_daily_build_group_report_result, - project: project, - ref_path: ref_path, - group_name: group_name, - data: { 'coverage' => coverage }, - date: date - ) - end - - def csv_response - CSV.parse(response.body) - end + let(:allowed_to_read) { true } + let(:user) { create(:user) } before do create_daily_coverage('rspec', 79.0, '2020-03-09') + create_daily_coverage('rspec', 77.0, '2020-03-08') create_daily_coverage('karma', 81.0, '2019-12-10') - create_daily_coverage('rspec', 67.0, '2019-12-09') - create_daily_coverage('karma', 71.0, '2019-12-09') + create_daily_coverage('minitest', 67.0, '2019-12-09') + create_daily_coverage('mocha', 71.0, '2019-12-09') + + sign_in(user) + + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(user, :read_build_report_results, project).and_return(allowed_to_read) get :index, params: { namespace_id: project.namespace, @@ -38,43 +31,126 @@ describe Projects::Ci::DailyBuildGroupReportResultsController do param_type: param_type, start_date: start_date, end_date: end_date, - format: :csv + format: format } end - it 'serves the results in CSV' do - expect(response).to have_gitlab_http_status(:ok) - expect(response.headers['Content-Type']).to eq('text/csv; charset=utf-8') + shared_examples_for 'validating param_type' do + context 'when given param_type is invalid' do + let(:param_type) { 'something_else' } - expect(csv_response).to eq([ - %w[date group_name coverage], - ['2020-03-09', 'rspec', '79.0'], - ['2019-12-10', 'karma', '81.0'] - ]) + it 'responds with 422 error' do + expect(response).to have_gitlab_http_status(:unprocessable_entity) + end + end end - context 'when given date range spans more than 90 days' do - let(:start_date) { '2019-12-09' } - let(:end_date) { '2020-03-09' } + shared_examples_for 'ensuring policy' do + context 'when user is not allowed to read build report results' do + let(:allowed_to_read) { false } + + it 'responds with 404 error' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end - it 'limits the result to 90 days from the given start_date' do + context 'when format is CSV' do + let(:format) { :csv } + + it 'serves the results in CSV' do expect(response).to have_gitlab_http_status(:ok) expect(response.headers['Content-Type']).to eq('text/csv; charset=utf-8') expect(csv_response).to eq([ %w[date group_name coverage], ['2020-03-09', 'rspec', '79.0'], + ['2020-03-08', 'rspec', '77.0'], ['2019-12-10', 'karma', '81.0'] ]) end + + context 'when given date range spans more than 90 days' do + let(:start_date) { '2019-12-09' } + let(:end_date) { '2020-03-09' } + + it 'limits the result to 90 days from the given start_date' do + expect(csv_response).to eq([ + %w[date group_name coverage], + ['2020-03-09', 'rspec', '79.0'], + ['2020-03-08', 'rspec', '77.0'], + ['2019-12-10', 'karma', '81.0'] + ]) + end + end + + it_behaves_like 'validating param_type' + it_behaves_like 'ensuring policy' end - context 'when given param_type is invalid' do - let(:param_type) { 'something_else' } + context 'when format is JSON' do + let(:format) { :json } + + it 'serves the results in JSON' do + expect(response).to have_gitlab_http_status(:ok) - it 'responds with 422 error' do - expect(response).to have_gitlab_http_status(:unprocessable_entity) + expect(json_response).to eq([ + { + 'group_name' => 'rspec', + 'data' => [ + { 'date' => '2020-03-09', 'coverage' => 79.0 }, + { 'date' => '2020-03-08', 'coverage' => 77.0 } + ] + }, + { + 'group_name' => 'karma', + 'data' => [ + { 'date' => '2019-12-10', 'coverage' => 81.0 } + ] + } + ]) end + + context 'when given date range spans more than 90 days' do + let(:start_date) { '2019-12-09' } + let(:end_date) { '2020-03-09' } + + it 'limits the result to 90 days from the given start_date' do + expect(json_response).to eq([ + { + 'group_name' => 'rspec', + 'data' => [ + { 'date' => '2020-03-09', 'coverage' => 79.0 }, + { 'date' => '2020-03-08', 'coverage' => 77.0 } + ] + }, + { + 'group_name' => 'karma', + 'data' => [ + { 'date' => '2019-12-10', 'coverage' => 81.0 } + ] + } + ]) + end + end + + it_behaves_like 'validating param_type' + it_behaves_like 'ensuring policy' end end + + def create_daily_coverage(group_name, coverage, date) + create( + :ci_daily_build_group_report_result, + project: project, + ref_path: ref_path, + group_name: group_name, + data: { 'coverage' => coverage }, + date: date + ) + end + + def csv_response + CSV.parse(response.body) + end end diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb index f45b1d7ddd8..eb92385fc83 100644 --- a/spec/controllers/projects/ci/lints_controller_spec.rb +++ b/spec/controllers/projects/ci/lints_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Ci::LintsController do +RSpec.describe Projects::Ci::LintsController do include StubRequests let(:project) { create(:project, :repository) } diff --git a/spec/controllers/projects/clusters/applications_controller_spec.rb b/spec/controllers/projects/clusters/applications_controller_spec.rb index 6de3593be28..b50814b4790 100644 --- a/spec/controllers/projects/clusters/applications_controller_spec.rb +++ b/spec/controllers/projects/clusters/applications_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Clusters::ApplicationsController do +RSpec.describe Projects::Clusters::ApplicationsController do include AccessMatchersForController def current_application diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb index 698a3773d59..5645e25b741 100644 --- a/spec/controllers/projects/clusters_controller_spec.rb +++ b/spec/controllers/projects/clusters_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ClustersController do +RSpec.describe Projects::ClustersController do include AccessMatchersForController include GoogleApi::CloudPlatformHelpers include KubernetesHelpers @@ -41,6 +41,13 @@ describe Projects::ClustersController do expect(response).to match_response_schema('cluster_list') end + it 'sets the polling interval header for json requests' do + go(format: :json) + + expect(response).to have_gitlab_http_status(:ok) + expect(response.headers['Poll-Interval']).to eq("10000") + end + context 'when page is specified' do let(:last_page) { project.clusters.page.total_pages } let(:total_count) { project.clusters.page.total_count } diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb index c8ddd181d10..706bf787b2d 100644 --- a/spec/controllers/projects/commit_controller_spec.rb +++ b/spec/controllers/projects/commit_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::CommitController do +RSpec.describe Projects::CommitController do let_it_be(:project) { create(:project, :repository) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb index 1977e92e42b..557002acbc0 100644 --- a/spec/controllers/projects/commits_controller_spec.rb +++ b/spec/controllers/projects/commits_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::CommitsController do +RSpec.describe Projects::CommitsController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb index d1a4a9a0058..6aa4bfe235b 100644 --- a/spec/controllers/projects/compare_controller_spec.rb +++ b/spec/controllers/projects/compare_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::CompareController do +RSpec.describe Projects::CompareController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb index 942e095d669..408ce51d34b 100644 --- a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb +++ b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::CycleAnalytics::EventsController do +RSpec.describe Projects::CycleAnalytics::EventsController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb index 65eee7b8ead..8feb964cdde 100644 --- a/spec/controllers/projects/cycle_analytics_controller_spec.rb +++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::CycleAnalyticsController do +RSpec.describe Projects::CycleAnalyticsController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/deploy_keys_controller_spec.rb b/spec/controllers/projects/deploy_keys_controller_spec.rb index 9d41e2f59cb..821f7fca73d 100644 --- a/spec/controllers/projects/deploy_keys_controller_spec.rb +++ b/spec/controllers/projects/deploy_keys_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::DeployKeysController do +RSpec.describe Projects::DeployKeysController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:admin) { create(:admin) } diff --git a/spec/controllers/projects/deployments_controller_spec.rb b/spec/controllers/projects/deployments_controller_spec.rb index 37dcfa78772..85dd86d91e9 100644 --- a/spec/controllers/projects/deployments_controller_spec.rb +++ b/spec/controllers/projects/deployments_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::DeploymentsController do +RSpec.describe Projects::DeploymentsController do include ApiHelpers let(:user) { create(:user) } diff --git a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb index 30d2b79a92f..f664604ac15 100644 --- a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb +++ b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::DesignManagement::Designs::RawImagesController do +RSpec.describe Projects::DesignManagement::Designs::RawImagesController do include DesignManagementTestHelpers let_it_be(:project) { create(:project, :private) } diff --git a/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb b/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb index 6bfec1b314e..96ecbaf55b6 100644 --- a/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb +++ b/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::DesignManagement::Designs::ResizedImageController do +RSpec.describe Projects::DesignManagement::Designs::ResizedImageController do include DesignManagementTestHelpers let_it_be(:project) { create(:project, :private) } diff --git a/spec/controllers/projects/discussions_controller_spec.rb b/spec/controllers/projects/discussions_controller_spec.rb index b2e4a3b7b0d..f2efd40afdb 100644 --- a/spec/controllers/projects/discussions_controller_spec.rb +++ b/spec/controllers/projects/discussions_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::DiscussionsController do +RSpec.describe Projects::DiscussionsController do let(:user) { create(:user) } let(:merge_request) { create(:merge_request) } let(:project) { merge_request.source_project } diff --git a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb index fb8da52930c..17952aa0683 100644 --- a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb +++ b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Environments::PrometheusApiController do +RSpec.describe Projects::Environments::PrometheusApiController do let_it_be(:project) { create(:project) } let_it_be(:environment) { create(:environment, project: project) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/environments/sample_metrics_controller_spec.rb b/spec/controllers/projects/environments/sample_metrics_controller_spec.rb index 19b07a2ccc4..14e3ded76f2 100644 --- a/spec/controllers/projects/environments/sample_metrics_controller_spec.rb +++ b/spec/controllers/projects/environments/sample_metrics_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Environments::SampleMetricsController do +RSpec.describe Projects::Environments::SampleMetricsController do include StubENV let_it_be(:project) { create(:project) } diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 56fff2771ec..cca4b597f4c 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::EnvironmentsController do +RSpec.describe Projects::EnvironmentsController do include MetricsDashboardHelpers let_it_be(:project) { create(:project) } @@ -354,6 +354,19 @@ describe Projects::EnvironmentsController do expect(response).to redirect_to(environment_metrics_path(environment)) end + context 'with anonymous user and public dashboard visibility' do + let(:project) { create(:project, :public) } + let(:user) { create(:user) } + + it 'redirects successfully' do + project.project_feature.update!(metrics_dashboard_access_level: ProjectFeature::ENABLED) + + get :metrics_redirect, params: { namespace_id: project.namespace, project_id: project } + + expect(response).to redirect_to(environment_metrics_path(environment)) + end + end + context 'when there are no environments' do let(:environment) { } @@ -422,6 +435,19 @@ describe Projects::EnvironmentsController do get :metrics, params: environment_params end end + + context 'with anonymous user and public dashboard visibility' do + let(:project) { create(:project, :public) } + let(:user) { create(:user) } + + it 'returns success' do + project.project_feature.update!(metrics_dashboard_access_level: ProjectFeature::ENABLED) + + get :metrics, params: environment_params + + expect(response).to have_gitlab_http_status(:ok) + end + end end describe 'GET #additional_metrics' do @@ -497,6 +523,26 @@ describe Projects::EnvironmentsController do get :metrics, params: environment_params end end + + context 'with anonymous user and public dashboard visibility' do + let(:project) { create(:project, :public) } + let(:user) { create(:user) } + + it 'does not fail' do + allow(environment) + .to receive(:additional_metrics) + .and_return({ + success: true, + data: {}, + last_update: 42 + }) + project.project_feature.update!(metrics_dashboard_access_level: ProjectFeature::ENABLED) + + additional_metrics(window_params) + + expect(response).to have_gitlab_http_status(:ok) + end + end end describe 'GET #metrics_dashboard' do @@ -673,6 +719,17 @@ describe Projects::EnvironmentsController do it_behaves_like 'dashboard can be specified' it_behaves_like 'dashboard can be embedded' + context 'with anonymous user and public dashboard visibility' do + let(:project) { create(:project, :public) } + let(:user) { create(:user) } + + before do + project.project_feature.update!(metrics_dashboard_access_level: ProjectFeature::ENABLED) + end + + it_behaves_like 'the default dashboard' + end + context 'permissions' do before do allow(controller).to receive(:can?).and_return true diff --git a/spec/controllers/projects/error_tracking/projects_controller_spec.rb b/spec/controllers/projects/error_tracking/projects_controller_spec.rb index 1737528b597..67947d1c9d9 100644 --- a/spec/controllers/projects/error_tracking/projects_controller_spec.rb +++ b/spec/controllers/projects/error_tracking/projects_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ErrorTracking::ProjectsController do +RSpec.describe Projects::ErrorTracking::ProjectsController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb b/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb index 27d49147e99..7c080504c31 100644 --- a/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb +++ b/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ErrorTracking::StackTracesController do +RSpec.describe Projects::ErrorTracking::StackTracesController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/error_tracking_controller_spec.rb b/spec/controllers/projects/error_tracking_controller_spec.rb index 6be979418ad..5ea885e4fd6 100644 --- a/spec/controllers/projects/error_tracking_controller_spec.rb +++ b/spec/controllers/projects/error_tracking_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ErrorTrackingController do +RSpec.describe Projects::ErrorTrackingController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/find_file_controller_spec.rb b/spec/controllers/projects/find_file_controller_spec.rb index 4d8933f3aaf..a6c71cff74b 100644 --- a/spec/controllers/projects/find_file_controller_spec.rb +++ b/spec/controllers/projects/find_file_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::FindFileController do +RSpec.describe Projects::FindFileController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index e362790cd3c..4c0fd7b8954 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ForksController do +RSpec.describe Projects::ForksController do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:forked_project) { Projects::ForkService.new(project, user, name: 'Some name').execute } diff --git a/spec/controllers/projects/grafana_api_controller_spec.rb b/spec/controllers/projects/grafana_api_controller_spec.rb index 8502bd1ab0a..baee9705127 100644 --- a/spec/controllers/projects/grafana_api_controller_spec.rb +++ b/spec/controllers/projects/grafana_api_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::GrafanaApiController do +RSpec.describe Projects::GrafanaApiController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index e589815c45d..12cef6bea09 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::GraphsController do +RSpec.describe Projects::GraphsController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } @@ -42,23 +42,42 @@ describe Projects::GraphsController do expect(response).to render_template(:charts) end - it 'sets the daily coverage options' do - Timecop.freeze do + context 'when anonymous users can read build report results' do + it 'sets the daily coverage options' do + Timecop.freeze do + get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' }) + + expect(assigns[:daily_coverage_options]).to eq( + base_params: { + start_date: Date.current - 90.days, + end_date: Date.current, + ref_path: project.repository.expand_ref('master'), + param_type: 'coverage' + }, + download_path: namespace_project_ci_daily_build_group_report_results_path( + namespace_id: project.namespace, + project_id: project, + format: :csv + ), + graph_api_path: namespace_project_ci_daily_build_group_report_results_path( + namespace_id: project.namespace, + project_id: project, + format: :json + ) + ) + end + end + end + + context 'when anonymous users cannot read build report results' do + before do + project.update_column(:public_builds, false) + get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' }) + end - expect(assigns[:daily_coverage_options]).to eq( - base_params: { - start_date: Time.current.to_date - 90.days, - end_date: Time.current.to_date, - ref_path: project.repository.expand_ref('master'), - param_type: 'coverage' - }, - download_path: namespace_project_ci_daily_build_group_report_results_path( - namespace_id: project.namespace, - project_id: project, - format: :csv - ) - ) + it 'does not set daily coverage options' do + expect(assigns[:daily_coverage_options]).to be_nil end end end diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb index 28999257957..762ef795f6e 100644 --- a/spec/controllers/projects/group_links_controller_spec.rb +++ b/spec/controllers/projects/group_links_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::GroupLinksController do +RSpec.describe Projects::GroupLinksController do let(:group) { create(:group, :private) } let(:group2) { create(:group, :private) } let(:project) { create(:project, :private, group: group2) } diff --git a/spec/controllers/projects/hooks_controller_spec.rb b/spec/controllers/projects/hooks_controller_spec.rb index e97f602d9ab..440e6b2a74c 100644 --- a/spec/controllers/projects/hooks_controller_spec.rb +++ b/spec/controllers/projects/hooks_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::HooksController do +RSpec.describe Projects::HooksController do let(:project) { create(:project) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/import/jira_controller_spec.rb b/spec/controllers/projects/import/jira_controller_spec.rb index d1b0a086576..b82735a56b3 100644 --- a/spec/controllers/projects/import/jira_controller_spec.rb +++ b/spec/controllers/projects/import/jira_controller_spec.rb @@ -2,230 +2,101 @@ require 'spec_helper' -describe Projects::Import::JiraController do +RSpec.describe Projects::Import::JiraController do include JiraServiceHelper let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } let_it_be(:jira_project_key) { 'Test' } - context 'with anonymous user' do - before do - stub_feature_flags(jira_issue_import: true) - end + def ensure_correct_config + sign_in(user) + project.add_maintainer(user) + stub_feature_flags(jira_issue_import: true) + stub_jira_service_test + end - context 'get show' do - it 'redirects to issues page' do - get :show, params: { namespace_id: project.namespace, project_id: project } + shared_examples 'redirect with error' do |error| + it 'redirects to project issues path' do + subject - expect(response).to redirect_to(new_user_session_path) - end + expect(response).to redirect_to(project_issues_path(project)) end - context 'post import' do - it 'redirects to issues page' do - post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key } + it 'renders a correct error' do + subject - expect(response).to redirect_to(new_user_session_path) - end + expect(flash[:notice]).to eq(error) end end - context 'with logged in user' do - before do - sign_in(user) - project.add_maintainer(user) - end + shared_examples 'template with no message' do + it 'does not set any message' do + subject - context 'when feature flag not enabled' do - before do - stub_feature_flags(jira_issue_import: false) - end + expect(flash).to be_empty + end - context 'get show' do - it 'redirects to issues page' do - get :show, params: { namespace_id: project.namespace, project_id: project } + it 'renders show template' do + subject - expect(response).to redirect_to(project_issues_path(project)) - end - end + expect(response).to render_template(template) + end + end - context 'post import' do - it 'redirects to issues page' do - post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key } + shared_examples 'users without permissions' do + context 'with anonymous user' do + it 'redirects to new user page' do + subject - expect(response).to redirect_to(project_issues_path(project)) - end + expect(response).to redirect_to(new_user_session_path) end end - context 'when feature flag enabled' do + context 'when loged user is a developer' do before do - stub_feature_flags(jira_issue_import: true) - stub_feature_flags(jira_issue_import_vue: false) + create(:jira_service, project: project) stub_jira_service_test - end - - context 'when Jira service is enabled for the project' do - let_it_be(:jira_service) { create(:jira_service, project: project) } - - context 'when user is developer' do - let_it_be(:dev) { create(:user) } - - before do - sign_in(dev) - project.add_developer(dev) - end - - context 'get show' do - before do - get :show, params: { namespace_id: project.namespace.to_param, project_id: project } - end - - it 'does not query Jira service' do - expect(project).not_to receive(:jira_service) - end - - it 'renders show template' do - expect(response).to render_template(:show) - expect(assigns(:jira_projects)).not_to be_present - end - end - - context 'post import' do - it 'returns 404' do - post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key } - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'when issues disabled' do - let_it_be(:disabled_issues_project) { create(:project, :public, :issues_disabled) } - - context 'get show' do - it 'returs 404' do - get :show, params: { namespace_id: project.namespace.to_param, project_id: disabled_issues_project } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'post import' do - it 'returs 404' do - post :import, params: { namespace_id: disabled_issues_project.namespace, project_id: disabled_issues_project, jira_project_key: jira_project_key } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'when running Jira import first time' do - context 'get show' do - before do - allow(JIRA::Resource::Project).to receive(:all).and_return(jira_projects) - - expect(project.jira_imports).to be_empty - - get :show, params: { namespace_id: project.namespace.to_param, project_id: project } - end - - context 'when no projects have been retrieved from Jira' do - let(:jira_projects) { [] } - - it 'render an error message' do - expect(flash[:alert]).to eq('No projects have been returned from Jira. Please check your Jira configuration.') - expect(response).to render_template(:show) - end - end - - context 'when projects retrieved from Jira' do - let(:jira_projects) { [double(name: 'FOO project', key: 'FOO')] } - - it 'renders show template' do - expect(response).to render_template(:show) - end - end - end + sign_in(user) + project.add_developer(user) + end - context 'post import' do - context 'when Jira project key is empty' do - it 'redirects back to show with an error' do - post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: '' } + it_behaves_like 'redirect with error', 'You do not have permissions to run the import.' + end + end - expect(response).to redirect_to(project_import_jira_path(project)) - expect(flash[:alert]).to eq('No Jira project key has been provided.') - end - end + describe 'GET #show' do + let(:template) { 'show' } - context 'when everything is ok' do - it 'creates import state' do - expect(project.latest_jira_import).to be_nil + subject { get :show, params: { namespace_id: project.namespace, project_id: project } } - post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key } + it_behaves_like 'users without permissions' - project.reload + context 'jira service configuration' do + before do + sign_in(user) + project.add_maintainer(user) + stub_feature_flags(jira_issue_import: true) + end - jira_import = project.latest_jira_import - expect(project.import_type).to eq 'jira' - expect(jira_import.status).to eq 'scheduled' - expect(jira_import.jira_project_key).to eq jira_project_key - expect(response).to redirect_to(project_import_jira_path(project)) - end - end - end + context 'when Jira service is not enabled for the project' do + it 'does not query Jira service' do + expect(project).not_to receive(:jira_service) end - context 'when import state is scheduled' do - let_it_be(:jira_import_state) { create(:jira_import_state, :scheduled, project: project) } - - context 'get show' do - it 'renders import status' do - get :show, params: { namespace_id: project.namespace.to_param, project_id: project } - - jira_import = project.latest_jira_import - expect(jira_import.status).to eq 'scheduled' - expect(flash.now[:notice]).to eq 'Import scheduled' - end - end + it_behaves_like 'template with no message' + end - context 'post import' do - it 'uses the existing import data' do - post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' } + context 'when Jira service is not configured correctly for the project' do + let_it_be(:jira_service) { create(:jira_service, project: project) } - expect(flash[:notice]).to eq('Jira import is already running.') - expect(response).to redirect_to(project_import_jira_path(project)) - end - end + before do + WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/serverInfo') + .to_raise(JIRA::HTTPError.new(double(message: 'Some failure.'))) end - context 'when Jira import ran before' do - let_it_be(:jira_import_state) { create(:jira_import_state, :finished, project: project, jira_project_key: jira_project_key) } - - context 'get show' do - it 'renders import status' do - allow(JIRA::Resource::Project).to receive(:all).and_return([]) - get :show, params: { namespace_id: project.namespace.to_param, project_id: project } - - expect(project.latest_jira_import.status).to eq 'finished' - expect(flash.now[:notice]).to eq 'Import finished' - end - end - - context 'post import' do - it 'uses the existing import data' do - post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' } - - project.reload - expect(project.latest_jira_import.status).to eq 'scheduled' - expect(project.jira_imports.size).to eq 2 - expect(project.jira_imports.first.jira_project_key).to eq jira_project_key - expect(project.jira_imports.last.jira_project_key).to eq 'New Project' - expect(response).to redirect_to(project_import_jira_path(project)) - end - end - end + it_behaves_like 'template with no message' end end end diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb index bdc81efe3bc..29cfd1c352e 100644 --- a/spec/controllers/projects/imports_controller_spec.rb +++ b/spec/controllers/projects/imports_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ImportsController do +RSpec.describe Projects::ImportsController do let(:user) { create(:user) } let(:project) { create(:project) } diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 96f11f11dc4..bcd1a53bd47 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::IssuesController do +RSpec.describe Projects::IssuesController do include ProjectForksHelper include_context 'includes Spam constants' @@ -332,8 +332,7 @@ describe Projects::IssuesController do end before do - allow(controller).to receive(:find_routable!) - .with(Project, project.full_path, any_args).and_return(project) + allow(controller).to receive(:find_routable!).and_return(project) allow(project).to receive(:default_branch).and_return(master_branch) allow_next_instance_of(Issues::RelatedBranchesService) do |service| allow(service).to receive(:execute).and_return(related_branches) @@ -536,7 +535,7 @@ describe Projects::IssuesController do before do stub_application_setting(recaptcha_enabled: true) expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service| - expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA) + expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW) end end @@ -851,7 +850,7 @@ describe Projects::IssuesController do context 'when recaptcha is not verified' do before do expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service| - expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA) + expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW) end end @@ -1103,7 +1102,7 @@ describe Projects::IssuesController do context 'when captcha is not verified' do before do expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service| - expect(verdict_service).to receive(:execute).and_return(REQUIRE_RECAPTCHA) + expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW) end end diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index ef1253edda5..44dcb0caab2 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -describe Projects::JobsController, :clean_gitlab_redis_shared_state do +RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do include ApiHelpers include HttpIOHelpers @@ -1225,4 +1225,198 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do get :terminal_websocket_authorize, params: params.merge(extra_params) end end + + describe 'GET #proxy_websocket_authorize' do + let_it_be(:owner) { create(:owner) } + let_it_be(:admin) { create(:admin) } + let_it_be(:maintainer) { create(:user) } + let_it_be(:developer) { create(:user) } + let_it_be(:reporter) { create(:user) } + let_it_be(:guest) { create(:user) } + let_it_be(:project) { create(:project, :private, :repository, namespace: owner.namespace) } + let(:user) { maintainer } + let(:pipeline) { create(:ci_pipeline, project: project, source: :webide, config_source: :webide_source, user: user) } + let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline, user: user) } + let(:extra_params) { { id: job.id } } + let(:path) { :proxy_websocket_authorize } + let(:render_method) { :channel_websocket } + let(:expected_data) do + { + 'Channel' => { + 'Subprotocols' => ["terminal.gitlab.com"], + 'Url' => 'wss://localhost/proxy/build/default_port/', + 'Header' => { + 'Authorization' => [nil] + }, + 'MaxSessionTime' => nil, + 'CAPem' => nil + } + }.to_json + end + + before do + stub_feature_flags(build_service_proxy: true) + allow(job).to receive(:has_terminal?).and_return(true) + + project.add_maintainer(maintainer) + project.add_developer(developer) + project.add_reporter(reporter) + project.add_guest(guest) + + sign_in(user) + end + + context 'access rights' do + before do + allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_return(nil) + + make_request + end + + context 'with admin' do + let(:user) { admin } + + context 'when admin mode is enabled', :enable_admin_mode do + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when admin mode is disabled' do + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'with owner' do + let(:user) { owner } + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'with maintainer' do + let(:user) { maintainer } + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'with developer' do + let(:user) { developer } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'with reporter' do + let(:user) { reporter } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'with guest' do + let(:user) { guest } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'with non member' do + let(:user) { create(:user) } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'when pipeline is not from a webide source' do + context 'with admin' do + let(:user) { admin } + let(:pipeline) { create(:ci_pipeline, project: project, source: :chat, user: user) } + + before do + allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_return(nil) + make_request + end + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'when workhorse signature is valid' do + before do + allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_return(nil) + end + + context 'and the id is valid' do + it 'returns the proxy data for the service running in the job' do + make_request + + expect(response).to have_gitlab_http_status(:ok) + expect(response.headers["Content-Type"]).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + expect(response.body).to eq(expected_data) + end + end + + context 'and the id is invalid' do + let(:extra_params) { { id: non_existing_record_id } } + + it 'returns 404' do + make_request + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'with invalid workhorse signature' do + it 'aborts with an exception' do + allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_raise(JWT::DecodeError) + + expect { make_request }.to raise_error(JWT::DecodeError) + end + end + + context 'when feature flag :build_service_proxy is disabled' do + let(:user) { admin } + + it 'returns 404' do + allow(Gitlab::Workhorse).to receive(:verify_api_request!).and_return(nil) + stub_feature_flags(build_service_proxy: false) + + make_request + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + it 'converts the url scheme into wss' 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/")) + + make_request + end + + def make_request + params = { + namespace_id: project.namespace.to_param, + project_id: project + } + + get path, params: params.merge(extra_params) + end + end end diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index c6098f5934d..f213d104747 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::LabelsController do +RSpec.describe Projects::LabelsController do let(:group) { create(:group) } let(:project) { create(:project, namespace: group) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/logs_controller_spec.rb b/spec/controllers/projects/logs_controller_spec.rb index e86a42b03c8..1eb5a6fcc12 100644 --- a/spec/controllers/projects/logs_controller_spec.rb +++ b/spec/controllers/projects/logs_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::LogsController do +RSpec.describe Projects::LogsController do include KubernetesHelpers let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/mattermosts_controller_spec.rb b/spec/controllers/projects/mattermosts_controller_spec.rb index 693176d0cfc..001f2564698 100644 --- a/spec/controllers/projects/mattermosts_controller_spec.rb +++ b/spec/controllers/projects/mattermosts_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MattermostsController do +RSpec.describe Projects::MattermostsController do let!(:project) { create(:project) } let!(:user) { create(:user) } diff --git a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb index 8e4ac64f7b0..5f636bd4340 100644 --- a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MergeRequests::ConflictsController do +RSpec.describe Projects::MergeRequests::ConflictsController do let(:project) { create(:project, :repository) } let(:user) { project.owner } let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } diff --git a/spec/controllers/projects/merge_requests/content_controller_spec.rb b/spec/controllers/projects/merge_requests/content_controller_spec.rb index 72eedc837a4..7fb20b4666a 100644 --- a/spec/controllers/projects/merge_requests/content_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/content_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MergeRequests::ContentController do +RSpec.describe Projects::MergeRequests::ContentController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:merge_request) { create(:merge_request, target_project: project, source_project: project) } diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb index db25ad62019..091a44130a1 100644 --- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MergeRequests::CreationsController do +RSpec.describe Projects::MergeRequests::CreationsController do let(:project) { create(:project, :repository) } let(:user) { project.owner } let(:fork_project) { create(:forked_project_with_submodules) } diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb index 3d9193e3e33..02b4c2d1da9 100644 --- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MergeRequests::DiffsController do +RSpec.describe Projects::MergeRequests::DiffsController do include ProjectForksHelper shared_examples '404 for unexistent diffable' do diff --git a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb new file mode 100644 index 00000000000..7d74e872d29 --- /dev/null +++ b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb @@ -0,0 +1,455 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe Projects::MergeRequests::DraftsController do + include RepoHelpers + + let(:project) { create(:project, :repository) } + let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } + let(:user) { project.owner } + let(:user2) { create(:user) } + + let(:params) do + { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + merge_request_id: merge_request.iid + } + end + + before do + sign_in(user) + stub_licensed_features(multiple_merge_request_assignees: true) + stub_commonmark_sourcepos_disabled + end + + describe 'GET #index' do + let!(:draft_note) { create(:draft_note, merge_request: merge_request, author: user) } + + it 'list merge request draft notes for current user' do + get :index, params: params + + expect(json_response.first['merge_request_id']).to eq(merge_request.id) + expect(json_response.first['author']['id']).to eq(user.id) + expect(json_response.first['note_html']).not_to be_empty + end + end + + describe 'POST #create' do + def create_draft_note(draft_overrides: {}, overrides: {}) + post_params = params.merge({ + draft_note: { + note: 'This is a unpublished comment' + }.merge(draft_overrides) + }.merge(overrides)) + + post :create, params: post_params + end + + context 'without permissions' do + let(:project) { create(:project, :private) } + + before do + sign_in(user2) + end + + it 'does not allow draft note creation' do + expect { create_draft_note }.to change { DraftNote.count }.by(0) + expect(response).to have_gitlab_http_status(:not_found) + end + end + + it 'creates a draft note' do + expect { create_draft_note }.to change { DraftNote.count }.by(1) + end + + it 'creates draft note with position' do + diff_refs = project.commit(sample_commit.id).try(:diff_refs) + + position = Gitlab::Diff::Position.new( + old_path: "files/ruby/popen.rb", + new_path: "files/ruby/popen.rb", + old_line: nil, + new_line: 14, + diff_refs: diff_refs + ) + + create_draft_note(draft_overrides: { position: position.to_json }) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['position']).to be_present + expect(json_response['file_hash']).to be_present + expect(json_response['file_identifier_hash']).to be_present + expect(json_response['line_code']).to match(/\w+_\d+_\d+/) + expect(json_response['note_html']).to eq('<p dir="auto">This is a unpublished comment</p>') + end + + it 'creates a draft note with quick actions' do + create_draft_note(draft_overrides: { note: "#{user2.to_reference}\n/assign #{user.to_reference}" }) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['note_html']).to match(/#{user2.to_reference}/) + expect(json_response['references']['commands']).to match(/Assigns/) + expect(json_response['references']['users']).to include(user2.username) + end + + context 'in a thread' do + let(:discussion) { create(:discussion_note_on_merge_request, noteable: merge_request, project: project).discussion } + + it 'creates draft note as a reply' do + expect do + create_draft_note(overrides: { in_reply_to_discussion_id: discussion.reply_id }) + end.to change { DraftNote.count }.by(1) + + draft_note = DraftNote.last + + expect(draft_note).to be_valid + expect(draft_note.discussion_id).to eq(discussion.reply_id) + end + + it 'creates a draft note that will resolve a thread' do + expect do + create_draft_note( + overrides: { in_reply_to_discussion_id: discussion.reply_id }, + draft_overrides: { resolve_discussion: true } + ) + end.to change { DraftNote.count }.by(1) + + draft_note = DraftNote.last + + expect(draft_note).to be_valid + expect(draft_note.discussion_id).to eq(discussion.reply_id) + expect(draft_note.resolve_discussion).to eq(true) + end + + it 'cannot create more than one draft note per thread' do + expect do + create_draft_note( + overrides: { in_reply_to_discussion_id: discussion.reply_id }, + draft_overrides: { resolve_discussion: true } + ) + end.to change { DraftNote.count }.by(1) + + expect do + create_draft_note( + overrides: { in_reply_to_discussion_id: discussion.reply_id }, + draft_overrides: { resolve_discussion: true, note: 'A note' } + ) + end.to change { DraftNote.count }.by(0) + end + end + + context 'commit_id is present' do + let(:commit) { project.commit(sample_commit.id) } + + let(:position) do + Gitlab::Diff::Position.new( + old_path: "files/ruby/popen.rb", + new_path: "files/ruby/popen.rb", + old_line: nil, + new_line: 14, + diff_refs: commit.diff_refs + ) + end + + before do + create_draft_note(draft_overrides: { commit_id: commit_id, position: position.to_json }) + end + + context 'value is a commit sha' do + let(:commit_id) { commit.id } + + it 'creates the draft note with commit ID' do + expect(DraftNote.last.commit_id).to eq(commit_id) + end + end + + context 'value is "undefined"' do + let(:commit_id) { 'undefined' } + + it 'creates the draft note with nil commit ID' do + expect(DraftNote.last.commit_id).to be_nil + end + end + end + end + + describe 'PUT #update' do + let(:draft) { create(:draft_note, merge_request: merge_request, author: user) } + + def update_draft_note(overrides = {}) + put_params = params.merge({ + id: draft.id, + draft_note: { + note: 'This is an updated unpublished comment' + }.merge(overrides) + }) + + put :update, params: put_params + end + + context 'without permissions' do + before do + sign_in(user2) + project.add_developer(user2) + end + + it 'does not allow editing draft note belonging to someone else' do + update_draft_note + + expect(response).to have_gitlab_http_status(:not_found) + expect(draft.reload.note).not_to eq('This is an updated unpublished comment') + end + end + + it 'updates the draft' do + expect(draft.note).not_to be_empty + + expect { update_draft_note }.not_to change { DraftNote.count } + + draft.reload + + expect(draft.note).to eq('This is an updated unpublished comment') + expect(json_response['note_html']).not_to be_empty + end + end + + describe 'POST #publish' do + context 'without permissions' do + shared_examples_for 'action that does not allow publishing draft note' do + it 'does not allow publishing draft note' do + expect { action } + .to not_change { Note.count } + .and not_change { DraftNote.count } + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + before do + sign_in(user2) + end + + context 'when note belongs to someone else' do + before do + project.add_developer(user2) + end + + it_behaves_like 'action that does not allow publishing draft note' do + let!(:draft) { create(:draft_note, merge_request: merge_request, author: user) } + let(:action) { post :publish, params: params.merge(id: draft.id) } + end + end + + context 'when merge request discussion is locked' do + let(:project) { create(:project, :public, :merge_requests_public, :repository) } + + before do + create(:draft_note, merge_request: merge_request, author: user2) + merge_request.update!(discussion_locked: true) + end + + it_behaves_like 'action that does not allow publishing draft note' do + let(:action) { post :publish, params: params } + end + end + end + + context 'when PublishService errors' do + it 'returns message and 500 response' do + create(:draft_note, merge_request: merge_request, author: user) + error_message = "Something went wrong" + + expect_next_instance_of(DraftNotes::PublishService) do |service| + allow(service).to receive(:execute).and_return({ message: error_message, status: :error }) + end + + post :publish, params: params + + expect(response).to have_gitlab_http_status(:error) + expect(json_response["message"]).to include(error_message) + end + end + + it 'publishes draft notes with position' do + diff_refs = project.commit(sample_commit.id).try(:diff_refs) + + position = Gitlab::Diff::Position.new( + old_path: "files/ruby/popen.rb", + new_path: "files/ruby/popen.rb", + old_line: nil, + new_line: 14, + diff_refs: diff_refs + ) + + draft = create(:draft_note_on_text_diff, merge_request: merge_request, author: user, position: position) + + expect { post :publish, params: params }.to change { Note.count }.by(1) + .and change { DraftNote.count }.by(-1) + + note = merge_request.notes.reload.last + + expect(note.note).to eq(draft.note) + expect(note.position).to eq(draft.position) + end + + it 'does nothing if there are no draft notes' do + expect { post :publish, params: params }.to change { Note.count }.by(0).and change { DraftNote.count }.by(0) + end + + it 'publishes a draft note with quick actions and applies them' do + project.add_developer(user2) + create(:draft_note, merge_request: merge_request, author: user, + note: "/assign #{user2.to_reference}") + + expect(merge_request.assignees).to be_empty + + expect { post :publish, params: params }.to change { Note.count }.by(1) + .and change { DraftNote.count }.by(-1) + + expect(response).to have_gitlab_http_status(:ok) + expect(merge_request.reload.assignee_ids).to match_array([user2.id]) + expect(Note.last.system?).to be true + end + + it 'publishes all draft notes for an MR' do + draft_params = { merge_request: merge_request, author: user } + + drafts = create_list(:draft_note, 4, draft_params) + + note = create(:discussion_note_on_merge_request, noteable: merge_request, project: project) + draft_reply = create(:draft_note, draft_params.merge(discussion_id: note.discussion_id)) + + diff_note = create(:diff_note_on_merge_request, noteable: merge_request, project: project) + diff_draft_reply = create(:draft_note, draft_params.merge(discussion_id: diff_note.discussion_id)) + + expect { post :publish, params: params }.to change { Note.count }.by(6) + .and change { DraftNote.count }.by(-6) + + expect(response).to have_gitlab_http_status(:ok) + + notes = merge_request.notes.reload + + expect(notes.pluck(:note)).to include(*drafts.map(&:note)) + expect(note.discussion.notes.last.note).to eq(draft_reply.note) + expect(diff_note.discussion.notes.last.note).to eq(diff_draft_reply.note) + end + + it 'can publish just a single draft note' do + draft_params = { merge_request: merge_request, author: user } + + drafts = create_list(:draft_note, 4, draft_params) + + expect { post :publish, params: params.merge(id: drafts.first.id) }.to change { Note.count }.by(1) + .and change { DraftNote.count }.by(-1) + end + + context 'when publishing drafts in a thread' do + let(:note) { create(:discussion_note_on_merge_request, noteable: merge_request, project: project) } + + def create_reply(discussion_id, resolves: false) + create(:draft_note, + merge_request: merge_request, + author: user, + discussion_id: discussion_id, + resolve_discussion: resolves + ) + end + + it 'resolves a thread if the draft note resolves it' do + draft_reply = create_reply(note.discussion_id, resolves: true) + + post :publish, params: params + + discussion = note.discussion + + expect(discussion.notes.last.note).to eq(draft_reply.note) + expect(discussion.resolved?).to eq(true) + expect(discussion.resolved_by.id).to eq(user.id) + end + + it 'unresolves a thread if the draft note unresolves it' do + note.discussion.resolve!(user) + expect(note.discussion.resolved?).to eq(true) + + draft_reply = create_reply(note.discussion_id, resolves: false) + + post :publish, params: params + + discussion = note.discussion + + expect(discussion.notes.last.note).to eq(draft_reply.note) + expect(discussion.resolved?).to eq(false) + end + end + end + + describe 'DELETE #destroy' do + let(:draft) { create(:draft_note, merge_request: merge_request, author: user) } + + def create_draft + create(:draft_note, merge_request: merge_request, author: user) + end + + context 'without permissions' do + before do + sign_in(user2) + project.add_developer(user2) + end + + it 'does not allow destroying a draft note belonging to someone else' do + draft = create(:draft_note, merge_request: merge_request, author: user) + + expect { post :destroy, params: params.merge(id: draft.id) } + .not_to change { DraftNote.count } + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + it 'destroys the draft note when ID is given' do + draft = create_draft + + expect { delete :destroy, params: params.merge(id: draft.id) }.to change { DraftNote.count }.by(-1) + expect(response).to have_gitlab_http_status(:ok) + end + + context 'without permissions' do + before do + sign_in(user2) + end + + it 'does not allow editing draft note belonging to someone else' do + draft = create_draft + + expect { delete :destroy, params: params.merge(id: draft.id) }.to change { DraftNote.count }.by(0) + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + describe 'DELETE #discard' do + it 'deletes all DraftNotes belonging to a user in a Merge Request' do + create_list(:draft_note, 6, merge_request: merge_request, author: user) + + expect { delete :discard, params: params }.to change { DraftNote.count }.by(-6) + expect(response).to have_gitlab_http_status(:ok) + end + + context 'without permissions' do + before do + sign_in(user2) + project.add_developer(user2) + end + + it 'does not destroys a draft note belonging to someone else' do + create(:draft_note, merge_request: merge_request, author: user) + + expect { post :discard, params: params } + .not_to change { DraftNote.count } + + expect(response).to have_gitlab_http_status(:ok) + end + end + end +end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 7d9e42fcc2d..382593fd7cb 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MergeRequestsController do +RSpec.describe Projects::MergeRequestsController do include ProjectForksHelper include Gitlab::Routing @@ -1183,15 +1183,19 @@ describe Projects::MergeRequestsController do subject expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to match( - a_hash_including( - 'tfplan.json' => hash_including( - 'create' => 0, - 'delete' => 0, - 'update' => 1 + + pipeline.builds.each do |build| + expect(json_response).to match( + a_hash_including( + build.id.to_s => hash_including( + 'create' => 0, + 'delete' => 0, + 'update' => 1, + 'job_name' => build.options.dig(:artifacts, :name).to_s + ) ) ) - ) + end end end @@ -1409,20 +1413,6 @@ describe Projects::MergeRequestsController do end end - context 'when feature flag is disabled' do - let(:accessibility_comparison) { { status: :parsed, data: { summary: 1 } } } - - before do - stub_feature_flags(accessibility_report_view: false) - end - - it 'returns 204 HTTP status' do - subject - - expect(response).to have_gitlab_http_status(:no_content) - end - end - context 'when pipeline has jobs with accessibility reports' do before do allow_any_instance_of(MergeRequest) diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb index ee61ef73b45..0c7391c1b9c 100644 --- a/spec/controllers/projects/milestones_controller_spec.rb +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MilestonesController do +RSpec.describe Projects::MilestonesController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:milestone) { create(:milestone, project: project) } @@ -145,7 +145,7 @@ describe Projects::MilestonesController do delete :destroy, params: { namespace_id: project.namespace.id, project_id: project.id, id: milestone.iid }, format: :js expect(response).to be_successful - expect(Event.recent.first.action).to eq(Event::DESTROYED) + expect(Event.recent.first).to be_destroyed_action expect { Milestone.find(milestone.id) }.to raise_exception(ActiveRecord::RecordNotFound) issue.reload diff --git a/spec/controllers/projects/mirrors_controller_spec.rb b/spec/controllers/projects/mirrors_controller_spec.rb index 8cd940978c0..7c5d14d3a22 100644 --- a/spec/controllers/projects/mirrors_controller_spec.rb +++ b/spec/controllers/projects/mirrors_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::MirrorsController do +RSpec.describe Projects::MirrorsController do include ReactiveCachingHelpers shared_examples 'only admin is allowed when mirroring is disabled' do diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index 39594ff287d..b3a83723189 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::NotesController do +RSpec.describe Projects::NotesController do include ProjectForksHelper let(:user) { create(:user) } @@ -37,7 +37,7 @@ describe Projects::NotesController do project.add_developer(user) end - it 'passes last_fetched_at from headers to NotesFinder' do + it 'passes last_fetched_at from headers to NotesFinder and MergeIntoNotesService' do last_fetched_at = 3.hours.ago.to_i request.headers['X-Last-Fetched-At'] = last_fetched_at @@ -46,6 +46,10 @@ describe Projects::NotesController do .with(anything, hash_including(last_fetched_at: last_fetched_at)) .and_call_original + expect(ResourceEvents::MergeIntoNotesService).to receive(:new) + .with(anything, anything, hash_including(last_fetched_at: last_fetched_at)) + .and_call_original + get :index, params: request_params end diff --git a/spec/controllers/projects/pages_controller_spec.rb b/spec/controllers/projects/pages_controller_spec.rb index 102c0b6b048..1fa8838b548 100644 --- a/spec/controllers/projects/pages_controller_spec.rb +++ b/spec/controllers/projects/pages_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::PagesController do +RSpec.describe Projects::PagesController do let(:user) { create(:user) } let(:project) { create(:project, :public) } diff --git a/spec/controllers/projects/pages_domains_controller_spec.rb b/spec/controllers/projects/pages_domains_controller_spec.rb index 40a6f77f0d6..691508d1e14 100644 --- a/spec/controllers/projects/pages_domains_controller_spec.rb +++ b/spec/controllers/projects/pages_domains_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::PagesDomainsController do +RSpec.describe Projects::PagesDomainsController do let(:user) { create(:user) } let(:project) { create(:project) } let!(:pages_domain) { create(:pages_domain, project: project) } diff --git a/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb b/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb index 6a53e8f3dbf..8a344a72120 100644 --- a/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb +++ b/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::PerformanceMonitoring::DashboardsController do +RSpec.describe Projects::PerformanceMonitoring::DashboardsController do let_it_be(:user) { create(:user) } let_it_be(:namespace) { create(:namespace) } let!(:project) { create(:project, :repository, name: 'dashboard-project', namespace: namespace) } diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index 635980ba93b..27a3e95896a 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::PipelineSchedulesController do +RSpec.describe Projects::PipelineSchedulesController do include AccessMatchersForController let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index b3d8fb94fb3..ca09d2b1428 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::PipelinesController do +RSpec.describe Projects::PipelinesController do include ApiHelpers let_it_be(:user) { create(:user) } @@ -26,10 +26,6 @@ describe Projects::PipelinesController do context 'when using persisted stages', :request_store do render_views - before do - stub_feature_flags(ci_pipeline_persisted_stages: true) - end - it 'returns serialized pipelines' do expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original @@ -66,46 +62,6 @@ describe Projects::PipelinesController do end end - context 'when using legacy stages', :request_store do - before do - stub_feature_flags(ci_pipeline_persisted_stages: false) - end - - it 'returns JSON with serialized pipelines' do - get_pipelines_index_json - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('pipeline') - - expect(json_response).to include('pipelines') - expect(json_response['pipelines'].count).to eq 6 - expect(json_response['count']['all']).to eq '6' - expect(json_response['count']['running']).to eq '2' - expect(json_response['count']['pending']).to eq '1' - expect(json_response['count']['finished']).to eq '3' - - json_response.dig('pipelines', 0, 'details', 'stages').tap do |stages| - expect(stages.count).to eq 3 - end - end - - it 'does not execute N+1 queries' do - get_pipelines_index_json - - control_count = ActiveRecord::QueryRecorder.new do - get_pipelines_index_json - end.count - - create_all_pipeline_types - - # There appears to be one extra query for Pipelines#has_warnings? for some reason - expect { get_pipelines_index_json }.not_to exceed_query_limit(control_count + 1) - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['pipelines'].count).to eq 12 - end - end - it 'does not include coverage data for the pipelines' do get_pipelines_index_json @@ -215,6 +171,40 @@ describe Projects::PipelinesController do end end + context 'filter by status' do + context 'when pipelines with the status exists' do + it 'returns matched pipelines' do + get_pipelines_index_json(status: 'success') + + check_pipeline_response(returned: 1, all: 1, running: 0, pending: 0, finished: 1) + end + + context 'when filter by unrelated scope' do + it 'returns empty list' do + get_pipelines_index_json(status: 'success', scope: 'running') + + check_pipeline_response(returned: 0, all: 1, running: 0, pending: 0, finished: 1) + end + end + end + + context 'when no pipeline with the status exists' do + it 'returns empty list' do + get_pipelines_index_json(status: 'manual') + + check_pipeline_response(returned: 0, all: 0, running: 0, pending: 0, finished: 0) + end + end + + context 'when invalid status' do + it 'returns all list' do + get_pipelines_index_json(status: 'invalid-status') + + check_pipeline_response(returned: 6, all: 6, running: 2, pending: 1, finished: 3) + end + end + end + def get_pipelines_index_json(params = {}) get :index, params: { namespace_id: project.namespace, @@ -548,6 +538,39 @@ describe Projects::PipelinesController do end end + describe 'GET dag.json' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + before do + create_build('build', 1, 'build') + create_build('test', 2, 'test', scheduling_type: 'dag').tap do |job| + create(:ci_build_need, build: job, name: 'build') + end + end + + it 'returns the pipeline with DAG serialization' do + get :dag, params: { namespace_id: project.namespace, project_id: project, id: pipeline }, format: :json + + expect(response).to have_gitlab_http_status(:ok) + + expect(json_response.fetch('stages')).not_to be_empty + + build_stage = json_response['stages'].first + expect(build_stage.fetch('name')).to eq 'build' + expect(build_stage.fetch('groups').first.fetch('jobs')) + .to eq [{ 'name' => 'build', 'scheduling_type' => 'stage' }] + + test_stage = json_response['stages'].last + expect(test_stage.fetch('name')).to eq 'test' + expect(test_stage.fetch('groups').first.fetch('jobs')) + .to eq [{ 'name' => 'test', 'scheduling_type' => 'dag', 'needs' => ['build'] }] + end + + def create_build(stage, stage_idx, name, params = {}) + create(:ci_build, pipeline: pipeline, stage: stage, stage_idx: stage_idx, name: name, **params) + end + end + describe 'GET stages.json' do let(:pipeline) { create(:ci_pipeline, project: project) } @@ -685,7 +708,7 @@ describe Projects::PipelinesController do end shared_examples 'creates a pipeline' do - it do + specify do expect { post_request }.to change { project.ci_pipelines.count }.by(1) pipeline = project.ci_pipelines.last diff --git a/spec/controllers/projects/pipelines_settings_controller_spec.rb b/spec/controllers/projects/pipelines_settings_controller_spec.rb index 789b2104d3c..ad631b7c3da 100644 --- a/spec/controllers/projects/pipelines_settings_controller_spec.rb +++ b/spec/controllers/projects/pipelines_settings_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::PipelinesSettingsController do +RSpec.describe Projects::PipelinesSettingsController do let_it_be(:user) { create(:user) } let_it_be(:project_auto_devops) { create(:project_auto_devops) } let(:project) { project_auto_devops.project } diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index f354bba902a..7457e4c5023 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -describe Projects::ProjectMembersController do +RSpec.describe Projects::ProjectMembersController do let(:user) { create(:user) } let(:group) { create(:group, :public) } let(:project) { create(:project, :public) } diff --git a/spec/controllers/projects/prometheus/alerts_controller_spec.rb b/spec/controllers/projects/prometheus/alerts_controller_spec.rb index e936cb5916e..6e3148231bd 100644 --- a/spec/controllers/projects/prometheus/alerts_controller_spec.rb +++ b/spec/controllers/projects/prometheus/alerts_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Prometheus::AlertsController do +RSpec.describe Projects::Prometheus::AlertsController do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } let_it_be(:environment) { create(:environment, project: project) } diff --git a/spec/controllers/projects/prometheus/metrics_controller_spec.rb b/spec/controllers/projects/prometheus/metrics_controller_spec.rb index 36f694cda29..c7c3be20f29 100644 --- a/spec/controllers/projects/prometheus/metrics_controller_spec.rb +++ b/spec/controllers/projects/prometheus/metrics_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Prometheus::MetricsController do +RSpec.describe Projects::Prometheus::MetricsController do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:prometheus_project) } diff --git a/spec/controllers/projects/protected_branches_controller_spec.rb b/spec/controllers/projects/protected_branches_controller_spec.rb index 262f77a7328..09eb1a45c73 100644 --- a/spec/controllers/projects/protected_branches_controller_spec.rb +++ b/spec/controllers/projects/protected_branches_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -describe Projects::ProtectedBranchesController do +RSpec.describe Projects::ProtectedBranchesController do let(:project) { create(:project, :repository) } let(:protected_branch) { create(:protected_branch, project: project) } let(:project_params) { { namespace_id: project.namespace.to_param, project_id: project } } diff --git a/spec/controllers/projects/protected_tags_controller_spec.rb b/spec/controllers/projects/protected_tags_controller_spec.rb index a900947d82e..2c2240cb0d0 100644 --- a/spec/controllers/projects/protected_tags_controller_spec.rb +++ b/spec/controllers/projects/protected_tags_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -describe Projects::ProtectedTagsController do +RSpec.describe Projects::ProtectedTagsController do describe "GET #index" do let(:project) { create(:project_empty_repo, :public) } diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb index 4a684dcfbc6..5f10343eb76 100644 --- a/spec/controllers/projects/raw_controller_spec.rb +++ b/spec/controllers/projects/raw_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::RawController do +RSpec.describe Projects::RawController do include RepoHelpers let(:project) { create(:project, :public, :repository) } diff --git a/spec/controllers/projects/refs_controller_spec.rb b/spec/controllers/projects/refs_controller_spec.rb index b043e7f2538..a6a4aff7ce9 100644 --- a/spec/controllers/projects/refs_controller_spec.rb +++ b/spec/controllers/projects/refs_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::RefsController do +RSpec.describe Projects::RefsController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } @@ -73,7 +73,7 @@ describe Projects::RefsController do cache_key = "projects/#{project.id}/logs/#{project.commit.id}/#{path}/25" expect(Rails.cache.fetch(cache_key)).to eq(['logs', 50]) - expect(response.headers['More-Logs-Offset']).to eq(50) + expect(response.headers['More-Logs-Offset']).to eq("50") end end end diff --git a/spec/controllers/projects/registry/repositories_controller_spec.rb b/spec/controllers/projects/registry/repositories_controller_spec.rb index badb84f9b50..098fa9bac2c 100644 --- a/spec/controllers/projects/registry/repositories_controller_spec.rb +++ b/spec/controllers/projects/registry/repositories_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Registry::RepositoriesController do +RSpec.describe Projects::Registry::RepositoriesController do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :private) } @@ -46,7 +46,7 @@ describe Projects::Registry::RepositoriesController do context 'when root container repository is not created' do context 'when there are tags for this repository' do before do - stub_container_registry_tags(repository: project.full_path, + stub_container_registry_tags(repository: :any, tags: %w[rc1 latest]) end diff --git a/spec/controllers/projects/registry/tags_controller_spec.rb b/spec/controllers/projects/registry/tags_controller_spec.rb index 5ab32b7d81d..6adee35b60a 100644 --- a/spec/controllers/projects/registry/tags_controller_spec.rb +++ b/spec/controllers/projects/registry/tags_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Registry::TagsController do +RSpec.describe Projects::Registry::TagsController do let(:user) { create(:user) } let(:project) { create(:project, :private) } diff --git a/spec/controllers/projects/releases/evidences_controller_spec.rb b/spec/controllers/projects/releases/evidences_controller_spec.rb index d3808087681..d5a9665d6a5 100644 --- a/spec/controllers/projects/releases/evidences_controller_spec.rb +++ b/spec/controllers/projects/releases/evidences_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Releases::EvidencesController do +RSpec.describe Projects::Releases::EvidencesController do let!(:project) { create(:project, :repository, :public) } let_it_be(:private_project) { create(:project, :repository, :private) } let_it_be(:developer) { create(:user) } @@ -31,8 +31,8 @@ describe Projects::Releases::EvidencesController do end describe 'GET #show' do - let_it_be(:tag_name) { "v1.1.0-evidence" } - let!(:release) { create(:release, :with_evidence, project: project, tag: tag_name) } + let(:tag_name) { "v1.1.0-evidence" } + let!(:release) { create(:release, project: project, tag: tag_name) } let(:evidence) { release.evidences.first } let(:tag) { CGI.escape(release.tag) } let(:format) { :json } @@ -48,6 +48,8 @@ describe Projects::Releases::EvidencesController do end before do + ::Releases::CreateEvidenceService.new(release).execute + sign_in(user) end @@ -84,14 +86,9 @@ describe Projects::Releases::EvidencesController do end context 'when release is associated to a milestone which includes an issue' do - let_it_be(:project) { create(:project, :repository, :public) } - let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:milestone) { create(:milestone, project: project, issues: [issue]) } - let_it_be(:release) { create(:release, project: project, tag: tag_name, milestones: [milestone]) } - - before do - create(:evidence, release: release) - end + let(:issue) { create(:issue, project: project) } + let(:milestone) { create(:milestone, project: project, issues: [issue]) } + let(:release) { create(:release, project: project, tag: tag_name, milestones: [milestone]) } shared_examples_for 'does not show the issue in evidence' do it do @@ -111,7 +108,9 @@ describe Projects::Releases::EvidencesController do end end - shared_examples_for 'safely expose evidence' do + context 'when user is non-project member' do + let(:user) { create(:user) } + it_behaves_like 'does not show the issue in evidence' context 'when the issue is confidential' do @@ -127,28 +126,50 @@ describe Projects::Releases::EvidencesController do end context 'when project is private' do - let!(:project) { create(:project, :repository, :private) } + let(:project) { create(:project, :repository, :private) } it_behaves_like 'evidence not found' end context 'when project restricts the visibility of issues to project members only' do - let!(:project) { create(:project, :repository, :issues_private) } + let(:project) { create(:project, :repository, :issues_private) } it_behaves_like 'evidence not found' end end - context 'when user is non-project member' do - let(:user) { create(:user) } - - it_behaves_like 'safely expose evidence' - end - context 'when user is auditor', if: Gitlab.ee? do let(:user) { create(:user, :auditor) } - it_behaves_like 'safely expose evidence' + it_behaves_like 'does not show the issue in evidence' + + context 'when the issue is confidential' do + let(:issue) { create(:issue, :confidential, project: project) } + + it_behaves_like 'does not show the issue in evidence' + end + + context 'when the user is the author of the confidential issue' do + let(:issue) { create(:issue, :confidential, project: project, author: user) } + + it_behaves_like 'does not show the issue in evidence' + end + + context 'when project is private' do + let(:project) { create(:project, :repository, :private) } + + it 'returns evidence ' do + subject + + expect(json_response).to eq(evidence.summary) + end + end + + context 'when project restricts the visibility of issues to project members only' do + let(:project) { create(:project, :repository, :issues_private) } + + it_behaves_like 'evidence not found' + end end context 'when external authorization control is enabled' do diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb index 45f4433ed0a..96c38c1b726 100644 --- a/spec/controllers/projects/releases_controller_spec.rb +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ReleasesController do +RSpec.describe Projects::ReleasesController do let!(:project) { create(:project, :repository, :public) } let_it_be(:private_project) { create(:project, :repository, :private) } let_it_be(:developer) { create(:user) } diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb index 42032b4cad0..97eea7c7e9d 100644 --- a/spec/controllers/projects/repositories_controller_spec.rb +++ b/spec/controllers/projects/repositories_controller_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -describe Projects::RepositoriesController do +RSpec.describe Projects::RepositoriesController do let(:project) { create(:project, :repository) } describe "GET archive" do diff --git a/spec/controllers/projects/runners_controller_spec.rb b/spec/controllers/projects/runners_controller_spec.rb index 1893180fe9b..66f20bd50c4 100644 --- a/spec/controllers/projects/runners_controller_spec.rb +++ b/spec/controllers/projects/runners_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::RunnersController do +RSpec.describe Projects::RunnersController do let(:user) { create(:user) } let(:project) { create(:project) } let(:runner) { create(:ci_runner, :project, projects: [project]) } diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb index 203e1e49994..3071d0b7f54 100644 --- a/spec/controllers/projects/serverless/functions_controller_spec.rb +++ b/spec/controllers/projects/serverless/functions_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Serverless::FunctionsController do +RSpec.describe Projects::Serverless::FunctionsController do include KubernetesHelpers include ReactiveCachingHelpers diff --git a/spec/controllers/projects/service_hook_logs_controller_spec.rb b/spec/controllers/projects/service_hook_logs_controller_spec.rb index a5130cd6e32..97fb31f0546 100644 --- a/spec/controllers/projects/service_hook_logs_controller_spec.rb +++ b/spec/controllers/projects/service_hook_logs_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ServiceHookLogsController do +RSpec.describe Projects::ServiceHookLogsController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:service) { create(:drone_ci_service, project: project) } diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb index c669119fa4e..04c74dfdefe 100644 --- a/spec/controllers/projects/services_controller_spec.rb +++ b/spec/controllers/projects/services_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::ServicesController do +RSpec.describe Projects::ServicesController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:service) { create(:jira_service, project: project) } @@ -134,24 +134,50 @@ describe Projects::ServicesController do describe 'PUT #update' do describe 'as HTML' do let(:service_params) { { active: true } } + let(:params) { project_params(service: service_params) } + + let(:message) { 'Jira activated.' } + let(:redirect_url) { project_settings_integrations_path(project) } before do - put :update, params: project_params(service: service_params) + put :update, params: params + end + + shared_examples 'service update' do + it 'redirects to the correct url with a flash message' do + expect(response).to redirect_to(redirect_url) + expect(flash[:notice]).to eq(message) + end end context 'when param `active` is set to true' do - it 'activates the service and redirects to integrations paths' do - expect(response).to redirect_to(project_settings_integrations_path(project)) - expect(flash[:notice]).to eq 'Jira activated.' + let(:params) { project_params(service: service_params, redirect_to: redirect) } + + context 'when redirect_to param is present' do + let(:redirect) { '/redirect_here' } + let(:redirect_url) { redirect } + + it_behaves_like 'service update' + end + + context 'when redirect_to is an external domain' do + let(:redirect) { 'http://examle.com' } + + it_behaves_like 'service update' + end + + context 'when redirect_to param is an empty string' do + let(:redirect) { '' } + + it_behaves_like 'service update' end end context 'when param `active` is set to false' do let(:service_params) { { active: false } } + let(:message) { 'Jira settings saved, but not activated.' } - it 'does not activate the service but saves the settings' do - expect(flash[:notice]).to eq 'Jira settings saved, but not activated.' - end + it_behaves_like 'service update' end end diff --git a/spec/controllers/projects/settings/access_tokens_controller_spec.rb b/spec/controllers/projects/settings/access_tokens_controller_spec.rb index 884a5bc2836..4743ab2b7c1 100644 --- a/spec/controllers/projects/settings/access_tokens_controller_spec.rb +++ b/spec/controllers/projects/settings/access_tokens_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -describe Projects::Settings::AccessTokensController do +RSpec.describe Projects::Settings::AccessTokensController do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project) } diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb index 6891af54eb4..8498ff49826 100644 --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -describe Projects::Settings::CiCdController do +RSpec.describe Projects::Settings::CiCdController do let_it_be(:user) { create(:user) } let_it_be(:project_auto_devops) { create(:project_auto_devops) } let(:project) { project_auto_devops.project } diff --git a/spec/controllers/projects/settings/integrations_controller_spec.rb b/spec/controllers/projects/settings/integrations_controller_spec.rb index 5d9fe3da912..0652786c787 100644 --- a/spec/controllers/projects/settings/integrations_controller_spec.rb +++ b/spec/controllers/projects/settings/integrations_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Settings::IntegrationsController do +RSpec.describe Projects::Settings::IntegrationsController do let(:project) { create(:project, :public) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb index c9afff0b73d..6b440e910ad 100644 --- a/spec/controllers/projects/settings/operations_controller_spec.rb +++ b/spec/controllers/projects/settings/operations_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Settings::OperationsController do +RSpec.describe Projects::Settings::OperationsController do let_it_be(:user) { create(:user) } let_it_be(:project, reload: true) { create(:project) } diff --git a/spec/controllers/projects/settings/repository_controller_spec.rb b/spec/controllers/projects/settings/repository_controller_spec.rb index fb9cdd860dc..46dba691bc4 100644 --- a/spec/controllers/projects/settings/repository_controller_spec.rb +++ b/spec/controllers/projects/settings/repository_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Settings::RepositoryController do +RSpec.describe Projects::Settings::RepositoryController do let(:project) { create(:project_empty_repo, :public) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb index b5f4929d8ce..8bbfaa8d327 100644 --- a/spec/controllers/projects/snippets_controller_spec.rb +++ b/spec/controllers/projects/snippets_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::SnippetsController do +RSpec.describe Projects::SnippetsController do include Gitlab::Routing let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/stages_controller_spec.rb b/spec/controllers/projects/stages_controller_spec.rb index c38e3d2544f..dcf8607ae18 100644 --- a/spec/controllers/projects/stages_controller_spec.rb +++ b/spec/controllers/projects/stages_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::StagesController do +RSpec.describe Projects::StagesController do let(:user) { create(:user) } let(:project) { create(:project, :repository) } diff --git a/spec/controllers/projects/starrers_controller_spec.rb b/spec/controllers/projects/starrers_controller_spec.rb index 5774ff7c576..66888fa3024 100644 --- a/spec/controllers/projects/starrers_controller_spec.rb +++ b/spec/controllers/projects/starrers_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::StarrersController do +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) } diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb index 7b470254de1..384218504b9 100644 --- a/spec/controllers/projects/static_site_editor_controller_spec.rb +++ b/spec/controllers/projects/static_site_editor_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::StaticSiteEditorController do +RSpec.describe Projects::StaticSiteEditorController do let_it_be(:project) { create(:project, :public, :repository) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/tags/releases_controller_spec.rb b/spec/controllers/projects/tags/releases_controller_spec.rb index cb12e074732..b3d4d944440 100644 --- a/spec/controllers/projects/tags/releases_controller_spec.rb +++ b/spec/controllers/projects/tags/releases_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::Tags::ReleasesController do +RSpec.describe Projects::Tags::ReleasesController do let!(:project) { create(:project, :repository) } let!(:user) { create(:user) } let!(:release) { create(:release, project: project) } @@ -16,7 +16,7 @@ describe Projects::Tags::ReleasesController do describe 'GET #edit' do it 'initializes a new release' do tag_id = release.tag - project.releases.destroy_all # rubocop: disable DestroyAll + project.releases.destroy_all # rubocop: disable Cop/DestroyAll response = get :edit, params: { namespace_id: project.namespace, project_id: project, tag_id: tag_id } diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb index 15ef1c65c53..122d1b072d0 100644 --- a/spec/controllers/projects/tags_controller_spec.rb +++ b/spec/controllers/projects/tags_controller_spec.rb @@ -2,10 +2,11 @@ require 'spec_helper' -describe Projects::TagsController do +RSpec.describe Projects::TagsController do let(:project) { create(:project, :public, :repository) } let!(:release) { create(:release, project: project) } let!(:invalid_release) { create(:release, project: project, tag: 'does-not-exist') } + let(:user) { create(:user) } describe 'GET index' do before do @@ -61,4 +62,69 @@ describe Projects::TagsController do end end end + + describe 'POST #create' do + before do + project.add_developer(user) + sign_in(user) + end + + let(:release_description) { nil } + let(:request) do + post(:create, params: { + namespace_id: project.namespace.to_param, + project_id: project, + tag_name: '1.0', + ref: 'master', + release_description: release_description + }) + end + + it 'creates tag' do + request + + expect(response).to have_gitlab_http_status(:found) + expect(project.repository.find_tag('1.0')).to be_present + end + + # TODO: remove this with the release creation moved to it's own form https://gitlab.com/gitlab-org/gitlab/-/issues/214245 + context 'when release description is set' do + let(:release_description) { 'some release description' } + + it 'creates tag and release' do + request + + expect(response).to have_gitlab_http_status(:found) + expect(project.repository.find_tag('1.0')).to be_present + + release = project.releases.find_by_tag!('1.0') + + expect(release).to be_present + expect(release.description).to eq(release_description) + end + + it 'passes the last pipeline for evidence creation', :sidekiq_inline do + sha = project.repository.commit('master').sha + create(:ci_empty_pipeline, sha: sha, project: project) # old pipeline + pipeline = create(:ci_empty_pipeline, sha: sha, project: project) + + # simulating pipeline creation by new tag + expect_any_instance_of(Repository).to receive(:add_tag).and_wrap_original do |m, *args| + create(:ci_empty_pipeline, sha: sha, project: project) + m.call(*args) + end + + expect_next_instance_of(Releases::CreateEvidenceService, anything, pipeline: pipeline) do |service| + expect(service).to receive(:execute).and_call_original + end + + request + + release = project.releases.find_by_tag!('1.0') + + expect(release).to be_present + expect(release.description).to eq(release_description) + end + end + end end diff --git a/spec/controllers/projects/templates_controller_spec.rb b/spec/controllers/projects/templates_controller_spec.rb index fcd9b4aa8bd..40632e0dea7 100644 --- a/spec/controllers/projects/templates_controller_spec.rb +++ b/spec/controllers/projects/templates_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::TemplatesController do +RSpec.describe Projects::TemplatesController do let(:project) { create(:project, :repository, :private) } let(:user) { create(:user) } let(:file_path_1) { '.gitlab/issue_templates/issue_template.md' } diff --git a/spec/controllers/projects/todos_controller_spec.rb b/spec/controllers/projects/todos_controller_spec.rb index b7d40d2a452..e1e1e455094 100644 --- a/spec/controllers/projects/todos_controller_spec.rb +++ b/spec/controllers/projects/todos_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -describe Projects::TodosController do +RSpec.describe Projects::TodosController do let(:user) { create(:user) } let(:project) { create(:project) } let(:issue) { create(:issue, project: project) } diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb index 96838383540..f6ec04d4dd7 100644 --- a/spec/controllers/projects/tree_controller_spec.rb +++ b/spec/controllers/projects/tree_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::TreeController do +RSpec.describe Projects::TreeController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb index bb5415ee62c..dda58f06a37 100644 --- a/spec/controllers/projects/uploads_controller_spec.rb +++ b/spec/controllers/projects/uploads_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::UploadsController do +RSpec.describe Projects::UploadsController do include WorkhorseHelpers let(:model) { create(:project, :public) } diff --git a/spec/controllers/projects/usage_ping_controller_spec.rb b/spec/controllers/projects/usage_ping_controller_spec.rb index a68967c228f..9ace072d561 100644 --- a/spec/controllers/projects/usage_ping_controller_spec.rb +++ b/spec/controllers/projects/usage_ping_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::UsagePingController do +RSpec.describe Projects::UsagePingController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/variables_controller_spec.rb b/spec/controllers/projects/variables_controller_spec.rb index 21e106660d0..8bb4c2dae4b 100644 --- a/spec/controllers/projects/variables_controller_spec.rb +++ b/spec/controllers/projects/variables_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe Projects::VariablesController do +RSpec.describe Projects::VariablesController do let(:project) { create(:project) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/web_ide_terminals_controller_spec.rb b/spec/controllers/projects/web_ide_terminals_controller_spec.rb new file mode 100644 index 00000000000..2ae5899c258 --- /dev/null +++ b/spec/controllers/projects/web_ide_terminals_controller_spec.rb @@ -0,0 +1,304 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::WebIdeTerminalsController do + let_it_be(:owner) { create(:owner) } + let_it_be(:admin) { create(:admin) } + let_it_be(:maintainer) { create(:user) } + let_it_be(:developer) { create(:user) } + let_it_be(:reporter) { create(:user) } + let_it_be(:guest) { create(:user) } + let_it_be(:project) { create(:project, :private, :repository, namespace: owner.namespace) } + let(:pipeline) { create(:ci_pipeline, project: project, source: :webide, config_source: :webide_source, user: user) } + let(:job) { create(:ci_build, pipeline: pipeline, user: user, project: project) } + let(:user) { maintainer } + + before do + project.add_maintainer(maintainer) + project.add_developer(developer) + project.add_reporter(reporter) + project.add_guest(guest) + + sign_in(user) + end + + shared_examples 'terminal access rights' do + context 'with admin' do + let(:user) { admin } + + context 'when admin mode is enabled', :enable_admin_mode do + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when admin mode is disabled' do + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'with owner' do + let(:user) { owner } + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'with maintainer' do + let(:user) { maintainer } + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'with developer' do + let(:user) { developer } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'with reporter' do + let(:user) { reporter } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'with guest' do + let(:user) { guest } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'with non member' do + let(:user) { create(:user) } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + shared_examples 'when pipeline is not from a webide source' do + context 'with admin' do + let(:user) { admin } + let(:pipeline) { create(:ci_pipeline, project: project, source: :chat, user: user) } + + it 'returns 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + describe 'GET show' do + before do + get(:show, params: { namespace_id: project.namespace.to_param, project_id: project, id: job.id }) + end + + it_behaves_like 'terminal access rights' + it_behaves_like 'when pipeline is not from a webide source' + end + + describe 'POST check_config' do + let(:result) { { status: :success } } + + before do + allow_next_instance_of(::Ci::WebIdeConfigService) do |instance| + allow(instance).to receive(:execute).and_return(result) + end + + post :check_config, params: { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + branch: 'master' + } + end + + it_behaves_like 'terminal access rights' + + context 'when invalid config file' do + let(:user) { admin } + let(:result) { { status: :error } } + + it 'returns 422', :enable_admin_mode do + expect(response).to have_gitlab_http_status(:unprocessable_entity) + end + end + end + + describe 'POST create' do + let(:branch) { 'master' } + + subject do + post :create, params: { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + branch: branch + } + end + + context 'when terminal job is created successfully' do + let(:build) { create(:ci_build, project: project) } + let(:pipeline) { build.pipeline } + + before do + allow_next_instance_of(::Ci::CreateWebIdeTerminalService) do |instance| + allow(instance).to receive(:execute).and_return(status: :success, pipeline: pipeline) + end + end + + context 'access rights' do + before do + subject + end + + it_behaves_like 'terminal access rights' + end + + it 'increases the web ide terminal counter' do + expect(Gitlab::UsageDataCounters::WebIdeCounter).to receive(:increment_terminals_count) + + subject + end + end + + shared_examples 'web ide terminal usage counter' do + it 'does not increase', :enable_admin_mode do + expect(Gitlab::UsageDataCounters::WebIdeCounter).not_to receive(:increment_terminals_count) + + subject + end + end + + context 'when branch does not exist' do + let(:user) { admin } + let(:branch) { 'foobar' } + + it 'returns 400', :enable_admin_mode do + subject + + expect(response).to have_gitlab_http_status(:bad_request) + end + + it_behaves_like 'web ide terminal usage counter' + end + + context 'when there is an error creating the job' do + let(:user) { admin } + + before do + allow_next_instance_of(::Ci::CreateWebIdeTerminalService) do |instance| + allow(instance).to receive(:execute).and_return(status: :error, message: 'foobar') + end + end + + it 'returns 400', :enable_admin_mode do + subject + + expect(response).to have_gitlab_http_status(:bad_request) + end + + it_behaves_like 'web ide terminal usage counter' + end + + context 'when the current build is nil' do + let(:user) { admin } + + before do + allow(pipeline).to receive(:builds).and_return([]) + allow_next_instance_of(::Ci::CreateWebIdeTerminalService) do |instance| + allow(instance).to receive(:execute).and_return(status: :success, pipeline: pipeline) + end + end + + it 'returns 400', :enable_admin_mode do + subject + + expect(response).to have_gitlab_http_status(:bad_request) + end + + it_behaves_like 'web ide terminal usage counter' + end + end + + describe 'POST cancel' do + let(:job) { create(:ci_build, :running, pipeline: pipeline, user: user, project: project) } + + before do + post(:cancel, params: { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: job.id + }) + end + + it_behaves_like 'terminal access rights' + it_behaves_like 'when pipeline is not from a webide source' + + context 'when job is not cancelable' do + let!(:job) { create(:ci_build, :failed, pipeline: pipeline, user: user) } + + it 'returns 422' do + expect(response).to have_gitlab_http_status(:unprocessable_entity) + end + end + end + + describe 'POST retry' do + let(:status) { :failed } + let(:job) { create(:ci_build, status, pipeline: pipeline, user: user, project: project) } + + before do + post(:retry, params: { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: job.id + }) + end + + it_behaves_like 'terminal access rights' + it_behaves_like 'when pipeline is not from a webide source' + + context 'when job is not retryable' do + let(:status) { :running } + + it 'returns 422' do + expect(response).to have_gitlab_http_status(:unprocessable_entity) + end + end + + context 'when job is cancelled' do + let(:status) { :canceled } + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when job fails' do + let(:status) { :failed } + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when job is successful' do + let(:status) { :success } + + it 'returns 200' do + expect(response).to have_gitlab_http_status(:ok) + end + end + end +end diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb index b4bbf76ce18..4e58822b613 100644 --- a/spec/controllers/projects/wikis_controller_spec.rb +++ b/spec/controllers/projects/wikis_controller_spec.rb @@ -2,283 +2,9 @@ require 'spec_helper' -describe Projects::WikisController do - let_it_be(:project) { create(:project, :public, :repository) } - let(:user) { project.owner } - let(:project_wiki) { ProjectWiki.new(project, user) } - let(:wiki) { project_wiki.wiki } - let(:wiki_title) { 'page title test' } - - before do - create_page(wiki_title, 'hello world') - - sign_in(user) - end - - after do - destroy_page(wiki_title) - end - - describe 'GET #new' do - subject { get :new, params: { namespace_id: project.namespace, project_id: project } } - - it 'redirects to #show and appends a `random_title` param' do - subject - - expect(response).to have_gitlab_http_status(:found) - expect(Rails.application.routes.recognize_path(response.redirect_url)).to include( - controller: 'projects/wikis', - action: 'show' - ) - expect(response.redirect_url).to match(/\?random_title=true\Z/) - end - end - - describe 'GET #pages' do - subject { get :pages, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } } - - it 'does not load the pages content' do - expect(controller).to receive(:load_wiki).and_return(project_wiki) - - expect(project_wiki).to receive(:list_pages).twice.and_call_original - - subject - end - end - - describe 'GET #history' do - before do - allow(controller) - .to receive(:can?) - .with(any_args) - .and_call_original - - # The :create_wiki permission is irrelevant to reading history. - expect(controller) - .not_to receive(:can?) - .with(anything, :create_wiki, any_args) - - allow(controller) - .to receive(:can?) - .with(anything, :read_wiki, any_args) - .and_return(allow_read_wiki) - end - - shared_examples 'fetching history' do |expected_status| - before do - get :history, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } - end - - it "returns status #{expected_status}" do - expect(response).to have_gitlab_http_status(expected_status) - end - end - - it_behaves_like 'fetching history', :ok do - let(:allow_read_wiki) { true } - - it 'assigns @page_versions' do - expect(assigns(:page_versions)).to be_present - end - end - - it_behaves_like 'fetching history', :not_found do - let(:allow_read_wiki) { false } - end - end - - describe 'GET #show' do - render_views - - let(:random_title) { nil } - - subject { get :show, params: { namespace_id: project.namespace, project_id: project, id: id, random_title: random_title } } - - context 'when page exists' do - let(:id) { wiki_title } - - it 'limits the retrieved pages for the sidebar' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(assigns(:page).title).to eq(wiki_title) - expect(assigns(:sidebar_wiki_entries)).to contain_exactly(an_instance_of(WikiPage)) - expect(assigns(:sidebar_limited)).to be(false) - end - - context 'when page content encoding is invalid' do - it 'sets flash error' do - allow(controller).to receive(:valid_encoding?).and_return(false) - - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(flash[:notice]).to eq(_('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.')) - end - end - end - - context 'when the page does not exist' do - let(:id) { 'does not exist' } - - before do - subject - end - - it 'builds a new wiki page with the id as the title' do - expect(assigns(:page).title).to eq(id) - end - - context 'when a random_title param is present' do - let(:random_title) { true } - - it 'builds a new wiki page with no title' do - expect(assigns(:page).title).to be_empty - end - end - end - - context 'when page is a file' do - include WikiHelpers - - let(:id) { upload_file_to_wiki(project, user, file_name) } - - context 'when file is an image' do - let(:file_name) { 'dk.png' } - - it 'delivers the image' do - subject - - expect(response.headers['Content-Disposition']).to match(/^inline/) - expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" - end - - context 'when file is a svg' do - let(:file_name) { 'unsanitized.svg' } - - it 'delivers the image' do - subject - - expect(response.headers['Content-Disposition']).to match(/^inline/) - expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" - end - end - - it_behaves_like 'project cache control headers' - end - - context 'when file is a pdf' do - let(:file_name) { 'git-cheat-sheet.pdf' } - - it 'sets the content type to sets the content response headers' do - subject - - expect(response.headers['Content-Disposition']).to match(/^inline/) - expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" - end - - it_behaves_like 'project cache control headers' - end - end - end - - describe 'POST #preview_markdown' do - it 'renders json in a correct format' do - post :preview_markdown, params: { namespace_id: project.namespace, project_id: project, id: 'page/path', text: '*Markdown* text' } - - expect(json_response.keys).to match_array(%w(body references)) - end - end - - describe 'GET #edit' do - subject { get(:edit, params: { namespace_id: project.namespace, project_id: project, id: wiki_title }) } - - context 'when page content encoding is invalid' do - it 'redirects to show' do - allow(controller).to receive(:valid_encoding?).and_return(false) - - subject - - expect(response).to redirect_to_wiki(project, project_wiki.list_pages.first) - end - end - - context 'when the page has nil content' do - let(:page) { create(:wiki_page) } - - it 'redirects to show' do - allow(page).to receive(:content).and_return(nil) - allow(controller).to receive(:find_page).and_return(page) - - subject - - expect(response).to redirect_to_wiki(project, page) - end - end - - context 'when page content encoding is valid' do - render_views - - it 'shows the edit page' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response.body).to include(s_('Wiki|Edit Page')) - end - end - end - - describe 'PATCH #update' do - let(:new_title) { 'New title' } - let(:new_content) { 'New content' } - - subject do - patch(:update, - params: { - namespace_id: project.namespace, - project_id: project, - id: wiki_title, - wiki: { title: new_title, content: new_content } - }) - end - - context 'when page content encoding is invalid' do - it 'redirects to show' do - allow(controller).to receive(:valid_encoding?).and_return(false) - - subject - expect(response).to redirect_to_wiki(project, project_wiki.list_pages.first) - end - end - - context 'when page content encoding is valid' do - render_views - - it 'updates the page' do - subject - - wiki_page = project_wiki.list_pages(load_content: true).first - - expect(wiki_page.title).to eq new_title - expect(wiki_page.content).to eq new_content - end - end - end - - def create_page(name, content) - wiki.write_page(name, :markdown, content, commit_details(name)) - end - - def commit_details(name) - Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "created page #{name}") - end - - def destroy_page(title, dir = '') - page = wiki.page(title: title, dir: dir) - project_wiki.delete_page(page, "test commit") - end - - def redirect_to_wiki(project, page) - redirect_to(controller.project_wiki_path(project, page)) +RSpec.describe Projects::WikisController do + it_behaves_like 'wiki controller actions' do + let(:container) { create(:project, :public, :repository, namespace: user.namespace) } + let(:routing_params) { { namespace_id: container.namespace, project_id: container } } end end |