diff options
Diffstat (limited to 'spec/controllers')
55 files changed, 1447 insertions, 764 deletions
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb index f71f859a704..f0b224484c6 100644 --- a/spec/controllers/admin/application_settings_controller_spec.rb +++ b/spec/controllers/admin/application_settings_controller_spec.rb @@ -157,6 +157,44 @@ RSpec.describe Admin::ApplicationSettingsController do expect(ApplicationSetting.current.default_branch_name).to eq("example_branch_name") end + context "personal access token prefix settings" do + let(:application_settings) { ApplicationSetting.current } + + shared_examples "accepts prefix setting" do |prefix| + it "updates personal_access_token_prefix setting" do + put :update, params: { application_setting: { personal_access_token_prefix: prefix } } + + expect(response).to redirect_to(general_admin_application_settings_path) + expect(application_settings.reload.personal_access_token_prefix).to eq(prefix) + end + end + + shared_examples "rejects prefix setting" do |prefix| + it "does not update personal_access_token_prefix setting" do + put :update, params: { application_setting: { personal_access_token_prefix: prefix } } + + expect(response).not_to redirect_to(general_admin_application_settings_path) + expect(application_settings.reload.personal_access_token_prefix).not_to eq(prefix) + end + end + + context "with valid prefix" do + include_examples("accepts prefix setting", "a_prefix@") + end + + context "with blank prefix" do + include_examples("accepts prefix setting", "") + end + + context "with too long prefix" do + include_examples("rejects prefix setting", "a_prefix@" * 10) + end + + context "with invalid characters prefix" do + include_examples("rejects prefix setting", "a_préfixñ:") + end + end + context 'external policy classification settings' do let(:settings) do { diff --git a/spec/controllers/admin/clusters/applications_controller_spec.rb b/spec/controllers/admin/clusters/applications_controller_spec.rb index 2a77693061c..d1ca64d6bd2 100644 --- a/spec/controllers/admin/clusters/applications_controller_spec.rb +++ b/spec/controllers/admin/clusters/applications_controller_spec.rb @@ -22,7 +22,7 @@ RSpec.describe Admin::Clusters::ApplicationsController do post :create, params: params end - let(:application) { 'helm' } + let(:application) { 'ingress' } let(:params) { { application: application, id: cluster.id } } describe 'functionality' do @@ -37,7 +37,7 @@ RSpec.describe Admin::Clusters::ApplicationsController do expect { subject }.to change { current_application.count } expect(response).to have_gitlab_http_status(:no_content) - expect(cluster.application_helm).to be_scheduled + expect(cluster.application_ingress).to be_scheduled end context 'when cluster do not exists' do @@ -61,7 +61,7 @@ RSpec.describe Admin::Clusters::ApplicationsController do context 'when application is already installing' do before do - create(:clusters_applications_helm, :installing, cluster: cluster) + create(:clusters_applications_ingress, :installing, cluster: cluster) end it 'returns 400' do diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb index 69bdc79c5f5..85aa77d8473 100644 --- a/spec/controllers/admin/clusters_controller_spec.rb +++ b/spec/controllers/admin/clusters_controller_spec.rb @@ -341,7 +341,7 @@ RSpec.describe Admin::ClustersController do expect { post_create_aws }.not_to change { Clusters::Cluster.count } expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(response.content_type).to eq('application/json') + expect(response.media_type).to eq('application/json') expect(response.body).to include('is invalid') end end diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb index 1a13d016b73..e14619a9916 100644 --- a/spec/controllers/admin/integrations_controller_spec.rb +++ b/spec/controllers/admin/integrations_controller_spec.rb @@ -73,4 +73,28 @@ RSpec.describe Admin::IntegrationsController do end end end + + describe '#reset' do + let_it_be(:integration) { create(:jira_service, :instance) } + let_it_be(:inheriting_integration) { create(:jira_service, inherit_from_id: integration.id) } + + subject do + post :reset, params: { id: integration.class.to_param } + end + + it 'returns 200 OK', :aggregate_failures do + subject + + expected_json = {}.to_json + + expect(flash[:notice]).to eq('This integration, and inheriting projects were reset.') + expect(response).to have_gitlab_http_status(:ok) + expect(response.body).to eq(expected_json) + end + + it 'deletes the integration and all inheriting integrations' do + expect { subject }.to change { JiraService.for_instance.count }.by(-1) + .and change { JiraService.inherit_from_id(integration.id).count }.by(-1) + end + end end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index d0d1fa6a6bc..f902a3d2541 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -102,6 +102,57 @@ RSpec.describe Admin::UsersController do end end + describe 'DELETE #reject' do + subject { put :reject, params: { id: user.username } } + + context 'when rejecting a pending user' do + let(:user) { create(:user, :blocked_pending_approval) } + + it 'hard deletes the user', :sidekiq_inline do + subject + + expect(User.exists?(user.id)).to be_falsy + end + + it 'displays the rejection message' do + subject + + expect(response).to redirect_to(admin_users_path) + expect(flash[:notice]).to eq("You've rejected #{user.name}") + end + + it 'sends the user a rejection email' do + expect_next_instance_of(NotificationService) do |notification| + allow(notification).to receive(:user_admin_rejection).with(user.name, user.notification_email) + end + + subject + end + end + + context 'when user is not pending' do + let(:user) { create(:user, state: 'active') } + + it 'does not reject and delete the user' do + subject + + expect(User.exists?(user.id)).to be_truthy + end + + it 'displays the error' do + subject + + expect(flash[:alert]).to eq('This user does not have a pending request') + end + + it 'does not email the user' do + expect(NotificationService).not_to receive(:new) + + subject + end + end + end + describe 'PUT #approve' do let(:user) { create(:user, :blocked_pending_approval) } diff --git a/spec/controllers/boards/lists_controller_spec.rb b/spec/controllers/boards/lists_controller_spec.rb index 9b09f46d17e..29141582c6f 100644 --- a/spec/controllers/boards/lists_controller_spec.rb +++ b/spec/controllers/boards/lists_controller_spec.rb @@ -22,7 +22,7 @@ RSpec.describe Boards::ListsController do read_board_list user: user, board: board expect(response).to have_gitlab_http_status(:ok) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end it 'returns a list of board lists' do @@ -85,20 +85,22 @@ RSpec.describe Boards::ListsController do context 'with invalid params' do context 'when label is nil' do - it 'returns a not found 404 response' do + it 'returns an unprocessable entity 422 response' do create_board_list user: user, board: board, label_id: nil - expect(response).to have_gitlab_http_status(:not_found) + expect(response).to have_gitlab_http_status(:unprocessable_entity) + expect(json_response['errors']).to eq(['Label not found']) end end context 'when label that does not belongs to project' do - it 'returns a not found 404 response' do + it 'returns an unprocessable entity 422 response' do label = create(:label, name: 'Development') create_board_list user: user, board: board, label_id: label.id - expect(response).to have_gitlab_http_status(:not_found) + expect(response).to have_gitlab_http_status(:unprocessable_entity) + expect(json_response['errors']).to eq(['Label not found']) end end end diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb index 9b78f841cce..c838affa239 100644 --- a/spec/controllers/dashboard_controller_spec.rb +++ b/spec/controllers/dashboard_controller_spec.rb @@ -15,16 +15,6 @@ RSpec.describe DashboardController do describe 'GET issues' do it_behaves_like 'issuables list meta-data', :issue, :issues it_behaves_like 'issuables requiring filter', :issues - - it 'lists only incidents and issues' do - issue = create(:incident, project: project, author: user) - incident = create(:incident, project: project, author: user) - create(:quality_test_case, project: project, author: user) - - get :issues, params: { author_id: user.id } - - expect(assigns(:issues)).to match_array([issue, incident]) - end end describe 'GET merge requests' do diff --git a/spec/controllers/groups/boards_controller_spec.rb b/spec/controllers/groups/boards_controller_spec.rb index 66595c27531..a7480130e0a 100644 --- a/spec/controllers/groups/boards_controller_spec.rb +++ b/spec/controllers/groups/boards_controller_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Groups::BoardsController do list_boards expect(response).to render_template :index - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end context 'with unauthorized user' do @@ -36,7 +36,7 @@ RSpec.describe Groups::BoardsController do list_boards expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end @@ -52,7 +52,7 @@ RSpec.describe Groups::BoardsController do list_boards expect(response).to render_template :index - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end end @@ -81,7 +81,7 @@ RSpec.describe Groups::BoardsController do list_boards format: :json expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end end end @@ -103,7 +103,7 @@ RSpec.describe Groups::BoardsController do expect { read_board board: board }.to change(BoardGroupRecentVisit, :count).by(1) expect(response).to render_template :show - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end context 'with unauthorized user' do @@ -118,7 +118,7 @@ RSpec.describe Groups::BoardsController do read_board board: board expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end @@ -131,7 +131,7 @@ RSpec.describe Groups::BoardsController do expect { read_board board: board }.to change(BoardGroupRecentVisit, :count).by(0) expect(response).to render_template :show - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end end @@ -157,7 +157,7 @@ RSpec.describe Groups::BoardsController do read_board board: board, format: :json expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end end end diff --git a/spec/controllers/groups/clusters/applications_controller_spec.rb b/spec/controllers/groups/clusters/applications_controller_spec.rb index c1d170edce3..c3947c27399 100644 --- a/spec/controllers/groups/clusters/applications_controller_spec.rb +++ b/spec/controllers/groups/clusters/applications_controller_spec.rb @@ -28,7 +28,7 @@ RSpec.describe Groups::Clusters::ApplicationsController do post :create, params: params.merge(group_id: group) end - let(:application) { 'helm' } + let(:application) { 'ingress' } let(:params) { { application: application, id: cluster.id } } describe 'functionality' do @@ -44,7 +44,7 @@ RSpec.describe Groups::Clusters::ApplicationsController do expect { subject }.to change { current_application.count } expect(response).to have_gitlab_http_status(:no_content) - expect(cluster.application_helm).to be_scheduled + expect(cluster.application_ingress).to be_scheduled end context 'when cluster do not exists' do @@ -68,7 +68,7 @@ RSpec.describe Groups::Clusters::ApplicationsController do context 'when application is already installing' do before do - create(:clusters_applications_helm, :installing, cluster: cluster) + create(:clusters_applications_ingress, :installing, cluster: cluster) end it 'returns 400' do diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb index 140b7b0f2a8..b287aca1e46 100644 --- a/spec/controllers/groups/clusters_controller_spec.rb +++ b/spec/controllers/groups/clusters_controller_spec.rb @@ -476,7 +476,7 @@ RSpec.describe Groups::ClustersController do expect { post_create_aws }.not_to change { Clusters::Cluster.count } expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(response.content_type).to eq('application/json') + expect(response.media_type).to eq('application/json') expect(response.body).to include('is invalid') end end diff --git a/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb b/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb new file mode 100644 index 00000000000..857e0570621 --- /dev/null +++ b/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Groups::DependencyProxyAuthController do + include DependencyProxyHelpers + + describe 'GET #authenticate' do + subject { get :authenticate } + + context 'feature flag disabled' do + before do + stub_feature_flags(dependency_proxy_for_private_groups: false) + end + + it 'returns successfully', :aggregate_failures do + subject + + expect(response).to have_gitlab_http_status(:success) + end + end + + context 'without JWT' do + it 'returns unauthorized with oauth realm', :aggregate_failures do + subject + + expect(response).to have_gitlab_http_status(:unauthorized) + expect(response.headers['WWW-Authenticate']).to eq DependencyProxy::Registry.authenticate_header + end + end + + context 'with valid JWT' do + let_it_be(:user) { create(:user) } + let(:jwt) { build_jwt(user) } + let(:token_header) { "Bearer #{jwt.encoded}" } + + before do + request.headers['HTTP_AUTHORIZATION'] = token_header + end + + it { is_expected.to have_gitlab_http_status(:success) } + end + + context 'with invalid JWT' do + context 'bad user' do + let(:jwt) { build_jwt(double('bad_user', id: 999)) } + let(:token_header) { "Bearer #{jwt.encoded}" } + + before do + request.headers['HTTP_AUTHORIZATION'] = token_header + end + + it { is_expected.to have_gitlab_http_status(:not_found) } + end + + context 'token with no user id' do + let(:token_header) { "Bearer #{build_jwt.encoded}" } + + before do + request.headers['HTTP_AUTHORIZATION'] = token_header + end + + it { is_expected.to have_gitlab_http_status(:not_found) } + end + + context 'expired token' do + let_it_be(:user) { create(:user) } + let(:jwt) { build_jwt(user, expire_time: Time.zone.now - 1.hour) } + let(:token_header) { "Bearer #{jwt.encoded}" } + + before do + request.headers['HTTP_AUTHORIZATION'] = token_header + end + + it { is_expected.to have_gitlab_http_status(:unauthorized) } + end + end + end +end diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb index 615b56ff22f..39cbdfb9123 100644 --- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb +++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb @@ -3,8 +3,77 @@ require 'spec_helper' RSpec.describe Groups::DependencyProxyForContainersController do + include HttpBasicAuthHelpers + include DependencyProxyHelpers + + let_it_be(:user) { create(:user) } let(:group) { create(:group) } let(:token_response) { { status: :success, token: 'abcd1234' } } + let(:jwt) { build_jwt(user) } + let(:token_header) { "Bearer #{jwt.encoded}" } + + shared_examples 'without a token' do + before do + request.headers['HTTP_AUTHORIZATION'] = nil + end + + context 'feature flag disabled' do + before do + stub_feature_flags(dependency_proxy_for_private_groups: false) + end + + it { is_expected.to have_gitlab_http_status(:ok) } + end + + it { is_expected.to have_gitlab_http_status(:unauthorized) } + end + + shared_examples 'feature flag disabled with private group' do + before do + stub_feature_flags(dependency_proxy_for_private_groups: false) + end + + it 'redirects', :aggregate_failures do + group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) + + subject + + expect(response).to have_gitlab_http_status(:redirect) + expect(response.location).to end_with(new_user_session_path) + end + end + + shared_examples 'without permission' do + context 'with invalid user' do + before do + user = double('bad_user', id: 999) + token_header = "Bearer #{build_jwt(user).encoded}" + request.headers['HTTP_AUTHORIZATION'] = token_header + end + + it { is_expected.to have_gitlab_http_status(:not_found) } + end + + context 'with valid user that does not have access' do + let(:group) { create(:group, :private) } + + before do + user = double('bad_user', id: 999) + token_header = "Bearer #{build_jwt(user).encoded}" + request.headers['HTTP_AUTHORIZATION'] = token_header + end + + it { is_expected.to have_gitlab_http_status(:not_found) } + end + + context 'when user is not found' do + before do + allow(User).to receive(:find).and_return(nil) + end + + it { is_expected.to have_gitlab_http_status(:unauthorized) } + end + end shared_examples 'not found when disabled' do context 'feature disabled' do @@ -27,14 +96,16 @@ RSpec.describe Groups::DependencyProxyForContainersController do allow_next_instance_of(DependencyProxy::RequestTokenService) do |instance| allow(instance).to receive(:execute).and_return(token_response) end + + request.headers['HTTP_AUTHORIZATION'] = token_header end describe 'GET #manifest' do - let(:manifest) { { foo: 'bar' }.to_json } + let_it_be(:manifest) { create(:dependency_proxy_manifest) } let(:pull_response) { { status: :success, manifest: manifest } } before do - allow_next_instance_of(DependencyProxy::PullManifestService) do |instance| + allow_next_instance_of(DependencyProxy::FindOrCreateManifestService) do |instance| allow(instance).to receive(:execute).and_return(pull_response) end end @@ -46,6 +117,10 @@ RSpec.describe Groups::DependencyProxyForContainersController do enable_dependency_proxy end + it_behaves_like 'without a token' + it_behaves_like 'without permission' + it_behaves_like 'feature flag disabled with private group' + context 'remote token request fails' do let(:token_response) do { @@ -80,11 +155,17 @@ RSpec.describe Groups::DependencyProxyForContainersController do end end - it 'returns 200 with manifest file' do + it 'sends a file' do + expect(controller).to receive(:send_file).with(manifest.file.path, {}) + + subject + end + + it 'returns Content-Disposition: attachment' do subject expect(response).to have_gitlab_http_status(:ok) - expect(response.body).to eq(manifest) + expect(response.headers['Content-Disposition']).to match(/^attachment/) end end @@ -96,7 +177,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do end describe 'GET #blob' do - let(:blob) { create(:dependency_proxy_blob) } + let_it_be(:blob) { create(:dependency_proxy_blob) } let(:blob_sha) { blob.file_name.sub('.gz', '') } let(:blob_response) { { status: :success, blob: blob } } @@ -113,6 +194,10 @@ RSpec.describe Groups::DependencyProxyForContainersController do enable_dependency_proxy end + it_behaves_like 'without a token' + it_behaves_like 'without permission' + it_behaves_like 'feature flag disabled with private group' + context 'remote blob request fails' do let(:blob_response) do { diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb index 2c85fe482e2..05e93da18e7 100644 --- a/spec/controllers/groups/milestones_controller_spec.rb +++ b/spec/controllers/groups/milestones_controller_spec.rb @@ -177,7 +177,7 @@ RSpec.describe Groups::MilestonesController do expect(milestones.count).to eq(3) expect(milestones.collect { |m| m['title'] }).to match_array(['same name', 'same name', 'group milestone']) expect(response).to have_gitlab_http_status(:ok) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end context 'with subgroup milestones' do diff --git a/spec/controllers/groups/releases_controller_spec.rb b/spec/controllers/groups/releases_controller_spec.rb index 0925548f60a..50701382945 100644 --- a/spec/controllers/groups/releases_controller_spec.rb +++ b/spec/controllers/groups/releases_controller_spec.rb @@ -28,7 +28,7 @@ RSpec.describe Groups::ReleasesController do end it 'returns an application/json content_type' do - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end it 'returns OK' do diff --git a/spec/controllers/groups/settings/integrations_controller_spec.rb b/spec/controllers/groups/settings/integrations_controller_spec.rb index beb2ad3afec..3233e814184 100644 --- a/spec/controllers/groups/settings/integrations_controller_spec.rb +++ b/spec/controllers/groups/settings/integrations_controller_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' RSpec.describe Groups::Settings::IntegrationsController do - let(:user) { create(:user) } - let(:group) { create(:group) } + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } before do sign_in(user) @@ -24,16 +24,6 @@ RSpec.describe Groups::Settings::IntegrationsController do group.add_owner(user) end - context 'when group_level_integrations not enabled' do - it 'returns not_found' do - stub_feature_flags(group_level_integrations: false) - - get :index, params: { group_id: group } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - it 'successfully displays the template' do get :index, params: { group_id: group } @@ -57,16 +47,6 @@ RSpec.describe Groups::Settings::IntegrationsController do group.add_owner(user) end - context 'when group_level_integrations not enabled' do - it 'returns not_found' do - stub_feature_flags(group_level_integrations: false) - - get :edit, params: { group_id: group, id: Service.available_services_names(include_project_specific: false).sample } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - Service.available_services_names(include_project_specific: false).each do |integration_name| context "#{integration_name}" do it 'successfully displays the template' do @@ -111,4 +91,42 @@ RSpec.describe Groups::Settings::IntegrationsController do end end end + + describe '#reset' do + let_it_be(:integration) { create(:jira_service, group: group, project: nil) } + let_it_be(:inheriting_integration) { create(:jira_service, inherit_from_id: integration.id) } + + subject do + post :reset, params: { group_id: group, id: integration.class.to_param } + end + + context 'when user is not owner' do + it 'renders not_found' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when user is owner' do + before do + group.add_owner(user) + end + + it 'returns 200 OK', :aggregate_failures do + subject + + expected_json = {}.to_json + + expect(flash[:notice]).to eq('This integration, and inheriting projects were reset.') + expect(response).to have_gitlab_http_status(:ok) + expect(response.body).to eq(expected_json) + end + + it 'deletes the integration and all inheriting integrations' do + expect { subject }.to change { JiraService.for_group(group.id).count }.by(-1) + .and change { JiraService.inherit_from_id(integration.id).count }.by(-1) + end + end + end end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 55833ee3aad..939c36a98b2 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -333,7 +333,7 @@ RSpec.describe GroupsController, factory_default: :keep do context 'and the user is part of the control group' do before do - stub_experiment_for_user(onboarding_issues: false) + stub_experiment_for_subject(onboarding_issues: false) end it 'tracks the event with the "created_namespace" action with the "control_group" property', :snowplow do @@ -350,7 +350,7 @@ RSpec.describe GroupsController, factory_default: :keep do context 'and the user is part of the experimental group' do before do - stub_experiment_for_user(onboarding_issues: true) + stub_experiment_for_subject(onboarding_issues: true) end it 'tracks the event with the "created_namespace" action with the "experimental_group" property', :snowplow do @@ -400,15 +400,6 @@ RSpec.describe GroupsController, factory_default: :keep do sign_in(user) end - it 'lists only incidents and issues' do - incident = create(:incident, project: project) - create(:quality_test_case, project: project) - - get :issues, params: { id: group.to_param } - - expect(assigns(:issues)).to match_array([issue_1, issue_2, incident]) - end - context 'sorting by votes' do it 'sorts most popular issues' do get :issues, params: { id: group.to_param, sort: 'upvotes_desc' } diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb index 32b72eec0d6..7f55c4407dd 100644 --- a/spec/controllers/health_check_controller_spec.rb +++ b/spec/controllers/health_check_controller_spec.rb @@ -34,14 +34,14 @@ RSpec.describe HealthCheckController, :request_store do get :index expect(response).to be_successful - expect(response.content_type).to eq 'text/plain' + expect(response.media_type).to eq 'text/plain' end it 'supports passing the token in query params' do get :index, params: { token: token } expect(response).to be_successful - expect(response.content_type).to eq 'text/plain' + expect(response.media_type).to eq 'text/plain' end end end @@ -55,14 +55,14 @@ RSpec.describe HealthCheckController, :request_store do get :index expect(response).to be_successful - expect(response.content_type).to eq 'text/plain' + expect(response.media_type).to eq 'text/plain' end it 'supports successful json response' do get :index, format: :json expect(response).to be_successful - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['healthy']).to be true end @@ -70,7 +70,7 @@ RSpec.describe HealthCheckController, :request_store do get :index, format: :xml expect(response).to be_successful - expect(response.content_type).to eq 'application/xml' + expect(response.media_type).to eq 'application/xml' expect(xml_response['healthy']).to be true end @@ -78,7 +78,7 @@ RSpec.describe HealthCheckController, :request_store do get :index, params: { checks: 'email' }, format: :json expect(response).to be_successful - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['healthy']).to be true end end @@ -102,7 +102,7 @@ RSpec.describe HealthCheckController, :request_store do get :index expect(response).to have_gitlab_http_status(:internal_server_error) - expect(response.content_type).to eq 'text/plain' + expect(response.media_type).to eq 'text/plain' expect(response.body).to include('The server is on fire') end @@ -110,7 +110,7 @@ RSpec.describe HealthCheckController, :request_store do get :index, format: :json expect(response).to have_gitlab_http_status(:internal_server_error) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['healthy']).to be false expect(json_response['message']).to include('The server is on fire') end @@ -119,7 +119,7 @@ RSpec.describe HealthCheckController, :request_store do get :index, format: :xml expect(response).to have_gitlab_http_status(:internal_server_error) - expect(response.content_type).to eq 'application/xml' + expect(response.media_type).to eq 'application/xml' expect(xml_response['healthy']).to be false expect(xml_response['message']).to include('The server is on fire') end @@ -128,7 +128,7 @@ RSpec.describe HealthCheckController, :request_store do get :index, params: { checks: 'email' }, format: :json expect(response).to have_gitlab_http_status(:internal_server_error) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['healthy']).to be false expect(json_response['message']).to include('Email is on fire') end diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb index 9ac42cbc3ec..6927df3b1c7 100644 --- a/spec/controllers/help_controller_spec.rb +++ b/spec/controllers/help_controller_spec.rb @@ -101,7 +101,8 @@ RSpec.describe HelpController do context 'for Markdown formats' do context 'when requested file exists' do before do - expect(File).to receive(:read).and_return(fixture_file('blockquote_fence_after.md')) + expect_file_read(File.join(Rails.root, 'doc/ssh/README.md'), content: fixture_file('blockquote_fence_after.md')) + get :show, params: { path: 'ssh/README' }, format: :md end @@ -213,6 +214,6 @@ RSpec.describe HelpController do end def stub_readme(content) - expect(File).to receive(:read).and_return(content) + expect_file_read(Rails.root.join('doc', 'README.md'), content: content) end end diff --git a/spec/controllers/ide_controller_spec.rb b/spec/controllers/ide_controller_spec.rb deleted file mode 100644 index 39d92846863..00000000000 --- a/spec/controllers/ide_controller_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe IdeController do - let(:user) { create(:user) } - - before do - sign_in(user) - end - - it 'increases the views counter' do - expect(Gitlab::UsageDataCounters::WebIdeCounter).to receive(:increment_views_count) - - get :index - end -end diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb index dd850a86227..436daed0af6 100644 --- a/spec/controllers/import/bulk_imports_controller_spec.rb +++ b/spec/controllers/import/bulk_imports_controller_spec.rb @@ -57,8 +57,8 @@ RSpec.describe Import::BulkImportsController do let(:client_response) do double( parsed_response: [ - { 'id' => 1, 'full_name' => 'group1', 'full_path' => 'full/path/group1' }, - { 'id' => 2, 'full_name' => 'group2', 'full_path' => 'full/path/group2' } + { 'id' => 1, 'full_name' => 'group1', 'full_path' => 'full/path/group1', 'web_url' => 'http://demo.host/full/path/group1' }, + { 'id' => 2, 'full_name' => 'group2', 'full_path' => 'full/path/group2', 'web_url' => 'http://demo.host/full/path/group1' } ] ) end @@ -132,12 +132,27 @@ RSpec.describe Import::BulkImportsController do end describe 'POST create' do + let(:instance_url) { "http://fake-intance" } + let(:pat) { "fake-pat" } + + before do + session[:bulk_import_gitlab_access_token] = pat + session[:bulk_import_gitlab_url] = instance_url + end + it 'executes BulkImportService' do - expect_next_instance_of(BulkImportService) do |service| + bulk_import_params = [{ "source_type" => "group_entity", + "source_full_path" => "full_path", + "destination_name" => + "destination_name", + "destination_namespace" => "root" }] + + expect_next_instance_of( + BulkImportService, user, bulk_import_params, { url: instance_url, access_token: pat }) do |service| expect(service).to receive(:execute) end - post :create + post :create, params: { bulk_import: bulk_import_params } expect(response).to have_gitlab_http_status(:ok) end diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb index a408d821833..d82fff1f7ae 100644 --- a/spec/controllers/import/github_controller_spec.rb +++ b/spec/controllers/import/github_controller_spec.rb @@ -123,26 +123,33 @@ RSpec.describe Import::GithubController do end it 'fetches repos using latest github client' do - expect_next_instance_of(Gitlab::GithubImport::Client) do |client| - expect(client).to receive(:each_page).with(:repos).and_return([].to_enum) + expect_next_instance_of(Octokit::Client) do |client| + expect(client).to receive(:repos).and_return([].to_enum) end get :status end - it 'concatenates list of repos from multiple pages' do - repo_1 = OpenStruct.new(login: 'emacs', full_name: 'asd/emacs', name: 'emacs', owner: { login: 'owner' }) - repo_2 = OpenStruct.new(login: 'vim', full_name: 'asd/vim', name: 'vim', owner: { login: 'owner' }) - repos = [OpenStruct.new(objects: [repo_1]), OpenStruct.new(objects: [repo_2])].to_enum + context 'pagination' do + context 'when no page is specified' do + it 'requests first page' do + expect_next_instance_of(Octokit::Client) do |client| + expect(client).to receive(:repos).with(nil, { page: 1, per_page: 25 }).and_return([].to_enum) + end - allow(stub_client).to receive(:each_page).and_return(repos) + get :status + end + end - get :status, format: :json + context 'when page is specified' do + it 'requests repos with specified page' do + expect_next_instance_of(Octokit::Client) do |client| + expect(client).to receive(:repos).with(nil, { page: 2, per_page: 25 }).and_return([].to_enum) + end - expect(response).to have_gitlab_http_status(:ok) - expect(json_response.dig('provider_repos').count).to eq(2) - expect(json_response.dig('provider_repos', 0, 'id')).to eq(repo_1.id) - expect(json_response.dig('provider_repos', 1, 'id')).to eq(repo_2.id) + get :status, params: { page: 2 } + end + end end context 'when filtering' do @@ -150,6 +157,7 @@ RSpec.describe Import::GithubController do let(:user_login) { 'user' } let(:collaborations_subquery) { 'repo:repo1 repo:repo2' } let(:organizations_subquery) { 'org:org1 org:org2' } + let(:search_query) { "test in:name is:public,private user:#{user_login} #{collaborations_subquery} #{organizations_subquery}" } before do allow_next_instance_of(Octokit::Client) do |client| @@ -158,20 +166,56 @@ RSpec.describe Import::GithubController do end it 'makes request to github search api' do - expected_query = "test in:name is:public,private user:#{user_login} #{collaborations_subquery} #{organizations_subquery}" + expect_next_instance_of(Octokit::Client) do |client| + expect(client).to receive(:user).and_return(double(login: user_login)) + expect(client).to receive(:search_repositories).with(search_query, { page: 1, per_page: 25 }).and_return({ items: [].to_enum }) + end expect_next_instance_of(Gitlab::GithubImport::Client) do |client| expect(client).to receive(:collaborations_subquery).and_return(collaborations_subquery) expect(client).to receive(:organizations_subquery).and_return(organizations_subquery) - expect(client).to receive(:each_page).with(:search_repositories, expected_query).and_return([].to_enum) end get :status, params: { filter: filter }, format: :json end + context 'pagination' do + context 'when no page is specified' do + it 'requests first page' do + expect_next_instance_of(Octokit::Client) do |client| + expect(client).to receive(:user).and_return(double(login: user_login)) + expect(client).to receive(:search_repositories).with(search_query, { page: 1, per_page: 25 }).and_return({ items: [].to_enum }) + end + + expect_next_instance_of(Gitlab::GithubImport::Client) do |client| + expect(client).to receive(:collaborations_subquery).and_return(collaborations_subquery) + expect(client).to receive(:organizations_subquery).and_return(organizations_subquery) + end + + get :status, params: { filter: filter }, format: :json + end + end + + context 'when page is specified' do + it 'requests repos with specified page' do + expect_next_instance_of(Octokit::Client) do |client| + expect(client).to receive(:user).and_return(double(login: user_login)) + expect(client).to receive(:search_repositories).with(search_query, { page: 2, per_page: 25 }).and_return({ items: [].to_enum }) + end + + expect_next_instance_of(Gitlab::GithubImport::Client) do |client| + expect(client).to receive(:collaborations_subquery).and_return(collaborations_subquery) + expect(client).to receive(:organizations_subquery).and_return(organizations_subquery) + end + + get :status, params: { filter: filter, page: 2 }, format: :json + end + end + end + context 'when user input contains colons and spaces' do before do - stub_client(search_repos_by_name: []) + allow(controller).to receive(:client_repos).and_return([]) end it 'sanitizes user input' do diff --git a/spec/controllers/import/google_code_controller_spec.rb b/spec/controllers/import/google_code_controller_spec.rb deleted file mode 100644 index 0fda111c029..00000000000 --- a/spec/controllers/import/google_code_controller_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Import::GoogleCodeController do - include ImportSpecHelper - - let(:user) { create(:user) } - let(:dump_file) { fixture_file_upload('spec/fixtures/GoogleCodeProjectHosting.json', 'application/json') } - - before do - sign_in(user) - end - - describe "POST callback" do - it "stores Google Takeout dump list in session" do - post :callback, params: { dump_file: dump_file } - - expect(session[:google_code_dump]).to be_a(Hash) - expect(session[:google_code_dump]["kind"]).to eq("projecthosting#user") - expect(session[:google_code_dump]).to have_key("projects") - end - end - - describe "GET status" do - before do - @repo = OpenStruct.new(name: 'vim') - stub_client(valid?: true) - end - - it "assigns variables" do - @project = create(:project, import_type: 'google_code', creator_id: user.id) - stub_client(repos: [@repo], incompatible_repos: []) - - get :status - - expect(assigns(:already_added_projects)).to eq([@project]) - expect(assigns(:repos)).to eq([@repo]) - expect(assigns(:incompatible_repos)).to eq([]) - end - - it "does not show already added project" do - @project = create(:project, import_type: 'google_code', creator_id: user.id, import_source: 'vim') - stub_client(repos: [@repo], incompatible_repos: []) - - get :status - - expect(assigns(:already_added_projects)).to eq([@project]) - expect(assigns(:repos)).to eq([]) - end - - it "does not show any invalid projects" do - stub_client(repos: [], incompatible_repos: [@repo]) - - get :status - - expect(assigns(:repos)).to be_empty - expect(assigns(:incompatible_repos)).to eq([@repo]) - end - end - - describe "POST create" do - it_behaves_like 'project import rate limiter' - end -end diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb index 2d13b942c31..e863f5ef2fc 100644 --- a/spec/controllers/invites_controller_spec.rb +++ b/spec/controllers/invites_controller_spec.rb @@ -22,43 +22,6 @@ RSpec.describe InvitesController, :snowplow do end end - shared_examples "tracks the 'accepted' event for the invitation reminders experiment" do - before do - stub_experiment(invitation_reminders: true) - allow(Gitlab::Experimentation).to receive(:enabled_for_attribute?).with(:invitation_reminders, member.invite_email).and_return(experimental_group) - end - - context 'when in the control group' do - let(:experimental_group) { false } - - it "tracks the 'accepted' event" do - request - - expect_snowplow_event( - category: 'Growth::Acquisition::Experiment::InvitationReminders', - label: md5_member_global_id, - property: 'control_group', - action: 'accepted' - ) - end - end - - context 'when in the experimental group' do - let(:experimental_group) { true } - - it "tracks the 'accepted' event" do - request - - expect_snowplow_event( - category: 'Growth::Acquisition::Experiment::InvitationReminders', - label: md5_member_global_id, - property: 'experimental_group', - action: 'accepted' - ) - end - end - end - describe 'GET #show' do subject(:request) { get :show, params: params } @@ -87,7 +50,6 @@ RSpec.describe InvitesController, :snowplow do expect(flash[:notice]).to be_nil end - it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment" it_behaves_like 'invalid token' end @@ -119,7 +81,6 @@ RSpec.describe InvitesController, :snowplow do subject(:request) { post :accept, params: params } - it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment" it_behaves_like 'invalid token' end diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb index 291d51348e6..edd587389cb 100644 --- a/spec/controllers/omniauth_callbacks_controller_spec.rb +++ b/spec/controllers/omniauth_callbacks_controller_spec.rb @@ -367,8 +367,8 @@ RSpec.describe OmniauthCallbacksController, type: :controller do before do stub_last_request_id(last_request_id) - stub_omniauth_saml_config({ enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], - providers: [saml_config] }) + stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], + providers: [saml_config]) mock_auth_hash_with_saml_xml('saml', +'my-uid', user.email, mock_saml_response) request.env['devise.mapping'] = Devise.mappings[:user] request.env['omniauth.auth'] = Rails.application.env_config['omniauth.auth'] diff --git a/spec/controllers/profiles/gpg_keys_controller_spec.rb b/spec/controllers/profiles/gpg_keys_controller_spec.rb new file mode 100644 index 00000000000..93f899df484 --- /dev/null +++ b/spec/controllers/profiles/gpg_keys_controller_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Profiles::GpgKeysController do + let(:user) { create(:user, email: GpgHelpers::User1.emails[0]) } + + describe 'POST #create' do + before do + sign_in(user) + end + + it 'creates a new key' do + expect do + post :create, params: { gpg_key: build(:gpg_key).attributes } + end.to change { GpgKey.count }.by(1) + end + end +end diff --git a/spec/controllers/profiles/keys_controller_spec.rb b/spec/controllers/profiles/keys_controller_spec.rb index 17964ef4a43..66f6135df1e 100644 --- a/spec/controllers/profiles/keys_controller_spec.rb +++ b/spec/controllers/profiles/keys_controller_spec.rb @@ -20,108 +20,4 @@ RSpec.describe Profiles::KeysController do expect(Key.last.expires_at).to be_like_time(expires_at) end end - - describe "#get_keys" do - describe "non existent user" do - it "does not generally work" do - get :get_keys, params: { username: 'not-existent' } - - expect(response).not_to be_successful - end - end - - describe "user with no keys" do - it "does generally work" do - get :get_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all keys separated with a new line" do - get :get_keys, params: { username: user.username } - - expect(response.body).to eq("") - end - it "responds with text/plain content type" do - get :get_keys, params: { username: user.username } - expect(response.content_type).to eq("text/plain") - end - end - - describe "user with keys" do - let!(:key) { create(:key, user: user) } - let!(:another_key) { create(:another_key, user: user) } - let!(:deploy_key) { create(:deploy_key, user: user) } - - describe "while signed in" do - before do - sign_in(user) - end - - it "does generally work" do - get :get_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all non deploy keys separated with a new line" do - get :get_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - expect(response.body).to eq(user.all_ssh_keys.join("\n")) - - expect(response.body).to include(key.key.sub(' dummy@gitlab.com', '')) - expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', '')) - - expect(response.body).not_to include(deploy_key.key) - end - - it "does not render the comment of the key" do - get :get_keys, params: { username: user.username } - expect(response.body).not_to match(/dummy@gitlab.com/) - end - - it "responds with text/plain content type" do - get :get_keys, params: { username: user.username } - - expect(response.content_type).to eq("text/plain") - end - end - - describe 'when logged out' do - before do - sign_out(user) - end - - it "still does generally work" do - get :get_keys, params: { username: user.username } - - expect(response).to be_successful - end - - it "renders all non deploy keys separated with a new line" do - get :get_keys, params: { username: user.username } - - expect(response.body).not_to eq('') - expect(response.body).to eq(user.all_ssh_keys.join("\n")) - - expect(response.body).to include(key.key.sub(' dummy@gitlab.com', '')) - expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', '')) - - expect(response.body).not_to include(deploy_key.key) - end - - it "does not render the comment of the key" do - get :get_keys, params: { username: user.username } - expect(response.body).not_to match(/dummy@gitlab.com/) - end - - it "responds with text/plain content type" do - get :get_keys, params: { username: user.username } - - expect(response.content_type).to eq("text/plain") - end - end - end - end end diff --git a/spec/controllers/projects/alerting/notifications_controller_spec.rb b/spec/controllers/projects/alerting/notifications_controller_spec.rb index b3d37723ccf..3656cfbcc30 100644 --- a/spec/controllers/projects/alerting/notifications_controller_spec.rb +++ b/spec/controllers/projects/alerting/notifications_controller_spec.rb @@ -38,7 +38,7 @@ RSpec.describe Projects::Alerting::NotificationsController do expect(notify_service_class) .to have_received(:new) - .with(project, nil, permitted_params) + .with(project, permitted_params) end end diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb index dad932f9cdf..1ed61e0990f 100644 --- a/spec/controllers/projects/boards_controller_spec.rb +++ b/spec/controllers/projects/boards_controller_spec.rb @@ -27,7 +27,7 @@ RSpec.describe Projects::BoardsController do list_boards expect(response).to render_template :index - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end context 'with unauthorized user' do @@ -41,7 +41,7 @@ RSpec.describe Projects::BoardsController do list_boards expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end @@ -57,7 +57,7 @@ RSpec.describe Projects::BoardsController do list_boards expect(response).to render_template :index - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end end @@ -85,7 +85,7 @@ RSpec.describe Projects::BoardsController do list_boards format: :json expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end end end @@ -127,7 +127,7 @@ RSpec.describe Projects::BoardsController do expect { read_board board: board }.to change(BoardProjectRecentVisit, :count).by(1) expect(response).to render_template :show - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end context 'with unauthorized user' do @@ -141,7 +141,7 @@ RSpec.describe Projects::BoardsController do read_board board: board expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end @@ -154,7 +154,7 @@ RSpec.describe Projects::BoardsController do expect { read_board board: board }.to change(BoardProjectRecentVisit, :count).by(0) expect(response).to render_template :show - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end end end @@ -179,7 +179,7 @@ RSpec.describe Projects::BoardsController do read_board board: board, format: :json expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end end end diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 625fc5bddda..14a5e7da7d2 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -512,7 +512,8 @@ RSpec.describe Projects::BranchesController do state: 'all' } - expect(controller.instance_variable_get(:@branch_pipeline_statuses)["master"].group).to eq("success") + expect(assigns[:branch_pipeline_statuses]["master"].group).to eq("success") + expect(assigns[:sort]).to eq('updated_desc') end end @@ -543,8 +544,8 @@ RSpec.describe Projects::BranchesController do 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") + expect(assigns[:branch_pipeline_statuses]["master"].group).to eq("running") + expect(assigns[:branch_pipeline_statuses]["test"].group).to eq("success") end end @@ -555,10 +556,11 @@ RSpec.describe Projects::BranchesController do params: { namespace_id: project.namespace, project_id: project, - state: 'all' + state: 'stale' } - expect(controller.instance_variable_get(:@branch_pipeline_statuses)).to be_blank + expect(assigns[:branch_pipeline_statuses]).to be_blank + expect(assigns[:sort]).to eq('updated_asc') end end @@ -573,10 +575,12 @@ RSpec.describe Projects::BranchesController do params: { namespace_id: project.namespace, project_id: project, + sort: 'name_asc', state: 'all' } expect(response).to have_gitlab_http_status(:ok) + expect(assigns[:sort]).to eq('name_asc') end end @@ -635,6 +639,34 @@ RSpec.describe Projects::BranchesController do expect(response).to redirect_to project_branches_filtered_path(project, state: 'all') end end + + context 'fetching branches for overview' do + before do + get :index, format: :html, params: { + namespace_id: project.namespace, project_id: project, state: 'overview' + } + end + + it 'sets active and stale branches' do + expect(assigns[:active_branches]).to eq([]) + expect(assigns[:stale_branches].map(&:name)).to eq( + ["feature", "improve/awesome", "merge-test", "markdown", "feature_conflict", "'test'"] + ) + end + + context 'branch_list_keyset_pagination is disabled' do + before do + stub_feature_flags(branch_list_keyset_pagination: false) + end + + it 'sets active and stale branches' do + expect(assigns[:active_branches]).to eq([]) + expect(assigns[:stale_branches].map(&:name)).to eq( + ["feature", "improve/awesome", "merge-test", "markdown", "feature_conflict", "'test'"] + ) + end + end + end end describe 'GET diverging_commit_counts' do diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb index c4e040b0287..d778739be38 100644 --- a/spec/controllers/projects/ci/lints_controller_spec.rb +++ b/spec/controllers/projects/ci/lints_controller_spec.rb @@ -82,7 +82,7 @@ RSpec.describe Projects::Ci::LintsController do end it 'renders json' do - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(parsed_body).to include('errors', 'warnings', 'jobs', 'valid') expect(parsed_body).to match_schema('entities/lint_result_entity') end diff --git a/spec/controllers/projects/clusters/applications_controller_spec.rb b/spec/controllers/projects/clusters/applications_controller_spec.rb index b50814b4790..cc6170252c1 100644 --- a/spec/controllers/projects/clusters/applications_controller_spec.rb +++ b/spec/controllers/projects/clusters/applications_controller_spec.rb @@ -32,7 +32,7 @@ RSpec.describe Projects::Clusters::ApplicationsController do let(:cluster) { create(:cluster, :project, :provided_by_gcp) } let(:project) { cluster.project } - let(:application) { 'helm' } + let(:application) { 'ingress' } let(:params) { { application: application, id: cluster.id } } describe 'functionality' do @@ -48,7 +48,7 @@ RSpec.describe Projects::Clusters::ApplicationsController do expect { subject }.to change { current_application.count } expect(response).to have_gitlab_http_status(:no_content) - expect(cluster.application_helm).to be_scheduled + expect(cluster.application_ingress).to be_scheduled end context 'when cluster do not exists' do @@ -72,7 +72,7 @@ RSpec.describe Projects::Clusters::ApplicationsController do context 'when application is already installing' do before do - create(:clusters_applications_helm, :installing, cluster: cluster) + create(:clusters_applications_ingress, :installing, cluster: cluster) end it 'returns 400' do diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb index 52cd6869b04..dd3440f7660 100644 --- a/spec/controllers/projects/clusters_controller_spec.rb +++ b/spec/controllers/projects/clusters_controller_spec.rb @@ -500,7 +500,7 @@ RSpec.describe Projects::ClustersController do expect { post_create_aws }.not_to change { Clusters::Cluster.count } expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(response.content_type).to eq('application/json') + expect(response.media_type).to eq('application/json') expect(response.body).to include('is invalid') end end diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb index 557002acbc0..4cf77fde3a1 100644 --- a/spec/controllers/projects/commits_controller_spec.rb +++ b/spec/controllers/projects/commits_controller_spec.rb @@ -80,7 +80,7 @@ RSpec.describe Projects::CommitsController do it "renders as atom" do expect(response).to be_successful - expect(response.content_type).to eq('application/atom+xml') + expect(response.media_type).to eq('application/atom+xml') end it 'renders summary with type=html' do @@ -105,7 +105,7 @@ RSpec.describe Projects::CommitsController do it "renders as HTML" do expect(response).to be_successful - expect(response.content_type).to eq('text/html') + expect(response.media_type).to eq('text/html') end end end diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb index 24c2d568d9a..ccd213fdffa 100644 --- a/spec/controllers/projects/cycle_analytics_controller_spec.rb +++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb @@ -32,41 +32,5 @@ RSpec.describe Projects::CycleAnalyticsController do end end - describe 'value stream analytics not set up flag' do - context 'with no data' do - it 'is true' do - get(:show, - params: { - namespace_id: project.namespace, - project_id: project - }) - - expect(response).to be_successful - expect(assigns(:cycle_analytics_no_data)).to eq(true) - end - end - - context 'with data' do - before do - issue = create(:issue, project: project, created_at: 4.days.ago) - milestone = create(:milestone, project: project, created_at: 5.days.ago) - issue.update(milestone: milestone) - - create_merge_request_closing_issue(user, project, issue) - end - - it 'is false' do - get(:show, - params: { - namespace_id: project.namespace, - project_id: project - }) - - expect(response).to be_successful - expect(assigns(:cycle_analytics_no_data)).to eq(false) - end - end - end - include_examples GracefulTimeoutHandling end diff --git a/spec/controllers/projects/feature_flags_controller_spec.rb b/spec/controllers/projects/feature_flags_controller_spec.rb index 1473ec95192..d5fc80bd5a7 100644 --- a/spec/controllers/projects/feature_flags_controller_spec.rb +++ b/spec/controllers/projects/feature_flags_controller_spec.rb @@ -217,15 +217,6 @@ RSpec.describe Projects::FeatureFlagsController do expect(json_response['feature_flags'].count).to eq(3) end - - it 'returns only version 1 flags when new version flags are disabled' do - stub_feature_flags(feature_flags_new_version: false) - - subject - - expected = [feature_flag_active.name, feature_flag_inactive.name].sort - expect(json_response['feature_flags'].map { |f| f['name'] }.sort).to eq(expected) - end end end @@ -283,24 +274,6 @@ RSpec.describe Projects::FeatureFlagsController do expect(json_response['name']).to eq(other_feature_flag.name) end - it 'routes based on iid when new version flags are disabled' do - stub_feature_flags(feature_flags_new_version: false) - other_project = create(:project) - other_project.add_developer(user) - other_feature_flag = create(:operations_feature_flag, project: other_project, - name: 'other_flag') - params = { - namespace_id: other_project.namespace, - project_id: other_project, - iid: other_feature_flag.iid - } - - get(:show, params: params, format: :json) - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['name']).to eq(other_feature_flag.name) - end - context 'when feature flag is not found' do let!(:feature_flag) { } @@ -386,14 +359,6 @@ RSpec.describe Projects::FeatureFlagsController do expect(json_response['version']).to eq('new_version_flag') end - it 'returns a 404 when new version flags are disabled' do - stub_feature_flags(feature_flags_new_version: false) - - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - it 'returns strategies ordered by id' do first_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag) second_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag) @@ -791,54 +756,6 @@ RSpec.describe Projects::FeatureFlagsController do expect(Operations::FeatureFlag.count).to eq(0) end end - - context 'when version 2 flags are disabled' do - context 'and attempting to create a version 2 flag' do - let(:params) do - { - namespace_id: project.namespace, - project_id: project, - operations_feature_flag: { - name: 'my_feature_flag', - active: true, - version: 'new_version_flag' - } - } - end - - it 'returns a 400' do - stub_feature_flags(feature_flags_new_version: false) - - subject - - expect(response).to have_gitlab_http_status(:bad_request) - expect(Operations::FeatureFlag.count).to eq(0) - end - end - - context 'and attempting to create a version 1 flag' do - let(:params) do - { - namespace_id: project.namespace, - project_id: project, - operations_feature_flag: { - name: 'my_feature_flag', - active: true - } - } - end - - it 'creates the flag' do - stub_feature_flags(feature_flags_new_version: false) - - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(Operations::FeatureFlag.count).to eq(1) - expect(json_response['version']).to eq('legacy_flag') - end - end - end end describe 'DELETE destroy.json' do @@ -913,15 +830,6 @@ RSpec.describe Projects::FeatureFlagsController do it 'deletes the flag' do expect { subject }.to change { Operations::FeatureFlag.count }.by(-1) end - - context 'when new version flags are disabled' do - it 'returns a 404' do - stub_feature_flags(feature_flags_new_version: false) - - expect { subject }.not_to change { Operations::FeatureFlag.count } - expect(response).to have_gitlab_http_status(:not_found) - end - end end end @@ -1610,15 +1518,6 @@ RSpec.describe Projects::FeatureFlagsController do expect(json_response['strategies'].first['scopes']).to eq([]) end - it 'does not update the flag if version 2 flags are disabled' do - stub_feature_flags(feature_flags_new_version: false) - - put_request(new_version_flag, { name: 'some-other-name' }) - - expect(response).to have_gitlab_http_status(:not_found) - expect(new_version_flag.reload.name).to eq('new-feature') - end - it 'updates the flag when legacy feature flags are set to be read only' do stub_feature_flags(feature_flags_legacy_read_only: true) diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 26e1842468b..12c8c84dd77 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -62,6 +62,56 @@ RSpec.describe Projects::IssuesController do expect(response).to have_gitlab_http_status(:moved_permanently) end end + + describe 'the null hypothesis experiment', :snowplow do + it 'defines the expected before actions' do + expect(controller).to use_before_action(:run_null_hypothesis_experiment) + end + + context 'when rolled out to 100%' do + it 'assigns the candidate experience and tracks the event' do + get :index, params: { namespace_id: project.namespace, project_id: project } + + expect_snowplow_event( + category: 'null_hypothesis', + action: 'index', + context: [{ + schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0', + data: { variant: 'candidate', experiment: 'null_hypothesis', key: anything } + }] + ) + end + end + + context 'when not rolled out' do + before do + stub_feature_flags(null_hypothesis: false) + end + + it 'assigns the control experience and tracks the event' do + get :index, params: { namespace_id: project.namespace, project_id: project } + + expect_snowplow_event( + category: 'null_hypothesis', + action: 'index', + context: [{ + schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0', + data: { variant: 'control', experiment: 'null_hypothesis', key: anything } + }] + ) + end + end + + context 'when gitlab_experiments is disabled' do + it 'does not run the experiment at all' do + stub_feature_flags(gitlab_experiments: false) + + expect(controller).not_to receive(:run_null_hypothesis_experiment) + + get :index, params: { namespace_id: project.namespace, project_id: project } + end + end + end end context 'internal issue tracker' do @@ -1128,12 +1178,12 @@ RSpec.describe Projects::IssuesController do { merge_request_to_resolve_discussions_of: merge_request.iid } end - def post_issue(issue_params, other_params: {}) + def post_issue(other_params: {}, **issue_params) post :create, params: { namespace_id: project.namespace.to_param, project_id: project, issue: issue_params, merge_request_to_resolve_discussions_of: merge_request.iid }.merge(other_params) end it 'creates an issue for the project' do - expect { post_issue({ title: 'Hello' }) }.to change { project.issues.reload.size }.by(1) + expect { post_issue(title: 'Hello') }.to change { project.issues.reload.size }.by(1) end it "doesn't overwrite given params" do @@ -1157,7 +1207,7 @@ RSpec.describe Projects::IssuesController do describe "resolving a single discussion" do before do - post_issue({ title: 'Hello' }, other_params: { discussion_to_resolve: discussion.id }) + post_issue(title: 'Hello', other_params: { discussion_to_resolve: discussion.id }) end it 'resolves a single discussion' do discussion.first_note.reload diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index 80cb16966e5..3309b15b276 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -15,6 +15,54 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do end describe 'GET index' do + describe 'pushing tracking_data to Gon' do + before do + stub_experiment(jobs_empty_state: experiment_active) + stub_experiment_for_subject(jobs_empty_state: in_experiment_group) + + get_index + end + + context 'when experiment not active' do + let(:experiment_active) { false } + let(:in_experiment_group) { false } + + it 'does not push tracking_data to Gon' do + expect(Gon.tracking_data).to be_nil + end + end + + context 'when experiment active and user in control group' do + let(:experiment_active) { true } + let(:in_experiment_group) { false } + + it 'pushes tracking_data to Gon' do + expect(Gon.tracking_data).to match( + { + category: 'Growth::Activation::Experiment::JobsEmptyState', + action: 'click_button', + label: anything, + property: 'control_group' + } + ) + end + end + + context 'when experiment active and user in experimental group' do + let(:experiment_active) { true } + let(:in_experiment_group) { true } + + it 'pushes tracking_data to gon' do + expect(Gon.tracking_data).to match( + category: 'Growth::Activation::Experiment::JobsEmptyState', + action: 'click_button', + label: anything, + property: 'experimental_group' + ) + end + end + end + context 'when scope is pending' do before do create(:ci_build, :pending, pipeline: pipeline) @@ -113,11 +161,11 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do context 'when requesting HTML' do context 'when job exists' do - before do - get_show(id: job.id) - end + let(:extra_params) { { id: job.id } } it 'has a job' do + get_show(**extra_params) + expect(response).to have_gitlab_http_status(:ok) expect(assigns(:build).id).to eq(job.id) end @@ -599,6 +647,46 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(json_response['total']).to be_present expect(json_response['lines'].count).to be_positive end + + context 'when CI_DEBUG_TRACE enabled' do + let!(:variable) { create(:ci_instance_variable, key: 'CI_DEBUG_TRACE', value: 'true') } + + context 'with proper permissions on a project' do + before do + project.add_developer(user) + sign_in(user) + end + + it 'returns response ok' do + get_trace + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'without proper permissions for debug logging' do + before do + project.add_guest(user) + sign_in(user) + end + + it 'returns response forbidden' do + get_trace + + expect(response).to have_gitlab_http_status(:forbidden) + end + + context 'with restrict_access_to_build_debug_mode feature disabled' do + before do + stub_feature_flags(restrict_access_to_build_debug_mode: false) + end + + it 'returns response forbidden' do + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end end context 'when job has a trace' do @@ -806,18 +894,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(job.reload).to be_pending end - - context 'when FF ci_manual_bridges is disabled' do - before do - stub_feature_flags(ci_manual_bridges: false) - end - - it 'returns 404' do - post_play - - expect(response).to have_gitlab_http_status(:not_found) - end - end end end @@ -1027,7 +1103,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do } end - context "when job has a trace artifact" do + context 'when job has a trace artifact' do let(:job) { create(:ci_build, :trace_artifact, pipeline: pipeline) } it "sets #{Gitlab::Workhorse::DETECT_HEADER} header" do @@ -1038,6 +1114,62 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(response.body).to eq(job.job_artifacts_trace.open.read) expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" end + + context 'when CI_DEBUG_TRACE enabled' do + before do + create(:ci_instance_variable, key: 'CI_DEBUG_TRACE', value: 'true') + end + + context 'with proper permissions for debug logging on a project' do + before do + project.add_developer(user) + sign_in(user) + end + + it 'returns response ok' do + response = subject + + expect(response).to have_gitlab_http_status(:ok) + end + + context 'with restrict_access_to_build_debug_mode feature disabled' do + before do + stub_feature_flags(restrict_access_to_build_debug_mode: false) + end + + it 'returns response ok' do + response = subject + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context 'without proper permissions for debug logging on a project' do + before do + project.add_reporter(user) + sign_in(user) + end + + it 'returns response forbidden' do + response = subject + + expect(response).to have_gitlab_http_status(:forbidden) + end + + context 'with restrict_access_to_build_debug_mode feature disabled' do + before do + stub_feature_flags(restrict_access_to_build_debug_mode: false) + end + + it 'returns response ok' do + response = subject + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end end context "when job has a trace file" do diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb index bda1f1a3b1c..f4f0a9f8108 100644 --- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb @@ -74,6 +74,8 @@ RSpec.describe Projects::MergeRequests::DiffsController do let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } before do + stub_feature_flags(diffs_gradual_load: false) + project.add_maintainer(user) sign_in(user) end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index f159f0e6099..cf8b4c564c4 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -1498,6 +1498,121 @@ RSpec.describe Projects::MergeRequestsController do end end + describe 'GET codequality_reports' do + let_it_be(:merge_request) do + create(:merge_request, + :with_diffs, + :with_merge_request_pipeline, + target_project: project, + source_project: project + ) + end + + let(:pipeline) do + create(:ci_pipeline, + :success, + project: merge_request.source_project, + ref: merge_request.source_branch, + sha: merge_request.diff_head_sha) + end + + before do + allow_any_instance_of(MergeRequest) + .to receive(:compare_codequality_reports) + .and_return(codequality_comparison) + + allow_any_instance_of(MergeRequest) + .to receive(:actual_head_pipeline) + .and_return(pipeline) + end + + subject do + get :codequality_reports, params: { + namespace_id: project.namespace.to_param, + project_id: project, + id: merge_request.iid + }, + format: :json + end + + context 'permissions on a public project with private CI/CD' do + let(:project) { project_public_with_private_builds } + let(:codequality_comparison) { { status: :parsed, data: { summary: 1 } } } + + context 'while signed out' do + before do + sign_out(user) + end + + it 'responds with a 404' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + expect(response.body).to be_blank + end + end + + context 'while signed in as an unrelated user' do + before do + sign_in(create(:user)) + end + + it 'responds with a 404' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + expect(response.body).to be_blank + end + end + end + + context 'when pipeline has jobs with codequality reports' do + before do + allow_any_instance_of(MergeRequest) + .to receive(:has_codequality_reports?) + .and_return(true) + end + + context 'when processing codequality reports is in progress' do + let(:codequality_comparison) { { status: :parsing } } + + it 'sends polling interval' do + expect(Gitlab::PollingInterval).to receive(:set_header) + + subject + end + + it 'returns 204 HTTP status' do + subject + + expect(response).to have_gitlab_http_status(:no_content) + end + end + + context 'when processing codequality reports is completed' do + let(:codequality_comparison) { { status: :parsed, data: { summary: 1 } } } + + it 'returns codequality reports' do + subject + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq({ 'summary' => 1 }) + end + end + end + + context 'when pipeline has job without a codequality report' do + let(:codequality_comparison) { { status: :error, status_reason: 'no codequality report' } } + + it 'returns a 400' do + subject + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response).to eq({ 'status_reason' => 'no codequality report' }) + end + end + end + describe 'POST remove_wip' do before do merge_request.title = merge_request.wip_title diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb index 9e5d41b1075..b93f1b41a7e 100644 --- a/spec/controllers/projects/milestones_controller_spec.rb +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -33,14 +33,14 @@ RSpec.describe Projects::MilestonesController do view_milestone expect(response).to have_gitlab_http_status(:ok) - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end it 'returns milestone json' do view_milestone format: :json expect(response).to have_gitlab_http_status(:not_found) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end end @@ -189,7 +189,7 @@ RSpec.describe Projects::MilestonesController do get :labels, params: { namespace_id: group.id, project_id: project.id, id: milestone.iid }, format: :json expect(response).to have_gitlab_http_status(:ok) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['html']).not_to include(label.title) end @@ -200,7 +200,7 @@ RSpec.describe Projects::MilestonesController do get :labels, params: { namespace_id: group.id, project_id: project.id, id: milestone.iid }, format: :json expect(response).to have_gitlab_http_status(:ok) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['html']).to include(label.title) end @@ -262,7 +262,7 @@ RSpec.describe Projects::MilestonesController do get :participants, params: params expect(response).to have_gitlab_http_status(:ok) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['html']).to include(issue_assignee.name) end end @@ -277,7 +277,7 @@ RSpec.describe Projects::MilestonesController do get :participants, params: params expect(response).to have_gitlab_http_status(:ok) - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' expect(json_response['html']).not_to include(issue_assignee.name) end end diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index d76432f71b3..e96113c0133 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -426,7 +426,7 @@ RSpec.describe Projects::NotesController do let(:note_text) { "/award :thumbsup:\n/estimate 1d\n/spend 3h" } let(:extra_request_params) { { format: :json } } - it 'includes changes in commands_changes ' do + it 'includes changes in commands_changes' do create! expect(response).to have_gitlab_http_status(:ok) diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index 0720124ea57..e1405660ccb 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -1149,11 +1149,17 @@ RSpec.describe Projects::PipelinesController do end end - describe 'GET config_variables.json' do + describe 'GET config_variables.json', :use_clean_rails_memory_store_caching do + include ReactiveCachingHelpers + let(:result) { YAML.dump(ci_config) } + let(:service) { Ci::ListConfigVariablesService.new(project, user) } before do stub_gitlab_ci_yml_for_sha(sha, result) + allow(Ci::ListConfigVariablesService) + .to receive(:new) + .and_return(service) end context 'when sending a valid sha' do @@ -1170,6 +1176,10 @@ RSpec.describe Projects::PipelinesController do } end + before do + synchronous_reactive_cache(service) + end + it 'returns variable list' do get_config_variables @@ -1182,6 +1192,10 @@ RSpec.describe Projects::PipelinesController do let(:sha) { 'invalid-sha' } let(:ci_config) { nil } + before do + synchronous_reactive_cache(service) + end + it 'returns empty json' do get_config_variables @@ -1204,6 +1218,10 @@ RSpec.describe Projects::PipelinesController do } end + before do + synchronous_reactive_cache(service) + end + it 'returns empty result' do get_config_variables @@ -1212,6 +1230,27 @@ RSpec.describe Projects::PipelinesController do end end + context 'when the cache is empty' do + let(:sha) { 'master' } + let(:ci_config) do + { + variables: { + KEY1: { value: 'val 1', description: 'description 1' } + }, + test: { + stage: 'test', + script: 'echo' + } + } + end + + it 'returns no content' do + get_config_variables + + expect(response).to have_gitlab_http_status(:no_content) + end + end + private def stub_gitlab_ci_yml_for_sha(sha, result) diff --git a/spec/controllers/projects/prometheus/alerts_controller_spec.rb b/spec/controllers/projects/prometheus/alerts_controller_spec.rb index cbd599506df..46de8aa4baf 100644 --- a/spec/controllers/projects/prometheus/alerts_controller_spec.rb +++ b/spec/controllers/projects/prometheus/alerts_controller_spec.rb @@ -168,7 +168,7 @@ RSpec.describe Projects::Prometheus::AlertsController do expect(Projects::Prometheus::Alerts::NotifyService) .to receive(:new) - .with(project, nil, duck_type(:permitted?)) + .with(project, duck_type(:permitted?)) .and_return(notify_service) end diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb index 43cf1a16051..dfe7ba34e6d 100644 --- a/spec/controllers/projects/raw_controller_spec.rb +++ b/spec/controllers/projects/raw_controller_spec.rb @@ -5,11 +5,11 @@ require 'spec_helper' RSpec.describe Projects::RawController do include RepoHelpers - let(:project) { create(:project, :public, :repository) } + let_it_be(:project) { create(:project, :public, :repository) } let(:inline) { nil } describe 'GET #show' do - subject do + def get_show get(:show, params: { namespace_id: project.namespace, @@ -19,6 +19,18 @@ RSpec.describe Projects::RawController do }) end + subject { get_show } + + shared_examples 'single Gitaly request' do + it 'makes a single Gitaly request', :request_store, :clean_gitlab_redis_cache do + # Warm up to populate repository cache + get_show + RequestStore.clear! + + expect { get_show }.to change { Gitlab::GitalyClient.get_request_count }.by(1) + end + end + context 'regular filename' do let(:filepath) { 'master/README.md' } @@ -33,6 +45,7 @@ RSpec.describe Projects::RawController do it_behaves_like 'project cache control headers' it_behaves_like 'content disposition headers' + include_examples 'single Gitaly request' end context 'image header' do @@ -48,6 +61,7 @@ RSpec.describe Projects::RawController do it_behaves_like 'project cache control headers' it_behaves_like 'content disposition headers' + include_examples 'single Gitaly request' end context 'with LFS files' do @@ -56,6 +70,7 @@ RSpec.describe Projects::RawController do it_behaves_like 'a controller that can serve LFS files' it_behaves_like 'project cache control headers' + include_examples 'single Gitaly request' end context 'when the endpoint receives requests above the limit', :clean_gitlab_redis_cache do diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb index 07fb03b39c6..c1f1373ddc2 100644 --- a/spec/controllers/projects/releases_controller_spec.rb +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -83,7 +83,7 @@ RSpec.describe Projects::ReleasesController do let(:format) { :html } it 'returns a text/html content_type' do - expect(response.content_type).to eq 'text/html' + expect(response.media_type).to eq 'text/html' end it_behaves_like 'common access controls' @@ -101,7 +101,7 @@ RSpec.describe Projects::ReleasesController do let(:format) { :json } it 'returns an application/json content_type' do - expect(response.content_type).to eq 'application/json' + expect(response.media_type).to eq 'application/json' end it "returns the project's releases as JSON, ordered by released_at" do diff --git a/spec/controllers/projects/runners_controller_spec.rb b/spec/controllers/projects/runners_controller_spec.rb index 2443a823070..d63d88f8283 100644 --- a/spec/controllers/projects/runners_controller_spec.rb +++ b/spec/controllers/projects/runners_controller_spec.rb @@ -78,40 +78,84 @@ RSpec.describe Projects::RunnersController do let(:group) { create(:group) } let(:project) { create(:project, group: group) } - it 'toggles shared_runners_enabled when the group allows shared runners' do - project.update!(shared_runners_enabled: true) + context 'without feature flag' do + before do + stub_feature_flags(vueify_shared_runners_toggle: false) + end - post :toggle_shared_runners, params: params + it 'toggles shared_runners_enabled when the group allows shared runners' do + project.update!(shared_runners_enabled: true) - project.reload + post :toggle_shared_runners, params: params - expect(response).to have_gitlab_http_status(:found) - expect(project.shared_runners_enabled).to eq(false) - end + project.reload - it 'toggles shared_runners_enabled when the group disallows shared runners but allows overrides' do - group.update!(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: true) - project.update!(shared_runners_enabled: false) + expect(response).to have_gitlab_http_status(:found) + expect(project.shared_runners_enabled).to eq(false) + end - post :toggle_shared_runners, params: params + it 'toggles shared_runners_enabled when the group disallows shared runners but allows overrides' do + group.update!(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: true) + project.update!(shared_runners_enabled: false) - project.reload + post :toggle_shared_runners, params: params - expect(response).to have_gitlab_http_status(:found) - expect(project.shared_runners_enabled).to eq(true) + project.reload + + expect(response).to have_gitlab_http_status(:found) + expect(project.shared_runners_enabled).to eq(true) + end + + it 'does not enable if the group disallows shared runners' do + group.update!(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: false) + project.update!(shared_runners_enabled: false) + + post :toggle_shared_runners, params: params + + project.reload + + expect(response).to have_gitlab_http_status(:found) + expect(project.shared_runners_enabled).to eq(false) + expect(flash[:alert]).to eq('Cannot enable shared runners because parent group does not allow it') + end end - it 'does not enable if the group disallows shared runners' do - group.update!(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: false) - project.update!(shared_runners_enabled: false) + context 'with feature flag: vueify_shared_runners_toggle' do + it 'toggles shared_runners_enabled when the group allows shared runners' do + project.update!(shared_runners_enabled: true) - post :toggle_shared_runners, params: params + post :toggle_shared_runners, params: params - project.reload + project.reload - expect(response).to have_gitlab_http_status(:found) - expect(project.shared_runners_enabled).to eq(false) - expect(flash[:alert]).to eq("Cannot enable shared runners because parent group does not allow it") + expect(response).to have_gitlab_http_status(:ok) + expect(project.shared_runners_enabled).to eq(false) + end + + it 'toggles shared_runners_enabled when the group disallows shared runners but allows overrides' do + group.update!(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: true) + project.update!(shared_runners_enabled: false) + + post :toggle_shared_runners, params: params + + project.reload + + expect(response).to have_gitlab_http_status(:ok) + expect(project.shared_runners_enabled).to eq(true) + end + + it 'does not enable if the group disallows shared runners' do + group.update!(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: false) + project.update!(shared_runners_enabled: false) + + post :toggle_shared_runners, params: params + + project.reload + + expect(response).to have_gitlab_http_status(:unauthorized) + expect(project.shared_runners_enabled).to eq(false) + expect(json_response['error']).to eq('Cannot enable shared runners because parent group does not allow it') + end end end end diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb index 867b2b51039..b563f3b667f 100644 --- a/spec/controllers/projects/static_site_editor_controller_spec.rb +++ b/spec/controllers/projects/static_site_editor_controller_spec.rb @@ -7,6 +7,21 @@ RSpec.describe Projects::StaticSiteEditorController do let_it_be(:user) { create(:user) } let(:data) { { key: 'value' } } + describe 'GET index' do + let(:default_params) do + { + namespace_id: project.namespace, + project_id: project + } + end + + it 'responds with 404 page' do + get :index, params: default_params + + expect(response).to have_gitlab_http_status(:not_found) + end + end + describe 'GET show' do render_views diff --git a/spec/controllers/projects/terraform_controller_spec.rb b/spec/controllers/projects/terraform_controller_spec.rb index 1978b9494fa..73f0a5b26fb 100644 --- a/spec/controllers/projects/terraform_controller_spec.rb +++ b/spec/controllers/projects/terraform_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Projects::TerraformController do - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, :public) } describe 'GET index' do subject { get :index, params: { namespace_id: project.namespace, project_id: project } } @@ -34,5 +34,15 @@ RSpec.describe Projects::TerraformController do expect(response).to have_gitlab_http_status(:not_found) end end + + context 'when no user is present' do + before do + subject + end + + it 'shows 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end end end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 012a98f433e..bd7ef3db8b6 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -6,15 +6,15 @@ RSpec.describe ProjectsController do include ExternalAuthorizationServiceHelpers include ProjectForksHelper - let(:project) { create(:project, service_desk_enabled: false) } - let(:public_project) { create(:project, :public) } - let(:user) { create(:user) } + let_it_be(:project, reload: true) { create(:project, service_desk_enabled: false) } + let_it_be(:public_project) { create(:project, :public) } + let_it_be(:user) { create(:user) } let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } describe 'GET new' do context 'with an authenticated user' do - let(:group) { create(:group) } + let_it_be(:group) { create(:group) } before do sign_in(user) @@ -41,27 +41,6 @@ RSpec.describe ProjectsController do end end end - - context 'with the new_create_project_ui experiment enabled and the user is part of the control group' do - before do - stub_experiment(new_create_project_ui: true) - stub_experiment_for_user(new_create_project_ui: false) - allow_any_instance_of(described_class).to receive(:experimentation_subject_id).and_return('uuid') - end - - it 'passes the right tracking parameters to the frontend' do - get(:new) - - expect(Gon.tracking_data).to eq( - { - category: 'Manage::Import::Experiment::NewCreateProjectUi', - action: 'click_tab', - label: 'uuid', - property: 'control_group' - } - ) - end - end end end @@ -89,7 +68,7 @@ RSpec.describe ProjectsController do include DesignManagementTestHelpers render_views - let(:project) { create(:project, :public, issues_access_level: ProjectFeature::PRIVATE) } + let_it_be(:project) { create(:project, :public, issues_access_level: ProjectFeature::PRIVATE) } before do enable_design_management @@ -248,10 +227,12 @@ RSpec.describe ProjectsController do end context "project with empty repo" do - let(:empty_project) { create(:project_empty_repo, :public) } + let_it_be(:empty_project) { create(:project_empty_repo, :public) } before do sign_in(user) + + allow(controller).to receive(:record_experiment_user).with(:invite_members_empty_project_version_a) end User.project_views.keys.each do |project_view| @@ -262,15 +243,16 @@ RSpec.describe ProjectsController do get :show, params: { namespace_id: empty_project.namespace, id: empty_project } end - it "renders the empty project view" do + it "renders the empty project view and records the experiment user", :aggregate_failures do expect(response).to render_template('empty') + expect(controller).to have_received(:record_experiment_user).with(:invite_members_empty_project_version_a) end end end end context "project with broken repo" do - let(:empty_project) { create(:project_broken_repo, :public) } + let_it_be(:empty_project) { create(:project_broken_repo, :public) } before do sign_in(user) @@ -294,15 +276,20 @@ RSpec.describe ProjectsController do end context "rendering default project view" do - let(:public_project) { create(:project, :public, :repository) } + let_it_be(:public_project) { create(:project, :public, :repository) } render_views + def get_show + get :show, params: { namespace_id: public_project.namespace, id: public_project } + end + it "renders the activity view" do allow(controller).to receive(:current_user).and_return(user) allow(user).to receive(:project_view).and_return('activity') - get :show, params: { namespace_id: public_project.namespace, id: public_project } + get_show + expect(response).to render_template('_activity') end @@ -310,7 +297,8 @@ RSpec.describe ProjectsController do allow(controller).to receive(:current_user).and_return(user) allow(user).to receive(:project_view).and_return('files') - get :show, params: { namespace_id: public_project.namespace, id: public_project } + get_show + expect(response).to render_template('_files') end @@ -318,9 +306,18 @@ RSpec.describe ProjectsController do allow(controller).to receive(:current_user).and_return(user) allow(user).to receive(:project_view).and_return('readme') - get :show, params: { namespace_id: public_project.namespace, id: public_project } + get_show + expect(response).to render_template('_readme') end + + it 'does not make Gitaly requests', :request_store, :clean_gitlab_redis_cache do + # Warm up to populate repository cache + get_show + RequestStore.clear! + + expect { get_show }.not_to change { Gitlab::GitalyClient.get_request_count } + end end context "when the url contains .atom" do @@ -403,8 +400,8 @@ RSpec.describe ProjectsController do end describe 'POST #archive' do - let(:group) { create(:group) } - let(:project) { create(:project, group: group) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } before do sign_in(user) @@ -451,8 +448,8 @@ RSpec.describe ProjectsController do end describe 'POST #unarchive' do - let(:group) { create(:group) } - let(:project) { create(:project, :archived, group: group) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :archived, group: group) } before do sign_in(user) @@ -499,8 +496,8 @@ RSpec.describe ProjectsController do end describe '#housekeeping' do - let(:group) { create(:group) } - let(:project) { create(:project, group: group) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } let(:housekeeping) { Projects::HousekeepingService.new(project) } context 'when authenticated as owner' do @@ -672,13 +669,13 @@ RSpec.describe ProjectsController do end context 'hashed storage' do - let(:project) { create(:project, :repository) } + let_it_be(:project) { create(:project, :repository) } it_behaves_like 'updating a project' end context 'legacy storage' do - let(:project) { create(:project, :repository, :legacy_storage) } + let_it_be(:project) { create(:project, :repository, :legacy_storage) } it_behaves_like 'updating a project' end @@ -713,14 +710,47 @@ RSpec.describe ProjectsController do end end end + + context 'when updating boolean values on project_settings' do + using RSpec::Parameterized::TableSyntax + + where(:boolean_value, :result) do + '1' | true + '0' | false + 1 | true + 0 | false + true | true + false | false + end + + with_them do + it 'updates project settings attributes accordingly' do + put :update, params: { + namespace_id: project.namespace, + id: project.path, + project: { + project_setting_attributes: { + show_default_award_emojis: boolean_value, + allow_editing_commit_messages: boolean_value + } + } + } + + project.reload + + expect(project.show_default_award_emojis?).to eq(result) + expect(project.allow_editing_commit_messages?).to eq(result) + end + end + end end describe '#transfer', :enable_admin_mode do render_views - let(:project) { create(:project, :repository) } - let(:admin) { create(:admin) } - let(:new_namespace) { create(:namespace) } + let_it_be(:project, reload: true) { create(:project, :repository) } + let_it_be(:admin) { create(:admin) } + let_it_be(:new_namespace) { create(:namespace) } it 'updates namespace' do sign_in(admin) @@ -764,7 +794,7 @@ RSpec.describe ProjectsController do end describe "#destroy", :enable_admin_mode do - let(:admin) { create(:admin) } + let_it_be(:admin) { create(:admin) } it "redirects to the dashboard", :sidekiq_might_not_need_inline do controller.instance_variable_set(:@project, project) @@ -944,7 +974,7 @@ RSpec.describe ProjectsController do end describe "GET refs" do - let(:project) { create(:project, :public, :repository) } + let_it_be(:project) { create(:project, :public, :repository) } it 'gets a list of branches and tags' do get :refs, params: { namespace_id: project.namespace, id: project, sort: 'updated_desc' } @@ -1016,7 +1046,7 @@ RSpec.describe ProjectsController do end context 'state filter on references' do - let(:issue) { create(:issue, :closed, project: public_project) } + let_it_be(:issue) { create(:issue, :closed, project: public_project) } let(:merge_request) { create(:merge_request, :closed, target_project: public_project) } it 'renders JSON body with state filter for issues' do @@ -1339,7 +1369,7 @@ RSpec.describe ProjectsController do end context 'private project with token authentication' do - let(:private_project) { create(:project, :private) } + let_it_be(:private_project) { create(:project, :private) } it_behaves_like 'authenticates sessionless user', :show, :atom, ignore_incrementing: true do before do @@ -1351,7 +1381,7 @@ RSpec.describe ProjectsController do end context 'public project with token authentication' do - let(:public_project) { create(:project, :public) } + let_it_be(:public_project) { create(:project, :public) } it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do before do diff --git a/spec/controllers/registrations/experience_levels_controller_spec.rb b/spec/controllers/registrations/experience_levels_controller_spec.rb index 4be67f29107..015daba8682 100644 --- a/spec/controllers/registrations/experience_levels_controller_spec.rb +++ b/spec/controllers/registrations/experience_levels_controller_spec.rb @@ -19,7 +19,7 @@ RSpec.describe Registrations::ExperienceLevelsController do context 'with an authenticated user' do before do sign_in(user) - stub_experiment_for_user(onboarding_issues: true) + stub_experiment_for_subject(onboarding_issues: true) end it { is_expected.to have_gitlab_http_status(:ok) } @@ -28,7 +28,7 @@ RSpec.describe Registrations::ExperienceLevelsController do context 'when not part of the onboarding issues experiment' do before do - stub_experiment_for_user(onboarding_issues: false) + stub_experiment_for_subject(onboarding_issues: false) end it { is_expected.to have_gitlab_http_status(:not_found) } @@ -47,12 +47,12 @@ RSpec.describe Registrations::ExperienceLevelsController do context 'with an authenticated user' do before do sign_in(user) - stub_experiment_for_user(onboarding_issues: true) + stub_experiment_for_subject(onboarding_issues: true) end context 'when not part of the onboarding issues experiment' do before do - stub_experiment_for_user(onboarding_issues: false) + stub_experiment_for_subject(onboarding_issues: false) end it { is_expected.to have_gitlab_http_status(:not_found) } @@ -90,7 +90,7 @@ RSpec.describe Registrations::ExperienceLevelsController do let(:issues_board) { build(:board, id: 123, project: project) } before do - stub_experiment_for_user( + stub_experiment_for_subject( onboarding_issues: true, default_to_issues_board: default_to_issues_board_xp? ) diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb index 851c1b7e519..551abf9241d 100644 --- a/spec/controllers/repositories/git_http_controller_spec.rb +++ b/spec/controllers/repositories/git_http_controller_spec.rb @@ -3,219 +3,87 @@ require 'spec_helper' RSpec.describe Repositories::GitHttpController do - include GitHttpHelpers - let_it_be(:project) { create(:project, :public, :repository) } let_it_be(:personal_snippet) { create(:personal_snippet, :public, :repository) } let_it_be(:project_snippet) { create(:project_snippet, :public, :repository, project: project) } - let(:namespace_id) { project.namespace.to_param } - let(:repository_id) { project.path + '.git' } - let(:container_params) do - { - namespace_id: namespace_id, - repository_id: repository_id - } - end - - let(:params) { container_params } - - describe 'HEAD #info_refs' do - it 'returns 403' do - head :info_refs, params: params - - expect(response).to have_gitlab_http_status(:forbidden) - end - end - - shared_examples 'info_refs behavior' do - describe 'GET #info_refs' do - let(:params) { container_params.merge(service: 'git-upload-pack') } - - it 'returns 401 for unauthenticated requests to public repositories when http protocol is disabled' do - stub_application_setting(enabled_git_access_protocol: 'ssh') - allow(controller).to receive(:basic_auth_provided?).and_call_original - - expect(controller).to receive(:http_download_allowed?).and_call_original - - get :info_refs, params: params - - expect(response).to have_gitlab_http_status(:unauthorized) - end + context 'when repository container is a project' do + it_behaves_like Repositories::GitHttpController do + let(:container) { project } + let(:user) { project.owner } + let(:access_checker_class) { Gitlab::GitAccess } - context 'with authorized user' do + describe 'POST #git_upload_pack' do before do - request.headers.merge! auth_env(user.username, user.password, nil) + allow(controller).to receive(:verify_workhorse_api!).and_return(true) end - it 'returns 200' do - get :info_refs, params: params - - expect(response).to have_gitlab_http_status(:ok) + def send_request + post :git_upload_pack, params: params end - it 'updates the user activity' do - expect_next_instance_of(Users::ActivityService) do |activity_service| - expect(activity_service).to receive(:execute) + context 'on a read-only instance' do + before do + allow(Gitlab::Database).to receive(:read_only?).and_return(true) end - get :info_refs, params: params - end - - include_context 'parsed logs' do - it 'adds user info to the logs' do - get :info_refs, params: params + it 'does not update project statistics' do + expect(ProjectDailyStatisticsWorker).not_to receive(:perform_async) - expect(log_data).to include('username' => user.username, - 'user_id' => user.id, - 'meta.user' => user.username) + send_request end end - end - - context 'with exceptions' do - before do - allow(controller).to receive(:authenticate_user).and_return(true) - allow(controller).to receive(:verify_workhorse_api!).and_return(true) - end - - it 'returns 503 with GRPC Unavailable' do - allow(controller).to receive(:access_check).and_raise(GRPC::Unavailable) - - get :info_refs, params: params - - expect(response).to have_gitlab_http_status(:service_unavailable) - end - - it 'returns 503 with timeout error' do - allow(controller).to receive(:access_check).and_raise(Gitlab::GitAccess::TimeoutError) - - get :info_refs, params: params - - expect(response).to have_gitlab_http_status(:service_unavailable) - expect(response.body).to eq 'Gitlab::GitAccess::TimeoutError' - end - end - end - end - - shared_examples 'git_upload_pack behavior' do |expected| - describe 'POST #git_upload_pack' do - before do - allow(controller).to receive(:authenticate_user).and_return(true) - allow(controller).to receive(:verify_workhorse_api!).and_return(true) - allow(controller).to receive(:access_check).and_return(nil) - end - - def send_request - post :git_upload_pack, params: params - end - - context 'on a read-only instance' do - before do - allow(Gitlab::Database).to receive(:read_only?).and_return(true) - end - it 'does not update project statistics' do - expect(ProjectDailyStatisticsWorker).not_to receive(:perform_async) - - send_request - end - end - - if expected context 'when project_statistics_sync feature flag is disabled' do before do stub_feature_flags(project_statistics_sync: false) end - it 'updates project statistics async' do + it 'updates project statistics async for projects' do expect(ProjectDailyStatisticsWorker).to receive(:perform_async) send_request end end - it 'updates project statistics sync' do + it 'updates project statistics sync for projects' do expect { send_request }.to change { - Projects::DailyStatisticsFinder.new(project).total_fetch_count + Projects::DailyStatisticsFinder.new(container).total_fetch_count }.from(0).to(1) end - else - context 'when project_statistics_sync feature flag is disabled' do - before do - stub_feature_flags(project_statistics_sync: false) - end - - it 'does not update project statistics' do - expect(ProjectDailyStatisticsWorker).not_to receive(:perform_async) - send_request + it 'records a namespace onboarding progress action' do + expect_next_instance_of(OnboardingProgressService) do |service| + expect(service).to receive(:execute).with(action: :git_read) end - end - it 'does not update project statistics' do - expect { send_request }.not_to change { - Projects::DailyStatisticsFinder.new(project).total_fetch_count - }.from(0) + send_request end end end end - shared_examples 'access checker class' do - let(:params) { container_params.merge(service: 'git-upload-pack') } - - it 'calls the right access class checker with the right object' do - allow(controller).to receive(:verify_workhorse_api!).and_return(true) - - access_double = double - expect(expected_class).to receive(:new).with(anything, expected_object, 'http', anything).and_return(access_double) - allow(access_double).to receive(:check).and_return(false) - - get :info_refs, params: params - end - end - - context 'when repository container is a project' do - it_behaves_like 'info_refs behavior' do + context 'when repository container is a project wiki' do + it_behaves_like Repositories::GitHttpController do + let(:container) { create(:project_wiki, :empty_repo, project: project) } let(:user) { project.owner } - end - - it_behaves_like 'git_upload_pack behavior', true - it_behaves_like 'access checker class' do - let(:expected_class) { Gitlab::GitAccess } - let(:expected_object) { project } + let(:access_checker_class) { Gitlab::GitAccessWiki } end end context 'when repository container is a personal snippet' do - let(:namespace_id) { 'snippets' } - let(:repository_id) { personal_snippet.to_param + '.git' } - - it_behaves_like 'info_refs behavior' do + it_behaves_like Repositories::GitHttpController do + let(:container) { personal_snippet } let(:user) { personal_snippet.author } - end - - it_behaves_like 'git_upload_pack behavior', false - it_behaves_like 'access checker class' do - let(:expected_class) { Gitlab::GitAccessSnippet } - let(:expected_object) { personal_snippet } + let(:access_checker_class) { Gitlab::GitAccessSnippet } end end context 'when repository container is a project snippet' do - let(:namespace_id) { project.full_path + '/snippets' } - let(:repository_id) { project_snippet.to_param + '.git' } - - it_behaves_like 'info_refs behavior' do + it_behaves_like Repositories::GitHttpController do + let(:container) { project_snippet } let(:user) { project_snippet.author } - end - - it_behaves_like 'git_upload_pack behavior', false - it_behaves_like 'access checker class' do - let(:expected_class) { Gitlab::GitAccessSnippet } - let(:expected_object) { project_snippet } + let(:access_checker_class) { Gitlab::GitAccessSnippet } end end end diff --git a/spec/controllers/repositories/lfs_storage_controller_spec.rb b/spec/controllers/repositories/lfs_storage_controller_spec.rb index 4f9d049cf87..e361a7442bb 100644 --- a/spec/controllers/repositories/lfs_storage_controller_spec.rb +++ b/spec/controllers/repositories/lfs_storage_controller_spec.rb @@ -23,8 +23,7 @@ RSpec.describe Repositories::LfsStorageController do let(:params) do { - namespace_id: project.namespace.path, - repository_id: "#{project.path}.git", + repository_path: "#{project.full_path}.git", oid: '6b9765d3888aaec789e8c309eb05b05c3a87895d6ad70d2264bd7270fff665ac', size: '6725030' } diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb index 1db99a09404..85f9ea66c5f 100644 --- a/spec/controllers/root_controller_spec.rb +++ b/spec/controllers/root_controller_spec.rb @@ -125,7 +125,7 @@ RSpec.describe RootController do context 'when experiment is enabled' do before do - stub_experiment_for_user(customize_homepage: true) + stub_experiment_for_subject(customize_homepage: true) end it 'renders the default dashboard' do diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index 993ab5d1c72..51cecb348c8 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -172,6 +172,13 @@ RSpec.describe SnippetsController do expect(assigns(:snippet)).to eq(public_snippet) expect(response).to have_gitlab_http_status(:ok) end + + it_behaves_like 'tracking unique hll events', :usage_data_i_snippets_show do + subject(:request) { get :show, params: { id: public_snippet.to_param } } + + let(:target_id) { 'i_snippets_show' } + let(:expected_type) { instance_of(String) } + end end context 'when not signed in' do diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 2e57a901319..916befe3f62 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -3,7 +3,8 @@ require 'spec_helper' RSpec.describe UsersController do - let(:user) { create(:user) } + # This user should have the same e-mail address associated with the GPG key prepared for tests + let(:user) { create(:user, email: GpgHelpers::User1.emails[0]) } let(:private_user) { create(:user, private_profile: true) } let(:public_user) { create(:user) } @@ -114,6 +115,335 @@ RSpec.describe UsersController do end end + describe 'GET #activity' do + context 'with rendered views' do + render_views + + describe 'when logged in' do + before do + sign_in(user) + end + + it 'renders the show template' do + get :show, params: { username: user.username } + + expect(response).to be_successful + expect(response).to render_template('show') + end + end + + describe 'when logged out' do + it 'renders the show template' do + get :activity, params: { username: user.username } + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template('show') + end + end + end + + context 'when public visibility level is restricted' do + before do + stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) + end + + context 'when logged out' do + it 'redirects to login page' do + get :activity, params: { username: user.username } + expect(response).to redirect_to new_user_session_path + end + end + + context 'when logged in' do + before do + sign_in(user) + end + + it 'renders show' do + get :activity, params: { username: user.username } + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template('show') + end + end + end + + context 'when a user by that username does not exist' do + context 'when logged out' do + it 'redirects to login page' do + get :activity, params: { username: 'nonexistent' } + expect(response).to redirect_to new_user_session_path + end + end + + context 'when logged in' do + before do + sign_in(user) + end + + it 'renders 404' do + get :activity, params: { username: 'nonexistent' } + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'json with events' do + let(:project) { create(:project) } + + before do + project.add_developer(user) + Gitlab::DataBuilder::Push.build_sample(project, user) + + sign_in(user) + end + + it 'loads events' do + get :activity, params: { username: user }, format: :json + + expect(assigns(:events)).not_to be_empty + end + + it 'hides events if the user cannot read cross project' do + allow(Ability).to receive(:allowed?).and_call_original + expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false } + + get :activity, params: { username: user }, format: :json + + expect(assigns(:events)).to be_empty + end + + it 'hides events if the user has a private profile' do + Gitlab::DataBuilder::Push.build_sample(project, private_user) + + get :activity, params: { username: private_user.username }, format: :json + + expect(assigns(:events)).to be_empty + end + end + end + + describe "#ssh_keys" do + describe "non existent user" do + it "does not generally work" do + get :ssh_keys, params: { username: 'not-existent' } + + expect(response).not_to be_successful + end + end + + describe "user with no keys" do + it "does generally work" do + get :ssh_keys, params: { username: user.username } + + expect(response).to be_successful + end + + it "renders all keys separated with a new line" do + get :ssh_keys, params: { username: user.username } + + expect(response.body).to eq("") + end + + it "responds with text/plain content type" do + get :ssh_keys, params: { username: user.username } + expect(response.content_type).to eq("text/plain") + end + end + + describe "user with keys" do + let!(:key) { create(:key, user: user) } + let!(:another_key) { create(:another_key, user: user) } + let!(:deploy_key) { create(:deploy_key, user: user) } + + describe "while signed in" do + before do + sign_in(user) + end + + it "does generally work" do + get :ssh_keys, params: { username: user.username } + + expect(response).to be_successful + end + + it "renders all non deploy keys separated with a new line" do + get :ssh_keys, params: { username: user.username } + + expect(response.body).not_to eq('') + expect(response.body).to eq(user.all_ssh_keys.join("\n")) + + expect(response.body).to include(key.key.sub(' dummy@gitlab.com', '')) + expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', '')) + + expect(response.body).not_to include(deploy_key.key) + end + + it "does not render the comment of the key" do + get :ssh_keys, params: { username: user.username } + expect(response.body).not_to match(/dummy@gitlab.com/) + end + + it "responds with text/plain content type" do + get :ssh_keys, params: { username: user.username } + + expect(response.content_type).to eq("text/plain") + end + end + + describe 'when logged out' do + before do + sign_out(user) + end + + it "still does generally work" do + get :ssh_keys, params: { username: user.username } + + expect(response).to be_successful + end + + it "renders all non deploy keys separated with a new line" do + get :ssh_keys, params: { username: user.username } + + expect(response.body).not_to eq('') + expect(response.body).to eq(user.all_ssh_keys.join("\n")) + + expect(response.body).to include(key.key.sub(' dummy@gitlab.com', '')) + expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', '')) + + expect(response.body).not_to include(deploy_key.key) + end + + it "does not render the comment of the key" do + get :ssh_keys, params: { username: user.username } + expect(response.body).not_to match(/dummy@gitlab.com/) + end + + it "responds with text/plain content type" do + get :ssh_keys, params: { username: user.username } + + expect(response.content_type).to eq("text/plain") + end + end + end + end + + describe "#gpg_keys" do + describe "non existent user" do + it "does not generally work" do + get :gpg_keys, params: { username: 'not-existent' } + + expect(response).not_to be_successful + end + end + + describe "user with no keys" do + it "does generally work" do + get :gpg_keys, params: { username: user.username } + + expect(response).to be_successful + end + + it "renders all keys separated with a new line" do + get :gpg_keys, params: { username: user.username } + + expect(response.body).to eq("") + end + + it "responds with text/plain content type" do + get :gpg_keys, params: { username: user.username } + + expect(response.content_type).to eq("text/plain") + end + end + + describe "user with keys" do + let!(:gpg_key) { create(:gpg_key, user: user) } + let!(:another_gpg_key) { create(:another_gpg_key, user: user) } + + describe "while signed in" do + before do + sign_in(user) + end + + it "does generally work" do + get :gpg_keys, params: { username: user.username } + + expect(response).to be_successful + end + + it "renders all verified keys separated with a new line" do + get :gpg_keys, params: { username: user.username } + + expect(response.body).not_to eq('') + expect(response.body).to eq(user.gpg_keys.select(&:verified?).map(&:key).join("\n")) + + expect(response.body).to include(gpg_key.key) + expect(response.body).to include(another_gpg_key.key) + end + + it "responds with text/plain content type" do + get :gpg_keys, params: { username: user.username } + + expect(response.content_type).to eq("text/plain") + end + end + + describe 'when logged out' do + before do + sign_out(user) + end + + it "still does generally work" do + get :gpg_keys, params: { username: user.username } + + expect(response).to be_successful + end + + it "renders all verified keys separated with a new line" do + get :gpg_keys, params: { username: user.username } + + expect(response.body).not_to eq('') + expect(response.body).to eq(user.gpg_keys.map(&:key).join("\n")) + + expect(response.body).to include(gpg_key.key) + expect(response.body).to include(another_gpg_key.key) + end + + it "responds with text/plain content type" do + get :gpg_keys, params: { username: user.username } + + expect(response.content_type).to eq("text/plain") + end + end + + describe 'when revoked' do + before do + sign_in(user) + another_gpg_key.revoke + end + + it "doesn't render revoked keys" do + get :gpg_keys, params: { username: user.username } + + expect(response.body).not_to eq('') + + expect(response.body).to include(gpg_key.key) + expect(response.body).not_to include(another_gpg_key.key) + end + + it "doesn't render revoked keys for non-authorized users" do + sign_out(user) + get :gpg_keys, params: { username: user.username } + + expect(response.body).not_to eq('') + + expect(response.body).to include(gpg_key.key) + expect(response.body).not_to include(another_gpg_key.key) + end + end + end + end + describe 'GET #calendar' do context 'for user' do let(:project) { create(:project) } |